[cfe-commits] r86884 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.param/p12.cpp test/SemaTemplate/default-arguments.cpp

Douglas Gregor dgregor at apple.com
Wed Nov 11 13:54:23 PST 2009


Author: dgregor
Date: Wed Nov 11 15:54:23 2009
New Revision: 86884

URL: http://llvm.org/viewvc/llvm-project?rev=86884&view=rev
Log:
Improve diagnostics when a default template argument does not match
with its corresponding template parameter. This can happen when we
performed some substitution into the default template argument and
what we had doesn't match any more, e.g.,

  template<int> struct A;
  template<typename T, template<T> class X = A> class B;

  B<long> b;

Previously, we'd emit a pretty but disembodied diagnostic showing how
the default argument didn't match the template parameter. The
diagnostic was good, but nothing tied it to the *use* of the default
argument in "B<long>". This commit fixes that.

Also, tweak the counting of active template instantiations to avoid
counting non-instantiation records, such as those we create for
(surprise!) checking default arguments, instantiating default
arguments, and performing substitutions as part of template argument
deduction.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/CXX/temp/temp.param/p12.cpp
    cfe/trunk/test/SemaTemplate/default-arguments.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=86884&r1=86883&r2=86884&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Nov 11 15:54:23 2009
@@ -1102,6 +1102,8 @@
 def note_prior_template_arg_substitution : Note<
   "while substituting prior template arguments into %select{non-type|template}0"
   " template parameter%1 %2">;
+def note_template_default_arg_checking : Note<
+  "while checking a default template argument used here">;
   
 def err_field_instantiates_to_function : Error<
   "data member instantiated with function type %0">;

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=86884&r1=86883&r2=86884&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Wed Nov 11 15:54:23 2009
@@ -355,8 +355,9 @@
     IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
     GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
     CompleteTranslationUnit(CompleteTranslationUnit),
-    NumSFINAEErrors(0), CurrentInstantiationScope(0) {
-
+    NumSFINAEErrors(0), NonInstantiationEntries(0), 
+    CurrentInstantiationScope(0) 
+{
   TUScope = 0;
   if (getLangOptions().CPlusPlus)
     FieldCollector.reset(new CXXFieldCollector());

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=86884&r1=86883&r2=86884&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 11 15:54:23 2009
@@ -2889,7 +2889,11 @@
       /// We are substituting prior template arguments into a new
       /// template parameter. The template parameter itself is either a
       /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
-      PriorTemplateArgumentSubstitution
+      PriorTemplateArgumentSubstitution,
+      
+      /// We are checking the validity of a default template argument that
+      /// has been used when naming a template-id.
+      DefaultTemplateArgumentChecking
     } Kind;
 
     /// \brief The point of instantiation within the source code.
@@ -2918,6 +2922,10 @@
       : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0), 
         NumTemplateArgs(0) {}
 
+    /// \brief Determines whether this template is an actual instantiation
+    /// that should be counted toward the maximum instantiation depth.
+    bool isInstantiationRecord() const;
+    
     friend bool operator==(const ActiveTemplateInstantiation &X,
                            const ActiveTemplateInstantiation &Y) {
       if (X.Kind != Y.Kind)
@@ -2931,6 +2939,7 @@
         return true;
 
       case PriorTemplateArgumentSubstitution:
+      case DefaultTemplateArgumentChecking:
         if (X.Template != Y.Template)
           return false;
           
@@ -2962,6 +2971,11 @@
   llvm::SmallVector<ActiveTemplateInstantiation, 16>
     ActiveTemplateInstantiations;
 
+  /// \brief The number of ActiveTemplateInstantiation entries in
+  /// \c ActiveTemplateInstantiations that are not actual instantiations and,
+  /// therefore, should not be counted as part of the instantiation depth.
+  unsigned NonInstantiationEntries;
+  
   /// \brief The last template from which a template instantiation
   /// error or warning was produced.
   ///
@@ -3037,6 +3051,16 @@
                           unsigned NumTemplateArgs,
                           SourceRange InstantiationRange);
     
