]> granicus.if.org Git - clang/commitdiff
<rdar://problem/12806802> Propagate access specifiers for conversion functions to...
authorDouglas Gregor <dgregor@apple.com>
Mon, 8 Apr 2013 17:12:58 +0000 (17:12 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 8 Apr 2013 17:12:58 +0000 (17:12 +0000)
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

include/clang/AST/ASTUnresolvedSet.h
include/clang/AST/DeclBase.h
lib/AST/DeclCXX.cpp

index c709895fc0f48a8933fa0b44b1ea5165eea625bb..5a56b4d2b46d43f830553bf7f0e0750251eebd08 100644 (file)
@@ -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;
   }
 
index 852bb9ab0400fbd971476f6c22dcb898ee9a8eac..a3e69c0af294c0868b6be8d6fb435be4cbdc2596 100644 (file)
@@ -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());
index ffad9ae93cc84830bfa57c2561348fafd61e271a..c8a203acb628e201eae838c0bad12f1195797682 100644 (file)
@@ -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);
       }
     }