Ownership.h revision 182f7093dd9dabbcf6df44b4ae004ead38804b48
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) 226 : Val(PtrTy()), Invalid(Invalid) {} 227 ActionResult(PtrTy val) : Val(val), Invalid(false) {} 228 ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {} 229 230 // These two overloads prevent void* -> bool conversions. 231 ActionResult(const void *); 232 ActionResult(volatile void *); 233 234 bool isInvalid() const { return Invalid; } 235 bool isUsable() const { return !Invalid && Val; } 236 237 PtrTy get() const { return Val; } 238 PtrTy release() const { return Val; } 239 PtrTy take() const { return Val; } 240 template <typename T> T *takeAs() { return static_cast<T*>(get()); } 241 242 void set(PtrTy V) { Val = V; } 243 244 const ActionResult &operator=(PtrTy RHS) { 245 Val = RHS; 246 Invalid = false; 247 return *this; 248 } 249 }; 250 251 // This ActionResult partial specialization places the "invalid" 252 // flag into the low bit of the pointer. 253 template<typename PtrTy> 254 class ActionResult<PtrTy, true> { 255 // A pointer whose low bit is 1 if this result is invalid, 0 256 // otherwise. 257 uintptr_t PtrWithInvalid; 258 typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits; 259 public: 260 ActionResult(bool Invalid = false) 261 : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { } 262 263 ActionResult(PtrTy V) { 264 void *VP = PtrTraits::getAsVoidPointer(V); 265 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); 266 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); 267 } 268 ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { } 269 270 // These two overloads prevent void* -> bool conversions. 271 ActionResult(const void *); 272 ActionResult(volatile void *); 273 274 bool isInvalid() const { return PtrWithInvalid & 0x01; } 275 bool isUsable() const { return PtrWithInvalid > 0x01; } 276 277 PtrTy get() const { 278 void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); 279 return PtrTraits::getFromVoidPointer(VP); 280 } 281 PtrTy take() const { return get(); } 282 PtrTy release() const { return get(); } 283 template <typename T> T *takeAs() { return static_cast<T*>(get()); } 284 285 void set(PtrTy V) { 286 void *VP = PtrTraits::getAsVoidPointer(V); 287 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); 288 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); 289 } 290 291 const ActionResult &operator=(PtrTy RHS) { 292 void *VP = PtrTraits::getAsVoidPointer(RHS); 293 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); 294 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); 295 return *this; 296 } 297 }; 298 299 /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns 300 /// the individual pointers, not the array holding them. 301 template <typename PtrTy> class ASTMultiPtr; 302 303 template <class PtrTy> 304 class ASTMultiPtr { 305 PtrTy *Nodes; 306 unsigned Count; 307 308 public: 309 // Normal copying implicitly defined 310 explicit ASTMultiPtr(Action &) : Nodes(0), Count(0) {} 311 ASTMultiPtr(Action &, PtrTy *nodes, unsigned count) 312 : Nodes(nodes), Count(count) {} 313 // Fake mover in Parse/AstGuard.h needs this: 314 ASTMultiPtr(PtrTy *nodes, unsigned count) : Nodes(nodes), Count(count) {} 315 316 /// Access to the raw pointers. 317 PtrTy *get() const { return Nodes; } 318 319 /// Access to the count. 320 unsigned size() const { return Count; } 321 322 PtrTy *release() { 323 return Nodes; 324 } 325 }; 326 327 class ParsedTemplateArgument; 328 329 class ASTTemplateArgsPtr { 330 ParsedTemplateArgument *Args; 331 mutable unsigned Count; 332 333 public: 334 ASTTemplateArgsPtr(Action &actions, ParsedTemplateArgument *args, 335 unsigned count) : 336 Args(args), Count(count) { } 337 338 // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. 339 ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : 340 Args(Other.Args), Count(Other.Count) { 341 } 342 343 // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. 344 ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) { 345 Args = Other.Args; 346 Count = Other.Count; 347 return *this; 348 } 349 350 ParsedTemplateArgument *getArgs() const { return Args; } 351 unsigned size() const { return Count; } 352 353 void reset(ParsedTemplateArgument *args, unsigned count) { 354 Args = args; 355 Count = count; 356 } 357 358 const ParsedTemplateArgument &operator[](unsigned Arg) const; 359 360 ParsedTemplateArgument *release() const { 361 return Args; 362 } 363 }; 364 365 /// \brief A small vector that owns a set of AST nodes. 366 template <class PtrTy, unsigned N = 8> 367 class ASTOwningVector : public llvm::SmallVector<PtrTy, N> { 368 ASTOwningVector(ASTOwningVector &); // do not implement 369 ASTOwningVector &operator=(ASTOwningVector &); // do not implement 370 371 public: 372 explicit ASTOwningVector(Action &Actions) 373 { } 374 375 PtrTy *take() { 376 return &this->front(); 377 } 378 379 template<typename T> T **takeAs() { return reinterpret_cast<T**>(take()); } 380 }; 381 382 /// A SmallVector of statements, with stack size 32 (as that is the only one 383 /// used.) 384 typedef ASTOwningVector<Stmt*, 32> StmtVector; 385 /// A SmallVector of expressions, with stack size 12 (the maximum used.) 386 typedef ASTOwningVector<Expr*, 12> ExprVector; 387 388 template <class T, unsigned N> inline 389 ASTMultiPtr<T> move_arg(ASTOwningVector<T, N> &vec) { 390 return ASTMultiPtr<T>(vec.take(), vec.size()); 391 } 392 393 // These versions are hopefully no-ops. 394 template <class T, bool C> 395 inline ActionResult<T,C> move(ActionResult<T,C> &ptr) { 396 return ptr; 397 } 398 399 template <class T> inline 400 ASTMultiPtr<T>& move(ASTMultiPtr<T> &ptr) { 401 return ptr; 402 } 403 404 // We can re-use the low bit of expression, statement, base, and 405 // member-initializer pointers for the "invalid" flag of 406 // ActionResult. 407 template<> struct IsResultPtrLowBitFree<Expr*> { 408 static const bool value = true; 409 }; 410 template<> struct IsResultPtrLowBitFree<Stmt*> { 411 static const bool value = true; 412 }; 413 template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> { 414 static const bool value = true; 415 }; 416 template<> struct IsResultPtrLowBitFree<CXXBaseOrMemberInitializer*> { 417 static const bool value = true; 418 }; 419 420 /// An opaque type for threading parsed type information through the 421 /// parser. 422 typedef OpaquePtr<QualType> ParsedType; 423 typedef UnionOpaquePtr<QualType> UnionParsedType; 424 425 typedef ActionResult<Expr*> ExprResult; 426 typedef ActionResult<Stmt*> StmtResult; 427 typedef ActionResult<ParsedType> TypeResult; 428 typedef ActionResult<CXXBaseSpecifier*> BaseResult; 429 typedef ActionResult<CXXBaseOrMemberInitializer*> MemInitResult; 430 431 typedef ActionResult<Decl*> DeclResult; 432 typedef OpaquePtr<TemplateName> ParsedTemplateTy; 433 434 typedef ActionResult<Expr*> OwningExprResult; 435 typedef ActionResult<Stmt*> OwningStmtResult; 436 437 inline Expr *move(Expr *E) { return E; } 438 inline Stmt *move(Stmt *S) { return S; } 439 440 typedef ASTMultiPtr<Expr*> MultiExprArg; 441 typedef ASTMultiPtr<TemplateParameterList*> MultiTemplateParamsArg; 442 443 inline Expr *AssertSuccess(OwningExprResult R) { 444 assert(!R.isInvalid() && "operation was asserted to never fail!"); 445 return R.get(); 446 } 447 448 inline Stmt *AssertSuccess(OwningStmtResult R) { 449 assert(!R.isInvalid() && "operation was asserted to never fail!"); 450 return R.get(); 451 } 452} 453 454#endif 455