[cfe-commits] r66572 - in /cfe/trunk: include/clang/AST/Type.h include/clang/Basic/DiagnosticSemaKinds.def include/clang/Frontend/TextDiagnosticPrinter.h lib/AST/Type.cpp lib/Frontend/TextDiagnosticPrinter.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiation-default-1.cpp test/SemaTemplate/instantiation-default-2.cpp

Douglas Gregor dgregor at apple.com
Tue Mar 10 13:44:00 PDT 2009


Author: dgregor
Date: Tue Mar 10 15:44:00 2009
New Revision: 66572

URL: http://llvm.org/viewvc/llvm-project?rev=66572&view=rev
Log:
Extend the notion of active template instantiations to include the
context of a template-id for which we need to instantiate default
template arguments.

In the TextDiagnosticPrinter, don't suppress the caret diagnostic if
we are producing a non-note diagnostic that follows a note diagnostic
with the same location, because notes are (conceptually) a part of the
warning or error that comes before them.


Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp
    cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=66572&r1=66571&r2=66572&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Mar 10 15:44:00 2009
@@ -1449,6 +1449,11 @@
   static bool anyDependentTemplateArguments(const TemplateArgument *Args,
                                             unsigned NumArgs);  
 
+  /// \brief Print a template argument list, including the '<' and '>'
+  /// enclosing the template arguments.
+  static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
+                                               unsigned NumArgs);
+
   typedef const TemplateArgument * iterator;
 
   iterator begin() const { return getArgs(); }

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Tue Mar 10 15:44:00 2009
@@ -649,6 +649,8 @@
      "implicit instantiation of undefined template %0")
 DIAG(note_template_class_instantiation_here, NOTE,
      "in instantiation of template class %0 requested here")
+DIAG(note_default_arg_instantiation_here, NOTE,
+     "in instantiation of default argument for '%0' required here")
 
 DIAG(err_unexpected_typedef, ERROR,
      "unexpected type name %0: expected expression")

Modified: cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h?rev=66572&r1=66571&r2=66572&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h (original)
+++ cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h Tue Mar 10 15:44:00 2009
@@ -28,6 +28,7 @@
 class TextDiagnosticPrinter : public DiagnosticClient {
   SourceLocation LastWarningLoc;
   FullSourceLoc LastLoc;
+  bool LastCaretDiagnosticWasNote;
   llvm::raw_ostream &OS;
   bool ShowColumn;
   bool CaretDiagnostics;
@@ -35,8 +36,8 @@
 public:
   TextDiagnosticPrinter(llvm::raw_ostream &os, bool showColumn = true,
                         bool caretDiagnistics = true, bool showLocation = true)
-    : OS(os), ShowColumn(showColumn), CaretDiagnostics(caretDiagnistics),
-      ShowLocation(showLocation) {}
+    : LastCaretDiagnosticWasNote(false), OS(os), ShowColumn(showColumn), 
+      CaretDiagnostics(caretDiagnistics), ShowLocation(showLocation) {}
 
   void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM);
 

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=66572&r1=66571&r2=66572&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Mar 10 15:44:00 2009
@@ -1287,10 +1287,9 @@
     InnerString = Name->getName() + InnerString;
 }
 
