Ownership.h revision b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970c
1//===--- Ownership.h - Parser ownership helpers -----------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file contains classes for managing ownership of Stmt and Expr nodes. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_SEMA_OWNERSHIP_H 15#define LLVM_CLANG_SEMA_OWNERSHIP_H 16 17#include "llvm/ADT/SmallVector.h" 18#include "llvm/ADT/PointerIntPair.h" 19 20//===----------------------------------------------------------------------===// 21// OpaquePtr 22//===----------------------------------------------------------------------===// 23 24namespace clang { 25 class Action; 26 class Attr; 27 class CXXBaseOrMemberInitializer; 28 class CXXBaseSpecifier; 29 class Decl; 30 class DeclGroupRef; 31 class Expr; 32 class NestedNameSpecifier; 33 class QualType; 34 class Stmt; 35 class TemplateName; 36 class TemplateParameterList; 37 38 /// OpaquePtr - This is a very simple POD type that wraps a pointer that the 39 /// Parser doesn't know about but that Sema or another client does. The UID 40 /// template argument is used to make sure that "Decl" pointers are not 41 /// compatible with "Type" pointers for example. 42 template <class PtrTy> 43 class OpaquePtr { 44 void *Ptr; 45 explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {} 46 47 typedef llvm::PointerLikeTypeTraits<PtrTy> Traits; 48 49 public: 50 OpaquePtr() : Ptr(0) {} 51 52 static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; } 53 54 template <typename T> T* getAs() const { 55 return get(); 56 } 57 58 template <typename T> T getAsVal() const { 59 return get(); 60 } 61 62 PtrTy get() const { 63 return Traits::getFromVoidPointer(Ptr); 64 } 65 66 void set(PtrTy P) { 67 Ptr = Traits::getAsVoidPointer(P); 68 } 69 70 operator bool() const { return Ptr != 0; } 71 72 void *getAsOpaquePtr() const { return Ptr; } 73 static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); } 74 }; 75 76 /// UnionOpaquePtr - A version of OpaquePtr suitable for membership 77 /// in a union. 78 template <class T> struct UnionOpaquePtr { 79 void *Ptr; 80 81 static UnionOpaquePtr make(OpaquePtr<T> P) { 82 UnionOpaquePtr OP = { P.getAsOpaquePtr() }; 83 return OP; 84 } 85 86 OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); } 87 operator OpaquePtr<T>() const { return get(); } 88 89 UnionOpaquePtr &operator=(OpaquePtr<T> P) { 90 Ptr = P.getAsOpaquePtr(); 91 return *this; 92 } 93 }; 94} 95 96namespace llvm { 97 template <class T> 98 class PointerLikeTypeTraits<clang::OpaquePtr<T> > { 99 public: 100 static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) { 101 // FIXME: Doesn't work? return P.getAs< void >(); 102 return P.getAsOpaquePtr(); 103 } 104 static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) { 105 return clang::OpaquePtr<T>::getFromOpaquePtr(P); 106 } 107 enum { NumLowBitsAvailable = 0 }; 108 }; 109} 110 111 112 113// -------------------------- About Move Emulation -------------------------- // 114// The smart pointer classes in this file attempt to emulate move semantics 115// as they appear in C++0x with rvalue references. Since C++03 doesn't have 116// rvalue references, some tricks are needed to get similar results. 117// Move semantics in C++0x have the following properties: 118// 1) "Moving" means transferring the value of an object to another object, 119// similar to copying, but without caring what happens to the old object. 120// In particular, this means that the new object can steal the old object's 121// resources instead of creating a copy. 122// 2) Since moving can modify the source object, it must either be explicitly 123// requested by the user, or the modifications must be unnoticeable. 124// 3) As such, C++0x moving is only allowed in three contexts: 125// * By explicitly using std::move() to request it. 126// * From a temporary object, since that object cannot be accessed 127// afterwards anyway, thus making the state unobservable. 128// * On function return, since the object is not observable afterwards. 129// 130// To sum up: moving from a named object should only be possible with an 131// explicit std::move(), or on function return. Moving from a temporary should 132// be implicitly done. Moving from a const object is forbidden. 133// 134// The emulation is not perfect, and has the following shortcomings: 135// * move() is not in namespace std. 136// * move() is required on function return. 137// * There are difficulties with implicit conversions. 138// * Microsoft's compiler must be given the /Za switch to successfully compile. 139// 140// -------------------------- Implementation -------------------------------- // 141// The move emulation relies on the peculiar reference binding semantics of 142// C++03: as a rule, a non-const reference may not bind to a temporary object, 143// except for the implicit object parameter in a member function call, which 144// can refer to a temporary even when not being const. 145// The moveable object has five important functions to facilitate moving: 146// * A private, unimplemented constructor taking a non-const reference to its 147// own class. This constructor serves a two-fold purpose. 148// - It prevents the creation of a copy constructor that takes a const 149// reference. Temporaries would be able to bind to the argument of such a 150// constructor, and that would be bad. 151// - Named objects will bind to the non-const reference, but since it's 152// private, this will fail to compile. This prevents implicit moving from 153// named objects. 154// There's also a copy assignment operator for the same purpose. 155// * An implicit, non-const conversion operator to a special mover type. This 156// type represents the rvalue reference of C++0x. Being a non-const member, 157// its implicit this parameter can bind to temporaries. 158// * A constructor that takes an object of this mover type. This constructor 159// performs the actual move operation. There is an equivalent assignment 160// operator. 161// There is also a free move() function that takes a non-const reference to 162// an object and returns a temporary. Internally, this function uses explicit 163// constructor calls to move the value from the referenced object to the return 164// value. 165// 166// There are now three possible scenarios of use. 167// * Copying from a const object. Constructor overload resolution will find the 168// non-const copy constructor, and the move constructor. The first is not 169// viable because the const object cannot be bound to the non-const reference. 170// The second fails because the conversion to the mover object is non-const. 171// Moving from a const object fails as intended. 172// * Copying from a named object. Constructor overload resolution will select 173// the non-const copy constructor, but fail as intended, because this 174// constructor is private. 175// * Copying from a temporary. Constructor overload resolution cannot select 176// the non-const copy constructor, because the temporary cannot be bound to 177// the non-const reference. It thus selects the move constructor. The 178// temporary can be bound to the implicit this parameter of the conversion 179// operator, because of the special binding rule. Construction succeeds. 180// Note that the Microsoft compiler, as an extension, allows binding 181// temporaries against non-const references. The compiler thus selects the 182// non-const copy constructor and fails, because the constructor is private. 183// Passing /Za (disable extensions) disables this behaviour. 184// The free move() function is used to move from a named object. 185// 186// Note that when passing an object of a different type (the classes below 187// have OwningResult and OwningPtr, which should be mixable), you get a problem. 188// Argument passing and function return use copy initialization rules. The 189// effect of this is that, when the source object is not already of the target 190// type, the compiler will first seek a way to convert the source object to the 191// target type, and only then attempt to copy the resulting object. This means 192// that when passing an OwningResult where an OwningPtr is expected, the 193// compiler will first seek a conversion from OwningResult to OwningPtr, then 194// copy the OwningPtr. The resulting conversion sequence is: 195// OwningResult object -> ResultMover -> OwningResult argument to 196// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr 197// This conversion sequence is too complex to be allowed. Thus the special 198// move_* functions, which help the compiler out with some explicit 199// conversions. 200 201namespace clang { 202 // Basic 203 class DiagnosticBuilder; 204 205 // Determines whether the low bit of the result pointer for the 206 // given UID is always zero. If so, ActionResult will use that bit 207 // for it's "invalid" flag. 208 template<class Ptr> 209 struct IsResultPtrLowBitFree { 210 static const bool value = false; 211 }; 212 213 /// ActionResult - This structure is used while parsing/acting on 214 /// expressions, stmts, etc. It encapsulates both the object returned by 215 /// the action, plus a sense of whether or not it is valid. 216 /// When CompressInvalid is true, the "invalid" flag will be 217 /// stored in the low bit of the Val pointer. 218 template<class PtrTy, 219 bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value> 220 class ActionResult { 221 PtrTy Val; 222 bool Invalid; 223 224 public: 225 ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {} 226 ActionResult(PtrTy val) : Val(val), Invalid(false) {} 227 ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {} 228 229 // These two overloads prevent void* -> bool conversions. 230 ActionResult(const void *); 231 ActionResult(volatile void *); 232 233 PtrTy get() const { return Val; } 234 void set(PtrTy V) { Val = V; } 235 bool isInvalid() const { return Invalid; } 236 237 const ActionResult &operator=(PtrTy RHS) { 238 Val = RHS; 239 Invalid = false; 240 return *this; 241 } 242 }; 243 244 // This ActionResult partial specialization places the "invalid" 245 // flag into the low bit of the pointer. 246 template<typename PtrTy> 247 class ActionResult<PtrTy, true> { 248 // A pointer whose low bit is 1 if this result is invalid, 0 249 // otherwise. 250 uintptr_t PtrWithInvalid; 251 typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits; 252 public: 253 ActionResult(bool Invalid = false) 254 : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { } 255 256 ActionResult(PtrTy V) { 257 void *VP = PtrTraits::getAsVoidPointer(V); 258 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); 259 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); 260 } 261 262 // These two overloads prevent void* -> bool conversions. 263 ActionResult(const void *); 264 ActionResult(volatile void *); 265 266 ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { } 267 268 PtrTy get() const { 269 void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); 270 return PtrTraits::getFromVoidPointer(VP); 271 } 272 273 void set(PtrTy V) { 274 void *VP = PtrTraits::getAsVoidPointer(V); 275 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); 276 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); 277 } 278 279 bool isInvalid() const { return PtrWithInvalid & 0x01; } 280 281 const ActionResult &operator=(PtrTy RHS) { 282 void *VP = PtrTraits::getAsVoidPointer(RHS); 283 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); 284 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); 285 return *this; 286 } 287 }; 288 289 /// ASTOwningResult - A moveable smart pointer for AST nodes that also 290 /// has an extra flag to indicate an additional success status. 291 template <typename PtrTy> class ASTOwningResult; 292 293 /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns 294 /// the individual pointers, not the array holding them. 295 template <typename PtrTy> class ASTMultiPtr; 296 297 template <class PtrTy> class ASTOwningResult { 298 public: 299 typedef ActionResult<PtrTy> DumbResult; 300 301 private: 302 DumbResult Result; 303 304 public: 305 explicit ASTOwningResult(bool invalid = false) 306 : Result(invalid) { } 307 ASTOwningResult(PtrTy node) : Result(node) { } 308 ASTOwningResult(const DumbResult &res) : Result(res) { } 309 // Normal copying semantics are defined implicitly. 310 311 // These two overloads prevent void* -> bool conversions. 312 explicit ASTOwningResult(const void *); 313 explicit ASTOwningResult(volatile void *); 314 315 /// Assignment from a raw pointer. 316 ASTOwningResult &operator=(PtrTy raw) { 317 Result = raw; 318 return *this; 319 } 320 321 /// Assignment from an ActionResult. 322 ASTOwningResult &operator=(const DumbResult &res) { 323 Result = res; 324 return *this; 325 } 326 327 bool isInvalid() const { return Result.isInvalid(); } 328 329 /// Does this point to a usable AST node? To be usable, the node 330 /// must be valid and non-null. 331 bool isUsable() const { return !Result.isInvalid() && get(); } 332 333 /// It is forbidden to call either of these methods on an invalid 334 /// pointer. We should assert that, but we're not going to, 335 /// because it's likely to trigger it unpredictable ways on 336 /// invalid code. 337 PtrTy get() const { return Result.get(); } 338 PtrTy take() const { return get(); } 339 340 /// Take outside ownership of the raw pointer and cast it down. 341 template<typename T> 342 T *takeAs() { return static_cast<T*>(get()); } 343 344 /// Alias for interface familiarity with unique_ptr. 345 PtrTy release() { return take(); } 346 347 /// Pass ownership to a classical ActionResult. 348 DumbResult result() { return Result; } 349 }; 350 351 template <class PtrTy> 352 class ASTMultiPtr { 353 PtrTy *Nodes; 354 unsigned Count; 355 356 public: 357 // Normal copying implicitly defined 358 explicit ASTMultiPtr(Action &) : Nodes(0), Count(0) {} 359 ASTMultiPtr(Action &, PtrTy *nodes, unsigned count) 360 : Nodes(nodes), Count(count) {} 361 // Fake mover in Parse/AstGuard.h needs this: 362 ASTMultiPtr(PtrTy *nodes, unsigned count) : Nodes(nodes), Count(count) {} 363 364 /// Access to the raw pointers. 365 PtrTy *get() const { return Nodes; } 366 367 /// Access to the count. 368 unsigned size() const { return Count; } 369 370 PtrTy *release() { 371 return Nodes; 372 } 373 }; 374 375 class ParsedTemplateArgument; 376 377 class ASTTemplateArgsPtr { 378 ParsedTemplateArgument *Args; 379 mutable unsigned Count; 380 381 public: 382 ASTTemplateArgsPtr(Action &actions, ParsedTemplateArgument *args, 383 unsigned count) : 384 Args(args), Count(count) { } 385 386 // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. 387 ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : 388 Args(Other.Args), Count(Other.Count) { 389 } 390 391 // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. 392 ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) { 393 Args = Other.Args; 394 Count = Other.Count; 395 return *this; 396 } 397 398 ParsedTemplateArgument *getArgs() const { return Args; } 399 unsigned size() const { return Count; } 400 401 void reset(ParsedTemplateArgument *args, unsigned count) { 402 Args = args; 403 Count = count; 404 } 405 406 const ParsedTemplateArgument &operator[](unsigned Arg) const; 407 408 ParsedTemplateArgument *release() const { 409 return Args; 410 } 411 }; 412 413 /// \brief A small vector that owns a set of AST nodes. 414 template <class PtrTy, unsigned N = 8> 415 class ASTOwningVector : public llvm::SmallVector<PtrTy, N> { 416 ASTOwningVector(ASTOwningVector &); // do not implement 417 ASTOwningVector &operator=(ASTOwningVector &); // do not implement 418 419 public: 420 explicit ASTOwningVector(Action &Actions) 421 { } 422 423 PtrTy *take() { 424 return &this->front(); 425 } 426 427 template<typename T> T **takeAs() { return reinterpret_cast<T**>(take()); } 428 }; 429 430 /// A SmallVector of statements, with stack size 32 (as that is the only one 431 /// used.) 432 typedef ASTOwningVector<Stmt*, 32> StmtVector; 433 /// A SmallVector of expressions, with stack size 12 (the maximum used.) 434 typedef ASTOwningVector<Expr*, 12> ExprVector; 435 436 template <class T, unsigned N> inline 437 ASTMultiPtr<T> move_arg(ASTOwningVector<T, N> &vec) { 438 return ASTMultiPtr<T>(vec.take(), vec.size()); 439 } 440 441 // These versions are hopefully no-ops. 442 template <class T> inline 443 ASTOwningResult<T> move(ASTOwningResult<T> &ptr) { 444 return ptr; 445 } 446 447 template <class T> inline 448 ASTMultiPtr<T>& move(ASTMultiPtr<T> &ptr) { 449 return ptr; 450 } 451 452 // We can re-use the low bit of expression, statement, base, and 453 // member-initializer pointers for the "invalid" flag of 454 // ActionResult. 455 template<> struct IsResultPtrLowBitFree<Expr*> { 456 static const bool value = true; 457 }; 458 template<> struct IsResultPtrLowBitFree<Stmt*> { 459 static const bool value = true; 460 }; 461 template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> { 462 static const bool value = true; 463 }; 464 template<> struct IsResultPtrLowBitFree<CXXBaseOrMemberInitializer*> { 465 static const bool value = true; 466 }; 467 468 /// An opaque type for threading parsed type information through the 469 /// parser. 470 typedef OpaquePtr<QualType> ParsedType; 471 typedef UnionOpaquePtr<QualType> UnionParsedType; 472 473 typedef ActionResult<Expr*> ExprResult; 474 typedef ActionResult<Stmt*> StmtResult; 475 typedef ActionResult<ParsedType> TypeResult; 476 typedef ActionResult<CXXBaseSpecifier*> BaseResult; 477 typedef ActionResult<CXXBaseOrMemberInitializer*> MemInitResult; 478 479 typedef ActionResult<Decl*> DeclResult; 480 typedef OpaquePtr<TemplateName> ParsedTemplateTy; 481 482 typedef ASTOwningResult<Expr*> OwningExprResult; 483 typedef ASTOwningResult<Stmt*> OwningStmtResult; 484 485 inline Expr *move(Expr *E) { return E; } 486 inline Stmt *move(Stmt *S) { return S; } 487 488 typedef ASTMultiPtr<Expr*> MultiExprArg; 489 typedef ASTMultiPtr<TemplateParameterList*> MultiTemplateParamsArg; 490 491 inline Expr *AssertSuccess(OwningExprResult R) { 492 assert(!R.isInvalid() && "operation was asserted to never fail!"); 493 return R.get(); 494 } 495 496 inline Stmt *AssertSuccess(OwningStmtResult R) { 497 assert(!R.isInvalid() && "operation was asserted to never fail!"); 498 return R.get(); 499 } 500} 501 502#endif 503