[cfe-commits] r113011 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp test/CodeGenCXX/template-anonymous-types.cpp test/SemaTemplate/temp_arg_type.cpp

Chandler Carruth chandlerc at gmail.com
Fri Sep 3 14:12:35 PDT 2010


Author: chandlerc
Date: Fri Sep  3 16:12:34 2010
New Revision: 113011

URL: http://llvm.org/viewvc/llvm-project?rev=113011&view=rev
Log:
Allow anonymous and local types. The support was already in place for these,
but this makes them work even as an extension in C++98. This resolves PR8077.

Added:
    cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp
    cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaTemplate/temp_arg_type.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=113011&r1=113010&r2=113011&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri Sep  3 16:12:34 2010
@@ -61,6 +61,7 @@
 def : DiagGroup<"int-to-pointer-cast">;
 def : DiagGroup<"invalid-pch">;
 def LiteralRange : DiagGroup<"literal-range">;
+def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">;
 def : DiagGroup<"main">;
 def MissingBraces : DiagGroup<"missing-braces">;
 def MissingDeclarations: DiagGroup<"missing-declarations">;
@@ -130,6 +131,7 @@
 def Uninitialized  : DiagGroup<"uninitialized">;
 def UnknownPragmas : DiagGroup<"unknown-pragmas">;
 def UnknownAttributes : DiagGroup<"unknown-attributes">;
+def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">;
 def UnusedArgument : DiagGroup<"unused-argument">;
 def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
 def UnusedFunction : DiagGroup<"unused-function">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=113011&r1=113010&r2=113011&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Sep  3 16:12:34 2010
@@ -1371,9 +1371,10 @@
   "template argument for non-type template parameter is treated as type %0">;
 def err_template_arg_must_be_template : Error<
   "template argument for template template parameter must be a class template">;
-def err_template_arg_local_type : Error<"template argument uses local type %0">;
-def err_template_arg_unnamed_type : Error<
-  "template argument uses unnamed type">;
+def ext_template_arg_local_type : ExtWarn<
+  "template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>;
+def ext_template_arg_unnamed_type : ExtWarn<
+  "template argument uses unnamed type">, InGroup<UnnamedTypeTemplateArgs>;
 def note_template_unnamed_type_here : Note<
   "unnamed type used in template argument was declared here">;
 def err_template_arg_overload_type : Error<

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=113011&r1=113010&r2=113011&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Sep  3 16:12:34 2010
@@ -2347,31 +2347,33 @@
   assert(ArgInfo && "invalid TypeSourceInfo");
   QualType Arg = ArgInfo->getType();
 
-  // C++ [temp.arg.type]p2:
+  // C++03 [temp.arg.type]p2:
   //   A local type, a type with no linkage, an unnamed type or a type
   //   compounded from any of these types shall not be used as a
   //   template-argument for a template type-parameter.
-  //
-  // FIXME: Perform the unnamed type check.
+  // C++0x allows these, and even in C++03 we allow them as an extension with
+  // a warning.
   SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
-  const TagType *Tag = 0;
-  if (const EnumType *EnumT = Arg->getAs<EnumType>())
-    Tag = EnumT;
-  else if (const RecordType *RecordT = Arg->getAs<RecordType>())
-    Tag = RecordT;
-  if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) {
-    SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
-    return Diag(SR.getBegin(), diag::err_template_arg_local_type)
-      << QualType(Tag, 0) << SR;
-  } else if (Tag && !Tag->getDecl()->getDeclName() &&
-           !Tag->getDecl()->getTypedefForAnonDecl()) {
-    Diag(SR.getBegin(), diag::err_template_arg_unnamed_type) << SR;
-    Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here);
-    return true;
-  } else if (Arg->isVariablyModifiedType()) {
-    Diag(SR.getBegin(), diag::err_variably_modified_template_arg)
-      << Arg;
-    return true;
+  if (!LangOpts.CPlusPlus0x) {
+    const TagType *Tag = 0;
+    if (const EnumType *EnumT = Arg->getAs<EnumType>())
+      Tag = EnumT;
+    else if (const RecordType *RecordT = Arg->getAs<RecordType>())
+      Tag = RecordT;
+    if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) {
+      SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
+      Diag(SR.getBegin(), diag::ext_template_arg_local_type)
+        << QualType(Tag, 0) << SR;
+    } else if (Tag && !Tag->getDecl()->getDeclName() &&
+               !Tag->getDecl()->getTypedefForAnonDecl()) {
+      Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR;
+      Diag(Tag->getDecl()->getLocation(),
+           diag::note_template_unnamed_type_here);
+    }
+  }
+
+  if (Arg->isVariablyModifiedType()) {
+    return Diag(SR.getBegin(), diag::err_variably_modified_template_arg) << Arg;
   } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
     return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;
   }

