From: Sebastian Redl Date: Tue, 17 Jan 2012 22:49:33 +0000 (+0000) Subject: Add Sema::isStdInitializerList, which will be necessary for the upcoming operations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=395e04dbd7294bae4640aef1705cec3d052578b0;p=clang Add Sema::isStdInitializerList, which will be necessary for the upcoming operations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148348 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 634a1aacc0..fdc525ccc9 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -488,6 +488,10 @@ public: /// standard library. LazyDeclPtr StdBadAlloc; + /// \brief The C++ "std::initializer_list" template, which is defined in + /// . + ClassTemplateDecl *StdInitializerList; + /// \brief The C++ "type_info" declaration, which is defined in . 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, diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 0e4d22fc7f..28f90241d6 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -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), diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 5e328ec841..85c292ff4c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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 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(); + if (!RT) + return false; + + ClassTemplateSpecializationDecl *Specialization = + dyn_cast(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(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) {