summaryrefslogtreecommitdiffstats
path: root/include/clang/AST/DeclCXX.h
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-05-17 22:44:15 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-05-17 22:44:15 +0000
commit1420a79d5fd73dbf009acd75e7224fcf8115ef09 (patch)
treeace2561060694c6e1384a24d29a9bbf961592653 /include/clang/AST/DeclCXX.h
parent3d996e269b2a4c446a67d89d9d8b1c510168169b (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.h48
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;
}