[cfe-commits] r73332 - in /cfe/trunk: include/clang/AST/ include/clang/Analysis/ include/clang/Basic/ include/clang/Driver/ include/clang/Frontend/ include/clang/Lex/ include/clang/Parse/ include/clang/Sema/ lib/Basic/ lib/Sema/ test/SemaTemplate/ www/

Douglas Gregor dgregor at apple.com
Sun Jun 14 00:33:31 PDT 2009


Author: dgregor
Date: Sun Jun 14 02:33:30 2009
New Revision: 73332

URL: http://llvm.org/viewvc/llvm-project?rev=73332&view=rev
Log:
Update LLVM.

Implement support for C++ Substitution Failure Is Not An Error
(SFINAE), which says that errors that occur during template argument
deduction do *not* produce diagnostics and do not necessarily make a
program ill-formed. Instead, template argument deduction silently
fails. This is currently implemented for template argument deduction
during matching of class template partial specializations, although
the mechanism will also apply to template argument deduction for
function templates. The scheme is simple:

  - If we are in a template argument deduction context, any diagnostic
    that is considered a SFINAE error (or warning) will be
    suppressed. The error will be propagated up the call stack via the
    normal means.
  - By default, all warnings and errors are SFINAE errors. Add the
    NoSFINAE class to a diagnostic in the .td file to make it a hard
    error (e.g., for access-control violations).

Note that, to make this fully work, every place in Sema that emits an
error *and then immediately recovers* will need to check
Sema::isSFINAEContext() to determine whether it must immediately
return an error rather than recovering.


Modified:
    cfe/trunk/include/clang/AST/ASTDiagnostic.h
    cfe/trunk/include/clang/Analysis/AnalysisDiagnostic.h
    cfe/trunk/include/clang/Basic/Diagnostic.h
    cfe/trunk/include/clang/Basic/Diagnostic.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Driver/DriverDiagnostic.h
    cfe/trunk/include/clang/Frontend/FrontendDiagnostic.h
    cfe/trunk/include/clang/Lex/LexDiagnostic.h
    cfe/trunk/include/clang/Parse/ParseDiagnostic.h
    cfe/trunk/include/clang/Sema/SemaDiagnostic.h
    cfe/trunk/lib/Basic/Diagnostic.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/SemaTemplate/temp_class_spec.cpp
    cfe/trunk/www/cxx_status.html

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

