]> granicus.if.org Git - clang/commitdiff
Fix a crash-on-invalid involving name lookup of tag names, where we
authorDouglas Gregor <dgregor@apple.com>
Mon, 12 Apr 2010 16:00:01 +0000 (16:00 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 12 Apr 2010 16:00:01 +0000 (16:00 +0000)
ended up finding a function template that we didn't expect. Recover
more gracefully, and fix a similar issue for class templates.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101040 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
test/CXX/temp/temp.decls/temp.mem/p1.cpp
test/SemaTemplate/class-template-decl.cpp
test/SemaTemplate/friend.cpp

index 8bdc31ef32651ae32b19e2f53445c49f09a61c39..aa24e395f04acad6c40a5fc19a8c42ca05784dcd 100644 (file)
@@ -2200,6 +2200,8 @@ def err_typecheck_deleted_function : Error<
   "conversion function from %0 to %1 invokes a deleted function">;
   
 def err_expected_class_or_namespace : Error<"expected a class or namespace">;
+def err_missing_qualified_for_redecl : Error<
+  "must qualify the name %0 to declare %q1 in this scope">;
 def err_invalid_declarator_scope : Error<
   "definition or redeclaration of %0 not in a namespace enclosing %1">;
 def err_invalid_declarator_global_scope : Error<
index 8e0e369af8f742a5482fdb0c4e837d8e2c9aa209..a4d86512125eb61bf2f4887d1bfdccbbcecfc587 100644 (file)
@@ -4948,8 +4948,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
   }
 
   if (!Previous.empty()) {
-    assert(Previous.isSingleResult());
-    NamedDecl *PrevDecl = Previous.getFoundDecl();
+    NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();
     if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
       // If this is a use of a previous tag, or if the tag is already declared
       // in the same scope (so that the definition/declaration completes or
index 285495a41b0a83a7466bc3a66d290a6710925590..d1577a5ab66afe41fd6d2be0e083a299faa8053e 100644 (file)
@@ -748,10 +748,12 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
     LookupName(Previous, S);
   }
 
-  assert(!Previous.isAmbiguous() && "Ambiguity in class template redecl?");
+  if (Previous.isAmbiguous())
+    return true;
+  
   NamedDecl *PrevDecl = 0;
   if (Previous.begin() != Previous.end())
-    PrevDecl = *Previous.begin();
+    PrevDecl = (*Previous.begin())->getUnderlyingDecl();
 
   // If there is a previous declaration with the same name, check
   // whether this is a valid redeclaration.
@@ -804,7 +806,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
     }
   } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
     PrevDecl = PrevClassTemplate = 0;
-
+  
   if (PrevClassTemplate) {
     // Ensure that the template parameter lists are compatible.
     if (!TemplateParameterListsAreEqual(TemplateParams,
@@ -861,9 +863,15 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
                                  TPC_ClassTemplate))
     Invalid = true;
 
-  // FIXME: If we had a scope specifier, we better have a previous template
-  // declaration!
-
+  if (SS.isSet()) {
+    // If the name of the template was qualified, we must be defining the 
+    // template out-of-line.
+    if (!SS.isInvalid() && !Invalid && !PrevClassTemplate &&
+        !(TUK == TUK_Friend && CurContext->isDependentContext()))
+      Diag(NameLoc, diag::err_member_def_does_not_match)
+        << Name << SemanticContext << SS.getRange();
+  } 
+  
   CXXRecordDecl *NewClass =
     CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, KWLoc,
                           PrevClassTemplate?
index b057eedf93b41db97185baad65b1985a20f98440..f5f12055c19ee0fb19951f2d83ba9e114502f1c8 100644 (file)
@@ -19,17 +19,17 @@ namespace PR6376 {
   template<typename T>
   struct X {
     template<typename Y>
-    struct Y { };
+    struct Y1 { }; //
   };
 
   template<>
   struct X<float> {
     template<typename Y>
-    struct Y { };
+    struct Y1 { };
   };
 
   template<typename T, typename U>
-  struct Z : public X<T>::template Y<U> { };
+  struct Z : public X<T>::template Y1<U> { };
 
   Z<float, int> z0;
 }
index 71aabe97f4e38a2fa5582f46176b5b9c55b7e3c4..1be1bc070a81bc1e83b91cb1c1b7287e21381f67 100644 (file)
@@ -51,3 +51,8 @@ void f() {
 }
 
 template<typename T> class X1 { } var; // expected-error{{declared as a template}}
+
+namespace M {
+}
+
+template<typename T> class M::C3 { }; // expected-error{{out-of-line definition of 'C3' does not match any declaration in namespace 'M'}}
index 61ef1865da5d5d49344eafa40df8d2807803bb30..99685f2396cf91cd87561363a211596a08db6ccb 100644 (file)
@@ -12,3 +12,22 @@ void f() {
 struct C0 {
   friend struct A<int>;
 };
+
+namespace PR6770 {
+  namespace N {
+    int f1(int);
+  }
+  using namespace N;
+
+  namespace M { 
+    float f1(float);
+  }
+  using M::f1;
+
+  template<typename T> void f1(T, T);
+  template <class T>
+  void f() {
+    friend class f; // expected-error{{'friend' used outside of class}}
+    friend class f1; // expected-error{{ 'friend' used outside of class}}
+  }
+}