Added: cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp?rev=113011&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp Fri Sep  3 16:12:34 2010
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s
+
+// C++03 imposed restrictions in this paragraph that were lifted with 0x, so we
+// just test that the example given now parses cleanly.
+
+template <class T> class X { };
+template <class T> void f(T t) { }
+struct { } unnamed_obj;
+void f() {
+  struct A { };
+  enum { e1 };
+  typedef struct { } B;
+  B b;
+  X<A> x1;
+  X<A*> x2;
+  X<B> x3;
+  f(e1);
+  f(unnamed_obj);
+  f(b);
+}

Added: cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp?rev=113011&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp Fri Sep  3 16:12:34 2010
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -o - | FileCheck %s
+
+struct S {
+  enum { FOO = 42 };
+  enum { BAR = 42 };
+};
+
+template <typename T> struct X {
+  T value;
+
+  X(T t) : value(t) {}
+
+  // Again, two instantiations should be present.
+  int f() { return value; }
+};
+
+template <typename T> int f(T t) {
+  X<T> x(t);
+  return x.f();
+}
+
+void test() {
+  // Look for two instantiations, entirely internal to this TU, one for FOO's
+  // type and one for BAR's.
+  // CHECK: define internal i32 @"_Z1fIN1S3$_0EEiT_"(i32 %t)
+  (void)f(S::FOO);
+  // CHECK: define internal i32 @"_Z1fIN1S3$_1EEiT_"(i32 %t)
+  (void)f(S::BAR);
+
+  // Now check for the class template instantiations. Annoyingly, they are in
+  // reverse order.
+  //
+  // BAR's instantiation of X:
+  // CHECK: define internal i32 @"_ZN1XIN1S3$_1EE1fEv"(%struct.X* %this)
+  // CHECK: define internal void @"_ZN1XIN1S3$_1EEC2ES1_"(%struct.X* %this, i32 %t)
+  //
+  // FOO's instantiation of X:
+  // CHECK: define internal i32 @"_ZN1XIN1S3$_0EE1fEv"(%struct.X* %this)
+  // CHECK: define internal void @"_ZN1XIN1S3$_0EEC2ES1_"(%struct.X* %this, i32 %t)
+}

Modified: cfe/trunk/test/SemaTemplate/temp_arg_type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_type.cpp?rev=113011&r1=113010&r2=113011&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_type.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_type.cpp Fri Sep  3 16:12:34 2010
@@ -24,11 +24,11 @@
 // [temp.arg.type]p2
 void f() {
   class X { };
-  A<X> * a = 0; // expected-error{{template argument uses local type 'X'}}
+  A<X> * a = 0; // expected-warning{{template argument uses local type 'X'}}
 }
 
 struct { int x; } Unnamed; // expected-note{{unnamed type used in template argument was declared here}}
-A<__typeof__(Unnamed)> *a9; // expected-error{{template argument uses unnamed type}}
+A<__typeof__(Unnamed)> *a9; // expected-warning{{template argument uses unnamed type}}
 
 template<typename T, unsigned N>
 struct Array {





More information about the cfe-commits mailing list