==============================================================================
--- cfe/trunk/include/clang/AST/ASTDiagnostic.h (original)
+++ cfe/trunk/include/clang/AST/ASTDiagnostic.h Sun Jun 14 02:33:30 2009
@@ -15,7 +15,7 @@
 namespace clang {
   namespace diag { 
     enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
 #define ASTSTART
 #include "clang/Basic/DiagnosticASTKinds.inc"
 #undef DIAG

Modified: cfe/trunk/include/clang/Analysis/AnalysisDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/AnalysisDiagnostic.h?rev=73332&r1=73331&r2=73332&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/AnalysisDiagnostic.h (original)
+++ cfe/trunk/include/clang/Analysis/AnalysisDiagnostic.h Sun Jun 14 02:33:30 2009
@@ -15,7 +15,7 @@
 namespace clang {
   namespace diag { 
     enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
 #define ANALYSISSTART
 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
 #undef DIAG

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=73332&r1=73331&r2=73332&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Sun Jun 14 02:33:30 2009
@@ -50,7 +50,7 @@
 
     // Get typedefs for common diagnostics.
     enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
 #include "clang/Basic/DiagnosticCommonKinds.inc"
       NUM_BUILTIN_COMMON_DIAGNOSTICS
 #undef DIAG
@@ -313,6 +313,16 @@
   /// the diagnostic, this returns null.
   static const char *getWarningOptionForDiag(unsigned DiagID);
 
+  /// \brief Determines whether the given built-in diagnostic ID is
+  /// for an error that is suppressed if it occurs during C++ template
+  /// argument deduction.
+  ///
+  /// When an error is suppressed due to SFINAE, the template argument
+  /// deduction fails but no diagnostic is emitted. Certain classes of
+  /// errors, such as those errors that involve C++ access control,
+  /// are not SFINAE errors.
+  static bool isBuiltinSFINAEDiag(unsigned DiagID);
+
   /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
   /// object, classify the specified diagnostic ID into a Level, consumable by
   /// the DiagnosticClient.
@@ -409,7 +419,10 @@
 
   /// ProcessDiag - This is the method used to report a diagnostic that is
   /// finally fully formed.
-  void ProcessDiag();
+  ///
+  /// \returns true if the diagnostic was emitted, false if it was
+  /// suppressed.
+  bool ProcessDiag();
 };
 
 //===----------------------------------------------------------------------===//
@@ -448,14 +461,26 @@
     NumCodeModificationHints = D.NumCodeModificationHints;
   }
 
+  /// \brief Simple enumeration value used to give a name to the
+  /// suppress-diagnostic constructor.
+  enum SuppressKind { Suppress };
+
+  /// \brief Create an empty DiagnosticBuilder object that represents
+  /// no actual diagnostic.
+  explicit DiagnosticBuilder(SuppressKind) 
+    : DiagObj(0), NumArgs(0), NumRanges(0), NumCodeModificationHints(0) { }
+
   /// \brief Force the diagnostic builder to emit the diagnostic now.
   ///
   /// Once this function has been called, the DiagnosticBuilder object
   /// should not be used again before it is destroyed.
-  void Emit() {
+  ///
+  /// \returns true if a diagnostic was emitted, false if the
+  /// diagnostic was suppressed.
+  bool Emit() {
     // If DiagObj is null, then its soul was stolen by the copy ctor
     // or the user called Emit().
-    if (DiagObj == 0) return;
+    if (DiagObj == 0) return false;
 
     // When emitting diagnostics, we set the final argument count into
     // the Diagnostic object.
@@ -465,13 +490,15 @@
 
     // Process the diagnostic, sending the accumulated information to the
     // DiagnosticClient.
-    DiagObj->ProcessDiag();
+    bool Emitted = DiagObj->ProcessDiag();
 
     // Clear out the current diagnostic object.
     DiagObj->Clear();
 
     // This diagnostic is dead.
     DiagObj = 0;
+
+    return Emitted;
   }
 
   /// Destructor - The dtor emits the diagnostic if it hasn't already
@@ -486,28 +513,34 @@
   void AddString(const std::string &S) const {
     assert(NumArgs < Diagnostic::MaxArguments &&
            "Too many arguments to diagnostic!");
-    DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
-    DiagObj->DiagArgumentsStr[NumArgs++] = S;
+    if (DiagObj) {
+      DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
+      DiagObj->DiagArgumentsStr[NumArgs++] = S;
+    }
   }
   
   void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
     assert(NumArgs < Diagnostic::MaxArguments &&
            "Too many arguments to diagnostic!");
-    DiagObj->DiagArgumentsKind[NumArgs] = Kind;
-    DiagObj->DiagArgumentsVal[NumArgs++] = V;
+    if (DiagObj) {
+      DiagObj->DiagArgumentsKind[NumArgs] = Kind;
+      DiagObj->DiagArgumentsVal[NumArgs++] = V;
+    }
   }
   
   void AddSourceRange(const SourceRange &R) const {
     assert(NumRanges < 
            sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
            "Too many arguments to diagnostic!");
-    DiagObj->DiagRanges[NumRanges++] = &R;
+    if (DiagObj)
+      DiagObj->DiagRanges[NumRanges++] = &R;
   }    
 
   void AddCodeModificationHint(const CodeModificationHint &Hint) const {
     assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints &&
            "Too many code modification hints!");
-    DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint;
+    if (DiagObj)
+      DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint;
   }
 };
 

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

==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.td (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.td Sun Jun 14 02:33:30 2009
@@ -45,6 +45,7 @@
   string      Component = ?;
   string      Text = text;
   DiagClass   Class = DC;
+  bit         SFINAE = 1;
   DiagMapping DefaultMapping = defaultmapping;
   DiagGroup   Group;
 }
