[cfe-commits] r70021 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/destructor.cpp

Chris Lattner sabre at nondot.org
Sat Apr 25 01:28:22 PDT 2009


Author: lattner
Date: Sat Apr 25 03:28:21 2009
New Revision: 70021

URL: http://llvm.org/viewvc/llvm-project?rev=70021&view=rev
Log:
various "is invalid" cleanups for C++ ctors/dtors.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/destructor.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=70021&r1=70020&r2=70021&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Apr 25 03:28:21 2009
@@ -1682,11 +1682,11 @@
                                                  ExprArg AssertExpr,
                                                  ExprArg AssertMessageExpr);
   
-  bool CheckConstructorDeclarator(Declarator &D, QualType &R,
-                                  FunctionDecl::StorageClass& SC);
+  QualType CheckConstructorDeclarator(Declarator &D, QualType R,
+                                      FunctionDecl::StorageClass& SC);
   bool CheckConstructor(CXXConstructorDecl *Constructor);
-  bool CheckDestructorDeclarator(Declarator &D, QualType &R,
-                                 FunctionDecl::StorageClass& SC);
+  QualType CheckDestructorDeclarator(Declarator &D,
+                                     FunctionDecl::StorageClass& SC);
   bool CheckConversionDeclarator(Declarator &D, QualType &R,
                                  FunctionDecl::StorageClass& SC);
   DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Apr 25 03:28:21 2009
@@ -1993,8 +1993,7 @@
     assert(DC->isRecord() &&
            "Constructors can only be declared in a member context");
 