+    /// \brief Note that we are checking the default template argument
+    /// against the template parameter for a given template-id.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Template,
+                          NamedDecl *Param,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs,
+                          SourceRange InstantiationRange);
+    
+    
     /// \brief Note that we have finished instantiating this template.
     void Clear();
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=86884&r1=86883&r2=86884&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Nov 11 15:54:23 2009
@@ -1856,73 +1856,87 @@
       continue;
     }
     
-    // Decode the template argument
+    if (ArgIdx < NumArgs) {
+      // Check the template argument we were given.
+      if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template, 
+                                TemplateLoc, RAngleLoc, Converted))
+        return true;
+      
+      continue;
+    }
+    
+    // We have a default template argument that we will use.
     TemplateArgumentLoc Arg;
+    
+    // Retrieve the default template argument from the template
+    // parameter. For each kind of template parameter, we substitute the
+    // template arguments provided thus far and any "outer" template arguments
+    // (when the template parameter was part of a nested template) into 
+    // the default argument.
+    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
+      if (!TTP->hasDefaultArgument()) {
+        assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+        break;
+      }
 
-    if (ArgIdx >= NumArgs) {
-      // Retrieve the default template argument from the template
-      // parameter.
-      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
-        if (TTP->isParameterPack()) {
-          // We have an empty argument pack.
-          Converted.BeginPack();
-          Converted.EndPack();
-          break;
-        }
-
-        if (!TTP->hasDefaultArgument())
-          break;
-
-        DeclaratorInfo *ArgType = SubstDefaultTemplateArgument(*this, 
-                                                               Template,
-                                                               TemplateLoc,
-                                                               RAngleLoc,
-                                                               TTP,
-                                                               Converted);
-        if (!ArgType)
-          return true;
-                                                               
-        Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()),
-                                  ArgType);
-      } else if (NonTypeTemplateParmDecl *NTTP
-                   = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
-        if (!NTTP->hasDefaultArgument())
-          break;
-
-        Sema::OwningExprResult E = SubstDefaultTemplateArgument(*this, Template,
-                                                                TemplateLoc, 
-                                                                RAngleLoc, 
-                                                                NTTP, 
-                                                                Converted);
-        if (E.isInvalid())
-          return true;
+      DeclaratorInfo *ArgType = SubstDefaultTemplateArgument(*this, 
+                                                             Template,
+                                                             TemplateLoc,
+                                                             RAngleLoc,
+                                                             TTP,
+                                                             Converted);
+      if (!ArgType)
+        return true;
+                                                             
+      Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()),
+                                ArgType);
+    } else if (NonTypeTemplateParmDecl *NTTP
+                 = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+      if (!NTTP->hasDefaultArgument()) {
+        assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+        break;
+      }
 
-        Expr *Ex = E.takeAs<Expr>();
-        Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
-      } else {
-        TemplateTemplateParmDecl *TempParm
-          = cast<TemplateTemplateParmDecl>(*Param);
+      Sema::OwningExprResult E = SubstDefaultTemplateArgument(*this, Template,
+                                                              TemplateLoc, 
+                                                              RAngleLoc, 
+                                                              NTTP, 
+                                                              Converted);
+      if (E.isInvalid())
+        return true;
 
-        if (!TempParm->hasDefaultArgument())
-          break;
+      Expr *Ex = E.takeAs<Expr>();
+      Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
+    } else {
+      TemplateTemplateParmDecl *TempParm
+        = cast<TemplateTemplateParmDecl>(*Param);
 
-        TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
-                                                         TemplateLoc, 
-                                                         RAngleLoc, 
-                                                         TempParm,
-                                                         Converted);
-        if (Name.isNull())
-          return true;
-        
-        Arg = TemplateArgumentLoc(TemplateArgument(Name), 
-                    TempParm->getDefaultArgument().getTemplateQualifierRange(),
-                    TempParm->getDefaultArgument().getTemplateNameLoc());
+      if (!TempParm->hasDefaultArgument()) {
+        assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+        break;
       }