@@ -61,6 +62,8 @@
 class DefaultError  { DiagMapping DefaultMapping = MAP_ERROR; }
 class DefaultFatal  { DiagMapping DefaultMapping = MAP_FATAL; }
 
+class NoSFINAE { bit SFINAE = 0; }
+
 // Definitions for Diagnostics.
 include "DiagnosticASTKinds.td"
 include "DiagnosticAnalysisKinds.td"

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Jun 14 02:33:30 2009
@@ -331,7 +331,7 @@
 def err_covariant_return_inaccessible_base : Error<
   "return type of virtual function %2 is not covariant with the return type "
   "of the function it overrides "
-  "(conversion from %0 to inaccessible base class %1)">;
+  "(conversion from %0 to inaccessible base class %1)">, NoSFINAE;
 def err_covariant_return_ambiguous_derived_to_base_conv : Error<
   "return type of virtual function %3 is not covariant with the return type of "
   "the function it overrides (ambiguous conversion from derived class "
@@ -782,7 +782,8 @@
 
 // C++ Template Instantiation
 def err_template_recursion_depth_exceeded : Error<
-  "recursive template instantiation exceeded maximum depth of %0">,DefaultFatal;
+  "recursive template instantiation exceeded maximum depth of %0">,
+  DefaultFatal, NoSFINAE;
 def note_template_recursion_depth : Note<
   "use -ftemplate-depth-N to increase recursive template instantiation depth">;
 
@@ -1604,7 +1605,7 @@
 
 // C++ access control
 def err_conv_to_inaccessible_base : Error<
-  "conversion from %0 to inaccessible base class %1">;
+  "conversion from %0 to inaccessible base class %1">, NoSFINAE;
 def note_inheritance_specifier_here : Note<
   "'%0' inheritance specifier here">;
 def note_inheritance_implicitly_private_here : Note<
@@ -1851,8 +1852,10 @@
   "local declaration of %0 hides instance variable">;
 def error_ivar_use_in_class_method : Error<
   "instance variable %0 accessed in class method">;
-def error_private_ivar_access : Error<"instance variable %0 is private">;
-def error_protected_ivar_access : Error<"instance variable %0 is protected">;
+def error_private_ivar_access : Error<"instance variable %0 is private">,
+    NoSFINAE;
+def error_protected_ivar_access : Error<"instance variable %0 is protected">,
+    NoSFINAE;
 def warn_maynot_respond : Warning<"%0  may not respond to %1">;
 def warn_attribute_method_def : Warning<
   "method attribute can only be specified on method declarations">;

Modified: cfe/trunk/include/clang/Driver/DriverDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/DriverDiagnostic.h?rev=73332&r1=73331&r2=73332&view=diff

