]> granicus.if.org Git - clang/commitdiff
Add Sema::isStdInitializerList, which will be necessary for the upcoming operations.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 17 Jan 2012 22:49:33 +0000 (22:49 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 17 Jan 2012 22:49:33 +0000 (22:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148348 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/Sema.cpp
lib/Sema/SemaDeclCXX.cpp

index 634a1aacc0d1eb72a6f93b69d4dfe0592dc403f6..fdc525ccc9bbd3260a191b05064b912cb3b48a63 100644 (file)
@@ -488,6 +488,10 @@ public:
   /// standard library.
   LazyDeclPtr StdBadAlloc;
 
+  /// \brief The C++ "std::initializer_list" template, which is defined in
+  /// <initializer_list>.
+  ClassTemplateDecl *StdInitializerList;
+
   /// \brief The C++ "type_info" declaration, which is defined in <typeinfo>.
   RecordDecl *CXXTypeInfoDecl;
 
@@ -2721,6 +2725,10 @@ public:
 
   CXXRecordDecl *getStdBadAlloc() const;
 
+  /// \brief Tests whether Ty is an instance of std::initializer_list and, if
+  /// it is and Element is not NULL, assigns the element type to Element.
+  bool isStdInitializerList(QualType Ty, QualType *Element);
+
   Decl *ActOnUsingDirective(Scope *CurScope,
                             SourceLocation UsingLoc,
                             SourceLocation NamespcLoc,
index 0e4d22fc7f57efc050f6b2df62e2af35b4e0df52..28f90241d6e3314a101541b4090e7679838dafe4 100644 (file)
@@ -89,7 +89,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     CurContext(0), OriginalLexicalContext(0),
     PackContext(0), MSStructPragmaOn(false), VisContext(0),
     ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
-    IdResolver(pp), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
+    IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     GlobalNewDeleteDeclared(false), 
     ObjCShouldCallSuperDealloc(false),
     ObjCShouldCallSuperFinalize(false),
index 5e328ec841161743a10692748153678bec3f64f2..85c292ff4cb0d246de9940a0c8cde71da6d71c15 100644 (file)
@@ -5767,6 +5767,59 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() {
   return getStdNamespace();
 }
 
+bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
+  assert(getLangOptions().CPlusPlus &&
+         "Looking for std::initializer_list outside of C++.");
+
+  // We're looking for implicit instantiations of
+  // template <typename E> class std::initializer_list.
+
+  if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it.
+    return false;
+
+  const RecordType *RT = Ty->getAs<RecordType>();
+  if (!RT)
+    return false;
+
+  ClassTemplateSpecializationDecl *Specialization =
+      dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+  if (!Specialization)
+    return false;
+
+  if (Specialization->getSpecializationKind() != TSK_ImplicitInstantiation)
+    return false;
+
+  ClassTemplateDecl *Template = Specialization->getSpecializedTemplate();
+
+  if (!StdInitializerList) {
+    // Haven't recognized std::initializer_list yet, maybe this is it.
+    CXXRecordDecl *TemplateClass = Template->getTemplatedDecl();
+    if (TemplateClass->getIdentifier() !=
+            &PP.getIdentifierTable().get("initializer_list") ||
+        !TemplateClass->getDeclContext()->Equals(getStdNamespace()))
+      return false;
+    // This is a template called std::initializer_list, but is it the right
+    // template?
+    TemplateParameterList *Params = Template->getTemplateParameters();
+    if (Params->size() != 1)
+      return false;
+    if (!isa<TemplateTypeParmDecl>(Params->getParam(0)))
+      return false;
+
+    // It's the right template.
+    StdInitializerList = Template;
+  }
+
+  if (Template != StdInitializerList)
+    return false;
+
+  // This is an instance of std::initializer_list. Find the argument type.
+  if (Element) {
+    *Element = Specialization->getTemplateArgs()[0].getAsType();
+  }
+  return true;
+}
+
 /// \brief Determine whether a using statement is in a context where it will be
 /// apply in all contexts.
 static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {