aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-04-08 17:12:58 +0000
committerDouglas Gregor <dgregor@apple.com>2013-04-08 17:12:58 +0000
commit109f5fc8dff6f3bd707e0e4140dc99ef7d4f3e88 (patch)
tree95c962bf515a337f219977f66cb12a349c37cf88
parentabe922342d67d4ffe05b366a5a2af972185272f8 (diff)
<rdar://problem/12806802> Propagate access specifiers for conversion functions to the conversion function set eagerly.
This slightly propagates an existing hack that delays when we provide access specifiers for the visible conversion functions of a class by copying the available access specifier early. The only client this affects is LLDB, which tends to discover and add conversion functions after the class is technically "complete". As such, the only observable difference is in LLDB, so the testing will go there. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179029 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTUnresolvedSet.h15
-rw-r--r--include/clang/AST/DeclBase.h6
-rw-r--r--lib/AST/DeclCXX.cpp18
3 files changed, 25 insertions, 14 deletions
diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h
index c709895fc0..5a56b4d2b4 100644
--- a/include/clang/AST/ASTUnresolvedSet.h
+++ b/include/clang/AST/ASTUnresolvedSet.h
@@ -41,10 +41,6 @@ public:
const_iterator begin() const { return const_iterator(Decls.begin()); }
const_iterator end() const { return const_iterator(Decls.end()); }
- void addDecl(ASTContext &C, NamedDecl *D) {
- addDecl(C, D, AS_none);
- }
-
void addDecl(ASTContext &C, NamedDecl *D, AccessSpecifier AS) {
Decls.push_back(DeclAccessPair::make(D, AS), C);
}
@@ -52,10 +48,13 @@ public:
/// Replaces the given declaration with the new one, once.
///
/// \return true if the set changed
- bool replace(const NamedDecl* Old, NamedDecl *New) {
- for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I)
- if (I->getDecl() == Old)
- return (I->setDecl(New), true);
+ bool replace(const NamedDecl* Old, NamedDecl *New, AccessSpecifier AS) {
+ for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) {
+ if (I->getDecl() == Old) {
+ I->set(New, AS);
+ return true;
+ }
+ }
return false;
}
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 852bb9ab04..a3e69c0af2 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -402,6 +402,12 @@ public:
return AccessSpecifier(Access);
}
+ /// \brief Retrieve the access specifier for this declaration, even though
+ /// it may not yet have been properly set.
+ AccessSpecifier getAccessUnsafe() const {
+ return AccessSpecifier(Access);
+ }
+
bool hasAttrs() const { return HasAttrs; }
void setAttrs(const AttrVec& Attrs) {
return setAttrsImpl(Attrs, getASTContext());
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index ffad9ae93c..c8a203acb6 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -542,22 +542,28 @@ void CXXRecordDecl::addedMember(Decl *D) {
// Keep the list of conversion functions up-to-date.
if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
- // FIXME: We intentionally don't use the decl's access here because it
- // hasn't been set yet. That's really just a misdesign in Sema.
+ // FIXME: We use the 'unsafe' accessor for the access specifier here,
+ // because Sema may not have set it yet. That's really just a misdesign
+ // in Sema. However, LLDB *will* have set the access specifier correctly,
+ // and adds declarations after the class is technically completed,
+ // so completeDefinition()'s overriding of the access specifiers doesn't
+ // work.
+ AccessSpecifier AS = Conversion->getAccessUnsafe();
+
if (Conversion->getPrimaryTemplate()) {
// We don't record specializations.
} else if (FunTmpl) {
if (FunTmpl->getPreviousDecl())
data().Conversions.replace(FunTmpl->getPreviousDecl(),
- FunTmpl);
+ FunTmpl, AS);
else
- data().Conversions.addDecl(getASTContext(), FunTmpl);
+ data().Conversions.addDecl(getASTContext(), FunTmpl, AS);
} else {
if (Conversion->getPreviousDecl())
data().Conversions.replace(Conversion->getPreviousDecl(),
- Conversion);
+ Conversion, AS);
else
- data().Conversions.addDecl(getASTContext(), Conversion);
+ data().Conversions.addDecl(getASTContext(), Conversion, AS);
}
}