==============================================================================
--- cfe/trunk/include/clang/Driver/DriverDiagnostic.h (original)
+++ cfe/trunk/include/clang/Driver/DriverDiagnostic.h Sun Jun 14 02:33:30 2009
@@ -15,7 +15,7 @@
 namespace clang {
   namespace diag { 
     enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
 #define DRIVERSTART
 #include "clang/Basic/DiagnosticDriverKinds.inc"
 #undef DIAG

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendDiagnostic.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendDiagnostic.h Sun Jun 14 02:33:30 2009
@@ -15,7 +15,7 @@
 namespace clang {
   namespace diag { 
     enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
 #define FRONTENDSTART
 #include "clang/Basic/DiagnosticFrontendKinds.inc"
 #undef DIAG

Modified: cfe/trunk/include/clang/Lex/LexDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/LexDiagnostic.h?rev=73332&r1=73331&r2=73332&view=diff

==============================================================================
--- cfe/trunk/include/clang/Lex/LexDiagnostic.h (original)
+++ cfe/trunk/include/clang/Lex/LexDiagnostic.h Sun Jun 14 02:33:30 2009
@@ -15,7 +15,7 @@
 namespace clang {
   namespace diag { 
     enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
 #define LEXSTART
 #include "clang/Basic/DiagnosticLexKinds.inc"
 #undef DIAG

Modified: cfe/trunk/include/clang/Parse/ParseDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/ParseDiagnostic.h?rev=73332&r1=73331&r2=73332&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/ParseDiagnostic.h (original)
+++ cfe/trunk/include/clang/Parse/ParseDiagnostic.h Sun Jun 14 02:33:30 2009
@@ -15,7 +15,7 @@
 namespace clang {
   namespace diag { 
     enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
 #define PARSESTART
 #include "clang/Basic/DiagnosticParseKinds.inc"
 #undef DIAG

Modified: cfe/trunk/include/clang/Sema/SemaDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaDiagnostic.h?rev=73332&r1=73331&r2=73332&view=diff

==============================================================================
--- cfe/trunk/include/clang/Sema/SemaDiagnostic.h (original)
+++ cfe/trunk/include/clang/Sema/SemaDiagnostic.h Sun Jun 14 02:33:30 2009
@@ -15,7 +15,7 @@
 namespace clang {
   namespace diag { 
     enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
 #define SEMASTART
 #include "clang/Basic/DiagnosticSemaKinds.inc"
 #undef DIAG

Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=73332&r1=73331&r2=73332&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Sun Jun 14 02:33:30 2009
@@ -46,6 +46,7 @@
   unsigned short DiagID;
   unsigned Mapping : 3;
   unsigned Class : 3;
+  bool SFINAE : 1;
   const char *Description;
   const char *OptionGroup;
   
@@ -58,8 +59,8 @@
 };
 
 static const StaticDiagInfoRec StaticDiagInfo[] = {
-#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP) \
-  { diag::ENUM, DEFAULT_MAPPING, CLASS, DESC, GROUP },
+#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE)    \
+  { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, DESC, GROUP },
 #include "clang/Basic/DiagnosticCommonKinds.inc"
 #include "clang/Basic/DiagnosticDriverKinds.inc"
 #include "clang/Basic/DiagnosticFrontendKinds.inc"
@@ -68,7 +69,7 @@
 #include "clang/Basic/DiagnosticASTKinds.inc"
 #include "clang/Basic/DiagnosticSemaKinds.inc"
 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
-{ 0, 0, 0, 0, 0 }
+  { 0, 0, 0, 0, 0, 0}
 };
 #undef DIAG
 
@@ -89,7 +90,7 @@
 #endif
   
   // Search the diagnostic table with a binary search.
-  StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0 };
+  StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0 };
   
   const StaticDiagInfoRec *Found =
     std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
@@ -115,6 +116,12 @@
   return 0;
 }
 
+bool Diagnostic::isBuiltinSFINAEDiag(unsigned DiagID) {
+  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+    return Info->SFINAE && Info->Class != CLASS_NOTE;
+  return false;
+}
+
 /// getDiagClass - Return the class field of the diagnostic.
 ///
 static unsigned getBuiltinDiagClass(unsigned DiagID) {
@@ -399,7 +406,7 @@
 
 /// ProcessDiag - This is the method used to report a diagnostic that is
 /// finally fully formed.
-void Diagnostic::ProcessDiag() {
+bool Diagnostic::ProcessDiag() {
   DiagnosticInfo Info(this);
     
   // Figure out the diagnostic level of this message.
@@ -449,13 +456,13 @@
   // If a fatal error has already been emitted, silence all subsequent
   // diagnostics.
   if (FatalErrorOccurred)
-    return;
+    return false;
 
   // If the client doesn't care about this message, don't issue it.  If this is
   // a note and the last real diagnostic was ignored, ignore it too.
   if (DiagLevel == Diagnostic::Ignored ||
       (DiagLevel == Diagnostic::Note && LastDiagLevel == Diagnostic::Ignored))
-    return;
+    return false;
 
   // If this diagnostic is in a system header and is not a clang error, suppress
   // it.
@@ -464,7 +471,7 @@
       Info.getLocation().getSpellingLoc().isInSystemHeader() &&
       (DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) {
     LastDiagLevel = Diagnostic::Ignored;
-    return;
+    return false;
   }
 
   if (DiagLevel >= Diagnostic::Error) {
@@ -477,6 +484,8 @@
   if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics;
 
   CurDiagID = ~0U;
+
+  return true;
 }
 
 

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Sun Jun 14 02:33:30 2009
@@ -316,7 +316,8 @@
 }
 
 Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
-  this->Emit();
+  if (!this->Emit())
+    return;
   
   // If this is not a note, and we're in a template instantiation
   // that is different from the last template instantiation where

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Jun 14 02:33:30 2009
@@ -297,11 +297,21 @@
     SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
       : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { }
 
+    explicit SemaDiagnosticBuilder(Sema &SemaRef) 
+      : DiagnosticBuilder(DiagnosticBuilder::Suppress), SemaRef(SemaRef) { }
+
     ~SemaDiagnosticBuilder();
   };
 
   /// \brief Emit a diagnostic.
   SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+    if (isSFINAEContext() && Diagnostic::isBuiltinSFINAEDiag(DiagID)) {
+      // If we encountered an error during template argument
+      // deduction, and that error is one of the SFINAE errors,
+      // supress the diagnostic.
+      return SemaDiagnosticBuilder(*this);
+    }
+
     DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
     return SemaDiagnosticBuilder(DB, *this, DiagID);
   }
@@ -2322,6 +2332,14 @@
 
   void PrintInstantiationStack();
 
+  /// \brief Determines whether we are currently in a context where
+  /// template argument substitution failures are not considered
+  /// errors.
+  ///
+  /// When this routine returns true, the emission of most diagnostics
+  /// will be suppressed and there will be no local error recovery.
+  bool isSFINAEContext() const;
+
   /// \brief A stack-allocated class that identifies which local
   /// variable declaration instantiations are present in this scope.
   ///

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Sun Jun 14 02:33:30 2009
@@ -199,6 +199,34 @@
   }
 }
 
+bool Sema::isSFINAEContext() const {
+  using llvm::SmallVector;
+  for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
+         Active = ActiveTemplateInstantiations.rbegin(),
+         ActiveEnd = ActiveTemplateInstantiations.rend();
+       Active != ActiveEnd;
+       ++Active) {
+
+    switch(Active->Kind) {
+    case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation:
+      // We're in a template argument deduction context, so SFINAE
+      // applies.
+      return true;
+
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
+      // A default template argument instantiation may or may not be a
+      // SFINAE context; look further up the stack.
+      break;
+
+    case ActiveTemplateInstantiation::TemplateInstantiation:
+      // This is a template instantiation, so there is no SFINAE.
+      return false;
+    }
+  }
+
+  return false;
+}
+
 //===----------------------------------------------------------------------===/
 // Template Instantiation for Types
 //===----------------------------------------------------------------------===/

Modified: cfe/trunk/test/SemaTemplate/temp_class_spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_class_spec.cpp?rev=73332&r1=73331&r2=73332&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_class_spec.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_class_spec.cpp Sun Jun 14 02:33:30 2009
@@ -251,9 +251,8 @@
             is_nested_value_type_identity<HasValueType<int> >::value? -1 : 1];
 int is_nested_value_type_identity1[
           is_nested_value_type_identity<HasIdentityValueType>::value? 1 : -1];
-// FIXME: Enable when we have SFINAE support
-//int is_nested_value_type_identity2[
-//                   is_nested_value_type_identity<NoValueType>::value? -1 : 1];
+int is_nested_value_type_identity2[
+                   is_nested_value_type_identity<NoValueType>::value? -1 : 1];
 
 
 // C++ [temp.class.spec]p4:

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=73332&r1=73331&r2=73332&view=diff

==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Sun Jun 14 02:33:30 2009
@@ -2085,10 +2085,10 @@
 </tr>
 <tr>
   <td>    14.8.2 [temp.deduct]</td>
-  <td class="broken" align="center"></td>
-  <td class="broken" align="center"></td>
-  <td class="broken" align="center"></td>
-  <td class="broken" align="center"></td>
+  <td class="na" align="center">N/A</td>
+  <td class="na" align="center">N/A</td>
+  <td class="medium" align="center"></td>
+  <td class="na" align="center">N/A</td>
   <td></td>
 </tr>
 <tr>





More information about the cfe-commits mailing list