diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-05-17 22:44:15 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-05-17 22:44:15 +0000 |
commit | 1420a79d5fd73dbf009acd75e7224fcf8115ef09 (patch) | |
tree | ace2561060694c6e1384a24d29a9bbf961592653 /include/clang/AST/DeclCXX.h | |
parent | 3d996e269b2a4c446a67d89d9d8b1c510168169b (diff) |
PR27754: CXXRecordDecl::data() needs to perform an update even if it's called
on a declaration that already knows the location of the DefinitionData object.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269858 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/AST/DeclCXX.h')
-rw-r--r-- | include/clang/AST/DeclCXX.h | 48 |
1 files changed, 14 insertions, 34 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 20aa7d1ab4..cd1e1d6b8d 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -257,30 +257,6 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; -/// \brief A lazy pointer to the definition data for a declaration. -/// FIXME: This is a little CXXRecordDecl-specific that the moment. -template<typename Decl, typename T> class LazyDefinitionDataPtr { - llvm::PointerUnion<T *, Decl *> DataOrCanonicalDecl; - - LazyDefinitionDataPtr update() { - if (Decl *Canon = DataOrCanonicalDecl.template dyn_cast<Decl*>()) { - if (Canon->isCanonicalDecl()) - Canon->getMostRecentDecl(); - else - // Declaration isn't canonical any more; - // update it and perform path compression. - *this = Canon->getPreviousDecl()->DefinitionData.update(); - } - return *this; - } - -public: - LazyDefinitionDataPtr(Decl *Canon) : DataOrCanonicalDecl(Canon) {} - LazyDefinitionDataPtr(T *Data) : DataOrCanonicalDecl(Data) {} - T *getNotUpdated() { return DataOrCanonicalDecl.template dyn_cast<T*>(); } - T *get() { return update().getNotUpdated(); } -}; - /// \brief Represents a C++ struct/union/class. class CXXRecordDecl : public RecordDecl { @@ -543,11 +519,7 @@ class CXXRecordDecl : public RecordDecl { CXXBaseSpecifier *getVBasesSlowCase() const; }; - typedef LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData> - DefinitionDataPtr; - friend class LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData>; - - mutable DefinitionDataPtr DefinitionData; + struct DefinitionData *DefinitionData; /// \brief Describes a C++ closure type (generated by a lambda expression). struct LambdaDefinitionData : public DefinitionData { @@ -610,8 +582,14 @@ class CXXRecordDecl : public RecordDecl { }; + struct DefinitionData *dataPtr() const { + // Complete the redecl chain (if necessary). + getMostRecentDecl(); + return DefinitionData; + } + struct DefinitionData &data() const { - auto *DD = DefinitionData.get(); + auto *DD = dataPtr(); assert(DD && "queried property of class with no definition"); return *DD; } @@ -619,7 +597,7 @@ class CXXRecordDecl : public RecordDecl { struct LambdaDefinitionData &getLambdaData() const { // No update required: a merged definition cannot change any lambda // properties. - auto *DD = DefinitionData.getNotUpdated(); + auto *DD = DefinitionData; assert(DD && DD->IsLambda && "queried lambda property of non-lambda class"); return static_cast<LambdaDefinitionData&>(*DD); } @@ -696,11 +674,13 @@ public: } CXXRecordDecl *getDefinition() const { - auto *DD = DefinitionData.get(); + // We only need an update if we don't already know which + // declaration is the definition. + auto *DD = DefinitionData ? DefinitionData : dataPtr(); return DD ? DD->Definition : nullptr; } - bool hasDefinition() const { return DefinitionData.get(); } + bool hasDefinition() const { return DefinitionData || dataPtr(); } static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -1044,7 +1024,7 @@ public: /// \brief Determine whether this class describes a lambda function object. bool isLambda() const { // An update record can't turn a non-lambda into a lambda. - auto *DD = DefinitionData.getNotUpdated(); + auto *DD = DefinitionData; return DD && DD->IsLambda; } |