-/// \brief Print a template argument list, including the '<' and '>'
-/// enclosing the template arguments.
-static std::string printTemplateArgumentList(const TemplateArgument *Args,
-                                             unsigned NumArgs) {
+std::string ClassTemplateSpecializationType::PrintTemplateArgumentList(
+                                              const TemplateArgument *Args,
+                                              unsigned NumArgs) {
   std::string SpecString;
   SpecString += '<';
   for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
@@ -1343,7 +1342,7 @@
 ClassTemplateSpecializationType::
 getAsStringInternal(std::string &InnerString) const {
   std::string SpecString = Template->getNameAsString();
-  SpecString += printTemplateArgumentList(getArgs(), getNumArgs());
+  SpecString += PrintTemplateArgumentList(getArgs(), getNumArgs());
   if (InnerString.empty())
     InnerString.swap(SpecString);
   else
@@ -1409,8 +1408,9 @@
   if (ClassTemplateSpecializationDecl *Spec 
         = dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
     std::string TemplateArgs 
-      = printTemplateArgumentList(Spec->getTemplateArgs(),
-                                  Spec->getNumTemplateArgs());
+      = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+                                                  Spec->getTemplateArgs(),
+                                                  Spec->getNumTemplateArgs());
     InnerString = TemplateArgs + InnerString;
   }
 

Modified: cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp?rev=66572&r1=66571&r2=66572&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp (original)
+++ cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp Tue Mar 10 15:44:00 2009
@@ -278,15 +278,19 @@
   OS.write(OutStr.begin(), OutStr.size());
   OS << '\n';
   
-  // If caret diagnostics are enabled and we have location, we want to emit the
-  // caret.  However, we only do this if the location moved from the last
-  // diagnostic, or if the diagnostic has ranges.  We don't want to emit the
-  // same caret multiple times if one loc has multiple diagnostics.
+  // If caret diagnostics are enabled and we have location, we want to
+  // emit the caret.  However, we only do this if the location moved
+  // from the last diagnostic, if the last diagnostic was a note that
+  // was part of a different warning or error diagnostic, or if the
+  // diagnostic has ranges.  We don't want to emit the same caret
+  // multiple times if one loc has multiple diagnostics.
   if (CaretDiagnostics && Info.getLocation().isValid() &&
       ((LastLoc != Info.getLocation()) || Info.getNumRanges() || 
+       (LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
        Info.getNumCodeModificationHints())) {
     // Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
     LastLoc = Info.getLocation();
+    LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
 
     // Get the ranges into a local array we can hack on.
     SourceRange Ranges[20];

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 10 15:44:00 2009
@@ -245,7 +245,7 @@
     DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
     if (!Diags.isBuiltinNote(DiagID) && 
         !ActiveTemplateInstantiations.empty() &&
-        ActiveTemplateInstantiations.back().Entity 
+        ActiveTemplateInstantiations.back() 
           != LastTemplateInstantiationErrorContext)
       DB << PostDiagnosticHook(PrintInstantiationStackHook, this);
     return DB;
@@ -1673,16 +1673,61 @@
 
   /// \brief A template instantiation that is currently in progress.
   struct ActiveTemplateInstantiation {
+    /// \brief The kind of template instantiation we are performing
+    enum {
+      /// We are instantiating a template declaration. The entity is
+      /// the declaration we're instantiation (e.g., a
+      /// ClassTemplateSpecializationDecl).
+      TemplateInstantiation,
+
+      /// We are instantiating a default argument for a template
+      /// parameter. The Entity is the template, and
+      /// TemplateArgs/NumTemplateArguments provides the template
+      /// arguments as specified.
+      DefaultTemplateArgumentInstantiation
+    } Kind;
+
     /// \brief The point of instantiation within the source code.
     SourceLocation PointOfInstantiation;
 
     /// \brief The entity that is being instantiated.
-    ClassTemplateSpecializationDecl *Entity;
+    uintptr_t Entity;
+
+    // \brief If this the instantiation of a default template
+    // argument, the list of tempalte arguments.
+    const TemplateArgument *TemplateArgs;
+
+    /// \brief The number of template arguments in TemplateArgs.
+    unsigned NumTemplateArgs;
 
     /// \brief The source range that covers the construct that cause
     /// the instantiation, e.g., the template-id that causes a class
     /// template instantiation.
     SourceRange InstantiationRange;
+
+    friend bool operator==(const ActiveTemplateInstantiation &X,
+                           const ActiveTemplateInstantiation &Y) {
+      if (X.Kind != Y.Kind)
+        return false;
+
+      if (X.Entity != Y.Entity)
+        return false;
+
+      switch (X.Kind) {
+      case TemplateInstantiation:
+        return true;
+
+      case DefaultTemplateArgumentInstantiation:
+        return X.TemplateArgs == Y.TemplateArgs;
+      }
+
+      return true;
+    }
+
+    friend bool operator!=(const ActiveTemplateInstantiation &X,
+                           const ActiveTemplateInstantiation &Y) {
+      return !(X == Y);
+    }
   };
 
   /// \brief List of active template instantiations.
@@ -1701,7 +1746,7 @@
   /// instantiation backtraces when there are multiple errors in the
   /// same instantiation. FIXME: Does this belong in Sema? It's tough
   /// to implement it anywhere else.
-  ClassTemplateSpecializationDecl *LastTemplateInstantiationErrorContext;
+  ActiveTemplateInstantiation LastTemplateInstantiationErrorContext;
 
   /// \brief A stack object to be created when performing template
   /// instantiation.
@@ -1715,9 +1760,19 @@
   /// Destruction of this object will pop the named instantiation off
   /// the stack.
   struct InstantiatingTemplate {
+    /// \brief Note that we are instantiating a class template.
     InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
                           ClassTemplateSpecializationDecl *Entity,
                           SourceRange InstantiationRange = SourceRange());
+
+    /// \brief Note that we are instantiating a default argument in a
+    /// template-id.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Template,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs,
+                          SourceRange InstantiationRange = SourceRange());
+
     ~InstantiatingTemplate();
 
     /// \brief Determines whether we have exceeded the maximum
@@ -1728,6 +1783,9 @@
     Sema &SemaRef;
     bool Invalid;
 
+    bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+                                 SourceRange InstantiationRange);
+
     InstantiatingTemplate(const InstantiatingTemplate&); // not implemented
 
     InstantiatingTemplate& 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Mar 10 15:44:00 2009
@@ -825,10 +825,15 @@
 
         // If the argument type is dependent, instantiate it now based
         // on the previously-computed template arguments.
-        if (ArgType->isDependentType())
+        if (ArgType->isDependentType()) {
+          InstantiatingTemplate Inst(*this, TemplateLoc, 
+                                     Template, &Converted[0], 
+                                     Converted.size(),
+                                     SourceRange(TemplateLoc, RAngleLoc));
           ArgType = InstantiateType(ArgType, &Converted[0], Converted.size(),
                                     TTP->getDefaultArgumentLoc(),
                                     TTP->getDeclName());
+        }
 
         if (ArgType.isNull())
           return true;
@@ -888,6 +893,11 @@
       QualType NTTPType = NTTP->getType();
       if (NTTPType->isDependentType()) {
         // Instantiate the type of the non-type template parameter.
+        InstantiatingTemplate Inst(*this, TemplateLoc, 
+                                   Template, &Converted[0], 
+                                   Converted.size(),
+                                   SourceRange(TemplateLoc, RAngleLoc));
+
         NTTPType = InstantiateType(NTTPType, 
                                    &Converted[0], Converted.size(),
                                    NTTP->getLocation(),

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Mar 10 15:44:00 2009
@@ -30,19 +30,38 @@
                       ClassTemplateSpecializationDecl *Entity,
                       SourceRange InstantiationRange)
   :  SemaRef(SemaRef) {
-  if (SemaRef.ActiveTemplateInstantiations.size() 
-        > SemaRef.getLangOptions().InstantiationDepth) {
-    SemaRef.Diag(PointOfInstantiation, 
-                 diag::err_template_recursion_depth_exceeded)
-      << SemaRef.getLangOptions().InstantiationDepth
-      << InstantiationRange;
-    SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
-      << SemaRef.getLangOptions().InstantiationDepth;
-    Invalid = true;
-  } else {
+
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+    Invalid = false;
+  }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, 
+                                         SourceLocation PointOfInstantiation,
+                                         TemplateDecl *Template,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceRange InstantiationRange)
+  : SemaRef(SemaRef) {
+
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
     ActiveTemplateInstantiation Inst;
+    Inst.Kind 
+      = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
     Inst.PointOfInstantiation = PointOfInstantiation;
-    Inst.Entity = Entity;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Template);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
     Inst.InstantiationRange = InstantiationRange;
     SemaRef.ActiveTemplateInstantiations.push_back(Inst);
     Invalid = false;
@@ -54,12 +73,28 @@
     SemaRef.ActiveTemplateInstantiations.pop_back();
 }
 
+bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
+                                        SourceLocation PointOfInstantiation,
+                                           SourceRange InstantiationRange) {
+  if (SemaRef.ActiveTemplateInstantiations.size() 
+       <= SemaRef.getLangOptions().InstantiationDepth)
+    return false;
+
+  SemaRef.Diag(PointOfInstantiation, 
+               diag::err_template_recursion_depth_exceeded)
+    << SemaRef.getLangOptions().InstantiationDepth
+    << InstantiationRange;
+  SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
+    << SemaRef.getLangOptions().InstantiationDepth;
+  return true;
+}
+
 /// \brief Post-diagnostic hook for printing the instantiation stack.
 void Sema::PrintInstantiationStackHook(unsigned, void *Cookie) {
   Sema &SemaRef = *static_cast<Sema*>(Cookie);
   SemaRef.PrintInstantiationStack();
   SemaRef.LastTemplateInstantiationErrorContext 
-    = SemaRef.ActiveTemplateInstantiations.back().Entity;
+    = SemaRef.ActiveTemplateInstantiations.back();
 }
 
 /// \brief Prints the current instantiation stack through a series of
@@ -70,10 +105,30 @@
          ActiveEnd = ActiveTemplateInstantiations.rend();
        Active != ActiveEnd;
        ++Active) {
-    Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), 
-                 diag::note_template_class_instantiation_here)
-      << Context.getTypeDeclType(Active->Entity)
-      << Active->InstantiationRange;
+    switch (Active->Kind) {
+    case ActiveTemplateInstantiation::TemplateInstantiation: {
+      ClassTemplateSpecializationDecl *Spec
+        = cast<ClassTemplateSpecializationDecl>((Decl*)Active->Entity);
+      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), 
+                   diag::note_template_class_instantiation_here)
+        << Context.getTypeDeclType(Spec)
+        << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
+      TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
+      std::string TemplateArgsStr
+        = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+                                                      Active->TemplateArgs, 
+                                                      Active->NumTemplateArgs);
+      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                   diag::note_default_arg_instantiation_here)
+        << (Template->getNameAsString() + TemplateArgsStr)
+        << Active->InstantiationRange;
+      break;
+    }
+    }
   }
 }
 
@@ -482,6 +537,10 @@
                                const TemplateArgument *TemplateArgs,
                                unsigned NumTemplateArgs,
                                SourceLocation Loc, DeclarationName Entity) {
+  assert(!ActiveTemplateInstantiations.empty() &&
+         "Cannot perform an instantiation without some context on the "
+         "instantiation stack");
+
   // If T is not a dependent type, there is nothing to do.
   if (!T->isDependentType())
     return T;

Modified: cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp?rev=66572&r1=66571&r2=66572&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp Tue Mar 10 15:44:00 2009
@@ -32,7 +32,8 @@
   d2->foo();
 }
 
-Def2<int&> *d2;
+typedef int& int_ref_t;
+Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}}
 
 
 template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1'}}

Modified: cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp?rev=66572&r1=66571&r2=66572&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp Tue Mar 10 15:44:00 2009
@@ -15,4 +15,4 @@
 
 Constant<float (*)(int, int), f> *c6; // expected-error{{non-type template argument of type 'float (*)(int, double)' cannot be converted to a value of type 'float (*)(int, int)'}}
 
-Constant<float, 0> *c7;
+Constant<float, 0> *c7; // expected-note{{in instantiation of default argument for 'Constant<float>' required here}}





More information about the cfe-commits mailing list