[cfe-commits] r153858 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/special/class.inhctor/elsewhere.cpp test/CXX/special/class.inhctor/p3.cpp test/CXX/special/class.inhctor/p7.cpp

Richard Smith richard-llvm at metafoo.co.uk
Sun Apr 1 18:30:27 PDT 2012


Author: rsmith
Date: Sun Apr  1 20:30:27 2012
New Revision: 153858

URL: http://llvm.org/viewvc/llvm-project?rev=153858&view=rev
Log:
Basic semantic analysis support for inheriting constructor declarations in
dependent contexts.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/CXX/special/class.inhctor/elsewhere.cpp
    cfe/trunk/test/CXX/special/class.inhctor/p3.cpp
    cfe/trunk/test/CXX/special/class.inhctor/p7.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=153858&r1=153857&r2=153858&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sun Apr  1 20:30:27 2012
@@ -2978,7 +2978,7 @@
                                    bool IsTypeName,
                                    SourceLocation TypenameLoc);
 
-  bool CheckInheritedConstructorUsingDecl(UsingDecl *UD);
+  bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
 
   Decl *ActOnUsingDeclaration(Scope *CurScope,
                               AccessSpecifier AS,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=153858&r1=153857&r2=153858&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Apr  1 20:30:27 2012
@@ -118,7 +118,7 @@
         //
         // We therefore do not perform any name lookup if the result would
         // refer to a member of an unknown specialization.
-        if (!isClassName)
+        if (!isClassName && !IsCtorOrDtorName)
           return ParsedType();
         
         // We know from the grammar that this name refers to a type,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=153858&r1=153857&r2=153858&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Apr  1 20:30:27 2012
@@ -6290,9 +6290,9 @@
     return UD;
   }
 
-  // Constructor inheriting using decls get special treatment.
+  // The normal rules do not apply to inheriting constructor declarations.
   if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
-    if (CheckInheritedConstructorUsingDecl(UD))
+    if (CheckInheritingConstructorUsingDecl(UD))
       UD->setInvalidDecl();
     return UD;
   }
@@ -6362,11 +6362,8 @@
 }
 
 /// Additional checks for a using declaration referring to a constructor name.
-bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) {
-  if (UD->isTypeName()) {
-    // FIXME: Cannot specify typename when specifying constructor
-    return true;
-  }
+bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
+  assert(!UD->isTypeName() && "expecting a constructor name");
 
   const Type *SourceType = UD->getQualifier()->getAsType();
   assert(SourceType &&
@@ -6381,6 +6378,8 @@
     CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified();
     if (CanonicalSourceType == BaseType)
       break;
+    if (BaseIt->getType()->isDependentType())
+      break;
   }
 
   if (BaseIt == BaseE) {
@@ -6392,7 +6391,8 @@
     return true;
   }
 
-  BaseIt->setInheritConstructors();
+  if (!CurContext->isDependentContext())
+    BaseIt->setInheritConstructors();
 
   return false;
 }
@@ -7041,7 +7041,6 @@
         Context.getCanonicalType(CtorIt->getType()).getTypePtr());
   }
 
-  Scope *S = getScopeForContext(ClassDecl);
   DeclarationName CreatedCtorName =
       Context.DeclarationNames.getCXXConstructorName(
           ClassDecl->getTypeForDecl()->getCanonicalTypeUnqualified());
@@ -7063,10 +7062,12 @@
                                       CtorE = BaseDecl->ctor_end();
          CtorIt != CtorE; ++CtorIt) {
       // Find the using declaration for inheriting this base's constructors.
+      // FIXME: Don't perform name lookup just to obtain a source location!
       DeclarationName Name =
           Context.DeclarationNames.getCXXConstructorName(CanonicalBase);
-      UsingDecl *UD = dyn_cast_or_null<UsingDecl>(
-          LookupSingleName(S, Name,SourceLocation(), LookupUsingDeclName));
+      LookupResult Result(*this, Name, SourceLocation(), LookupUsingDeclName);
+      LookupQualifiedName(Result, CurContext);
+      UsingDecl *UD = Result.getAsSingle<UsingDecl>();
       SourceLocation UsingLoc = UD ? UD->getLocation() :
                                      ClassDecl->getLocation();
 
@@ -7177,7 +7178,6 @@
         NewCtor->setParams(ParamDecls);
         NewCtor->setInheritedConstructor(BaseCtor);
 
-        PushOnScopeChains(NewCtor, S, false);
         ClassDecl->addDecl(NewCtor);
         result.first->second.second = NewCtor;
       }

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=153858&r1=153857&r2=153858&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Apr  1 20:30:27 2012
@@ -1856,6 +1856,12 @@
   if (NewUD->isInvalidDecl())
     return NewUD;
 