-    } else {
-      // Retrieve the template argument produced by the user.
-      Arg = TemplateArgs[ArgIdx];
+
+      TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
+                                                       TemplateLoc, 
+                                                       RAngleLoc, 
+                                                       TempParm,
+                                                       Converted);
+      if (Name.isNull())
+        return true;
+      
+      Arg = TemplateArgumentLoc(TemplateArgument(Name), 
+                  TempParm->getDefaultArgument().getTemplateQualifierRange(),
+                  TempParm->getDefaultArgument().getTemplateNameLoc());
     }
     
+    // Introduce an instantiation record that describes where we are using
+    // the default template argument.
+    InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param,
+                                        Converted.getFlatArguments(),
+                                        Converted.flatSize(),
+                                        SourceRange(TemplateLoc, RAngleLoc));    
+    
+    // Check the default template argument.
     if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
                               RAngleLoc, Converted))
       return true;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=86884&r1=86883&r2=86884&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Nov 11 15:54:23 2009
@@ -96,6 +96,23 @@
   return Result;
 }
 
+bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
+  switch (Kind) {
+  case TemplateInstantiation:
+  case DefaultTemplateArgumentInstantiation:
+  case DefaultFunctionArgumentInstantiation:
+    return true;
+      
+  case ExplicitTemplateArgumentSubstitution:
+  case DeducedTemplateArgumentSubstitution:
+  case PriorTemplateArgumentSubstitution:
+  case DefaultTemplateArgumentChecking:
+    return false;
+  }
+  
+  return true;
+}
+
 Sema::InstantiatingTemplate::
 InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
                       Decl *Entity,
@@ -113,7 +130,6 @@
     Inst.NumTemplateArgs = 0;
     Inst.InstantiationRange = InstantiationRange;
     SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-    Invalid = false;
   }
 }
 
@@ -137,7 +153,6 @@
     Inst.NumTemplateArgs = NumTemplateArgs;
     Inst.InstantiationRange = InstantiationRange;
     SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-    Invalid = false;
   }
 }
 
@@ -161,7 +176,9 @@
     Inst.NumTemplateArgs = NumTemplateArgs;
     Inst.InstantiationRange = InstantiationRange;
     SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-    Invalid = false;
+    
+    if (!Inst.isInstantiationRecord())
+      ++SemaRef.NonInstantiationEntries;
   }
 }
 
@@ -173,20 +190,19 @@
                                          SourceRange InstantiationRange)
   : SemaRef(SemaRef) {
 
-  Invalid = CheckInstantiationDepth(PointOfInstantiation,
-                                    InstantiationRange);
-  if (!Invalid) {
-    ActiveTemplateInstantiation Inst;
-    Inst.Kind
-      = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
-    Inst.PointOfInstantiation = PointOfInstantiation;
-    Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
-    Inst.TemplateArgs = TemplateArgs;
-    Inst.NumTemplateArgs = NumTemplateArgs;
-    Inst.InstantiationRange = InstantiationRange;
-    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-    Invalid = false;
-  }
+  Invalid = false;
+    
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+      
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
 }
 
 Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
@@ -219,19 +235,20 @@
                       const TemplateArgument *TemplateArgs,
                       unsigned NumTemplateArgs,
                       SourceRange InstantiationRange) : SemaRef(SemaRef) {
-  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+  Invalid = false;
   
-  if (!Invalid) {
-    ActiveTemplateInstantiation Inst;
-    Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
-    Inst.PointOfInstantiation = PointOfInstantiation;
-    Inst.Template = Template;
-    Inst.Entity = reinterpret_cast<uintptr_t>(Param);
-    Inst.TemplateArgs = TemplateArgs;
-    Inst.NumTemplateArgs = NumTemplateArgs;
-    Inst.InstantiationRange = InstantiationRange;
-    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-  }
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Template = Template;
+  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
 }
 
 Sema::InstantiatingTemplate::
