]> granicus.if.org Git - clang/commitdiff
Suggest adding 'typename' when it would make the compiler
authorKaelyn Uhrain <rikka@google.com>
Fri, 18 May 2012 23:42:49 +0000 (23:42 +0000)
committerKaelyn Uhrain <rikka@google.com>
Fri, 18 May 2012 23:42:49 +0000 (23:42 +0000)
accept the template argument expression as a type.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/typename-specifier.cpp

index 65c1bb42d78b1458d93c53fc1ee56898411c6f71..8b76ccb1343eddb07380afb853bb8544b1c93f37 100644 (file)
@@ -2361,6 +2361,8 @@ def note_template_decl_here : Note<"template is declared here">;
 def note_member_of_template_here : Note<"member is declared here">;
 def err_template_arg_must_be_type : Error<
   "template argument for template type parameter must be a type">;
+def err_template_arg_must_be_type_suggest : Error<
+  "template argument for template type parameter must be a type; did you forget 'typename'?">;
 def err_template_arg_must_be_expr : Error<
   "template argument for non-type template parameter must be an expression">;
 def err_template_arg_nontype_ambig : Error<
index 7faf80edfce46cb0c2b1e7fdf826a0de2bc19831..002b0b174e5ffb63bac7bb6043e2a9c50fe9322f 100644 (file)
@@ -2438,6 +2438,45 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
 
     return true;
   }
+  case TemplateArgument::Expression: {
+    // We have a template type parameter but the template argument is an
+    // expression; see if maybe it is missing the "typename" keyword.
+    CXXScopeSpec SS;
+    DeclarationNameInfo NameInfo;
+
+    if (DeclRefExpr *ArgExpr = dyn_cast<DeclRefExpr>(Arg.getAsExpr())) {
+      SS.Adopt(ArgExpr->getQualifierLoc());
+      NameInfo = ArgExpr->getNameInfo();
+    } else if (DependentScopeDeclRefExpr *ArgExpr =
+               dyn_cast<DependentScopeDeclRefExpr>(Arg.getAsExpr())) {
+      SS.Adopt(ArgExpr->getQualifierLoc());
+      NameInfo = ArgExpr->getNameInfo();
+    } else if (CXXDependentScopeMemberExpr *ArgExpr =
+               dyn_cast<CXXDependentScopeMemberExpr>(Arg.getAsExpr())) {
+      SS.Adopt(ArgExpr->getQualifierLoc());
+      NameInfo = ArgExpr->getMemberNameInfo();
+    }
+
+    if (NameInfo.getName()) {
+      LookupResult Result(*this, NameInfo, LookupOrdinaryName);
+      LookupParsedName(Result, CurScope, &SS);
+
+      bool CouldBeType = Result.getResultKind() ==
+          LookupResult::NotFoundInCurrentInstantiation;
+
+      for (LookupResult::iterator I = Result.begin(), IEnd = Result.end();
+           !CouldBeType && I != IEnd; ++I) {
+        CouldBeType = isa<TypeDecl>(*I);
+      }
+      if (CouldBeType) {
+        SourceLocation Loc = AL.getSourceRange().getBegin();
+        Diag(Loc, diag::err_template_arg_must_be_type_suggest);
+        Diag(Param->getLocation(), diag::note_template_param_here);
+        return true;
+      }
+    }
+    // fallthrough
+  }
   default: {
     // We have a template type parameter but the template argument
     // is not a type.
index 9eb4f33de0b95feecbfec3473a4d2d936a2596c6..1d38926c0ed09c0a32ae3f718e0dae9b798e4c55 100644 (file)
@@ -115,3 +115,37 @@ namespace PR10925 {
     using typename BasicGeometry<mydim, int>::operator[]; // expected-error {{typename is allowed for identifiers only}}
   };
 }
+
+
+namespace missing_typename {
+template <class T1, class T2> struct pair {}; // expected-note 5 {{template parameter is declared here}}
+
+template <class T1, class T2>
+struct map {
+  typedef T1* iterator;
+};
+
+template <class T>
+class ExampleClass1 {
+  struct ExampleItem;
+
+
+  struct ExampleItemSet {
+    typedef ExampleItem* iterator;
+  };
+
+  void foo() {
+    pair<ExampleItemSet::iterator, int> i; // expected-error {{template argument for template type parameter must be a type; did you forget 'typename'?}}
+  }
+  pair<ExampleItemSet::iterator, int> elt; // expected-error {{template argument for template type parameter must be a type; did you forget 'typename'?}}
+
+
+  typedef map<int, ExampleItem*> ExampleItemMap;
+
+  static void bar() {
+    pair<ExampleItemMap::iterator, int> i; // expected-error {{template argument for template type parameter must be a type; did you forget 'typename'?}}
+  }
+  pair<ExampleItemMap::iterator, int> entry; // expected-error {{template argument for template type parameter must be a type; did you forget 'typename'?}}
+  pair<bar, int> foobar; // expected-error {{template argument for template type parameter must be a type}}
+};
+} // namespace missing_typename