[cfe-commits] r81720 - in /cfe/trunk: lib/Sema/SemaDecl.cpp test/SemaCXX/conversion-function.cpp

Anders Carlsson andersca at mac.com
Sun Sep 13 14:33:06 PDT 2009


Author: andersca
Date: Sun Sep 13 16:33:06 2009
New Revision: 81720

URL: http://llvm.org/viewvc/llvm-project?rev=81720&view=rev
Log:
Perform the C++ specific semantic checks of a function declaration after it's been merged with the previous declaration. This ensures that getPreviousDecl() will have the right value when ActOnConversionDeclarator is called.

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaCXX/conversion-function.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=81720&r1=81719&r2=81720&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Sep 13 16:33:06 2009
@@ -2808,42 +2808,6 @@
   if (NewFD->isMain()) 
     CheckMain(NewFD);
 
-  // Semantic checking for this function declaration (in isolation).
-  if (getLangOptions().CPlusPlus) {
-    // C++-specific checks.
-    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
-      CheckConstructor(Constructor);
-    } else if (isa<CXXDestructorDecl>(NewFD)) {
-      CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
-      QualType ClassType = Context.getTypeDeclType(Record);
-      if (!ClassType->isDependentType()) {
-        DeclarationName Name
-          = Context.DeclarationNames.getCXXDestructorName(
-                                        Context.getCanonicalType(ClassType));
-        if (NewFD->getDeclName() != Name) {
-          Diag(NewFD->getLocation(), diag::err_destructor_name);
-          return NewFD->setInvalidDecl();
-        }
-      }
-      Record->setUserDeclaredDestructor(true);
-      // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
-      // user-defined destructor.
-      Record->setPOD(false);
-
-      // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly-
-      // declared destructor.
-      // FIXME: C++0x: don't do this for "= default" destructors
-      Record->setHasTrivialDestructor(false);
-    } else if (CXXConversionDecl *Conversion
-               = dyn_cast<CXXConversionDecl>(NewFD))
-      ActOnConversionDeclarator(Conversion);
-
-    // Extra checking for C++ overloaded operators (C++ [over.oper]).
-    if (NewFD->isOverloadedOperator() &&
-        CheckOverloadedOperatorDeclaration(NewFD))
-      return NewFD->setInvalidDecl();
-  }
-
   // Check for a previous declaration of this name.
   if (!PrevDecl && NewFD->isExternC()) {
     // Since we did not find anything by this name and we're declaring
@@ -2911,11 +2875,47 @@
     }
   }
 
-  // In C++, check default arguments now that we have merged decls. Unless
-  // the lexical context is the class, because in this case this is done
-  // during delayed parsing anyway.
-  if (getLangOptions().CPlusPlus && !CurContext->isRecord())
-    CheckCXXDefaultArguments(NewFD);
+  // Semantic checking for this function declaration (in isolation).
+  if (getLangOptions().CPlusPlus) {
+    // C++-specific checks.
+    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
+      CheckConstructor(Constructor);
+    } else if (isa<CXXDestructorDecl>(NewFD)) {
+      CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
+      QualType ClassType = Context.getTypeDeclType(Record);
+      if (!ClassType->isDependentType()) {
+        DeclarationName Name
+          = Context.DeclarationNames.getCXXDestructorName(
+                                        Context.getCanonicalType(ClassType));
+        if (NewFD->getDeclName() != Name) {
+          Diag(NewFD->getLocation(), diag::err_destructor_name);
+          return NewFD->setInvalidDecl();
+        }
+      }
+      Record->setUserDeclaredDestructor(true);
+      // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
+      // user-defined destructor.
+      Record->setPOD(false);
+
+      // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly-
+      // declared destructor.
+      // FIXME: C++0x: don't do this for "= default" destructors
+      Record->setHasTrivialDestructor(false);
+    } else if (CXXConversionDecl *Conversion
+               = dyn_cast<CXXConversionDecl>(NewFD))
+      ActOnConversionDeclarator(Conversion);
+
+    // Extra checking for C++ overloaded operators (C++ [over.oper]).
+    if (NewFD->isOverloadedOperator() &&
+        CheckOverloadedOperatorDeclaration(NewFD))
+      return NewFD->setInvalidDecl();
+    
+    // In C++, check default arguments now that we have merged decls. Unless
+    // the lexical context is the class, because in this case this is done
+    // during delayed parsing anyway.
+    if (!CurContext->isRecord())
+      CheckCXXDefaultArguments(NewFD);
+  }
 }
 
 void Sema::CheckMain(FunctionDecl* FD) {

Modified: cfe/trunk/test/SemaCXX/conversion-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-function.cpp?rev=81720&r1=81719&r2=81720&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/conversion-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/conversion-function.cpp Sun Sep 13 16:33:06 2009
@@ -64,3 +64,14 @@
   operator Flop() const;
 };
 Flop flop = Flip(); // expected-error {{cannot initialize 'flop' with an rvalue of type 'struct Flip'}}
+
+// This tests that we don't add the second conversion declaration to the list of user conversions
+struct C {
+  operator const char *() const;
+};
+
+C::operator const char*() const { return 0; }
+
+void f(const C& c) {
+  const char* v = c;
+}





More information about the cfe-commits mailing list