[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