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