+  if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
+    if (SemaRef.CheckInheritingConstructorUsingDecl(NewUD))
+      NewUD->setInvalidDecl();
+    return NewUD;
+  }
+
   bool isFunctionScope = Owner->isFunctionOrMethod();
 
   // Process the shadow decls.

Modified: cfe/trunk/test/CXX/special/class.inhctor/elsewhere.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.inhctor/elsewhere.cpp?rev=153858&r1=153857&r2=153858&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.inhctor/elsewhere.cpp (original)
+++ cfe/trunk/test/CXX/special/class.inhctor/elsewhere.cpp Sun Apr  1 20:30:27 2012
@@ -29,3 +29,29 @@
 struct D1 : I1 {
   using B1::B1; // expected-error {{'B1' is not a direct base of 'D1', can not inherit constructors}}
 };
+
+template<typename T> struct A {};
+
+template<typename T> struct B : A<bool>, A<char> {
+  using A<T>::A; // expected-error {{'A<double>::', which is not a base class of 'B<double>'}}
+};
+B<bool> bb;
+B<char> bc;
+B<double> bd; // expected-note {{here}}
+
+template<typename T> struct C : A<T> {
+  using A<bool>::A; // expected-error {{'A<bool>::', which is not a base class of 'C<char>'}}
+};
+C<bool> cb;
+C<char> cc; // expected-note {{here}}
+
+template<typename T> struct D : A<T> {};
+template<typename T> struct E : D<T> {
+  using A<bool>::A; // expected-error {{'A<bool>' is not a direct base of 'E<bool>', can not inherit}}
+};
+E<bool> eb; // expected-note {{here}}
+
+template<typename T> struct F : D<bool> {
+  using A<T>::A; // expected-error {{'A<bool>' is not a direct base of 'F<bool>'}}
+};
+F<bool> fb; // expected-note {{here}}

Modified: cfe/trunk/test/CXX/special/class.inhctor/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.inhctor/p3.cpp?rev=153858&r1=153857&r2=153858&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.inhctor/p3.cpp (original)
+++ cfe/trunk/test/CXX/special/class.inhctor/p3.cpp Sun Apr  1 20:30:27 2012
@@ -28,3 +28,21 @@
   using B3::B3; // expected-note {{candidate constructor (inherited)}}
 };
 D3 fd3() { return 1; } // expected-error {{no viable conversion}}
+
+template<typename T> struct T1 : B1 {
+  using B1::B1;
+};
+template<typename T> struct T2 : T1<T> {
+  using T1<int>::T1;
+};
+template<typename T> struct T3 : T1<int> {
+  using T1<T>::T1;
+};
+struct U {
+  friend T1<int>::T1(int);
+  friend T1<int>::T1(int, int);
+  friend T2<int>::T2(int);
+  friend T2<int>::T2(int, int);
+  friend T3<int>::T3(int);
+  friend T3<int>::T3(int, int);
+};

Modified: cfe/trunk/test/CXX/special/class.inhctor/p7.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.inhctor/p7.cpp?rev=153858&r1=153857&r2=153858&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.inhctor/p7.cpp (original)
+++ cfe/trunk/test/CXX/special/class.inhctor/p7.cpp Sun Apr  1 20:30:27 2012
@@ -2,7 +2,7 @@
 
 // Straight from the standard
 struct B1 {
-  B1(int); // expected-note {{previous constructor}}
+  B1(int); // expected-note {{previous constructor}} expected-note {{conflicting constructor}}
 };
 struct B2 {
   B2(int); // expected-note {{conflicting constructor}}
@@ -16,3 +16,14 @@
   using B2::B2;
   D2(int);
 };
+
+template<typename T> struct B3 {
+  B3(T); // expected-note {{previous constructor}}
+};
+template<typename T> struct B4 : B3<T>, B1 {
+  B4();
+  using B3<T>::B3; // expected-note {{inherited here}}
+  using B1::B1; // expected-error {{already inherited}}
+};
+B4<char> b4c;
+B4<int> b4i; // expected-note {{here}}





More information about the cfe-commits mailing list