]> granicus.if.org Git - clang/commitdiff
Remove CXXRecordDecl::getDefaultConstructor(), an inherently unsafe function due...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Mon, 13 Sep 2010 22:02:47 +0000 (22:02 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Mon, 13 Sep 2010 22:02:47 +0000 (22:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113794 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclCXX.h
lib/AST/DeclCXX.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/type-traits.cpp

index 3db147c1ab1e22998afab69418f4909abb00c0c3..c4b9292be49f80bb898f29b17507e961e810711d 100644 (file)
@@ -859,9 +859,6 @@ public:
   
   /// \brief Set the kind of specialization or template instantiation this is.
   void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
-  
-  /// getDefaultConstructor - Returns the default constructor for this class
-  CXXConstructorDecl *getDefaultConstructor();
 
   /// getDestructor - Returns the destructor decl for this class.
   CXXDestructorDecl *getDestructor() const;
index f2f0694826c6ab82c564e9474b2f661f5c1c34f7..88301c2d9d24bcdf965c4aba7d6e90b5951c12eb 100644 (file)
@@ -577,28 +577,6 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
   assert(false && "Not a class template or member class specialization");
 }
 
-CXXConstructorDecl *
-CXXRecordDecl::getDefaultConstructor() {
-  ASTContext &Context = getASTContext();
-  QualType ClassType = Context.getTypeDeclType(this);
-  DeclarationName ConstructorName
-    = Context.DeclarationNames.getCXXConstructorName(
-                      Context.getCanonicalType(ClassType.getUnqualifiedType()));
-
-  DeclContext::lookup_const_iterator Con, ConEnd;
-  for (llvm::tie(Con, ConEnd) = lookup(ConstructorName);
-       Con != ConEnd; ++Con) {
-    // FIXME: In C++0x, a constructor template can be a default constructor.
-    if (isa<FunctionTemplateDecl>(*Con))
-      continue;
-
-    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
-    if (Constructor->isDefaultConstructor())
-      return Constructor;
-  }
-  return 0;
-}
-
 CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
   ASTContext &Context = getASTContext();
   QualType ClassType = Context.getTypeDeclType(this);
index 2d31e8cc9a0508a51054447eb041596904a4d74b..d16d9e9763d897785c2cc36002e354a33d833b4d 100644 (file)
@@ -4322,6 +4322,28 @@ namespace {
   };
 }
 
+static CXXConstructorDecl *getDefaultConstructorUnsafe(Sema &Self,
+                                                       CXXRecordDecl *D) {
+  ASTContext &Context = Self.Context;
+  QualType ClassType = Context.getTypeDeclType(D);
+  DeclarationName ConstructorName
+    = Context.DeclarationNames.getCXXConstructorName(
+                      Context.getCanonicalType(ClassType.getUnqualifiedType()));
+
+  DeclContext::lookup_const_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName);
+       Con != ConEnd; ++Con) {
+    // FIXME: In C++0x, a constructor template can be a default constructor.
+    if (isa<FunctionTemplateDecl>(*Con))
+      continue;
+
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+    if (Constructor->isDefaultConstructor())
+      return Constructor;
+  }
+  return 0;
+}
+
 CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
                                                      CXXRecordDecl *ClassDecl) {
   // C++ [class.ctor]p5:
@@ -4349,8 +4371,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
       CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
       if (!BaseClassDecl->hasDeclaredDefaultConstructor())
         ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
-      else if (CXXConstructorDecl *Constructor 
-                                       = BaseClassDecl->getDefaultConstructor())
+      else if (CXXConstructorDecl *Constructor
+                            = getDefaultConstructorUnsafe(*this, BaseClassDecl))
         ExceptSpec.CalledDecl(Constructor);
     }
   }
@@ -4364,7 +4386,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
       if (!BaseClassDecl->hasDeclaredDefaultConstructor())
         ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
       else if (CXXConstructorDecl *Constructor
-                                       = BaseClassDecl->getDefaultConstructor())
+                            = getDefaultConstructorUnsafe(*this, BaseClassDecl))
         ExceptSpec.CalledDecl(Constructor);
     }
   }
@@ -4380,7 +4402,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
         ExceptSpec.CalledDecl(
                             DeclareImplicitDefaultConstructor(FieldClassDecl));
       else if (CXXConstructorDecl *Constructor
-                                      = FieldClassDecl->getDefaultConstructor())
+                           = getDefaultConstructorUnsafe(*this, FieldClassDecl))
         ExceptSpec.CalledDecl(Constructor);
     }
   }
index d026851f622c2e5936699cd7c72619481480e807..b380a4b7a79c567bb7e5aed48b5fa5ed12e4399f 100644 (file)
@@ -2145,8 +2145,6 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T) {
       bool FoundConstructor = false;
       bool AllNoThrow = true;
       unsigned FoundTQs;
-      DeclarationName ConstructorName
-          = C.DeclarationNames.getCXXConstructorName(C.getCanonicalType(T));
       DeclContext::lookup_const_iterator Con, ConEnd;
       for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
            Con != ConEnd; ++Con) {
@@ -2155,7 +2153,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T) {
           FoundConstructor = true;
           const FunctionProtoType *CPT
               = Constructor->getType()->getAs<FunctionProtoType>();
-          if (!CPT->hasEmptyExceptionSpec()) {
+          // TODO: check whether evaluating default arguments can throw.
+          // For now, we'll be conservative and assume that they can throw.
+          if (!CPT->hasEmptyExceptionSpec() || CPT->getNumArgs() > 1) {
             AllNoThrow = false;
             break;
           }
@@ -2178,13 +2178,17 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T) {
       if (RD->hasTrivialConstructor())
         return true;
 
-      if (CXXConstructorDecl *Constructor = RD->getDefaultConstructor()) {
-        const FunctionProtoType *CPT
-            = Constructor->getType()->getAs<FunctionProtoType>();
-        // TODO: check whether evaluating default arguments can throw.
-        // For now, we'll be conservative and assume that they can throw.
-        if (CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0)
-          return true;
+      DeclContext::lookup_const_iterator Con, ConEnd;
+      for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
+           Con != ConEnd; ++Con) {
+        CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+        if (Constructor->isDefaultConstructor()) {
+          const FunctionProtoType *CPT
+              = Constructor->getType()->getAs<FunctionProtoType>();
+          // TODO: check whether evaluating default arguments can throw.
+          // For now, we'll be conservative and assume that they can throw.
+          return CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0;
+        }
       }
     }
     return false;
index 61aba075975683db855a3e2e2c60edb202f3f6ce..cb88220bb1943f3b14357afccf4131f515bb234d 100644 (file)
@@ -393,6 +393,7 @@ void has_nothrow_constructor() {
   int t20[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))];
   int t21[F(__has_nothrow_constructor(void))];
   int t22[F(__has_nothrow_constructor(cvoid))];
+  int t23[T(__has_nothrow_constructor(HasVirtDest))];
 }
 
 void has_virtual_destructor() {