-    if (!D.isInvalidType())
-      D.setInvalidType(CheckConstructorDeclarator(D, R, SC));
+    R = CheckConstructorDeclarator(D, R, SC);
 
     // Create the new declaration
     NewFD = CXXConstructorDecl::Create(Context, 
@@ -2005,8 +2004,7 @@
   } else if (D.getKind() == Declarator::DK_Destructor) {
     // This is a C++ destructor declaration.
     if (DC->isRecord()) {
-      if (!D.isInvalidType())
-        D.setInvalidType(CheckDestructorDeclarator(D, R, SC));
+      R = CheckDestructorDeclarator(D, SC);
       
       NewFD = CXXDestructorDecl::Create(Context,
                                         cast<CXXRecordDecl>(DC),

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Apr 25 03:28:21 2009
@@ -1266,13 +1266,12 @@
 /// CheckConstructorDeclarator - Called by ActOnDeclarator to check
 /// the well-formedness of the constructor declarator @p D with type @p
 /// R. If there are any errors in the declarator, this routine will
-/// emit diagnostics and return true. Otherwise, it will return
-/// false. Either way, the type @p R will be updated to reflect a
-/// well-formed type for the constructor.
-bool Sema::CheckConstructorDeclarator(Declarator &D, QualType &R,
-                                      FunctionDecl::StorageClass& SC) {
+/// emit diagnostics and set the invalid bit to true.  In any case, the type
+/// will be updated to reflect a well-formed type for the constructor and
+/// returned.
+QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
+                                          FunctionDecl::StorageClass &SC) {
   bool isVirtual = D.getDeclSpec().isVirtualSpecified();
-  bool isInvalid = false;
 
   // C++ [class.ctor]p3:
   //   A constructor shall not be virtual (10.3) or static (9.4). A
@@ -1280,19 +1279,21 @@
   //   volatile object. A constructor shall not be declared const,
   //   volatile, or const volatile (9.3.2).
   if (isVirtual) {
-    Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
-      << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc())
-      << SourceRange(D.getIdentifierLoc());
-    isInvalid = true;
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
+        << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
   }
   if (SC == FunctionDecl::Static) {
-    Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
-      << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
-      << SourceRange(D.getIdentifierLoc());
-    isInvalid = true;
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
+        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
     SC = FunctionDecl::None;
   }
-  if (D.getDeclSpec().hasTypeSpecifier()) {
+  if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
     // Constructors don't have return types, but the parser will
     // happily parse something like:
     //
@@ -1304,9 +1305,10 @@
     Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
       << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
       << SourceRange(D.getIdentifierLoc());
-  } 
-  if (R->getAsFunctionProtoType()->getTypeQuals() != 0) {
-    DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  }
+  
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  if (FTI.TypeQuals != 0) {
     if (FTI.TypeQuals & QualType::Const)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
         << "const" << SourceRange(D.getIdentifierLoc());
@@ -1324,12 +1326,9 @@
   // *always* have to do this, because GetTypeForDeclarator will
   // put in a result type of "int" when none was specified.
   const FunctionProtoType *Proto = R->getAsFunctionProtoType();
-  R = Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
-                              Proto->getNumArgs(),
-                              Proto->isVariadic(),
-                              0);
-
-  return isInvalid;
+  return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
+                                 Proto->getNumArgs(),
+                                 Proto->isVariadic(), 0);
 }
 
 /// CheckConstructor - Checks a fully-formed constructor for
@@ -1371,23 +1370,21 @@
 /// CheckDestructorDeclarator - Called by ActOnDeclarator to check
 /// the well-formednes of the destructor declarator @p D with type @p
 /// R. If there are any errors in the declarator, this routine will
-/// emit diagnostics and return true. Otherwise, it will return
-/// false. Either way, the type @p R will be updated to reflect a
-/// well-formed type for the destructor.
-bool Sema::CheckDestructorDeclarator(Declarator &D, QualType &R,
-                                     FunctionDecl::StorageClass& SC) {
-  bool isInvalid = false;
-
+/// emit diagnostics and set the declarator to invalid.  Even if this happens,
+/// will be updated to reflect a well-formed type for the destructor and
+/// returned.
+QualType Sema::CheckDestructorDeclarator(Declarator &D,
+                                         FunctionDecl::StorageClass& SC) {
   // C++ [class.dtor]p1:
   //   [...] A typedef-name that names a class is a class-name
   //   (7.1.3); however, a typedef-name that names a class shall not
   //   be used as the identifier in the declarator for a destructor
   //   declaration.
   QualType DeclaratorType = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
-  if (DeclaratorType->getAsTypedefType()) {
-    Diag(D.getIdentifierLoc(),  diag::err_destructor_typedef_name)
+  if (isa<TypedefType>(DeclaratorType)) {
+    Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
       << DeclaratorType;
-    isInvalid = true;
+    D.setInvalidType();
   }
 
   // C++ [class.dtor]p2:
@@ -1399,13 +1396,14 @@
   //   volatile object. A destructor shall not be declared const,
   //   volatile or const volatile (9.3.2).
   if (SC == FunctionDecl::Static) {
-    Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
-      << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
-      << SourceRange(D.getIdentifierLoc());
-    isInvalid = true;
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
+        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
     SC = FunctionDecl::None;
+    D.setInvalidType();
   }
-  if (D.getDeclSpec().hasTypeSpecifier()) {
+  if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
     // Destructors don't have return types, but the parser will
     // happily parse something like:
     //
@@ -1418,8 +1416,9 @@
       << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
       << SourceRange(D.getIdentifierLoc());
   }
-  if (R->getAsFunctionProtoType()->getTypeQuals() != 0) {
-    DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
     if (FTI.TypeQuals & QualType::Const)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
         << "const" << SourceRange(D.getIdentifierLoc());
@@ -1429,28 +1428,30 @@
     if (FTI.TypeQuals & QualType::Restrict)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
         << "restrict" << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
   }
 
   // Make sure we don't have any parameters.
-  if (R->getAsFunctionProtoType()->getNumArgs() > 0) {
+  if (FTI.NumArgs > 0) {
     Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
 
     // Delete the parameters.
-    D.getTypeObject(0).Fun.freeArgs();
+    FTI.freeArgs();
+    D.setInvalidType();
   }
 
   // Make sure the destructor isn't variadic.  
-  if (R->getAsFunctionProtoType()->isVariadic())
+  if (FTI.isVariadic) {
     Diag(D.getIdentifierLoc(), diag::err_destructor_variadic);
+    D.setInvalidType();
+  }
 
   // Rebuild the function type "R" without any type qualifiers or
   // parameters (in case any of the errors above fired) and with
   // "void" as the return type, since destructors don't have return
   // types. We *always* have to do this, because GetTypeForDeclarator
   // will put in a result type of "int" when none was specified.
-  R = Context.getFunctionType(Context.VoidTy, 0, 0, false, 0);
-
-  return isInvalid;
+  return Context.getFunctionType(Context.VoidTy, 0, 0, false, 0);
 }
 
 /// CheckConversionDeclarator - Called by ActOnDeclarator to check the

Modified: cfe/trunk/test/SemaCXX/destructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=70021&r1=70020&r2=70021&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/destructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/destructor.cpp Sat Apr 25 03:28:21 2009
@@ -18,11 +18,15 @@
   static void ~D(int, ...) const { } //                          \
     // expected-error{{type qualifier is not allowed on this function}} \
     // expected-error{{destructor cannot be declared 'static'}}  \
-    // expected-error{{destructor cannot have a return type}}    \
     // expected-error{{destructor cannot have any parameters}}   \
     // expected-error{{destructor cannot be variadic}}
 };
 
+struct D2 {
+  void ~D2() { } //                          \
+  // expected-error{{destructor cannot have a return type}}  
+};
+
 
 struct E;
 





More information about the cfe-commits mailing list