@@ -241,23 +258,51 @@
                       const TemplateArgument *TemplateArgs,
                       unsigned NumTemplateArgs,
                       SourceRange InstantiationRange) : SemaRef(SemaRef) {
-  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+  Invalid = false;
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Template = Template;
+  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
   
-  if (!Invalid) {
-    ActiveTemplateInstantiation Inst;
-    Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
-    Inst.PointOfInstantiation = PointOfInstantiation;
-    Inst.Template = Template;
-    Inst.Entity = reinterpret_cast<uintptr_t>(Param);
-    Inst.TemplateArgs = TemplateArgs;
-    Inst.NumTemplateArgs = NumTemplateArgs;
-    Inst.InstantiationRange = InstantiationRange;
-    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-  }
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      TemplateDecl *Template,
+                      NamedDecl *Param,
+                      const TemplateArgument *TemplateArgs,
+                      unsigned NumTemplateArgs,
+                      SourceRange InstantiationRange) : SemaRef(SemaRef) {
+  Invalid = false;
+  
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Template = Template;
+  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
 }
 
 void Sema::InstantiatingTemplate::Clear() {
   if (!Invalid) {
+    if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) {
+      assert(SemaRef.NonInstantiationEntries > 0);
+      --SemaRef.NonInstantiationEntries;
+    }
+    
     SemaRef.ActiveTemplateInstantiations.pop_back();
     Invalid = true;
   }
@@ -266,8 +311,11 @@
 bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
                                         SourceLocation PointOfInstantiation,
                                            SourceRange InstantiationRange) {
-  if (SemaRef.ActiveTemplateInstantiations.size()
-       <= SemaRef.getLangOptions().InstantiationDepth)
+  assert(SemaRef.NonInstantiationEntries <=
+                                   SemaRef.ActiveTemplateInstantiations.size());
+  if ((SemaRef.ActiveTemplateInstantiations.size() - 
+          SemaRef.NonInstantiationEntries)
+        <= SemaRef.getLangOptions().InstantiationDepth)
     return false;
 
   SemaRef.Diag(PointOfInstantiation,
@@ -391,6 +439,17 @@
         << Active->InstantiationRange;
       break;
     }
+
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
+      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                   diag::note_template_default_arg_checking)
+        << getTemplateArgumentBindingsText(
+                                     Active->Template->getTemplateParameters(), 
+                                           Active->TemplateArgs, 
+                                           Active->NumTemplateArgs)
+        << Active->InstantiationRange;
+      break;
+    }
     }
   }
 }
@@ -401,17 +460,17 @@
          Active = ActiveTemplateInstantiations.rbegin(),
          ActiveEnd = ActiveTemplateInstantiations.rend();
        Active != ActiveEnd;
-       ++Active) {
-
+       ++Active) 
+  {
     switch(Active->Kind) {
     case ActiveTemplateInstantiation::TemplateInstantiation:
     case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
-
       // This is a template instantiation, so there is no SFINAE.
       return false;
 
     case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
     case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution:
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking:
       // A default template argument instantiation and substitution into
       // template parameters with arguments for prior parameters may or may 
       // not be a SFINAE context; look further up the stack.

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=86884&r1=86883&r2=86884&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Nov 11 15:54:23 2009
@@ -1285,6 +1285,7 @@
       (void) FunTmpl;
       ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
       ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
+      --SemaRef.NonInstantiationEntries;
     }
   }
 

Modified: cfe/trunk/test/CXX/temp/temp.param/p12.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.param/p12.cpp?rev=86884&r1=86883&r2=86884&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.param/p12.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.param/p12.cpp Wed Nov 11 15:54:23 2009
@@ -36,4 +36,4 @@
            = Y1> // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
   class C1 {};
 
-C1<> c1;
+C1<> c1; // expected-note{{while checking a default template argument}}

Modified: cfe/trunk/test/SemaTemplate/default-arguments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/default-arguments.cpp?rev=86884&r1=86883&r2=86884&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/default-arguments.cpp (original)
+++ cfe/trunk/test/SemaTemplate/default-arguments.cpp Wed Nov 11 15:54:23 2009
@@ -116,5 +116,5 @@
   struct X6 {};
 
 X6<int> x6a;
-X6<long> x6b;
+X6<long> x6b; // expected-note{{while checking a default template argument}}
 X6<long, X5b> x6c;





More information about the cfe-commits mailing list