diff options
Diffstat (limited to 'include/clang/AST')
30 files changed, 1108 insertions, 324 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 4ce5852545..ae779436a9 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -20,7 +20,6 @@ namespace clang { class Decl; class DeclGroupRef; class HandleTagDeclDefinition; - class PPMutationListener; class ASTMutationListener; class ASTDeserializationListener; // layering violation because void* is ugly class SemaConsumer; // layering violation required for safe SemaConsumer @@ -113,11 +112,6 @@ public: /// it was actually used. virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} - /// \brief If the consumer is interested in preprocessor entities getting - /// modified after their initial creation, it should return a pointer to - /// a PPMutationListener here. - virtual PPMutationListener *GetPPMutationListener() { return 0; } - /// \brief If the consumer is interested in entities getting modified after /// their initial creation, it should return a pointer to /// an ASTMutationListener here. diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index d4878a99a6..c5d3337fd2 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -867,6 +867,9 @@ public: const FunctionType *adjustFunctionType(const FunctionType *Fn, FunctionType::ExtInfo EInfo); + /// \brief Change the result type of a function type once it is deduced. + void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType); + /// \brief Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T) const; @@ -1100,7 +1103,8 @@ public: UnaryTransformType::UTTKind UKind) const; /// \brief C++11 deduced auto type. - QualType getAutoType(QualType DeducedType) const; + QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto, + bool IsDependent = false) const; /// \brief C++11 deduction pattern for 'auto' type. QualType getAutoDeductType() const; @@ -1451,7 +1455,18 @@ public: qs.addObjCLifetime(lifetime); return getQualifiedType(type, qs); } - + + /// getUnqualifiedObjCPointerType - Returns version of + /// Objective-C pointer type with lifetime qualifier removed. + QualType getUnqualifiedObjCPointerType(QualType type) const { + if (!type.getTypePtr()->isObjCObjectPointerType() || + !type.getQualifiers().hasObjCLifetime()) + return type; + Qualifiers Qs = type.getQualifiers(); + Qs.removeObjCLifetime(); + return getQualifiedType(type.getUnqualifiedType(), Qs); + } + DeclarationNameInfo getNameForTemplate(TemplateName Name, SourceLocation NameLoc) const; @@ -1578,6 +1593,14 @@ public: /// beneficial for performance to overalign a data type. unsigned getPreferredTypeAlign(const Type *T) const; + /// \brief Return the alignment in bits that should be given to a + /// global variable with type \p T. + unsigned getAlignOfGlobalVar(QualType T) const; + + /// \brief Return the alignment in characters that should be given to a + /// global variable with type \p T. + CharUnits getAlignOfGlobalVarInChars(QualType T) const; + /// \brief Return a conservative estimate of the alignment of the specified /// decl \p D. /// diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h index c709895fc0..5a56b4d2b4 100644 --- a/include/clang/AST/ASTUnresolvedSet.h +++ b/include/clang/AST/ASTUnresolvedSet.h @@ -41,10 +41,6 @@ public: const_iterator begin() const { return const_iterator(Decls.begin()); } const_iterator end() const { return const_iterator(Decls.end()); } - void addDecl(ASTContext &C, NamedDecl *D) { - addDecl(C, D, AS_none); - } - void addDecl(ASTContext &C, NamedDecl *D, AccessSpecifier AS) { Decls.push_back(DeclAccessPair::make(D, AS), C); } @@ -52,10 +48,13 @@ public: /// Replaces the given declaration with the new one, once. /// /// \return true if the set changed - bool replace(const NamedDecl* Old, NamedDecl *New) { - for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) - if (I->getDecl() == Old) - return (I->setDecl(New), true); + bool replace(const NamedDecl* Old, NamedDecl *New, AccessSpecifier AS) { + for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) { + if (I->getDecl() == Old) { + I->set(New, AS); + return true; + } + } return false; } diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 61c57f9928..27dcef2a1e 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -129,10 +129,27 @@ protected: public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { + // Relies on relative order of enum emission with respect to MS inheritance + // attrs. return A->getKind() <= attr::LAST_INHERITABLE_PARAM; } }; +class MSInheritanceAttr : public InheritableAttr { + virtual void anchor(); +protected: + MSInheritanceAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0) + : InheritableAttr(AK, R, SpellingListIndex) {} + +public: + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + // Relies on relative order of enum emission with respect to param attrs. + return (A->getKind() <= attr::LAST_MS_INHERITABLE && + A->getKind() > attr::LAST_INHERITABLE_PARAM); + } +}; + #include "clang/AST/Attrs.inc" } // end namespace clang diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index b1b92b0f84..946075739d 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -351,15 +351,12 @@ namespace llvm { /// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. /// to return smart pointer (proxies?). template<typename T> -struct simplify_type<const ::clang::CanQual<T> > { +struct simplify_type< ::clang::CanQual<T> > { typedef const T *SimpleType; - static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) { + static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) { return Val.getTypePtr(); } }; -template<typename T> -struct simplify_type< ::clang::CanQual<T> > -: public simplify_type<const ::clang::CanQual<T> > {}; // Teach SmallPtrSet that CanQual<T> is "basically a pointer". template<typename T> diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h index 9eb99d506b..d1f5209d1e 100644 --- a/include/clang/AST/CommentCommandTraits.h +++ b/include/clang/AST/CommentCommandTraits.h @@ -105,10 +105,10 @@ struct CommandInfo { unsigned IsFunctionDeclarationCommand : 1; /// \brief True if block command is further describing a container API; such - /// as @coclass, @classdesign, etc. + /// as \@coclass, \@classdesign, etc. unsigned IsRecordLikeDetailCommand : 1; - /// \brief True if block command is a container API; such as @interface. + /// \brief True if block command is a container API; such as \@interface. unsigned IsRecordLikeDeclarationCommand : 1; /// \brief True if this command is unknown. This \c CommandInfo object was diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td index e217834227..8c88494e9a 100644 --- a/include/clang/AST/CommentCommands.td +++ b/include/clang/AST/CommentCommands.td @@ -67,14 +67,12 @@ class DeclarationVerbatimLineCommand<string name> : } class FunctionDeclarationVerbatimLineCommand<string name> : - VerbatimLineCommand<name> { - let IsDeclarationCommand = 1; + DeclarationVerbatimLineCommand<name> { let IsFunctionDeclarationCommand = 1; } class RecordLikeDeclarationVerbatimLineCommand<string name> : - VerbatimLineCommand<name> { - let IsDeclarationCommand = 1; + DeclarationVerbatimLineCommand<name> { let IsRecordLikeDeclarationCommand = 1; } @@ -121,6 +119,7 @@ def Headerfile : BlockCommand<"headerfile"> { let IsHeaderfileCommand = 1; } // We don't do any additional semantic analysis for the following // BlockCommands. It might be a good idea to do something extra for them, but // for now we model them as plain BlockCommands. +def Arg : BlockCommand<"arg">; def Attention : BlockCommand<"attention">; def Author : BlockCommand<"author">; def Authors : BlockCommand<"authors">; @@ -128,7 +127,9 @@ def Bug : BlockCommand<"bug">; def Copyright : BlockCommand<"copyright">; def Date : BlockCommand<"date">; def Invariant : BlockCommand<"invariant">; +def Li : BlockCommand<"li">; def Note : BlockCommand<"note">; +def Par : BlockCommand<"par">; def Post : BlockCommand<"post">; def Pre : BlockCommand<"pre">; def Remark : BlockCommand<"remark">; @@ -140,9 +141,11 @@ def Todo : BlockCommand<"todo">; def Version : BlockCommand<"version">; def Warning : BlockCommand<"warning">; // HeaderDoc commands +def Abstract : BlockCommand<"abstract">; def ClassDesign : RecordLikeDetailCommand<"classdesign">; def CoClass : RecordLikeDetailCommand<"coclass">; def Dependency : RecordLikeDetailCommand<"dependency">; +def Discussion : BlockCommand<"discussion">; def Helper : RecordLikeDetailCommand<"helper">; def HelperClass : RecordLikeDetailCommand<"helperclass">; def Helps : RecordLikeDetailCommand<"helps">; @@ -150,6 +153,7 @@ def InstanceSize : RecordLikeDetailCommand<"instancesize">; def Ownership : RecordLikeDetailCommand<"ownership">; def Performance : RecordLikeDetailCommand<"performance">; def Security : RecordLikeDetailCommand<"security">; +def SeeAlso : BlockCommand<"seealso">; def SuperClass : RecordLikeDetailCommand<"superclass">; //===----------------------------------------------------------------------===// @@ -173,6 +177,10 @@ def FDollar : VerbatimBlockCommand<"f$">; // Inline LaTeX formula defm FBracket : VerbatimBlockCommand<"f[", "f]">; // Displayed LaTeX formula defm FBrace : VerbatimBlockCommand<"f{", "f}">; // LaTeX environment +// HeaderDoc commands +defm Textblock : VerbatimBlockCommand<"textblock", "/textblock">; +defm Link : VerbatimBlockCommand<"link", "/link">; + //===----------------------------------------------------------------------===// // VerbatimLineCommand //===----------------------------------------------------------------------===// @@ -213,7 +221,9 @@ def Union : RecordLikeDeclarationVerbatimLineCommand<"union">; def Category : DeclarationVerbatimLineCommand<"category">; def Template : DeclarationVerbatimLineCommand<"template">; def Function : FunctionDeclarationVerbatimLineCommand<"function">; +def FunctionGroup : FunctionDeclarationVerbatimLineCommand<"functiongroup">; def Method : FunctionDeclarationVerbatimLineCommand<"method">; +def MethodGroup : FunctionDeclarationVerbatimLineCommand<"methodgroup">; def Callback : FunctionDeclarationVerbatimLineCommand<"callback">; def Const : DeclarationVerbatimLineCommand<"const">; def Constant : DeclarationVerbatimLineCommand<"constant">; diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h index 4179f45e80..f152c778c9 100644 --- a/include/clang/AST/CommentLexer.h +++ b/include/clang/AST/CommentLexer.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_COMMENT_LEXER_H #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Diagnostic.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -227,6 +228,8 @@ private: /// computed (for example, resolved decimal character references). llvm::BumpPtrAllocator &Allocator; + DiagnosticsEngine &Diags; + const CommandTraits &Traits; const char *const BufferStart; @@ -316,6 +319,10 @@ private: return FileLoc.getLocWithOffset(CharNo); } + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { + return Diags.Report(Loc, DiagID); + } + /// Eat string matching regexp \code \s*\* \endcode. void skipLineStartingDecorations(); @@ -346,7 +353,8 @@ private: void lexHTMLEndTag(Token &T); public: - Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits, + Lexer(llvm::BumpPtrAllocator &Allocator, DiagnosticsEngine &Diags, + const CommandTraits &Traits, SourceLocation FileLoc, const char *BufferStart, const char *BufferEnd); diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index fd1dcaa872..a0c76c069b 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -238,9 +238,9 @@ public: Optional<Visibility> getExplicitVisibility(ExplicitVisibilityKind kind) const; - /// \brief Clear the linkage cache in response to a change - /// to the declaration. - void ClearLinkageCache(); + /// \brief True if the computed linkage is valid. Used for consistency + /// checking. Should always return true. + bool isLinkageValid() const; /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. @@ -637,6 +637,13 @@ public: ListInit ///< Direct list-initialization (C++11) }; + /// \brief Kinds of thread-local storage. + enum TLSKind { + TLS_None, ///< Not a TLS variable. + TLS_Static, ///< TLS with a known-constant initializer. + TLS_Dynamic ///< TLS with a dynamic initializer. + }; + protected: /// \brief Placeholder type used in Init to denote an unparsed C++ default /// argument. @@ -660,8 +667,7 @@ private: friend class ASTDeclReader; unsigned SClass : 3; - unsigned SClassAsWritten : 3; - unsigned ThreadSpecified : 1; + unsigned TSCSpec : 2; unsigned InitStyle : 2; /// \brief Whether this variable is the exception variable in a C++ catch @@ -684,7 +690,7 @@ private: /// \brief Whether this variable is (C++0x) constexpr. unsigned IsConstexpr : 1; }; - enum { NumVarDeclBits = 14 }; + enum { NumVarDeclBits = 12 }; friend class ASTDeclReader; friend class StmtIteratorBase; @@ -727,14 +733,12 @@ protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass SC, - StorageClass SCAsWritten) + QualType T, TypeSourceInfo *TInfo, StorageClass SC) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() { assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); AllBits = 0; VarDeclBits.SClass = SC; - VarDeclBits.SClassAsWritten = SCAsWritten; // Everything else is implicitly initialized to false. } @@ -757,27 +761,36 @@ public: static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten); + StorageClass S); static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID); virtual SourceRange getSourceRange() const LLVM_READONLY; + /// \brief Returns the storage class as written in the source. For the + /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return (StorageClass) VarDeclBits.SClass; } - StorageClass getStorageClassAsWritten() const { - return (StorageClass) VarDeclBits.SClassAsWritten; - } void setStorageClass(StorageClass SC); - void setStorageClassAsWritten(StorageClass SC) { - assert(isLegalForVariable(SC)); - VarDeclBits.SClassAsWritten = SC; - } - void setThreadSpecified(bool T) { VarDeclBits.ThreadSpecified = T; } - bool isThreadSpecified() const { - return VarDeclBits.ThreadSpecified; + void setTSCSpec(ThreadStorageClassSpecifier TSC) { + VarDeclBits.TSCSpec = TSC; + } + ThreadStorageClassSpecifier getTSCSpec() const { + return static_cast<ThreadStorageClassSpecifier>(VarDeclBits.TSCSpec); + } + TLSKind getTLSKind() const { + switch (VarDeclBits.TSCSpec) { + case TSCS_unspecified: + return TLS_None; + case TSCS___thread: // Fall through. + case TSCS__Thread_local: + return TLS_Static; + case TSCS_thread_local: + return TLS_Dynamic; + } + llvm_unreachable("Unknown thread storage class specifier!"); } /// hasLocalStorage - Returns true if a variable with function scope @@ -805,13 +818,6 @@ public: getStorageClass() == SC_PrivateExtern; } - /// \brief Returns true if a variable was written with extern or - /// __private_extern__ storage. - bool hasExternalStorageAsWritten() const { - return getStorageClassAsWritten() == SC_Extern || - getStorageClassAsWritten() == SC_PrivateExtern; - } - /// hasGlobalStorage - Returns true for all variables that do not /// have local storage. This includs all global variables as well /// as static variables declared within a function. @@ -822,9 +828,15 @@ public: /// \brief Determines whether this variable is a variable with /// external, C linkage. - bool isExternC() const { - return getLanguageLinkage() == CLanguageLinkage; - } + bool isExternC() const; + + /// \brief Determines whether this variable's context is, or is nested within, + /// a C++ extern "C" linkage spec. + bool isInExternCContext() const; + + /// \brief Determines whether this variable's context is, or is nested within, + /// a C++ extern "C++" linkage spec. + bool isInExternCXXContext() const; /// isLocalVarDecl - Returns true for local variable declarations /// other than parameters. Note that this includes static variables @@ -1147,7 +1159,7 @@ public: ImplicitParamDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType Type) : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type, - /*tinfo*/ 0, SC_None, SC_None) { + /*tinfo*/ 0, SC_None) { setImplicit(); } @@ -1166,8 +1178,8 @@ protected: ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, Expr *DefArg) - : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S, SCAsWritten) { + StorageClass S, Expr *DefArg) + : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S) { assert(ParmVarDeclBits.HasInheritedDefaultArg == false); assert(ParmVarDeclBits.IsKNRPromoted == false); assert(ParmVarDeclBits.IsObjCMethodParam == false); @@ -1179,8 +1191,7 @@ public: SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, - Expr *DefArg); + StorageClass S, Expr *DefArg); static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1385,7 +1396,6 @@ private: // FIXME: This can be packed into the bitfields in Decl. // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum unsigned SClass : 2; - unsigned SClassAsWritten : 2; bool IsInline : 1; bool IsInlineSpecified : 1; bool IsVirtualAsWritten : 1; @@ -1475,13 +1485,13 @@ protected: FunctionDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified, + StorageClass S, bool isInlineSpecified, bool isConstexprSpecified) : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, StartLoc), DeclContext(DK), ParamInfo(0), Body(), - SClass(S), SClassAsWritten(SCAsWritten), + SClass(S), IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), @@ -1512,14 +1522,13 @@ public: SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass SC = SC_None, - StorageClass SCAsWritten = SC_None, + StorageClass SC, bool isInlineSpecified = false, bool hasWrittenPrototype = true, bool isConstexprSpecified = false) { DeclarationNameInfo NameInfo(N, NLoc); return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, - SC, SCAsWritten, + SC, isInlineSpecified, hasWrittenPrototype, isConstexprSpecified); } @@ -1528,10 +1537,9 @@ public: SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass SC = SC_None, - StorageClass SCAsWritten = SC_None, - bool isInlineSpecified = false, - bool hasWrittenPrototype = true, + StorageClass SC, + bool isInlineSpecified, + bool hasWrittenPrototype, bool isConstexprSpecified = false); static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1713,9 +1721,15 @@ public: /// \brief Determines whether this function is a function with /// external, C linkage. - bool isExternC() const { - return getLanguageLinkage() == CLanguageLinkage; - } + bool isExternC() const; + + /// \brief Determines whether this function's context is, or is nested within, + /// a C++ extern "C" linkage spec. + bool isInExternCContext() const; + + /// \brief Determines whether this function's context is, or is nested within, + /// a C++ extern "C++" linkage spec. + bool isInExternCXXContext() const; /// \brief Determines whether this is a global function. bool isGlobal() const; @@ -1783,12 +1797,9 @@ public: return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); } + /// \brief Returns the storage class as written in the source. For the + /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return StorageClass(SClass); } - void setStorageClass(StorageClass SC); - - StorageClass getStorageClassAsWritten() const { - return StorageClass(SClassAsWritten); - } /// \brief Determine whether the "inline" keyword was specified for this /// function. @@ -2416,7 +2427,7 @@ protected: bool IsScopedUsingClassTag : 1; /// IsFixed - True if this is an enumeration with fixed underlying type. Only - /// possible in C++11 or Microsoft extensions mode. + /// possible in C++11, Microsoft extensions, or Objective C mode. bool IsFixed : 1; /// \brief Indicates whether it is possible for declarations of this kind @@ -2802,18 +2813,18 @@ public: NumNegativeBits = Num; } - /// \brief Returns true if this is a C++0x scoped enumeration. + /// \brief Returns true if this is a C++11 scoped enumeration. bool isScoped() const { return IsScoped; } - /// \brief Returns true if this is a C++0x scoped enumeration. + /// \brief Returns true if this is a C++11 scoped enumeration. bool isScopedUsingClassTag() const { return IsScopedUsingClassTag; } - /// \brief Returns true if this is a C++0x enumeration with fixed underlying - /// type. + /// \brief Returns true if this is an Objective-C, C++11, or + /// Microsoft-style enumeration with a fixed underlying type. bool isFixed() const { return IsFixed; } @@ -3184,6 +3195,67 @@ public: } }; +/// \brief This represents the body of a CapturedStmt, and serves as its +/// DeclContext. +class CapturedDecl : public Decl, public DeclContext { +private: + /// \brief The number of parameters to the outlined function. + unsigned NumParams; + /// \brief The body of the outlined function. + Stmt *Body; + + explicit CapturedDecl(DeclContext *DC, unsigned NumParams) + : Decl(Captured, DC, SourceLocation()), DeclContext(Captured), + NumParams(NumParams), Body(0) { } + + ImplicitParamDecl **getParams() const { + return reinterpret_cast<ImplicitParamDecl **>( + const_cast<CapturedDecl *>(this) + 1); + } + +public: + static CapturedDecl *Create(ASTContext &C, DeclContext *DC, unsigned NumParams); + static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumParams); + + Stmt *getBody() const { return Body; } + void setBody(Stmt *B) { Body = B; } + + unsigned getNumParams() const { return NumParams; } + + ImplicitParamDecl *getParam(unsigned i) const { + assert(i < NumParams); + return getParams()[i]; + } + void setParam(unsigned i, ImplicitParamDecl *P) { + assert(i < NumParams); + getParams()[i] = P; + } + + /// \brief Retrieve the parameter containing captured variables. + ImplicitParamDecl *getContextParam() const { return getParam(0); } + void setContextParam(ImplicitParamDecl *P) { setParam(0, P); } + + typedef ImplicitParamDecl **param_iterator; + /// \brief Retrieve an iterator pointing to the first parameter decl. + param_iterator param_begin() const { return getParams(); } + /// \brief Retrieve an iterator one past the last parameter decl. + param_iterator param_end() const { return getParams() + NumParams; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Captured; } + static DeclContext *castToDeclContext(const CapturedDecl *D) { + return static_cast<DeclContext *>(const_cast<CapturedDecl *>(D)); + } + static CapturedDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<CapturedDecl *>(const_cast<DeclContext *>(DC)); + } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + /// \brief Describes a module import declaration, which makes the contents /// of the named module visible in the current translation unit. /// @@ -3303,8 +3375,8 @@ void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) { // First one will point to this one as latest. First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); - if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this))) - ND->ClearLinkageCache(); + assert(!isa<NamedDecl>(static_cast<decl_type*>(this)) || + cast<NamedDecl>(static_cast<decl_type*>(this))->isLinkageValid()); } // Inline function definitions. diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 3248d23f42..754facfb59 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -135,7 +135,7 @@ public: /// or member ends up here. IDNS_Ordinary = 0x0020, - /// Objective C @protocol. + /// Objective C \@protocol. IDNS_ObjCProtocol = 0x0040, /// This declaration is a friend function. A friend function @@ -372,10 +372,13 @@ public: return const_cast<Decl*>(this)->getDeclContext(); } - /// Finds the innermost non-closure context of this declaration. - /// That is, walk out the DeclContext chain, skipping any blocks. - DeclContext *getNonClosureContext(); - const DeclContext *getNonClosureContext() const { + /// Find the innermost non-closure ancestor of this declaration, + /// walking up through blocks, lambdas, etc. If that ancestor is + /// not a code context (!isFunctionOrMethod()), returns null. + /// + /// A declaration may be its own non-closure context. + Decl *getNonClosureContext(); + const Decl *getNonClosureContext() const { return const_cast<Decl*>(this)->getNonClosureContext(); } @@ -402,6 +405,12 @@ public: return AccessSpecifier(Access); } + /// \brief Retrieve the access specifier for this declaration, even though + /// it may not yet have been properly set. + AccessSpecifier getAccessUnsafe() const { + return AccessSpecifier(Access); + } + bool hasAttrs() const { return HasAttrs; } void setAttrs(const AttrVec& Attrs) { return setAttrsImpl(Attrs, getASTContext()); @@ -1040,6 +1049,7 @@ public: bool isFunctionOrMethod() const { switch (DeclKind) { case Decl::Block: + case Decl::Captured: case Decl::ObjCMethod: return true; default: @@ -1086,14 +1096,6 @@ public: /// C++0x scoped enums), and C++ linkage specifications. bool isTransparentContext() const; - /// \brief Determines whether this context is, or is nested within, - /// a C++ extern "C" linkage spec. - bool isExternCContext() const; - - /// \brief Determines whether this context is, or is nested within, - /// a C++ extern "C++" linkage spec. - bool isExternCXXContext() const; - /// \brief Determine whether this declaration context is equivalent /// to the declaration context DC. bool Equals(const DeclContext *DC) const { @@ -1107,8 +1109,8 @@ public: /// \brief Find the nearest non-closure ancestor of this context, /// i.e. the innermost semantic parent of this context which is not /// a closure. A context may be its own non-closure ancestor. - DeclContext *getNonClosureAncestor(); - const DeclContext *getNonClosureAncestor() const { + Decl *getNonClosureAncestor(); + const Decl *getNonClosureAncestor() const { return const_cast<DeclContext*>(this)->getNonClosureAncestor(); } @@ -1402,6 +1404,9 @@ public: /// @brief Removes a declaration from this context. void removeDecl(Decl *D); + + /// @brief Checks whether a declaration is in this context. + bool containsDecl(Decl *D) const; /// lookup_iterator - An iterator that provides access to the results /// of looking up a name within this context. diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 70d8c33608..c483dde1f5 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -69,17 +69,6 @@ public: } // end namespace clang namespace llvm { - /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from - /// AnyFunctionDecl to any function or function template declaration. - template<> struct simplify_type<const ::clang::AnyFunctionDecl> { - typedef ::clang::NamedDecl* SimpleType; - static SimpleType getSimplifiedValue(const ::clang::AnyFunctionDecl &Val) { - return Val; - } - }; - template<> struct simplify_type< ::clang::AnyFunctionDecl> - : public simplify_type<const ::clang::AnyFunctionDecl> {}; - // Provide PointerLikeTypeTraits for non-cvr pointers. template<> class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> { @@ -265,6 +254,16 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; +/// The inheritance model to use for member pointers of a given CXXRecordDecl. +enum MSInheritanceModel { + MSIM_Single, + MSIM_SinglePolymorphic, + MSIM_Multiple, + MSIM_MultiplePolymorphic, + MSIM_Virtual, + MSIM_Unspecified +}; + /// CXXRecordDecl - Represents a C++ struct/union/class. /// FIXME: This class will disappear once we've properly taught RecordDecl /// to deal with C++-specific things. @@ -1543,6 +1542,9 @@ public: getLambdaData().ContextDecl = ContextDecl; } + /// \brief Returns the inheritance model used for this record. + MSInheritanceModel getMSInheritanceModel() const; + /// \brief Determine whether this lambda expression was known to be dependent /// at the time it was created, even if its context does not appear to be /// dependent. @@ -1581,11 +1583,10 @@ protected: CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic, StorageClass SCAsWritten, bool isInline, + StorageClass SC, bool isInline, bool isConstexpr, SourceLocation EndLocation) : FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo, - (isStatic ? SC_Static : SC_None), - SCAsWritten, isInline, isConstexpr) { + SC, isInline, isConstexpr) { if (EndLocation.isValid()) setRangeEnd(EndLocation); } @@ -1595,15 +1596,14 @@ public: SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic, - StorageClass SCAsWritten, + StorageClass SC, bool isInline, bool isConstexpr, SourceLocation EndLocation); static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - bool isStatic() const { return getStorageClass() == SC_Static; } + + bool isStatic() const; bool isInstance() const { return !isStatic(); } bool isConst() const { return getType()->castAs<FunctionType>()->isConst(); } @@ -1754,8 +1754,6 @@ class CXXCtorInitializer { /// \brief The argument used to initialize the base or member, which may /// end up constructing an object (when multiple arguments are involved). - /// If 0, this is a field initializer, and the in-class member initializer - /// will be used. Stmt *Init; /// LParenLoc - Location of the left paren of the ctor-initializer. @@ -1840,7 +1838,7 @@ public: /// implicit ctor initializer generated for a field with an initializer /// defined on the member declaration. bool isInClassMemberInitializer() const { - return !Init; + return isa<CXXDefaultInitExpr>(Init); } /// isDelegatingInitializer - Returns true when this initializer is creating @@ -1967,14 +1965,8 @@ public: getNumArrayIndices()); } - /// \brief Get the initializer. This is 0 if this is an in-class initializer - /// for a non-static data member which has not yet been parsed. - Expr *getInit() const { - if (!Init) - return getAnyMember()->getInClassInitializer(); - - return static_cast<Expr*>(Init); - } + /// \brief Get the initializer. + Expr *getInit() const { return static_cast<Expr*>(Init); } }; /// CXXConstructorDecl - Represents a C++ constructor within a @@ -2011,7 +2003,7 @@ class CXXConstructorDecl : public CXXMethodDecl { QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared, bool isConstexpr) - : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false, + : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, SourceLocation()), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), CtorInitializers(0), NumCtorInitializers(0) { @@ -2230,7 +2222,7 @@ class CXXDestructorDecl : public CXXMethodDecl { const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, false, + : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, /*isConstexpr=*/false, SourceLocation()), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); @@ -2297,7 +2289,7 @@ class CXXConversionDecl : public CXXMethodDecl { QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicitSpecified, bool isConstexpr, SourceLocation EndLocation) - : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, false, + : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, EndLocation), IsExplicitSpecified(isExplicitSpecified) { } @@ -2359,38 +2351,49 @@ public: }; private: /// Language - The language for this linkage specification. - LanguageIDs Language; + unsigned Language : 3; + /// True if this linkage spec has brances. This is needed so that hasBraces() + /// returns the correct result while the linkage spec body is being parsed. + /// Once RBraceLoc has been set this is not used, so it doesn't need to be + /// serialized. + unsigned HasBraces : 1; /// ExternLoc - The source location for the extern keyword. SourceLocation ExternLoc; /// RBraceLoc - The source location for the right brace (if valid). SourceLocation RBraceLoc; LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, - SourceLocation LangLoc, LanguageIDs lang, - SourceLocation RBLoc) + SourceLocation LangLoc, LanguageIDs lang, bool HasBraces) : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec), - Language(lang), ExternLoc(ExternLoc), RBraceLoc(RBLoc) { } + Language(lang), HasBraces(HasBraces), ExternLoc(ExternLoc), + RBraceLoc(SourceLocation()) { } public: static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation ExternLoc, SourceLocation LangLoc, LanguageIDs Lang, - SourceLocation RBraceLoc = SourceLocation()); + bool HasBraces); static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// \brief Return the language specified by this linkage specification. - LanguageIDs getLanguage() const { return Language; } + LanguageIDs getLanguage() const { return LanguageIDs(Language); } /// \brief Set the language specified by this linkage specification. void setLanguage(LanguageIDs L) { Language = L; } /// \brief Determines whether this linkage specification had braces in /// its syntactic form. - bool hasBraces() const { return RBraceLoc.isValid(); } + bool hasBraces() const { + assert(!RBraceLoc.isValid() || HasBraces); + return HasBraces; + } SourceLocation getExternLoc() const { return ExternLoc; } SourceLocation getRBraceLoc() const { return RBraceLoc; } void setExternLoc(SourceLocation L) { ExternLoc = L; } - void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + void setRBraceLoc(SourceLocation L) { + RBraceLoc = L; + HasBraces = RBraceLoc.isValid(); + } SourceLocation getLocEnd() const LLVM_READONLY { if (hasBraces()) @@ -2984,6 +2987,56 @@ public: friend class ASTDeclReader; }; +/// An instance of this class represents the declaration of a property +/// member. This is a Microsoft extension to C++, first introduced in +/// Visual Studio .NET 2003 as a parallel to similar features in C# +/// and Managed C++. +/// +/// A property must always be a non-static class member. +/// +/// A property member superficially resembles a non-static data +/// member, except preceded by a property attribute: +/// __declspec(property(get=GetX, put=PutX)) int x; +/// Either (but not both) of the 'get' and 'put' names may be omitted. +/// +/// A reference to a property is always an lvalue. If the lvalue +/// undergoes lvalue-to-rvalue conversion, then a getter name is +/// required, and that member is called with no arguments. +/// If the lvalue is assigned into, then a setter name is required, +/// and that member is called with one argument, the value assigned. +/// Both operations are potentially overloaded. Compound assignments +/// are permitted, as are the increment and decrement operators. +/// +/// The getter and putter methods are permitted to be overloaded, +/// although their return and parameter types are subject to certain +/// restrictions according to the type of the property. +/// +/// A property declared using an incomplete array type may +/// additionally be subscripted, adding extra parameters to the getter +/// and putter methods. +class MSPropertyDecl : public DeclaratorDecl { + IdentifierInfo *GetterId, *SetterId; + +public: + MSPropertyDecl(DeclContext *DC, SourceLocation L, + DeclarationName N, QualType T, TypeSourceInfo *TInfo, + SourceLocation StartL, IdentifierInfo *Getter, + IdentifierInfo *Setter): + DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL), GetterId(Getter), + SetterId(Setter) {} + + static MSPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + static bool classof(const Decl *D) { return D->getKind() == MSProperty; } + + bool hasGetter() const { return GetterId != NULL; } + IdentifierInfo* getGetterId() const { return GetterId; } + bool hasSetter() const { return SetterId != NULL; } + IdentifierInfo* getSetterId() const { return SetterId; } + + friend class ASTDeclReader; +}; + /// Insertion operator for diagnostics. This allows sending an AccessSpecifier /// into a diagnostic with <<. const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 253c23c199..3a12878e74 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -101,7 +101,7 @@ public: SourceLocation L, FriendUnion Friend_, SourceLocation FriendL, ArrayRef<TemplateParameterList*> FriendTypeTPLists - = ArrayRef<TemplateParameterList*>()); + = None); static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID, unsigned FriendTypeNumTPLists); diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 43f255fd04..40de0135a7 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -537,13 +537,16 @@ public: } // Get the local instance/class method declared in this interface. - ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const; - ObjCMethodDecl *getInstanceMethod(Selector Sel) const { - return getMethod(Sel, true/*isInstance*/); + ObjCMethodDecl *getMethod(Selector Sel, bool isInstance, + bool AllowHidden = false) const; + ObjCMethodDecl *getInstanceMethod(Selector Sel, + bool AllowHidden = false) const { + return getMethod(Sel, true/*isInstance*/, AllowHidden); } - ObjCMethodDecl *getClassMethod(Selector Sel) const { - return getMethod(Sel, false/*isInstance*/); + ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const { + return getMethod(Sel, false/*isInstance*/, AllowHidden); } + bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const; ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; @@ -1133,7 +1136,8 @@ public: // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, - bool shallowCategoryLookup= false) const; + bool shallowCategoryLookup= false, + const ObjCCategoryDecl *C= 0) const; ObjCMethodDecl *lookupInstanceMethod(Selector Sel, bool shallowCategoryLookup = false) const { return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup); @@ -1152,6 +1156,15 @@ public: return lookupPrivateMethod(Sel, false); } + /// \brief Lookup a setter or getter in the class hierarchy, + /// including in all categories except for category passed + /// as argument. + ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel, + const ObjCCategoryDecl *Cat) const { + return lookupMethod(Sel, true/*isInstance*/, + false/*shallowCategoryLookup*/, Cat); + } + SourceLocation getEndOfDefinitionLoc() const { if (!hasDefinition()) return getLocation(); @@ -1785,6 +1798,8 @@ class ObjCImplementationDecl : public ObjCImplDecl { virtual void anchor(); /// Implementation Class's super class. ObjCInterfaceDecl *SuperClass; + SourceLocation SuperLoc; + /// \@implementation may have private ivars. SourceLocation IvarLBraceLoc; SourceLocation IvarRBraceLoc; @@ -1805,10 +1820,11 @@ class ObjCImplementationDecl : public ObjCImplDecl { ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl, SourceLocation nameLoc, SourceLocation atStartLoc, + SourceLocation superLoc = SourceLocation(), SourceLocation IvarLBraceLoc=SourceLocation(), SourceLocation IvarRBraceLoc=SourceLocation()) : ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc), - SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc), + SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc), IvarInitializers(0), NumIvarInitializers(0), HasNonZeroConstructors(false), HasDestructors(false) {} @@ -1818,6 +1834,7 @@ public: ObjCInterfaceDecl *superDecl, SourceLocation nameLoc, SourceLocation atStartLoc, + SourceLocation superLoc = SourceLocation(), SourceLocation IvarLBraceLoc=SourceLocation(), SourceLocation IvarRBraceLoc=SourceLocation()); @@ -1890,6 +1907,7 @@ public: const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } ObjCInterfaceDecl *getSuperClass() { return SuperClass; } + SourceLocation getSuperClassLoc() const { return SuperLoc; } void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h new file mode 100644 index 0000000000..ca92040c32 --- /dev/null +++ b/include/clang/AST/DeclOpenMP.h @@ -0,0 +1,83 @@ +//===--- OpenMP.h - Classes for representing OpenMP directives ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file defines OpenMP nodes. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_OPENMP_H +#define LLVM_CLANG_AST_OPENMP_H + +#include "clang/AST/DeclBase.h" +#include "llvm/ADT/ArrayRef.h" + +namespace clang { + +class DeclRefExpr; + +/// \brief This represents '#pragma omp threadprivate ...' directive. +/// For example, in the following, both 'a' and 'A::b' are threadprivate: +/// +/// \code +/// int a; +/// #pragma omp threadprivate(a) +/// struct A { +/// static int b; +/// #pragma omp threadprivate(b) +/// }; +/// \endcode +/// +class OMPThreadPrivateDecl : public Decl { + friend class ASTDeclReader; + unsigned NumVars; + + virtual void anchor(); + + OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) : + Decl(DK, DC, L), NumVars(0) { } + + ArrayRef<const DeclRefExpr *> getVars() const { + return ArrayRef<const DeclRefExpr *>( + reinterpret_cast<const DeclRefExpr * const *>(this + 1), + NumVars); + } + + llvm::MutableArrayRef<DeclRefExpr *> getVars() { + return llvm::MutableArrayRef<DeclRefExpr *>( + reinterpret_cast<DeclRefExpr **>(this + 1), + NumVars); + } + + void setVars(ArrayRef<DeclRefExpr *> VL); + +public: + static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + ArrayRef<DeclRefExpr *> VL); + static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, + unsigned ID, unsigned N); + + typedef llvm::MutableArrayRef<DeclRefExpr *>::iterator varlist_iterator; + typedef ArrayRef<const DeclRefExpr *>::iterator varlist_const_iterator; + + unsigned varlist_size() const { return NumVars; } + bool varlist_empty() const { return NumVars == 0; } + varlist_iterator varlist_begin() { return getVars().begin(); } + varlist_iterator varlist_end() { return getVars().end(); } + varlist_const_iterator varlist_begin() const { return getVars().begin(); } + varlist_const_iterator varlist_end() const { return getVars().end(); } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == OMPThreadPrivate; } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 525a156a93..425a617738 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -458,18 +458,19 @@ public: /// }; /// \endcode class DependentFunctionTemplateSpecializationInfo { + struct CA { + /// The number of potential template candidates. + unsigned NumTemplates; + + /// The number of template arguments. + unsigned NumArgs; + }; + union { // Force sizeof to be a multiple of sizeof(void*) so that the // trailing data is aligned. void *Aligner; - - struct { - /// The number of potential template candidates. - unsigned NumTemplates; - - /// The number of template arguments. - unsigned NumArgs; - } d; + struct CA d; }; /// The locations of the left and right angle brackets. diff --git a/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h index 67be74bfdc..4eaae35778 100644 --- a/include/clang/AST/DeclVisitor.h +++ b/include/clang/AST/DeclVisitor.h @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" namespace clang { diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index d302db48b3..f28882b3bf 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -382,32 +382,35 @@ public: /// for a declaration name. Needs a DeclarationName in order /// to be interpreted correctly. struct DeclarationNameLoc { + // The source location for identifier stored elsewhere. + // struct {} Identifier; + + // Type info for constructors, destructors and conversion functions. + // Locations (if any) for the tilde (destructor) or operator keyword + // (conversion) are stored elsewhere. + struct NT { + TypeSourceInfo* TInfo; + }; + + // The location (if any) of the operator keyword is stored elsewhere. + struct CXXOpName { + unsigned BeginOpNameLoc; + unsigned EndOpNameLoc; + }; + + // The location (if any) of the operator keyword is stored elsewhere. + struct CXXLitOpName { + unsigned OpNameLoc; + }; + + // struct {} CXXUsingDirective; + // struct {} ObjCZeroArgSelector; + // struct {} ObjCOneArgSelector; + // struct {} ObjCMultiArgSelector; union { - // The source location for identifier stored elsewhere. - // struct {} Identifier; - - // Type info for constructors, destructors and conversion functions. - // Locations (if any) for the tilde (destructor) or operator keyword - // (conversion) are stored elsewhere. - struct { - TypeSourceInfo* TInfo; - } NamedType; - - // The location (if any) of the operator keyword is stored elsewhere. - struct { - unsigned BeginOpNameLoc; - unsigned EndOpNameLoc; - } CXXOperatorName; - - // The location (if any) of the operator keyword is stored elsewhere. - struct { - unsigned OpNameLoc; - } CXXLiteralOperatorName; - - // struct {} CXXUsingDirective; - // struct {} ObjCZeroArgSelector; - // struct {} ObjCOneArgSelector; - // struct {} ObjCMultiArgSelector; + struct NT NamedType; + struct CXXOpName CXXOperatorName; + struct CXXLitOpName CXXLiteralOperatorName; }; DeclarationNameLoc(DeclarationName Name); diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h index cb556ef1eb..004b45da0f 100644 --- a/include/clang/AST/DependentDiagnostic.h +++ b/include/clang/AST/DependentDiagnostic.h @@ -108,16 +108,14 @@ private: PartialDiagnostic Diag; - union { - struct { - unsigned Loc; - unsigned Access : 2; - unsigned IsMember : 1; - NamedDecl *TargetDecl; - CXXRecordDecl *NamingClass; - void *BaseObjectType; - } AccessData; - }; + struct { + unsigned Loc; + unsigned Access : 2; + unsigned IsMember : 1; + NamedDecl *TargetDecl; + CXXRecordDecl *NamingClass; + void *BaseObjectType; + } AccessData; }; /// diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index eb186c217e..2e3cbfad91 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -55,7 +55,7 @@ public: // Only the selected subexpression matters; the other one is not evaluated. return this->Visit(E->getChosenSubExpr(Context)); } - + void VisitDesignatedInitExpr(DesignatedInitExpr *E) { // Only the actual initializer matters; the designators are all constant // expressions. @@ -72,6 +72,15 @@ public: return static_cast<ImplClass*>(this)->VisitExpr(CE); } + void VisitLambdaExpr(LambdaExpr *LE) { + // Only visit the capture initializers, and not the body. + for (LambdaExpr::capture_init_iterator I = LE->capture_init_begin(), + E = LE->capture_init_end(); + I != E; ++I) + if (*I) + this->Visit(*I); + } + /// \brief The basis case walks all of the children of the statement or /// expression, assuming they are all potentially evaluated. void VisitStmt(Stmt *S) { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 9c5ea56f5e..4ff1257b7d 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -60,18 +60,21 @@ struct SubobjectAdjustment { MemberPointerAdjustment } Kind; - union { - struct { - const CastExpr *BasePath; - const CXXRecordDecl *DerivedClass; - } DerivedToBase; - FieldDecl *Field; + struct DTB { + const CastExpr *BasePath; + const CXXRecordDecl *DerivedClass; + }; + + struct P { + const MemberPointerType *MPT; + Expr *RHS; + }; - struct { - const MemberPointerType *MPT; - Expr *RHS; - } Ptr; + union { + struct DTB DerivedToBase; + FieldDecl *Field; + struct P Ptr; }; SubobjectAdjustment(const CastExpr *BasePath, @@ -424,12 +427,24 @@ private: public: + /// \brief Returns true if this expression is a gl-value that + /// potentially refers to a bit-field. + /// + /// In C++, whether a gl-value refers to a bitfield is essentially + /// an aspect of the value-kind type system. + bool refersToBitField() const { return getObjectKind() == OK_BitField; } + /// \brief If this expression refers to a bit-field, retrieve the /// declaration of that bit-field. - FieldDecl *getBitField(); + /// + /// Note that this returns a non-null pointer in subtly different + /// places than refersToBitField returns true. In particular, this can + /// return a non-null pointer even for r-values loaded from + /// bit-fields, but it will return null for a conditional bit-field. + FieldDecl *getSourceBitField(); - const FieldDecl *getBitField() const { - return const_cast<Expr*>(this)->getBitField(); + const FieldDecl *getSourceBitField() const { + return const_cast<Expr*>(this)->getSourceBitField(); } /// \brief If this expression is an l-value for an Objective C @@ -2641,7 +2656,7 @@ protected: (ty->isInstantiationDependentType() || (op && op->isInstantiationDependent())), (ty->containsUnexpandedParameterPack() || - op->containsUnexpandedParameterPack())), + (op && op->containsUnexpandedParameterPack()))), Op(op) { assert(kind != CK_Invalid && "creating cast with invalid cast kind"); CastExprBits.Kind = kind; @@ -2897,7 +2912,7 @@ public: SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; assert(!isCompoundAssignmentOp() && - "Use ArithAssignBinaryOperator for compound assignments"); + "Use CompoundAssignOperator for compound assignments"); } /// \brief Construct an empty binary operator. @@ -2957,6 +2972,33 @@ public: static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; } bool isComparisonOp() const { return isComparisonOp(getOpcode()); } + static Opcode negateComparisonOp(Opcode Opc) { + switch (Opc) { + default: + llvm_unreachable("Not a comparsion operator."); + case BO_LT: return BO_GE; + case BO_GT: return BO_LE; + case BO_LE: return BO_GT; + case BO_GE: return BO_LT; + case BO_EQ: return BO_NE; + case BO_NE: return BO_EQ; + } + } + + static Opcode reverseComparisonOp(Opcode Opc) { + switch (Opc) { + default: + llvm_unreachable("Not a comparsion operator."); + case BO_LT: return BO_GT; + case BO_GT: return BO_LT; + case BO_LE: return BO_GE; + case BO_GE: return BO_LE; + case BO_EQ: + case BO_NE: + return Opc; + } + } + static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; } bool isLogicalOp() const { return isLogicalOp(getOpcode()); } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 04f6fb64cf..91e5b21eac 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -29,6 +29,7 @@ class CXXConstructorDecl; class CXXDestructorDecl; class CXXMethodDecl; class CXXTemporary; +class MSPropertyDecl; class TemplateArgumentListInfo; class UuidAttr; @@ -560,6 +561,64 @@ public: } }; +/// A member reference to an MSPropertyDecl. This expression always +/// has pseudo-object type, and therefore it is typically not +/// encountered in a fully-typechecked expression except within the +/// syntactic form of a PseudoObjectExpr. +class MSPropertyRefExpr : public Expr { + Expr *BaseExpr; + MSPropertyDecl *TheDecl; + SourceLocation MemberLoc; + bool IsArrow; + NestedNameSpecifierLoc QualifierLoc; + +public: + MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow, + QualType ty, ExprValueKind VK, + NestedNameSpecifierLoc qualifierLoc, + SourceLocation nameLoc) + : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary, + /*type-dependent*/ false, baseExpr->isValueDependent(), + baseExpr->isInstantiationDependent(), + baseExpr->containsUnexpandedParameterPack()), + BaseExpr(baseExpr), TheDecl(decl), + MemberLoc(nameLoc), IsArrow(isArrow), + QualifierLoc(qualifierLoc) {} + + MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {} + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(getLocStart(), getLocEnd()); + } + bool isImplicitAccess() const { + return getBaseExpr() && getBaseExpr()->isImplicitCXXThis(); + } + SourceLocation getLocStart() const { + if (!isImplicitAccess()) + return BaseExpr->getLocStart(); + else if (QualifierLoc) + return QualifierLoc.getBeginLoc(); + else + return MemberLoc; + } + SourceLocation getLocEnd() const { return getMemberLoc(); } + + child_range children() { + return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == MSPropertyRefExprClass; + } + + Expr *getBaseExpr() const { return BaseExpr; } + MSPropertyDecl *getPropertyDecl() const { return TheDecl; } + bool isArrow() const { return IsArrow; } + SourceLocation getMemberLoc() const { return MemberLoc; } + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + friend class ASTStmtReader; +}; + /// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets /// the _GUID that corresponds to the supplied type or expression. /// @@ -825,6 +884,53 @@ public: friend class ASTStmtWriter; }; +/// \brief This wraps a use of a C++ default initializer (technically, +/// a brace-or-equal-initializer for a non-static data member) when it +/// is implicitly used in a mem-initializer-list in a constructor +/// (C++11 [class.base.init]p8) or in aggregate initialization +/// (C++1y [dcl.init.aggr]p7). +class CXXDefaultInitExpr : public Expr { + /// \brief The field whose default is being used. + FieldDecl *Field; + + /// \brief The location where the default initializer expression was used. + SourceLocation Loc; + + CXXDefaultInitExpr(ASTContext &C, SourceLocation Loc, FieldDecl *Field, + QualType T); + + CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {} + +public: + // Field is the non-static data member whose default initializer is used + // by this expression. + static CXXDefaultInitExpr *Create(ASTContext &C, SourceLocation Loc, + FieldDecl *Field) { + return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType()); + } + + // Get the field whose initializer will be used. + FieldDecl *getField() { return Field; } + const FieldDecl *getField() const { return Field; } + + // Get the initialization expression that will be used. + const Expr *getExpr() const { return Field->getInClassInitializer(); } + Expr *getExpr() { return Field->getInClassInitializer(); } + + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDefaultInitExprClass; + } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTReader; + friend class ASTStmtReader; +}; + /// CXXTemporary - Represents a C++ temporary. class CXXTemporary { /// Destructor - The destructor that needs to be called. diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index b6bf006645..a94c69a115 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -211,7 +211,13 @@ struct ObjCDictionaryElement { /// \brief Determines whether this dictionary element is a pack expansion. bool isPackExpansion() const { return EllipsisLoc.isValid(); } }; +} // end namespace clang +namespace llvm { +template <> struct isPodLike<clang::ObjCDictionaryElement> : llvm::true_type {}; +} + +namespace clang { /// ObjCDictionaryLiteral - AST node to represent objective-c dictionary /// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] }; class ObjCDictionaryLiteral : public Expr { @@ -411,9 +417,13 @@ public: child_range children() { return child_range(); } }; -/// ObjCProtocolExpr used for protocol expression in Objective-C. This is used -/// as: @protocol(foo), as in: -/// obj conformsToProtocol:@protocol(foo)] +/// ObjCProtocolExpr used for protocol expression in Objective-C. +/// +/// This is used as: \@protocol(foo), as in: +/// \code +/// [obj conformsToProtocol:@protocol(foo)] +/// \endcode +/// /// The return type is "Protocol*". class ObjCProtocolExpr : public Expr { ObjCProtocolDecl *TheProtocol; @@ -455,18 +465,24 @@ class ObjCIvarRefExpr : public Expr { ObjCIvarDecl *D; Stmt *Base; SourceLocation Loc; + /// OpLoc - This is the location of '.' or '->' + SourceLocation OpLoc; + bool IsArrow:1; // True if this is "X->F", false if this is "X.F". bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). public: ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, - SourceLocation l, Expr *base, + SourceLocation l, SourceLocation oploc, + Expr *base, bool arrow = false, bool freeIvar = false) : - Expr(ObjCIvarRefExprClass, t, VK_LValue, OK_Ordinary, + Expr(ObjCIvarRefExprClass, t, VK_LValue, + d->isBitField() ? OK_BitField : OK_Ordinary, /*TypeDependent=*/false, base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), - D(d), Base(base), Loc(l), IsArrow(arrow), IsFreeIvar(freeIvar) {} + D(d), Base(base), Loc(l), OpLoc(oploc), + IsArrow(arrow), IsFreeIvar(freeIvar) {} explicit ObjCIvarRefExpr(EmptyShell Empty) : Expr(ObjCIvarRefExprClass, Empty) {} @@ -491,6 +507,9 @@ public: return isFreeIvar() ? Loc : getBase()->getLocStart(); } SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + + SourceLocation getOpLoc() const { return OpLoc; } + void setOpLoc(SourceLocation L) { OpLoc = L; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIvarRefExprClass; @@ -1374,16 +1393,20 @@ class ObjCIsaExpr : public Expr { /// IsaMemberLoc - This is the location of the 'isa'. SourceLocation IsaMemberLoc; + + /// OpLoc - This is the location of '.' or '->' + SourceLocation OpLoc; /// IsArrow - True if this is "X->F", false if this is "X.F". bool IsArrow; public: - ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) + ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc, + QualType ty) : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary, /*TypeDependent=*/false, base->isValueDependent(), base->isInstantiationDependent(), /*ContainsUnexpandedParameterPack=*/false), - Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} + Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {} /// \brief Build an empty expression. explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { } @@ -1398,10 +1421,18 @@ public: /// location of 'F'. SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; } void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; } + + SourceLocation getOpLoc() const { return OpLoc; } + void setOpLoc(SourceLocation L) { OpLoc = L; } SourceLocation getLocStart() const LLVM_READONLY { return getBase()->getLocStart(); } + + SourceLocation getBaseLocEnd() const LLVM_READONLY { + return getBase()->getLocEnd(); + } + SourceLocation getLocEnd() const LLVM_READONLY { return IsaMemberLoc; } SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; } diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index 94faa19f1b..b6d22cfb5f 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -141,6 +141,16 @@ public: raw_ostream &) { llvm_unreachable("Target does not support mangling guard variables"); } + // FIXME: Revisit this once we know what we need to do for MSVC compatibility. + virtual void mangleItaniumThreadLocalInit(const VarDecl *D, + raw_ostream &) { + llvm_unreachable("Target does not support mangling thread_local variables"); + } + virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D, + raw_ostream &) { + llvm_unreachable("Target does not support mangling thread_local variables"); + } + /// @} }; diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h index 3a8b2183a5..84a6e96fa0 100644 --- a/include/clang/AST/RawCommentList.h +++ b/include/clang/AST/RawCommentList.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_AST_RAW_COMMENT_LIST_H #define LLVM_CLANG_AST_RAW_COMMENT_LIST_H +#include "clang/Basic/CommentOptions.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/ArrayRef.h" @@ -40,7 +41,7 @@ public: RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { } RawComment(const SourceManager &SourceMgr, SourceRange SR, - bool Merged = false); + bool Merged, bool ParseAllComments); CommentKind getKind() const LLVM_READONLY { return (CommentKind) Kind; @@ -82,7 +83,8 @@ public: /// Returns true if this comment is not a documentation comment. bool isOrdinary() const LLVM_READONLY { - return (Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC); + return ((Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC)) && + !ParseAllComments; } /// Returns true if this comment any kind of a documentation comment. @@ -90,6 +92,11 @@ public: return !isInvalid() && !isOrdinary(); } + /// Returns whether we are parsing all comments. + bool isParseAllComments() const LLVM_READONLY { + return ParseAllComments; + } + /// Returns raw comment text with comment markers. StringRef getRawText(const SourceManager &SourceMgr) const { if (RawTextValid) @@ -135,6 +142,10 @@ private: bool IsTrailingComment : 1; bool IsAlmostTrailingComment : 1; + /// When true, ordinary comments starting with "//" and "/*" will be + /// considered as documentation comments. + bool ParseAllComments : 1; + mutable bool BeginLineValid : 1; ///< True if BeginLine is valid mutable bool EndLineValid : 1; ///< True if EndLine is valid mutable unsigned BeginLine; ///< Cached line number @@ -142,10 +153,12 @@ private: /// \brief Constructor for AST deserialization. RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment, - bool IsAlmostTrailingComment) : + bool IsAlmostTrailingComment, + bool ParseAllComments) : Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K), IsAttached(false), IsTrailingComment(IsTrailingComment), IsAlmostTrailingComment(IsAlmostTrailingComment), + ParseAllComments(ParseAllComments), BeginLineValid(false), EndLineValid(false) { } @@ -207,4 +220,3 @@ private: } // end namespace clang #endif - diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 480263e943..b5a4b5e36d 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -18,6 +18,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -1227,8 +1228,9 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { for (DeclContext::decl_iterator Child = DC->decls_begin(), ChildEnd = DC->decls_end(); Child != ChildEnd; ++Child) { - // BlockDecls are traversed through BlockExprs. - if (!isa<BlockDecl>(*Child)) + // BlockDecls and CapturedDecls are traversed through BlockExprs and + // CapturedStmts respectively. + if (!isa<BlockDecl>(*Child) && !isa<CapturedDecl>(*Child)) TRY_TO(TraverseDecl(*Child)); } @@ -1257,6 +1259,14 @@ DEF_TRAVERSE_DECL(BlockDecl, { return true; }) +DEF_TRAVERSE_DECL(CapturedDecl, { + TRY_TO(TraverseStmt(D->getBody())); + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; + }) + DEF_TRAVERSE_DECL(EmptyDecl, { }) DEF_TRAVERSE_DECL(FileScopeAsmDecl, { @@ -1389,6 +1399,14 @@ DEF_TRAVERSE_DECL(UsingDirectiveDecl, { DEF_TRAVERSE_DECL(UsingShadowDecl, { }) +DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { + for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), + E = D->varlist_end(); + I != E; ++I) { + TRY_TO(TraverseStmt(*I)); + } + }) + // A helper method for TemplateDecl's children. template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( @@ -1662,6 +1680,10 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { return true; } +DEF_TRAVERSE_DECL(MSPropertyDecl, { + TRY_TO(TraverseDeclaratorHelper(D)); + }) + DEF_TRAVERSE_DECL(FieldDecl, { TRY_TO(TraverseDeclaratorHelper(D)); if (D->isBitField()) @@ -2049,6 +2071,10 @@ DEF_TRAVERSE_STMT(CXXTypeidExpr, { TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(MSPropertyRefExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); +}) + DEF_TRAVERSE_STMT(CXXUuidofExpr, { // The child-iterator will pick up the arg if it's an expression, // but not if it's a type. @@ -2144,6 +2170,7 @@ DEF_TRAVERSE_STMT(CompoundLiteralExpr, { DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { }) +DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { }) DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) DEF_TRAVERSE_STMT(ExprWithCleanups, { }) DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) @@ -2168,7 +2195,10 @@ DEF_TRAVERSE_STMT(ObjCEncodeExpr, { }) DEF_TRAVERSE_STMT(ObjCIsaExpr, { }) DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { }) -DEF_TRAVERSE_STMT(ObjCMessageExpr, { }) +DEF_TRAVERSE_STMT(ObjCMessageExpr, { + if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); +}) DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { }) DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, { }) DEF_TRAVERSE_STMT(ObjCProtocolExpr, { }) @@ -2201,6 +2231,9 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { DEF_TRAVERSE_STMT(SEHTryStmt, {}) DEF_TRAVERSE_STMT(SEHExceptStmt, {}) DEF_TRAVERSE_STMT(SEHFinallyStmt,{}) +DEF_TRAVERSE_STMT(CapturedStmt, { + TRY_TO(TraverseDecl(S->getCapturedDecl())); +}) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { }) DEF_TRAVERSE_STMT(OpaqueValueExpr, { }) diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index cf8fc249c5..74c9ec2053 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -16,10 +16,12 @@ #include "clang/AST/DeclGroup.h" #include "clang/AST/StmtIterator.h" +#include "clang/Basic/CapturedStmt.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include <string> @@ -31,6 +33,7 @@ namespace llvm { namespace clang { class ASTContext; class Attr; + class CapturedDecl; class Decl; class Expr; class IdentifierInfo; @@ -39,6 +42,7 @@ namespace clang { class PrinterHelper; struct PrintingPolicy; class QualType; + class RecordDecl; class SourceManager; class StringLiteral; class SwitchStmt; @@ -1384,7 +1388,6 @@ protected: unsigned NumInputs; unsigned NumClobbers; - IdentifierInfo **Names; Stmt **Exprs; AsmStmt(StmtClass SC, SourceLocation asmloc, bool issimple, bool isvolatile, @@ -1392,10 +1395,12 @@ protected: Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile), NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { } + friend class ASTStmtReader; + public: /// \brief Build an empty inline-assembly statement. explicit AsmStmt(StmtClass SC, EmptyShell Empty) : - Stmt(SC, Empty), Names(0), Exprs(0) { } + Stmt(SC, Empty), Exprs(0) { } SourceLocation getAsmLoc() const { return AsmLoc; } void setAsmLoc(SourceLocation L) { AsmLoc = L; } @@ -1418,17 +1423,6 @@ public: unsigned getNumOutputs() const { return NumOutputs; } - IdentifierInfo *getOutputIdentifier(unsigned i) const { - return Names[i]; - } - - StringRef getOutputName(unsigned i) const { - if (IdentifierInfo *II = getOutputIdentifier(i)) - return II->getName(); - - return StringRef(); - } - /// getOutputConstraint - Return the constraint string for the specified /// output operand. All output constraints are known to be non-empty (either /// '=' or '+'). @@ -1451,17 +1445,6 @@ public: unsigned getNumInputs() const { return NumInputs; } - IdentifierInfo *getInputIdentifier(unsigned i) const { - return Names[i + NumOutputs]; - } - - StringRef getInputName(unsigned i) const { - if (IdentifierInfo *II = getInputIdentifier(i)) - return II->getName(); - - return StringRef(); - } - /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. StringRef getInputConstraint(unsigned i) const; @@ -1532,6 +1515,9 @@ class GCCAsmStmt : public AsmStmt { // FIXME: If we wanted to, we could allocate all of these in one big array. StringLiteral **Constraints; StringLiteral **Clobbers; + IdentifierInfo **Names; + + friend class ASTStmtReader; public: GCCAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, @@ -1542,7 +1528,7 @@ public: /// \brief Build an empty inline-assembly statement. explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty), - Constraints(0), Clobbers(0) { } + Constraints(0), Clobbers(0), Names(0) { } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } @@ -1607,6 +1593,17 @@ public: //===--- Output operands ---===// + IdentifierInfo *getOutputIdentifier(unsigned i) const { + return Names[i]; + } + + StringRef getOutputName(unsigned i) const { + if (IdentifierInfo *II = getOutputIdentifier(i)) + return II->getName(); + + return StringRef(); + } + StringRef getOutputConstraint(unsigned i) const; const StringLiteral *getOutputConstraintLiteral(unsigned i) const { @@ -1624,6 +1621,17 @@ public: //===--- Input operands ---===// + IdentifierInfo *getInputIdentifier(unsigned i) const { + return Names[i + NumOutputs]; + } + + StringRef getInputName(unsigned i) const { + if (IdentifierInfo *II = getInputIdentifier(i)) + return II->getName(); + + return StringRef(); + } + StringRef getInputConstraint(unsigned i) const; const StringLiteral *getInputConstraintLiteral(unsigned i) const { @@ -1640,6 +1648,7 @@ public: return const_cast<GCCAsmStmt*>(this)->getInputExpr(i); } +private: void setOutputsAndInputsAndClobbers(ASTContext &C, IdentifierInfo **Names, StringLiteral **Constraints, @@ -1648,6 +1657,7 @@ public: unsigned NumInputs, StringLiteral **Clobbers, unsigned NumClobbers); +public: //===--- Other ---===// @@ -1674,7 +1684,7 @@ public: /// class MSAsmStmt : public AsmStmt { SourceLocation LBraceLoc, EndLoc; - std::string AsmStr; + StringRef AsmStr; unsigned NumAsmToks; @@ -1682,11 +1692,13 @@ class MSAsmStmt : public AsmStmt { StringRef *Constraints; StringRef *Clobbers; + friend class ASTStmtReader; + public: MSAsmStmt(ASTContext &C, SourceLocation asmloc, SourceLocation lbraceloc, bool issimple, bool isvolatile, ArrayRef<Token> asmtoks, unsigned numoutputs, unsigned numinputs, - ArrayRef<IdentifierInfo*> names, ArrayRef<StringRef> constraints, + ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs, StringRef asmstr, ArrayRef<StringRef> clobbers, SourceLocation endloc); @@ -1705,10 +1717,7 @@ public: Token *getAsmToks() { return AsmToks; } //===--- Asm String Analysis ---===// - - const std::string *getAsmString() const { return &AsmStr; } - std::string *getAsmString() { return &AsmStr; } - void setAsmString(StringRef &E) { AsmStr = E.str(); } + StringRef getAsmString() const { return AsmStr; } /// Assemble final IR asm string. std::string generateAsmString(ASTContext &C) const; @@ -1716,6 +1725,7 @@ public: //===--- Output operands ---===// StringRef getOutputConstraint(unsigned i) const { + assert(i < NumOutputs); return Constraints[i]; } @@ -1728,6 +1738,7 @@ public: //===--- Input operands ---===// StringRef getInputConstraint(unsigned i) const { + assert(i < NumInputs); return Constraints[i + NumOutputs]; } @@ -1740,7 +1751,27 @@ public: //===--- Other ---===// - StringRef getClobber(unsigned i) const { return Clobbers[i]; } + ArrayRef<StringRef> getAllConstraints() const { + return ArrayRef<StringRef>(Constraints, NumInputs + NumOutputs); + } + ArrayRef<StringRef> getClobbers() const { + return ArrayRef<StringRef>(Clobbers, NumClobbers); + } + ArrayRef<Expr*> getAllExprs() const { + return ArrayRef<Expr*>(reinterpret_cast<Expr**>(Exprs), + NumInputs + NumOutputs); + } + + StringRef getClobber(unsigned i) const { return getClobbers()[i]; } + +private: + void initialize(ASTContext &C, + StringRef AsmString, + ArrayRef<Token> AsmToks, + ArrayRef<StringRef> Constraints, + ArrayRef<Expr*> Exprs, + ArrayRef<StringRef> Clobbers); +public: SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; } @@ -1882,6 +1913,198 @@ public: } }; +/// \brief This captures a statement into a function. For example, the following +/// pragma annotated compound statement can be represented as a CapturedStmt, +/// and this compound statement is the body of an anonymous outlined function. +/// @code +/// #pragma omp parallel +/// { +/// compute(); +/// } +/// @endcode +class CapturedStmt : public Stmt { +public: + /// \brief The different capture forms: by 'this' or by reference, etc. + enum VariableCaptureKind { + VCK_This, + VCK_ByRef + }; + + /// \brief Describes the capture of either a variable or 'this'. + class Capture { + llvm::PointerIntPair<VarDecl *, 1, VariableCaptureKind> VarAndKind; + SourceLocation Loc; + + public: + /// \brief Create a new capture. + /// + /// \param Loc The source location associated with this capture. + /// + /// \param Kind The kind of capture (this, ByRef, ...). + /// + /// \param Var The variable being captured, or null if capturing this. + /// + Capture(SourceLocation Loc, VariableCaptureKind Kind, VarDecl *Var = 0) + : VarAndKind(Var, Kind), Loc(Loc) { + switch (Kind) { + case VCK_This: + assert(Var == 0 && "'this' capture cannot have a variable!"); + break; + case VCK_ByRef: + assert(Var && "capturing by reference must have a variable!"); + break; + } + } + + /// \brief Determine the kind of capture. + VariableCaptureKind getCaptureKind() const { return VarAndKind.getInt(); } + + /// \brief Retrieve the source location at which the variable or 'this' was + /// first used. + SourceLocation getLocation() const { return Loc; } + + /// \brief Determine whether this capture handles the C++ 'this' pointer. + bool capturesThis() const { return getCaptureKind() == VCK_This; } + + /// \brief Determine whether this capture handles a variable. + bool capturesVariable() const { return getCaptureKind() != VCK_This; } + + /// \brief Retrieve the declaration of the variable being captured. + /// + /// This operation is only valid if this capture does not capture 'this'. + VarDecl *getCapturedVar() const { + assert(!capturesThis() && "No variable available for 'this' capture"); + return VarAndKind.getPointer(); + } + friend class ASTStmtReader; + }; + +private: + /// \brief The number of variable captured, including 'this'. + unsigned NumCaptures; + + /// \brief The pointer part is the implicit the outlined function and the + /// int part is the captured region kind, 'CR_Default' etc. + llvm::PointerIntPair<CapturedDecl *, 1, CapturedRegionKind> CapDeclAndKind; + + /// \brief The record for captured variables, a RecordDecl or CXXRecordDecl. + RecordDecl *TheRecordDecl; + + /// \brief Construct a captured statement. + CapturedStmt(Stmt *S, CapturedRegionKind Kind, ArrayRef<Capture> Captures, + ArrayRef<Expr *> CaptureInits, CapturedDecl *CD, RecordDecl *RD); + + /// \brief Construct an empty captured statement. + CapturedStmt(EmptyShell Empty, unsigned NumCaptures); + + Stmt **getStoredStmts() const { + return reinterpret_cast<Stmt **>(const_cast<CapturedStmt *>(this) + 1); + } + + Capture *getStoredCaptures() const; + + void setCapturedStmt(Stmt *S) { getStoredStmts()[NumCaptures] = S; } + +public: + static CapturedStmt *Create(ASTContext &Context, Stmt *S, + CapturedRegionKind Kind, + ArrayRef<Capture> Captures, + ArrayRef<Expr *> CaptureInits, + CapturedDecl *CD, RecordDecl *RD); + + static CapturedStmt *CreateDeserialized(ASTContext &Context, + unsigned NumCaptures); + + /// \brief Retrieve the statement being captured. + Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; } + const Stmt *getCapturedStmt() const { + return const_cast<CapturedStmt *>(this)->getCapturedStmt(); + } + + /// \brief Retrieve the outlined function declaration. + CapturedDecl *getCapturedDecl() { return CapDeclAndKind.getPointer(); } + const CapturedDecl *getCapturedDecl() const { + return const_cast<CapturedStmt *>(this)->getCapturedDecl(); + } + + /// \brief Set the outlined function declaration. + void setCapturedDecl(CapturedDecl *D) { + assert(D && "null CapturedDecl"); + CapDeclAndKind.setPointer(D); + } + + /// \brief Retrieve the captured region kind. + CapturedRegionKind getCapturedRegionKind() const { + return CapDeclAndKind.getInt(); + } + + /// \brief Set the captured region kind. + void setCapturedRegionKind(CapturedRegionKind Kind) { + CapDeclAndKind.setInt(Kind); + } + + /// \brief Retrieve the record declaration for captured variables. + const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; } + + /// \brief Set the record declaration for captured variables. + void setCapturedRecordDecl(RecordDecl *D) { + assert(D && "null RecordDecl"); + TheRecordDecl = D; + } + + /// \brief True if this variable has been captured. + bool capturesVariable(const VarDecl *Var) const; + + /// \brief An iterator that walks over the captures. + typedef Capture *capture_iterator; + typedef const Capture *const_capture_iterator; + + /// \brief Retrieve an iterator pointing to the first capture. + capture_iterator capture_begin() { return getStoredCaptures(); } + const_capture_iterator capture_begin() const { return getStoredCaptures(); } + + /// \brief Retrieve an iterator pointing past the end of the sequence of + /// captures. + capture_iterator capture_end() const { + return getStoredCaptures() + NumCaptures; + } + + /// \brief Retrieve the number of captures, including 'this'. + unsigned capture_size() const { return NumCaptures; } + + /// \brief Iterator that walks over the capture initialization arguments. + typedef Expr **capture_init_iterator; + + /// \brief Retrieve the first initialization argument. + capture_init_iterator capture_init_begin() const { + return reinterpret_cast<Expr **>(getStoredStmts()); + } + + /// \brief Retrieve the iterator pointing one past the last initialization + /// argument. + capture_init_iterator capture_init_end() const { + return capture_init_begin() + NumCaptures; + } + + SourceLocation getLocStart() const LLVM_READONLY { + return getCapturedStmt()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getCapturedStmt()->getLocEnd(); + } + SourceRange getSourceRange() const LLVM_READONLY { + return getCapturedStmt()->getSourceRange(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CapturedStmtClass; + } + + child_range children(); + + friend class ASTStmtReader; +}; + } // end namespace clang #endif diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 1e22de76f3..70b934f36c 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -72,32 +72,36 @@ private: /// \brief The kind of template argument we're storing. unsigned Kind; + struct DA { + ValueDecl *D; + bool ForRefParam; + }; + struct I { + // We store a decomposed APSInt with the data allocated by ASTContext if + // BitWidth > 64. The memory may be shared between multiple + // TemplateArgument instances. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + unsigned BitWidth : 31; + unsigned IsUnsigned : 1; + void *Type; + }; + struct A { + const TemplateArgument *Args; + unsigned NumArgs; + }; + struct TA { + void *Name; + unsigned NumExpansions; + }; union { + struct DA DeclArg; + struct I Integer; + struct A Args; + struct TA TemplateArg; uintptr_t TypeOrValue; - struct { - ValueDecl *D; - bool ForRefParam; - } DeclArg; - struct { - // We store a decomposed APSInt with the data allocated by ASTContext if - // BitWidth > 64. The memory may be shared between multiple - // TemplateArgument instances. - union { - uint64_t VAL; ///< Used to store the <= 64 bits integer value. - const uint64_t *pVal; ///< Used to store the >64 bits integer value. - }; - unsigned BitWidth : 31; - unsigned IsUnsigned : 1; - void *Type; - } Integer; - struct { - const TemplateArgument *Args; - unsigned NumArgs; - } Args; - struct { - void *Name; - unsigned NumExpansions; - } TemplateArg; }; TemplateArgument(TemplateName, bool) LLVM_DELETED_FUNCTION; @@ -341,17 +345,20 @@ public: /// Location information for a TemplateArgument. struct TemplateArgumentLocInfo { private: + + struct T { + // FIXME: We'd like to just use the qualifier in the TemplateName, + // but template arguments get canonicalized too quickly. + NestedNameSpecifier *Qualifier; + void *QualifierLocData; + unsigned TemplateNameLoc; + unsigned EllipsisLoc; + }; + union { + struct T Template; Expr *Expression; TypeSourceInfo *Declarator; - struct { - // FIXME: We'd like to just use the qualifier in the TemplateName, - // but template arguments get canonicalized too quickly. - NestedNameSpecifier *Qualifier; - void *QualifierLocData; - unsigned TemplateNameLoc; - unsigned EllipsisLoc; - } Template; }; public: diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index 174b451b2b..0b9d4c8547 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -46,16 +46,17 @@ protected: SubstTemplateTemplateParmPack }; - union { - struct { - /// \brief A Kind. - unsigned Kind : 2; - - /// \brief The number of stored templates or template arguments, - /// depending on which subclass we have. - unsigned Size : 30; - } Bits; + struct BitsTag { + /// \brief A Kind. + unsigned Kind : 2; + /// \brief The number of stored templates or template arguments, + /// depending on which subclass we have. + unsigned Size : 30; + }; + + union { + struct BitsTag Bits; void *PointerAlignment; }; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 10143a67ca..39f10d3393 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -998,14 +998,12 @@ private: namespace llvm { /// Implement simplify_type for QualType, so that we can dyn_cast from QualType /// to a specific Type class. -template<> struct simplify_type<const ::clang::QualType> { +template<> struct simplify_type< ::clang::QualType> { typedef const ::clang::Type *SimpleType; - static SimpleType getSimplifiedValue(const ::clang::QualType &Val) { + static SimpleType getSimplifiedValue(::clang::QualType Val) { return Val.getTypePtr(); } }; -template<> struct simplify_type< ::clang::QualType> - : public simplify_type<const ::clang::QualType> {}; // Teach SmallPtrSet that QualType is "basically a pointer". template<> @@ -1328,10 +1326,20 @@ protected: unsigned AttrKind : 32 - NumTypeBits; }; + class AutoTypeBitfields { + friend class AutoType; + + unsigned : NumTypeBits; + + /// Was this placeholder type spelled as 'decltype(auto)'? + unsigned IsDecltypeAuto : 1; + }; + union { TypeBitfields TypeBits; ArrayTypeBitfields ArrayTypeBits; AttributedTypeBitfields AttributedTypeBits; + AutoTypeBitfields AutoTypeBits; BuiltinTypeBitfields BuiltinTypeBits; FunctionTypeBitfields FunctionTypeBits; ObjCObjectTypeBitfields ObjCObjectTypeBits; @@ -1445,8 +1453,8 @@ public: } /// isLiteralType - Return true if this is a literal type - /// (C++0x [basic.types]p10) - bool isLiteralType() const; + /// (C++11 [basic.types]p10) + bool isLiteralType(ASTContext &Ctx) const; /// \brief Test if this type is a standard-layout type. /// (C++0x [basic.type]p9) @@ -1611,6 +1619,10 @@ public: return TypeBits.InstantiationDependent; } + /// \brief Determine whether this type is an undeduced type, meaning that + /// it somehow involves a C++11 'auto' type which has not yet been deduced. + bool isUndeducedType() const; + /// \brief Whether this type is a variably-modified type (C99 6.7.5). bool isVariablyModifiedType() const { return TypeBits.VariablyModified; } @@ -1774,8 +1786,9 @@ public: /// \brief Determine the linkage and visibility of this type. LinkageInfo getLinkageAndVisibility() const; - /// \brief Note that the linkage is no longer known. - void ClearLinkageCache(); + /// \brief True if the computed linkage is valid. Used for consistency + /// checking. Should always return true. + bool isLinkageValid() const; const char *getTypeClassName() const; @@ -2862,6 +2875,9 @@ public: assert(i < NumArgs && "Invalid argument number!"); return arg_type_begin()[i]; } + ArrayRef<QualType> getArgTypes() const { + return ArrayRef<QualType>(arg_type_begin(), arg_type_end()); + } ExtProtoInfo getExtProtoInfo() const { ExtProtoInfo EPI; @@ -3540,41 +3556,48 @@ public: } }; -/// \brief Represents a C++0x auto type. +/// \brief Represents a C++11 auto or C++1y decltype(auto) type. /// -/// These types are usually a placeholder for a deduced type. However, within -/// templates and before the initializer is attached, there is no deduced type -/// and an auto type is type-dependent and canonical. +/// These types are usually a placeholder for a deduced type. However, before +/// the initializer is attached, or if the initializer is type-dependent, there +/// is no deduced type and an auto type is canonical. In the latter case, it is +/// also a dependent type. class AutoType : public Type, public llvm::FoldingSetNode { - AutoType(QualType DeducedType) + AutoType(QualType DeducedType, bool IsDecltypeAuto, bool IsDependent) : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType, - /*Dependent=*/DeducedType.isNull(), - /*InstantiationDependent=*/DeducedType.isNull(), + /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent, /*VariablyModified=*/false, /*ContainsParameterPack=*/false) { - assert((DeducedType.isNull() || !DeducedType->isDependentType()) && - "deduced a dependent type for auto"); + assert((DeducedType.isNull() || !IsDependent) && + "auto deduced to dependent type"); + AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto; } friend class ASTContext; // ASTContext creates these public: - bool isSugared() const { return isDeduced(); } + bool isDecltypeAuto() const { return AutoTypeBits.IsDecltypeAuto; } + + bool isSugared() const { return !isCanonicalUnqualified(); } QualType desugar() const { return getCanonicalTypeInternal(); } + /// \brief Get the type deduced for this auto type, or null if it's either + /// not been deduced or was deduced to a dependent type. QualType getDeducedType() const { - return isDeduced() ? getCanonicalTypeInternal() : QualType(); + return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType(); } bool isDeduced() const { - return !isDependentType(); + return !isCanonicalUnqualified() || isDependentType(); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getDeducedType()); + Profile(ID, getDeducedType(), isDecltypeAuto(), isDependentType()); } - static void Profile(llvm::FoldingSetNodeID &ID, - QualType Deduced) { + static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced, + bool IsDecltypeAuto, bool IsDependent) { ID.AddPointer(Deduced.getAsOpaquePtr()); + ID.AddBoolean(IsDecltypeAuto); + ID.AddBoolean(IsDependent); } static bool classof(const Type *T) { @@ -4624,7 +4647,7 @@ inline QualType QualType::getUnqualifiedType() const { return QualType(getSplitUnqualifiedTypeImpl(*this).Ty, 0); } - + inline SplitQualType QualType::getSplitUnqualifiedType() const { if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers()) return split(); @@ -4656,7 +4679,7 @@ inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { inline unsigned QualType::getAddressSpace() const { return getQualifiers().getAddressSpace(); } - + /// getObjCGCAttr - Return the gc attribute of this type. inline Qualifiers::GC QualType::getObjCGCAttr() const { return getQualifiers().getObjCGCAttr(); @@ -5017,6 +5040,11 @@ inline bool Type::isBooleanType() const { return false; } +inline bool Type::isUndeducedType() const { + const AutoType *AT = getContainedAutoType(); + return AT && !AT->isDeduced(); +} + /// \brief Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index d5c485f8a3..840e07d94a 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -94,7 +94,7 @@ DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Auto, Type) +TYPE(Auto, Type) DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) DEPENDENT_TYPE(DependentTemplateSpecialization, Type) |