diff options
Diffstat (limited to 'include')
162 files changed, 16122 insertions, 8489 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index b377b6d5fe2c..4631c65bf05a 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -98,6 +98,27 @@ struct CXUnsavedFile { }; /** + * \brief Describes the availability of a particular entity, which indicates + * whether the use of this entity will result in a warning or error due to + * it being deprecated or unavailable. + */ +enum CXAvailabilityKind { + /** + * \brief The entity is available. + */ + CXAvailability_Available, + /** + * \brief The entity is available, but has been deprecated (and its use is + * not recommended). + */ + CXAvailability_Deprecated, + /** + * \brief The entity is not available; any use of it will be an error. + */ + CXAvailability_NotAvailable +}; + +/** * \defgroup CINDEX_STRING String manipulation routines * * @{ @@ -624,7 +645,7 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( CXIndex CIdx, const char *source_filename, int num_clang_command_line_args, - const char **clang_command_line_args, + const char * const *clang_command_line_args, unsigned num_unsaved_files, struct CXUnsavedFile *unsaved_files); @@ -635,11 +656,261 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, const char *ast_filename); /** + * \brief Flags that control the creation of translation units. + * + * The enumerators in this enumeration type are meant to be bitwise + * ORed together to specify which options should be used when + * constructing the translation unit. + */ +enum CXTranslationUnit_Flags { + /** + * \brief Used to indicate that no special translation-unit options are + * needed. + */ + CXTranslationUnit_None = 0x0, + + /** + * \brief Used to indicate that the parser should construct a "detailed" + * preprocessing record, including all macro definitions and instantiations. + * + * Constructing a detailed preprocessing record requires more memory + * and time to parse, since the information contained in the record + * is usually not retained. However, it can be useful for + * applications that require more detailed information about the + * behavior of the preprocessor. + */ + CXTranslationUnit_DetailedPreprocessingRecord = 0x01, + + /** + * \brief Used to indicate that the translation unit is incomplete. + * + * When a translation unit is considered "incomplete", semantic + * analysis that is typically performed at the end of the + * translation unit will be suppressed. For example, this suppresses + * the completion of tentative declarations in C and of + * instantiation of implicitly-instantiation function templates in + * C++. This option is typically used when parsing a header with the + * intent of producing a precompiled header. + */ + CXTranslationUnit_Incomplete = 0x02, + + /** + * \brief Used to indicate that the translation unit should be built with an + * implicit precompiled header for the preamble. + * + * An implicit precompiled header is used as an optimization when a + * particular translation unit is likely to be reparsed many times + * when the sources aren't changing that often. In this case, an + * implicit precompiled header will be built containing all of the + * initial includes at the top of the main file (what we refer to as + * the "preamble" of the file). In subsequent parses, if the + * preamble or the files in it have not changed, \c + * clang_reparseTranslationUnit() will re-use the implicit + * precompiled header to improve parsing performance. + */ + CXTranslationUnit_PrecompiledPreamble = 0x04, + + /** + * \brief Used to indicate that the translation unit should cache some + * code-completion results with each reparse of the source file. + * + * Caching of code-completion results is a performance optimization that + * introduces some overhead to reparsing but improves the performance of + * code-completion operations. + */ + CXTranslationUnit_CacheCompletionResults = 0x08 +}; + +/** + * \brief Returns the set of flags that is suitable for parsing a translation + * unit that is being edited. + * + * The set of flags returned provide options for \c clang_parseTranslationUnit() + * to indicate that the translation unit is likely to be reparsed many times, + * either explicitly (via \c clang_reparseTranslationUnit()) or implicitly + * (e.g., by code completion (\c clang_codeCompletionAt())). The returned flag + * set contains an unspecified set of optimizations (e.g., the precompiled + * preamble) geared toward improving the performance of these routines. The + * set of optimizations enabled may change from one version to the next. + */ +CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void); + +/** + * \brief Parse the given source file and the translation unit corresponding + * to that file. + * + * This routine is the main entry point for the Clang C API, providing the + * ability to parse a source file into a translation unit that can then be + * queried by other functions in the API. This routine accepts a set of + * command-line arguments so that the compilation can be configured in the same + * way that the compiler is configured on the command line. + * + * \param CIdx The index object with which the translation unit will be + * associated. + * + * \param source_filename The name of the source file to load, or NULL if the + * source file is included in \p clang_command_line_args. + * + * \param command_line_args The command-line arguments that would be + * passed to the \c clang executable if it were being invoked out-of-process. + * These command-line options will be parsed and will affect how the translation + * unit is parsed. Note that the following options are ignored: '-c', + * '-emit-ast', '-fsyntex-only' (which is the default), and '-o <output file>'. + * + * \param num_command_line_args The number of command-line arguments in + * \p command_line_args. + * + * \param unsaved_files the files that have not yet been saved to disk + * but may be required for parsing, including the contents of + * those files. The contents and name of these files (as specified by + * CXUnsavedFile) are copied when necessary, so the client only needs to + * guarantee their validity until the call to this function returns. + * + * \param num_unsaved_files the number of unsaved file entries in \p + * unsaved_files. + * + * \param options A bitmask of options that affects how the translation unit + * is managed but not its compilation. This should be a bitwise OR of the + * CXTranslationUnit_XXX flags. + * + * \returns A new translation unit describing the parsed code and containing + * any diagnostics produced by the compiler. If there is a failure from which + * the compiler cannot recover, returns NULL. + */ +CINDEX_LINKAGE CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx, + const char *source_filename, + const char * const *command_line_args, + int num_command_line_args, + struct CXUnsavedFile *unsaved_files, + unsigned num_unsaved_files, + unsigned options); + +/** + * \brief Flags that control how translation units are saved. + * + * The enumerators in this enumeration type are meant to be bitwise + * ORed together to specify which options should be used when + * saving the translation unit. + */ +enum CXSaveTranslationUnit_Flags { + /** + * \brief Used to indicate that no special saving options are needed. + */ + CXSaveTranslationUnit_None = 0x0 +}; + +/** + * \brief Returns the set of flags that is suitable for saving a translation + * unit. + * + * The set of flags returned provide options for + * \c clang_saveTranslationUnit() by default. The returned flag + * set contains an unspecified set of options that save translation units with + * the most commonly-requested data. + */ +CINDEX_LINKAGE unsigned clang_defaultSaveOptions(CXTranslationUnit TU); + +/** + * \brief Saves a translation unit into a serialized representation of + * that translation unit on disk. + * + * Any translation unit that was parsed without error can be saved + * into a file. The translation unit can then be deserialized into a + * new \c CXTranslationUnit with \c clang_createTranslationUnit() or, + * if it is an incomplete translation unit that corresponds to a + * header, used as a precompiled header when parsing other translation + * units. + * + * \param TU The translation unit to save. + * + * \param FileName The file to which the translation unit will be saved. + * + * \param options A bitmask of options that affects how the translation unit + * is saved. This should be a bitwise OR of the + * CXSaveTranslationUnit_XXX flags. + * + * \returns Zero if the translation unit was saved successfully, a + * non-zero value otherwise. + */ +CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU, + const char *FileName, + unsigned options); + +/** * \brief Destroy the specified CXTranslationUnit object. */ CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); /** + * \brief Flags that control the reparsing of translation units. + * + * The enumerators in this enumeration type are meant to be bitwise + * ORed together to specify which options should be used when + * reparsing the translation unit. + */ +enum CXReparse_Flags { + /** + * \brief Used to indicate that no special reparsing options are needed. + */ + CXReparse_None = 0x0 +}; + +/** + * \brief Returns the set of flags that is suitable for reparsing a translation + * unit. + * + * The set of flags returned provide options for + * \c clang_reparseTranslationUnit() by default. The returned flag + * set contains an unspecified set of optimizations geared toward common uses + * of reparsing. The set of optimizations enabled may change from one version + * to the next. + */ +CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU); + +/** + * \brief Reparse the source files that produced this translation unit. + * + * This routine can be used to re-parse the source files that originally + * created the given translation unit, for example because those source files + * have changed (either on disk or as passed via \p unsaved_files). The + * source code will be reparsed with the same command-line options as it + * was originally parsed. + * + * Reparsing a translation unit invalidates all cursors and source locations + * that refer into that translation unit. This makes reparsing a translation + * unit semantically equivalent to destroying the translation unit and then + * creating a new translation unit with the same command-line arguments. + * However, it may be more efficient to reparse a translation + * unit using this routine. + * + * \param TU The translation unit whose contents will be re-parsed. The + * translation unit must originally have been built with + * \c clang_createTranslationUnitFromSourceFile(). + * + * \param num_unsaved_files The number of unsaved file entries in \p + * unsaved_files. + * + * \param unsaved_files The files that have not yet been saved to disk + * but may be required for parsing, including the contents of + * those files. The contents and name of these files (as specified by + * CXUnsavedFile) are copied when necessary, so the client only needs to + * guarantee their validity until the call to this function returns. + * + * \param options A bitset of options composed of the flags in CXReparse_Flags. + * The function \c clang_defaultReparseOptions() produces a default set of + * options recommended for most uses, based on the translation unit. + * + * \returns 0 if the sources could be reparsed. A non-zero value will be + * returned if reparsing was impossible, such that the translation unit is + * invalid. In such cases, the only valid call for \p TU is + * \c clang_disposeTranslationUnit(TU). + */ +CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU, + unsigned num_unsaved_files, + struct CXUnsavedFile *unsaved_files, + unsigned options); + +/** * @} */ @@ -705,9 +976,33 @@ enum CXCursorKind { CXCursor_Namespace = 22, /** \brief A linkage specification, e.g. 'extern "C"'. */ CXCursor_LinkageSpec = 23, - + /** \brief A C++ constructor. */ + CXCursor_Constructor = 24, + /** \brief A C++ destructor. */ + CXCursor_Destructor = 25, + /** \brief A C++ conversion function. */ + CXCursor_ConversionFunction = 26, + /** \brief A C++ template type parameter. */ + CXCursor_TemplateTypeParameter = 27, + /** \brief A C++ non-type template parameter. */ + CXCursor_NonTypeTemplateParameter = 28, + /** \brief A C++ template template parameter. */ + CXCursor_TemplateTemplateParameter = 29, + /** \brief A C++ function template. */ + CXCursor_FunctionTemplate = 30, + /** \brief A C++ class template. */ + CXCursor_ClassTemplate = 31, + /** \brief A C++ class template partial specialization. */ + CXCursor_ClassTemplatePartialSpecialization = 32, + /** \brief A C++ namespace alias declaration. */ + CXCursor_NamespaceAlias = 33, + /** \brief A C++ using directive. */ + CXCursor_UsingDirective = 34, + /** \brief A using declaration. */ + CXCursor_UsingDeclaration = 35, + CXCursor_FirstDecl = CXCursor_UnexposedDecl, - CXCursor_LastDecl = CXCursor_LinkageSpec, + CXCursor_LastDecl = CXCursor_UsingDeclaration, /* References */ CXCursor_FirstRef = 40, /* Decl references */ @@ -730,7 +1025,17 @@ enum CXCursorKind { * referenced by the type of size is the typedef for size_type. */ CXCursor_TypeRef = 43, - CXCursor_LastRef = 43, + CXCursor_CXXBaseSpecifier = 44, + /** + * \brief A reference to a class template, function template, or template + * template parameter. + */ + CXCursor_TemplateRef = 45, + /** + * \brief A reference to a namespace or namespace alias. + */ + CXCursor_NamespaceRef = 46, + CXCursor_LastRef = CXCursor_NamespaceRef, /* Error conditions */ CXCursor_FirstInvalid = 70, @@ -949,6 +1254,16 @@ enum CXLinkageKind { CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor); /** + * \brief Determine the availability of the entity that this cursor refers to. + * + * \param cursor The cursor to query. + * + * \returns The availability of the cursor. + */ +CINDEX_LINKAGE enum CXAvailabilityKind +clang_getCursorAvailability(CXCursor cursor); + +/** * \brief Describe the "language" of the entity referred to by a cursor. */ CINDEX_LINKAGE enum CXLanguageKind { @@ -1023,7 +1338,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor); /** * @} */ - + /** * \defgroup CINDEX_TYPES Type information for CXCursors * @@ -1152,6 +1467,53 @@ CINDEX_LINKAGE CXType clang_getResultType(CXType T); CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C); /** + * \brief Return 1 if the CXType is a POD (plain old data) type, and 0 + * otherwise. + */ +CINDEX_LINKAGE unsigned clang_isPODType(CXType T); + +/** + * \brief Returns 1 if the base class specified by the cursor with kind + * CX_CXXBaseSpecifier is virtual. + */ +CINDEX_LINKAGE unsigned clang_isVirtualBase(CXCursor); + +/** + * \brief Represents the C++ access control level to a base class for a + * cursor with kind CX_CXXBaseSpecifier. + */ +enum CX_CXXAccessSpecifier { + CX_CXXInvalidAccessSpecifier, + CX_CXXPublic, + CX_CXXProtected, + CX_CXXPrivate +}; + +/** + * \brief Returns the access control level for the C++ base specifier + * represented by a cursor with kind CX_CXXBaseSpecifier. + */ +CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor); + +/** + * @} + */ + +/** + * \defgroup CINDEX_ATTRIBUTES Information for attributes + * + * @{ + */ + + +/** + * \brief For cursors representing an iboutletcollection attribute, + * this function returns the collection element type. + * + */ +CINDEX_LINKAGE CXType clang_getIBOutletCollectionType(CXCursor); + +/** * @} */ @@ -1364,11 +1726,61 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor); */ /** - * \brief Determine if a C++ member function is declared 'static'. + * \brief Determine if a C++ member function or member function template is + * declared 'static'. */ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C); /** + * \brief Given a cursor that represents a template, determine + * the cursor kind of the specializations would be generated by instantiating + * the template. + * + * This routine can be used to determine what flavor of function template, + * class template, or class template partial specialization is stored in the + * cursor. For example, it can describe whether a class template cursor is + * declared with "struct", "class" or "union". + * + * \param C The cursor to query. This cursor should represent a template + * declaration. + * + * \returns The cursor kind of the specializations that would be generated + * by instantiating the template \p C. If \p C is not a template, returns + * \c CXCursor_NoDeclFound. + */ +CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C); + +/** + * \brief Given a cursor that may represent a specialization or instantiation + * of a template, retrieve the cursor that represents the template that it + * specializes or from which it was instantiated. + * + * This routine determines the template involved both for explicit + * specializations of templates and for implicit instantiations of the template, + * both of which are referred to as "specializations". For a class template + * specialization (e.g., \c std::vector<bool>), this routine will return + * either the primary template (\c std::vector) or, if the specialization was + * instantiated from a class template partial specialization, the class template + * partial specialization. For a class template partial specialization and a + * function template specialization (including instantiations), this + * this routine will return the specialized template. + * + * For members of a class template (e.g., member functions, member classes, or + * static data members), returns the specialized or instantiated member. + * Although not strictly "templates" in the C++ language, members of class + * templates have the same notions of specializations and instantiations that + * templates do, so this routine treats them similarly. + * + * \param C A cursor that may be a specialization of a template or a member + * of a template. + * + * \returns If the given cursor is a specialization or instantiation of a + * template or a member thereof, the template or member that it specializes or + * from which it was instantiated. Otherwise, returns a NULL cursor. + */ +CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C); + +/** * @} */ @@ -1817,6 +2229,17 @@ CINDEX_LINKAGE unsigned clang_getCompletionPriority(CXCompletionString completion_string); /** + * \brief Determine the availability of the entity that this code-completion + * string refers to. + * + * \param completion_string The completion string to query. + * + * \returns The availability of the completion string. + */ +CINDEX_LINKAGE enum CXAvailabilityKind +clang_getCompletionAvailability(CXCompletionString completion_string); + +/** * \brief Contains the results of code-completion. * * This data structure contains the results of code completion, as @@ -1922,7 +2345,7 @@ CINDEX_LINKAGE CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, const char *source_filename, int num_command_line_args, - const char **command_line_args, + const char * const *command_line_args, unsigned num_unsaved_files, struct CXUnsavedFile *unsaved_files, const char *complete_filename, @@ -1930,11 +2353,126 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, unsigned complete_column); /** + * \brief Flags that can be passed to \c clang_codeCompleteAt() to + * modify its behavior. + * + * The enumerators in this enumeration can be bitwise-OR'd together to + * provide multiple options to \c clang_codeCompleteAt(). + */ +enum CXCodeComplete_Flags { + /** + * \brief Whether to include macros within the set of code + * completions returned. + */ + CXCodeComplete_IncludeMacros = 0x01, + + /** + * \brief Whether to include code patterns for language constructs + * within the set of code completions, e.g., for loops. + */ + CXCodeComplete_IncludeCodePatterns = 0x02 +}; + +/** + * \brief Returns a default set of code-completion options that can be + * passed to\c clang_codeCompleteAt(). + */ +CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void); + +/** + * \brief Perform code completion at a given location in a translation unit. + * + * This function performs code completion at a particular file, line, and + * column within source code, providing results that suggest potential + * code snippets based on the context of the completion. The basic model + * for code completion is that Clang will parse a complete source file, + * performing syntax checking up to the location where code-completion has + * been requested. At that point, a special code-completion token is passed + * to the parser, which recognizes this token and determines, based on the + * current location in the C/Objective-C/C++ grammar and the state of + * semantic analysis, what completions to provide. These completions are + * returned via a new \c CXCodeCompleteResults structure. + * + * Code completion itself is meant to be triggered by the client when the + * user types punctuation characters or whitespace, at which point the + * code-completion location will coincide with the cursor. For example, if \c p + * is a pointer, code-completion might be triggered after the "-" and then + * after the ">" in \c p->. When the code-completion location is afer the ">", + * the completion results will provide, e.g., the members of the struct that + * "p" points to. The client is responsible for placing the cursor at the + * beginning of the token currently being typed, then filtering the results + * based on the contents of the token. For example, when code-completing for + * the expression \c p->get, the client should provide the location just after + * the ">" (e.g., pointing at the "g") to this code-completion hook. Then, the + * client can filter the results based on the current token text ("get"), only + * showing those results that start with "get". The intent of this interface + * is to separate the relatively high-latency acquisition of code-completion + * results from the filtering of results on a per-character basis, which must + * have a lower latency. + * + * \param TU The translation unit in which code-completion should + * occur. The source files for this translation unit need not be + * completely up-to-date (and the contents of those source files may + * be overridden via \p unsaved_files). Cursors referring into the + * translation unit may be invalidated by this invocation. + * + * \param complete_filename The name of the source file where code + * completion should be performed. This filename may be any file + * included in the translation unit. + * + * \param complete_line The line at which code-completion should occur. + * + * \param complete_column The column at which code-completion should occur. + * Note that the column should point just after the syntactic construct that + * initiated code completion, and not in the middle of a lexical token. + * + * \param unsaved_files the Tiles that have not yet been saved to disk + * but may be required for parsing or code completion, including the + * contents of those files. The contents and name of these files (as + * specified by CXUnsavedFile) are copied when necessary, so the + * client only needs to guarantee their validity until the call to + * this function returns. + * + * \param num_unsaved_files The number of unsaved file entries in \p + * unsaved_files. + * + * \param options Extra options that control the behavior of code + * completion, expressed as a bitwise OR of the enumerators of the + * CXCodeComplete_Flags enumeration. The + * \c clang_defaultCodeCompleteOptions() function returns a default set + * of code-completion options. + * + * \returns If successful, a new \c CXCodeCompleteResults structure + * containing code-completion results, which should eventually be + * freed with \c clang_disposeCodeCompleteResults(). If code + * completion fails, returns NULL. + */ +CINDEX_LINKAGE +CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU, + const char *complete_filename, + unsigned complete_line, + unsigned complete_column, + struct CXUnsavedFile *unsaved_files, + unsigned num_unsaved_files, + unsigned options); + +/** + * \brief Sort the code-completion results in case-insensitive alphabetical + * order. + * + * \param Results The set of results to sort. + * \param NumResults The number of results in \p Results. + */ +CINDEX_LINKAGE +void clang_sortCodeCompletionResults(CXCompletionResult *Results, + unsigned NumResults); + +/** * \brief Free the given set of code-completion results. */ CINDEX_LINKAGE void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results); - + /** * \brief Determine the number of diagnostics produced prior to the * location where code completion was performed. diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 06113954fc48..84833c099f97 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -18,9 +18,10 @@ namespace clang { class ASTContext; class CXXRecordDecl; class DeclGroupRef; - class TagDecl; class HandleTagDeclDefinition; + class ASTDeserializationListener; // layering violation because void* is ugly class SemaConsumer; // layering violation required for safe SemaConsumer + class TagDecl; class VarDecl; /// ASTConsumer - This is an abstract interface that should be implemented by @@ -48,6 +49,11 @@ public: /// elements). Use Decl::getNextDeclarator() to walk the chain. virtual void HandleTopLevelDecl(DeclGroupRef D); + /// HandleInterestingDecl - Handle the specified interesting declaration. This + /// is called by the AST reader when deserializing things that might interest + /// the consumer. The default implementation forwards to HandleTopLevelDecl. + virtual void HandleInterestingDecl(DeclGroupRef D); + /// HandleTranslationUnit - This method is called when the ASTs for entire /// translation unit have been parsed. virtual void HandleTranslationUnit(ASTContext &Ctx) {} @@ -80,6 +86,12 @@ public: /// it was actually used. virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} + /// \brief If the consumer is interested in entities being deserialized from + /// AST files, it should return a pointer to a ASTDeserializationListener here + /// + /// The return type is void* because ASTDS lives in Frontend. + virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; } + /// PrintStats - If desired, print any statistics. virtual void PrintStats() {} diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 3799451360f4..ae4ee946fe27 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -18,7 +18,6 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" -#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" @@ -50,6 +49,7 @@ namespace clang { class SelectorTable; class SourceManager; class TargetInfo; + class CXXABI; // Decls class DeclContext; class CXXMethodDecl; @@ -198,7 +198,7 @@ class ASTContext { /// /// Since so few decls have attrs, we keep them in a hash map instead of /// wasting space in the Decl class. - llvm::DenseMap<const Decl*, Attr*> DeclAttrs; + llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs; /// \brief Keeps track of the static data member templates from which /// static data members of class template specializations were instantiated. @@ -275,13 +275,18 @@ class ASTContext { /// this ASTContext object. LangOptions LangOpts; - /// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects. - bool FreeMemory; - llvm::MallocAllocator MallocAlloc; + /// \brief The allocator used to create AST objects. + /// + /// AST objects are never destructed; rather, all memory associated with the + /// AST objects will be released when the ASTContext itself is destroyed. llvm::BumpPtrAllocator BumpAlloc; /// \brief Allocator for partial diagnostics. PartialDiagnostic::StorageAllocator DiagAllocator; + + /// \brief The current C++ ABI. + llvm::OwningPtr<CXXABI> ABI; + CXXABI *createCXXABI(const TargetInfo &T); public: const TargetInfo &Target; @@ -301,13 +306,9 @@ public: SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } void *Allocate(unsigned Size, unsigned Align = 8) { - return FreeMemory ? MallocAlloc.Allocate(Size, Align) : - BumpAlloc.Allocate(Size, Align); - } - void Deallocate(void *Ptr) { - if (FreeMemory) - MallocAlloc.Deallocate(Ptr); + return BumpAlloc.Allocate(Size, Align); } + void Deallocate(void *Ptr) { } PartialDiagnostic::StorageAllocator &getDiagAllocator() { return DiagAllocator; @@ -320,10 +321,10 @@ public: } /// \brief Retrieve the attributes for the given declaration. - Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; } + AttrVec& getDeclAttrs(const Decl *D); /// \brief Erase the attributes corresponding to the given declaration. - void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); } + void eraseDeclAttrs(const Decl *D); /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member @@ -393,7 +394,7 @@ public: ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, - bool FreeMemory = true, unsigned size_reserve=0); + unsigned size_reserve); ~ASTContext(); @@ -520,7 +521,7 @@ public: llvm::SmallVectorImpl<const Expr *> &Layout); /// This builds the struct used for __block variables. - QualType BuildByRefType(const char *DeclName, QualType Ty); + QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty); /// Returns true iff we need copy/dispose helpers for the given type. bool BlockRequiresCopying(QualType Ty); @@ -873,7 +874,8 @@ public: return getExtQualType(T, Qs); } - DeclarationName getNameForTemplate(TemplateName Name); + DeclarationNameInfo getNameForTemplate(TemplateName Name, + SourceLocation NameLoc); TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -909,6 +911,11 @@ public: /// Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const; + /// areCompatibleVectorTypes - Return true if the given vector types either + /// are of the same unqualified type or if one is GCC and other - equivalent + /// AltiVec vector type. + bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec); + /// isObjCNSObjectType - Return true if this is an NSObject object with /// its NSObject attribute set. bool isObjCNSObjectType(QualType Ty) const; @@ -1002,13 +1009,12 @@ public: /// of class definition. const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); - void CollectObjCIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<FieldDecl*> &Fields); - void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); - void CollectNonClassIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + + void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI); void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); @@ -1067,8 +1073,6 @@ public: bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); - /// \brief Retrieves the "canonical" declaration of - /// \brief Retrieves the "canonical" nested name specifier for a /// given nested name specifier. /// @@ -1218,7 +1222,8 @@ public: //===--------------------------------------------------------------------===// /// Compatibility predicates used to check assignment expressions. - bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1 + bool typesAreCompatible(QualType T1, QualType T2, + bool CompareUnqualified = false); // C99 6.2.7p1 bool typesAreBlockPointerCompatible(QualType, QualType); @@ -1235,6 +1240,8 @@ public: bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, bool ForCompare); + bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS); + // Check the safety of assignment from LHS to RHS bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); @@ -1246,10 +1253,13 @@ public: bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); - + bool canBindObjCObjectType(QualType To, QualType From); + // Functions for calculating composite types - QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false); - QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false); + QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false, + bool Unqualified = false); + QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, + bool Unqualified = false); QualType mergeObjCGCQualifiers(QualType, QualType); @@ -1257,6 +1267,10 @@ public: /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9) /// and returns the result type of that conversion. QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs); + + void ResetObjCLayout(const ObjCContainerDecl *CD) { + ObjCLayouts[CD] = 0; + } //===--------------------------------------------------------------------===// // Integer Predicates @@ -1337,6 +1351,17 @@ public: /// when it is called. void AddDeallocation(void (*Callback)(void*), void *Data); + GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD); + GVALinkage GetGVALinkageForVariable(const VarDecl *VD); + + /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH + /// lazily, only when used; this is only relevant for function or file scoped + /// var definitions. + /// + /// \returns true if the function/var must be CodeGen'ed/deserialized even if + /// it is not used. + bool DeclMustBeEmitted(const Decl *D); + //===--------------------------------------------------------------------===// // Statistics //===--------------------------------------------------------------------===// @@ -1386,7 +1411,7 @@ private: const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl); - + private: /// \brief A set of deallocations that should be performed when the /// ASTContext is destroyed. diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 7975c4378876..9380058118c5 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -14,8 +14,8 @@ #ifndef LLVM_CLANG_AST_ASTIMPORTER_H #define LLVM_CLANG_AST_ASTIMPORTER_H -#include "clang/AST/Type.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 9faa62eef6f7..62ca49fbf3b1 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -15,8 +15,11 @@ #define LLVM_CLANG_AST_ATTR_H #include "llvm/Support/Casting.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "clang/Basic/AttrKinds.h" +#include "clang/AST/Type.h" +#include "clang/Basic/SourceLocation.h" #include <cassert> #include <cstring> #include <algorithm> @@ -27,28 +30,39 @@ namespace clang { class IdentifierInfo; class ObjCInterfaceDecl; class Expr; + class QualType; + class FunctionDecl; + class TypeSourceInfo; } // Defined in ASTContext.h void *operator new(size_t Bytes, clang::ASTContext &C, size_t Alignment = 16) throw (); +// FIXME: Being forced to not have a default argument here due to redeclaration +// rules on default arguments sucks +void *operator new[](size_t Bytes, clang::ASTContext &C, + size_t Alignment) throw (); // It is good practice to pair new/delete operators. Also, MSVC gives many // warnings if a matching delete overload is not declared, even though the // throw() spec guarantees it will not be implicitly called. void operator delete(void *Ptr, clang::ASTContext &C, size_t) throw (); +void operator delete[](void *Ptr, clang::ASTContext &C, size_t) + throw (); namespace clang { /// Attr - This represents one attribute. class Attr { private: - Attr *Next; - attr::Kind AttrKind; + SourceLocation Loc; + unsigned AttrKind : 16; bool Inherited : 1; protected: + virtual ~Attr(); + void* operator new(size_t bytes) throw() { assert(0 && "Attrs cannot be allocated with regular 'new'."); return 0; @@ -57,41 +71,36 @@ protected: assert(0 && "Attrs cannot be released with regular 'delete'."); } -protected: - Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {} - virtual ~Attr() { - assert(Next == 0 && "Destroy didn't work"); +public: + // Forward so that the regular new and delete do not hide global ones. + void* operator new(size_t Bytes, ASTContext &C, + size_t Alignment = 16) throw() { + return ::operator new(Bytes, C, Alignment); } + void operator delete(void *Ptr, ASTContext &C, + size_t Alignment) throw() { + return ::operator delete(Ptr, C, Alignment); + } + +protected: + Attr(attr::Kind AK, SourceLocation L) + : Loc(L), AttrKind(AK), Inherited(false) {} + public: - virtual void Destroy(ASTContext &C); /// \brief Whether this attribute should be merged to new /// declarations. virtual bool isMerged() const { return true; } - attr::Kind getKind() const { return AttrKind; } - - Attr *getNext() { return Next; } - const Attr *getNext() const { return Next; } - void setNext(Attr *next) { Next = next; } - - template<typename T> const T *getNext() const { - for (const Attr *attr = getNext(); attr; attr = attr->getNext()) - if (const T *V = dyn_cast<T>(attr)) - return V; - return 0; + attr::Kind getKind() const { + return static_cast<attr::Kind>(AttrKind); } - bool isInherited() const { return Inherited; } - void setInherited(bool value) { Inherited = value; } - - void addAttr(Attr *attr) { - assert((attr != 0) && "addAttr(): attr is null"); + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } - // FIXME: This doesn't preserve the order in any way. - attr->Next = Next; - Next = attr; - } + bool isInherited() const { return Inherited; } + void setInherited(bool I) { Inherited = I; } // Clone this attribute. virtual Attr* clone(ASTContext &C) const = 0; @@ -101,490 +110,112 @@ public: }; #include "clang/AST/Attrs.inc" - -class AttrWithString : public Attr { -private: - const char *Str; - unsigned StrLen; -protected: - AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s); - llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); } - void ReplaceString(ASTContext &C, llvm::StringRef newS); -public: - virtual void Destroy(ASTContext &C); -}; - -#define DEF_SIMPLE_ATTR(ATTR) \ -class ATTR##Attr : public Attr { \ -public: \ - ATTR##Attr() : Attr(attr::ATTR) {} \ - virtual Attr *clone(ASTContext &C) const; \ - static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \ - static bool classof(const ATTR##Attr *A) { return true; } \ -} -DEF_SIMPLE_ATTR(Packed); - -/// \brief Attribute for specifying a maximum field alignment; this is only -/// valid on record decls. -class MaxFieldAlignmentAttr : public Attr { - unsigned Alignment; - -public: - MaxFieldAlignmentAttr(unsigned alignment) - : Attr(attr::MaxFieldAlignment), Alignment(alignment) {} +/// AttrVec - A vector of Attr, which is how they are stored on the AST. +typedef llvm::SmallVector<Attr*, 2> AttrVec; +typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec; - /// getAlignment - The specified alignment in bits. - unsigned getAlignment() const { return Alignment; } - - virtual Attr* clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::MaxFieldAlignment; - } - static bool classof(const MaxFieldAlignmentAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(AlignMac68k); - -/// \brief Atribute for specifying the alignment of a variable or type. -/// -/// This node will either contain the precise Alignment (in bits, not bytes!) -/// or will contain the expression for the alignment attribute in the case of -/// a dependent expression within a class or function template. At template -/// instantiation time these are transformed into concrete attributes. -class AlignedAttr : public Attr { - unsigned Alignment; - Expr *AlignmentExpr; -public: - AlignedAttr(unsigned alignment) - : Attr(attr::Aligned), Alignment(alignment), AlignmentExpr(0) {} - AlignedAttr(Expr *E) - : Attr(attr::Aligned), Alignment(0), AlignmentExpr(E) {} - - /// getAlignmentExpr - Get a dependent alignment expression if one is present. - Expr *getAlignmentExpr() const { - return AlignmentExpr; - } - - /// isDependent - Is the alignment a dependent expression - bool isDependent() const { - return getAlignmentExpr(); - } +/// DestroyAttrs - Destroy the contents of an AttrVec. +inline void DestroyAttrs (AttrVec& V, ASTContext &C) { +} - /// getAlignment - The specified alignment in bits. Requires !isDependent(). - unsigned getAlignment() const { - assert(!isDependent() && "Cannot get a value dependent alignment"); - return Alignment; - } +/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only +/// providing attributes that are of a specifc type. +template <typename SpecificAttr> +class specific_attr_iterator { + /// Current - The current, underlying iterator. + /// In order to ensure we don't dereference an invalid iterator unless + /// specifically requested, we don't necessarily advance this all the + /// way. Instead, we advance it when an operation is requested; if the + /// operation is acting on what should be a past-the-end iterator, + /// then we offer no guarantees, but this way we do not dererence a + /// past-the-end iterator when we move to a past-the-end position. + mutable AttrVec::const_iterator Current; - /// getMaxAlignment - Get the maximum alignment of attributes on this list. - unsigned getMaxAlignment() const { - const AlignedAttr *Next = getNext<AlignedAttr>(); - if (Next) - return std::max(Next->getMaxAlignment(), getAlignment()); - else - return getAlignment(); + void AdvanceToNext() const { + while (!llvm::isa<SpecificAttr>(*Current)) + ++Current; } - virtual Attr* clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::Aligned; + void AdvanceToNext(AttrVec::const_iterator I) const { + while (Current != I && !llvm::isa<SpecificAttr>(*Current)) + ++Current; } - static bool classof(const AlignedAttr *A) { return true; } -}; -class AnnotateAttr : public AttrWithString { public: - AnnotateAttr(ASTContext &C, llvm::StringRef ann) - : AttrWithString(attr::Annotate, C, ann) {} - - llvm::StringRef getAnnotation() const { return getString(); } + typedef SpecificAttr* value_type; + typedef SpecificAttr* reference; + typedef SpecificAttr* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; - virtual Attr* clone(ASTContext &C) const; + specific_attr_iterator() : Current() { } + explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { } - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::Annotate; + reference operator*() const { + AdvanceToNext(); + return llvm::cast<SpecificAttr>(*Current); } - static bool classof(const AnnotateAttr *A) { return true; } -}; - -class AsmLabelAttr : public AttrWithString { -public: - AsmLabelAttr(ASTContext &C, llvm::StringRef L) - : AttrWithString(attr::AsmLabel, C, L) {} - - llvm::StringRef getLabel() const { return getString(); } - - virtual Attr* clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::AsmLabel; - } - static bool classof(const AsmLabelAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(AlwaysInline); - -class AliasAttr : public AttrWithString { -public: - AliasAttr(ASTContext &C, llvm::StringRef aliasee) - : AttrWithString(attr::Alias, C, aliasee) {} - - llvm::StringRef getAliasee() const { return getString(); } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Alias; } - static bool classof(const AliasAttr *A) { return true; } -}; - -class ConstructorAttr : public Attr { - int priority; -public: - ConstructorAttr(int p) : Attr(attr::Constructor), priority(p) {} - - int getPriority() const { return priority; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) - { return A->getKind() == attr::Constructor; } - static bool classof(const ConstructorAttr *A) { return true; } -}; - -class DestructorAttr : public Attr { - int priority; -public: - DestructorAttr(int p) : Attr(attr::Destructor), priority(p) {} - - int getPriority() const { return priority; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) - { return A->getKind() == attr::Destructor; } - static bool classof(const DestructorAttr *A) { return true; } -}; - -class IBOutletAttr : public Attr { -public: - IBOutletAttr() : Attr(attr::IBOutlet) {} - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::IBOutlet; - } - static bool classof(const IBOutletAttr *A) { return true; } -}; - -class IBOutletCollectionAttr : public Attr { - const ObjCInterfaceDecl *D; -public: - IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0) - : Attr(attr::IBOutletCollection), D(d) {} - - const ObjCInterfaceDecl *getClass() const { return D; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::IBOutletCollection; + pointer operator->() const { + AdvanceToNext(); + return llvm::cast<SpecificAttr>(*Current); } - static bool classof(const IBOutletCollectionAttr *A) { return true; } -}; - -class IBActionAttr : public Attr { -public: - IBActionAttr() : Attr(attr::IBAction) {} - - virtual Attr *clone(ASTContext &C) const; - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::IBAction; + specific_attr_iterator& operator++() { + ++Current; + return *this; } - static bool classof(const IBActionAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(AnalyzerNoReturn); -DEF_SIMPLE_ATTR(Deprecated); -DEF_SIMPLE_ATTR(GNUInline); -DEF_SIMPLE_ATTR(Malloc); -DEF_SIMPLE_ATTR(NoReturn); -DEF_SIMPLE_ATTR(NoInstrumentFunction); - -class SectionAttr : public AttrWithString { -public: - SectionAttr(ASTContext &C, llvm::StringRef N) - : AttrWithString(attr::Section, C, N) {} - - llvm::StringRef getName() const { return getString(); } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::Section; + specific_attr_iterator operator++(int) { + specific_attr_iterator Tmp(*this); + ++(*this); + return Tmp; } - static bool classof(const SectionAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(Unavailable); -DEF_SIMPLE_ATTR(Unused); -DEF_SIMPLE_ATTR(Used); -DEF_SIMPLE_ATTR(Weak); -DEF_SIMPLE_ATTR(WeakImport); -DEF_SIMPLE_ATTR(WeakRef); -DEF_SIMPLE_ATTR(NoThrow); -DEF_SIMPLE_ATTR(Const); -DEF_SIMPLE_ATTR(Pure); - -class NonNullAttr : public Attr { - unsigned* ArgNums; - unsigned Size; -public: - NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0); - - virtual void Destroy(ASTContext &C); - - typedef const unsigned *iterator; - iterator begin() const { return ArgNums; } - iterator end() const { return ArgNums + Size; } - unsigned size() const { return Size; } - bool isNonNull(unsigned arg) const { - return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true; + friend bool operator==(specific_attr_iterator Left, + specific_attr_iterator Right) { + if (Left.Current < Right.Current) + Left.AdvanceToNext(Right.Current); + else + Right.AdvanceToNext(Left.Current); + return Left.Current == Right.Current; } - - virtual Attr *clone(ASTContext &C) const; - - static bool classof(const Attr *A) { return A->getKind() == attr::NonNull; } - static bool classof(const NonNullAttr *A) { return true; } -}; - -class FormatAttr : public AttrWithString { - int formatIdx, firstArg; -public: - FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first) - : AttrWithString(attr::Format, C, type), formatIdx(idx), firstArg(first) {} - - llvm::StringRef getType() const { return getString(); } - void setType(ASTContext &C, llvm::StringRef type); - int getFormatIdx() const { return formatIdx; } - int getFirstArg() const { return firstArg; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Format; } - static bool classof(const FormatAttr *A) { return true; } -}; - -class FormatArgAttr : public Attr { - int formatIdx; -public: - FormatArgAttr(int idx) : Attr(attr::FormatArg), formatIdx(idx) {} - int getFormatIdx() const { return formatIdx; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::FormatArg; } - static bool classof(const FormatArgAttr *A) { return true; } -}; - -class SentinelAttr : public Attr { - int sentinel, NullPos; -public: - SentinelAttr(int sentinel_val, int nullPos) : Attr(attr::Sentinel), - sentinel(sentinel_val), NullPos(nullPos) {} - int getSentinel() const { return sentinel; } - int getNullPos() const { return NullPos; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Sentinel; } - static bool classof(const SentinelAttr *A) { return true; } -}; - -class VisibilityAttr : public Attr { -public: - /// @brief An enumeration for the kinds of visibility of symbols. - enum VisibilityTypes { - DefaultVisibility = 0, - HiddenVisibility, - ProtectedVisibility - }; -private: - VisibilityTypes VisibilityType; -public: - VisibilityAttr(VisibilityTypes v) : Attr(attr::Visibility), - VisibilityType(v) {} - - VisibilityTypes getVisibility() const { return VisibilityType; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) - { return A->getKind() == attr::Visibility; } - static bool classof(const VisibilityAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(FastCall); -DEF_SIMPLE_ATTR(StdCall); -DEF_SIMPLE_ATTR(ThisCall); -DEF_SIMPLE_ATTR(CDecl); -DEF_SIMPLE_ATTR(TransparentUnion); -DEF_SIMPLE_ATTR(ObjCNSObject); -DEF_SIMPLE_ATTR(ObjCException); - -class OverloadableAttr : public Attr { -public: - OverloadableAttr() : Attr(attr::Overloadable) { } - - virtual bool isMerged() const { return false; } - - virtual Attr *clone(ASTContext &C) const; - - static bool classof(const Attr *A) - { return A->getKind() == attr::Overloadable; } - static bool classof(const OverloadableAttr *) { return true; } -}; - -class BlocksAttr : public Attr { -public: - enum BlocksAttrTypes { - ByRef = 0 - }; -private: - BlocksAttrTypes BlocksAttrType; -public: - BlocksAttr(BlocksAttrTypes t) : Attr(attr::Blocks), BlocksAttrType(t) {} - - BlocksAttrTypes getType() const { return BlocksAttrType; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Blocks; } - static bool classof(const BlocksAttr *A) { return true; } -}; - -class FunctionDecl; - -class CleanupAttr : public Attr { - FunctionDecl *FD; - -public: - CleanupAttr(FunctionDecl *fd) : Attr(attr::Cleanup), FD(fd) {} - - const FunctionDecl *getFunctionDecl() const { return FD; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Cleanup; } - static bool classof(const CleanupAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(NoDebug); -DEF_SIMPLE_ATTR(WarnUnusedResult); -DEF_SIMPLE_ATTR(NoInline); - -class RegparmAttr : public Attr { - unsigned NumParams; - -public: - RegparmAttr(unsigned np) : Attr(attr::Regparm), NumParams(np) {} - - unsigned getNumParams() const { return NumParams; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Regparm; } - static bool classof(const RegparmAttr *A) { return true; } -}; - -class ReqdWorkGroupSizeAttr : public Attr { - unsigned X, Y, Z; -public: - ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z) - : Attr(attr::ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {} - - unsigned getXDim() const { return X; } - unsigned getYDim() const { return Y; } - unsigned getZDim() const { return Z; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::ReqdWorkGroupSize; + friend bool operator!=(specific_attr_iterator Left, + specific_attr_iterator Right) { + return !(Left == Right); } - static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; } }; -class InitPriorityAttr : public Attr { - unsigned Priority; -public: - InitPriorityAttr(unsigned priority) - : Attr(attr::InitPriority), Priority(priority) {} - - virtual void Destroy(ASTContext &C) { Attr::Destroy(C); } - - unsigned getPriority() const { return Priority; } - - virtual Attr *clone(ASTContext &C) const; - - static bool classof(const Attr *A) - { return A->getKind() == attr::InitPriority; } - static bool classof(const InitPriorityAttr *A) { return true; } -}; - -// Checker-specific attributes. -DEF_SIMPLE_ATTR(CFReturnsNotRetained); -DEF_SIMPLE_ATTR(CFReturnsRetained); -DEF_SIMPLE_ATTR(NSReturnsNotRetained); -DEF_SIMPLE_ATTR(NSReturnsRetained); - -// Target-specific attributes -DEF_SIMPLE_ATTR(DLLImport); -DEF_SIMPLE_ATTR(DLLExport); - -class MSP430InterruptAttr : public Attr { - unsigned Number; - -public: - MSP430InterruptAttr(unsigned n) : Attr(attr::MSP430Interrupt), Number(n) {} - - unsigned getNumber() const { return Number; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) - { return A->getKind() == attr::MSP430Interrupt; } - static bool classof(const MSP430InterruptAttr *A) { return true; } -}; +template <typename T> +inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) { + return specific_attr_iterator<T>(vec.begin()); +} +template <typename T> +inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) { + return specific_attr_iterator<T>(vec.end()); +} -DEF_SIMPLE_ATTR(X86ForceAlignArgPointer); +template <typename T> +inline bool hasSpecificAttr(const AttrVec& vec) { + return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec); +} +template <typename T> +inline T *getSpecificAttr(const AttrVec& vec) { + specific_attr_iterator<T> i = specific_attr_begin<T>(vec); + if (i != specific_attr_end<T>(vec)) + return *i; + else + return 0; +} -#undef DEF_SIMPLE_ATTR +/// getMaxAlignment - Returns the highest alignment value found among +/// AlignedAttrs in an AttrVec, or 0 if there are none. +inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) { + unsigned Align = 0; + specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end()); + for(; i != e; ++i) + Align = std::max(Align, i->getAlignment(Ctx)); + return Align; +} } // end namespace clang diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index 3b090715e083..800c58361b02 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -5,6 +5,12 @@ tablegen(Attrs.inc add_custom_target(ClangAttrClasses DEPENDS Attrs.inc) +tablegen(AttrImpl.inc + -gen-clang-attr-impl + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) +add_custom_target(ClangAttrImpl + DEPENDS AttrImpl.inc) + set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td) tablegen(StmtNodes.inc -gen-clang-stmt-nodes) diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 9f97fd8a7aee..dad4dfc926e1 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -273,6 +273,9 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) @@ -700,9 +703,9 @@ inline CanQual<Type> CanQual<T>::getNonReferenceType() const { template<typename T> CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { CanQual<T> Result; - Result.Stored.setFromOpaqueValue(Ptr); - assert((!Result || Result.Stored.isCanonical()) - && "Type is not canonical!"); + Result.Stored = QualType::getFromOpaquePtr(Ptr); + assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 || + Result.Stored.isCanonical()) && "Type is not canonical!"); return Result; } diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 39cd51f606b5..674925532210 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -118,16 +118,6 @@ public: return getIdentifier() ? getIdentifier()->getName() : ""; } - /// getNameAsCString - Get the name of identifier for this declaration as a - /// C string (const char*). This requires that the declaration have a name - /// and that it be a simple identifier. - // - // FIXME: Deprecated, move clients to getName(). - const char *getNameAsCString() const { - assert(Name.isIdentifier() && "Name is not a simple identifier"); - return getIdentifier() ? getIdentifier()->getNameStart() : ""; - } - /// getNameAsString - Get a human-readable name for the declaration, even if /// it is one of the special kinds of names (C++ constructor, Objective-C /// selector, etc). Creating this name requires expensive string @@ -229,6 +219,8 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, /// NamespaceDecl - Represent a C++ namespace. class NamespaceDecl : public NamedDecl, public DeclContext { + bool IsInline : 1; + SourceLocation LBracLoc, RBracLoc; // For extended namespace definitions: @@ -239,7 +231,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext { // there will be one NamespaceDecl for each declaration. // NextNamespace points to the next extended declaration. // OrigNamespace points to the original namespace declaration. - // OrigNamespace of the first namespace decl points to itself. + // OrigNamespace of the first namespace decl points to its anonymous namespace NamespaceDecl *NextNamespace; /// \brief A pointer to either the original namespace definition for @@ -258,28 +250,36 @@ class NamespaceDecl : public NamedDecl, public DeclContext { NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), - NextNamespace(0), OrigOrAnonNamespace(0, true) { } + IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { } public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); - virtual void Destroy(ASTContext& C); - - // \brief Returns true if this is an anonymous namespace declaration. - // - // For example: + /// \brief Returns true if this is an anonymous namespace declaration. + /// + /// For example: /// \code - // namespace { - // ... - // }; - // \endcode - // q.v. C++ [namespace.unnamed] + /// namespace { + /// ... + /// }; + /// \endcode + /// q.v. C++ [namespace.unnamed] bool isAnonymousNamespace() const { return !getIdentifier(); } - /// \brief Return the next extended namespace declaration or null if this + /// \brief Returns true if this is an inline namespace declaration. + bool isInline() const { + return IsInline; + } + + /// \brief Set whether this is an inline namespace declaration. + void setInline(bool Inline) { + IsInline = Inline; + } + + /// \brief Return the next extended namespace declaration or null if there /// is none. NamespaceDecl *getNextNamespace() { return NextNamespace; } const NamespaceDecl *getNextNamespace() const { return NextNamespace; } @@ -345,8 +345,8 @@ public: return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// ValueDecl - Represent the declaration of a variable (in which case it is @@ -392,8 +392,6 @@ struct QualifierInfo { unsigned NumTPLists, TemplateParameterList **TPLists); - void Destroy(ASTContext &Context); - private: // Copy constructor and copy assignment are disabled. QualifierInfo(const QualifierInfo&); @@ -421,9 +419,6 @@ protected: : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {} public: - virtual ~DeclaratorDecl(); - virtual void Destroy(ASTContext &C); - TypeSourceInfo *getTypeSourceInfo() const { return hasExtInfo() ? getExtInfo()->TInfo @@ -507,36 +502,11 @@ struct EvaluatedStmt { APValue Evaluated; }; -// \brief Describes the kind of template specialization that a -// particular template specialization declaration represents. -enum TemplateSpecializationKind { - /// This template specialization was formed from a template-id but - /// has not yet been declared, defined, or instantiated. - TSK_Undeclared = 0, - /// This template specialization was implicitly instantiated from a - /// template. (C++ [temp.inst]). - TSK_ImplicitInstantiation, - /// This template specialization was declared or defined by an - /// explicit specialization (C++ [temp.expl.spec]) or partial - /// specialization (C++ [temp.class.spec]). - TSK_ExplicitSpecialization, - /// This template specialization was instantiated from a template - /// due to an explicit instantiation declaration request - /// (C++0x [temp.explicit]). - TSK_ExplicitInstantiationDeclaration, - /// This template specialization was instantiated from a template - /// due to an explicit instantiation definition request - /// (C++ [temp.explicit]). - TSK_ExplicitInstantiationDefinition -}; - /// VarDecl - An instance of this class is created to represent a variable /// declaration or definition. class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { public: - enum StorageClass { - None, Auto, Register, Extern, Static, PrivateExtern - }; + typedef clang::StorageClass StorageClass; /// getStorageClassSpecifierString - Return the string used to /// specify the storage class \arg SC. @@ -568,10 +538,6 @@ private: bool ThreadSpecified : 1; bool HasCXXDirectInit : 1; - /// DeclaredInCondition - Whether this variable was declared in a - /// condition, e.g., if (int x = foo()) { ... }. - bool DeclaredInCondition : 1; - /// \brief Whether this variable is the exception variable in a C++ catch /// or an Objective-C @catch statement. bool ExceptionVar : 1; @@ -587,7 +553,7 @@ protected: StorageClass SCAsWritten) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - DeclaredInCondition(false), ExceptionVar(false), NRVOVariable(false) { + ExceptionVar(false), NRVOVariable(false) { SClass = SC; SClassAsWritten = SCAsWritten; } @@ -609,9 +575,6 @@ public: QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten); - virtual void Destroy(ASTContext& C); - virtual ~VarDecl(); - virtual SourceLocation getInnerLocStart() const; virtual SourceRange getSourceRange() const; @@ -619,8 +582,14 @@ public: StorageClass getStorageClassAsWritten() const { return (StorageClass) SClassAsWritten; } - void setStorageClass(StorageClass SC) { SClass = SC; } - void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } + void setStorageClass(StorageClass SC) { + assert(isLegalForVariable(SC)); + SClass = SC; + } + void setStorageClassAsWritten(StorageClass SC) { + assert(isLegalForVariable(SC)); + SClassAsWritten = SC; + } void setThreadSpecified(bool T) { ThreadSpecified = T; } bool isThreadSpecified() const { @@ -630,25 +599,26 @@ public: /// hasLocalStorage - Returns true if a variable with function scope /// is a non-static local variable. bool hasLocalStorage() const { - if (getStorageClass() == None) + if (getStorageClass() == SC_None) return !isFileVarDecl(); // Return true for: Auto, Register. // Return false for: Extern, Static, PrivateExtern. - return getStorageClass() <= Register; + return getStorageClass() >= SC_Auto; } /// isStaticLocal - Returns true if a variable with function scope is a /// static local variable. bool isStaticLocal() const { - return getStorageClass() == Static && !isFileVarDecl(); + return getStorageClass() == SC_Static && !isFileVarDecl(); } /// hasExternStorage - Returns true if a variable has extern or /// __private_extern__ storage. bool hasExternalStorage() const { - return getStorageClass() == Extern || getStorageClass() == PrivateExtern; + return getStorageClass() == SC_Extern || + getStorageClass() == SC_PrivateExtern; } /// hasGlobalStorage - Returns true for all variables that do not @@ -670,7 +640,7 @@ public: if (getKind() != Decl::Var) return false; if (const DeclContext *DC = getDeclContext()) - return DC->getLookupContext()->isFunctionOrMethod(); + return DC->getRedeclContext()->isFunctionOrMethod(); return false; } @@ -679,10 +649,8 @@ public: bool isFunctionOrMethodVarDecl() const { if (getKind() != Decl::Var) return false; - if (const DeclContext *DC = getDeclContext()) - return DC->getLookupContext()->isFunctionOrMethod() && - DC->getLookupContext()->getDeclKind() != Decl::Block; - return false; + const DeclContext *DC = getDeclContext()->getRedeclContext(); + return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block; } /// \brief Determines whether this is a static data member. @@ -696,7 +664,7 @@ public: /// \endcode bool isStaticDataMember() const { // If it wasn't static, it would be a FieldDecl. - return getDeclContext()->isRecord(); + return getKind() != Decl::ParmVar && getDeclContext()->isRecord(); } virtual VarDecl *getCanonicalDecl(); @@ -743,11 +711,10 @@ public: bool isFileVarDecl() const { if (getKind() != Decl::Var) return false; - if (const DeclContext *Ctx = getDeclContext()) { - Ctx = Ctx->getLookupContext(); - if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) ) - return true; - } + + if (getDeclContext()->getRedeclContext()->isFileContext()) + return true; + if (isStaticDataMember()) return true; @@ -912,18 +879,6 @@ public: return HasCXXDirectInit; } - /// isDeclaredInCondition - Whether this variable was declared as - /// part of a condition in an if/switch/while statement, e.g., - /// @code - /// if (int x = foo()) { ... } - /// @endcode - bool isDeclaredInCondition() const { - return DeclaredInCondition; - } - void setDeclaredInCondition(bool InCondition) { - DeclaredInCondition = InCondition; - } - /// \brief Determine whether this variable is the exception variable in a /// C++ catch statememt or an Objective-C @catch statement. bool isExceptionVariable() const { @@ -973,7 +928,7 @@ class ImplicitParamDecl : public VarDecl { protected: ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType Tw) - : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None, VarDecl::None) {} + : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {} public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -1117,9 +1072,7 @@ public: class FunctionDecl : public DeclaratorDecl, public DeclContext, public Redeclarable<FunctionDecl> { public: - enum StorageClass { - None, Extern, Static, PrivateExtern - }; + typedef clang::StorageClass StorageClass; /// \brief The kind of templated function a FunctionDecl can be. enum TemplatedKind { @@ -1179,11 +1132,15 @@ private: DependentFunctionTemplateSpecializationInfo *> TemplateOrSpecialization; + /// DNLoc - Provides source/type location info for the + /// declaration name embedded in the DeclaratorDecl base class. + DeclarationNameLoc DNLoc; + protected: - FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo, + FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, bool isInline) - : DeclaratorDecl(DK, DC, L, N, T, TInfo), + : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo), DeclContext(DK), ParamInfo(0), Body(), SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline), @@ -1191,10 +1148,9 @@ protected: HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsCopyAssignment(false), HasImplicitReturnZero(false), - EndRangeLoc(L), TemplateOrSpecialization() {} - - virtual ~FunctionDecl() {} - virtual void Destroy(ASTContext& C); + EndRangeLoc(NameInfo.getEndLoc()), + TemplateOrSpecialization(), + DNLoc(NameInfo.getInfo()) {} typedef Redeclarable<FunctionDecl> redeclarable_base; virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); } @@ -1211,11 +1167,27 @@ public: static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass S = None, - StorageClass SCAsWritten = None, + StorageClass S = SC_None, + StorageClass SCAsWritten = SC_None, + bool isInline = false, + bool hasWrittenPrototype = true) { + DeclarationNameInfo NameInfo(N, L); + return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten, + isInline, hasWrittenPrototype); + } + + static FunctionDecl *Create(ASTContext &C, DeclContext *DC, + const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, + StorageClass S = SC_None, + StorageClass SCAsWritten = SC_None, bool isInline = false, bool hasWrittenPrototype = true); + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); + } + virtual void getNameForDiagnostic(std::string &S, const PrintingPolicy &Policy, bool Qualified) const; @@ -1245,7 +1217,7 @@ public: /// set that function declaration to the actual declaration /// containing the body (if there is one). /// NOTE: For checking if there is a body, use hasBody() instead, to avoid - /// unnecessary PCH de-serialization of the body. + /// unnecessary AST de-serialization of the body. Stmt *getBody(const FunctionDecl *&Definition) const; virtual Stmt *getBody() const { @@ -1389,12 +1361,18 @@ public: } StorageClass getStorageClass() const { return StorageClass(SClass); } - void setStorageClass(StorageClass SC) { SClass = SC; } + void setStorageClass(StorageClass SC) { + assert(isLegalForFunction(SC)); + SClass = SC; + } StorageClass getStorageClassAsWritten() const { return StorageClass(SClassAsWritten); } - void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } + void setStorageClassAsWritten(StorageClass SC) { + assert(isLegalForFunction(SC)); + SClassAsWritten = SC; + } /// \brief Determine whether the "inline" keyword was specified for this /// function. @@ -1632,8 +1610,8 @@ public: return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC)); } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; @@ -1705,7 +1683,6 @@ protected: const llvm::APSInt &V) : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {} - virtual ~EnumConstantDecl() {} public: static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC, @@ -1713,8 +1690,6 @@ public: QualType T, Expr *E, const llvm::APSInt &V); - virtual void Destroy(ASTContext& C); - const Expr *getInitExpr() const { return (const Expr*) Init; } Expr *getInitExpr() { return (Expr*) Init; } const llvm::APSInt &getInitVal() const { return Val; } @@ -1722,6 +1697,8 @@ public: void setInitExpr(Expr *E) { Init = (Stmt*) E; } void setInitVal(const llvm::APSInt &V) { Val = V; } + SourceRange getSourceRange() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const EnumConstantDecl *D) { return true; } @@ -1770,8 +1747,6 @@ class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> { IdentifierInfo *Id, TypeSourceInfo *TInfo) : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} - virtual ~TypedefDecl(); - protected: typedef Redeclarable<TypedefDecl> redeclarable_base; virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } @@ -1832,6 +1807,9 @@ private: /// it is a declaration ("struct foo;"). bool IsDefinition : 1; + /// IsBeingDefined - True if this is currently being defined. + bool IsBeingDefined : 1; + /// IsEmbeddedInDeclarator - True if this tag declaration is /// "embedded" (i.e., defined or declared for the very first time) /// in the syntax of a declarator. @@ -1873,6 +1851,7 @@ protected: "EnumDecl not matched with TTK_Enum"); TagDeclKind = TK; IsDefinition = false; + IsBeingDefined = false; IsEmbeddedInDeclarator = false; setPreviousDeclaration(PrevDecl); } @@ -1881,8 +1860,6 @@ protected: virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } public: - void Destroy(ASTContext &C); - typedef redeclarable_base::redecl_iterator redecl_iterator; redecl_iterator redecls_begin() const { return redeclarable_base::redecls_begin(); @@ -1911,11 +1888,22 @@ public: return const_cast<TagDecl*>(this)->getCanonicalDecl(); } + /// isThisDeclarationADefinition() - Return true if this declaration + /// defines the type. Provided for consistency. + bool isThisDeclarationADefinition() const { + return isDefinition(); + } + /// isDefinition - Return true if this decl has its body specified. bool isDefinition() const { return IsDefinition; } + /// isBeingDefined - Return true if this decl is currently being defined. + bool isBeingDefined() const { + return IsBeingDefined; + } + bool isEmbeddedInDeclarator() const { return IsEmbeddedInDeclarator; } @@ -2003,8 +1991,8 @@ public: return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// EnumDecl - Represents an enum. As an extension, we allow forward-declared @@ -2037,6 +2025,8 @@ class EnumDecl : public TagDecl { IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { IntegerType = QualType(); + NumNegativeBits = 0; + NumPositiveBits = 0; } public: EnumDecl *getCanonicalDecl() { @@ -2058,8 +2048,6 @@ public: SourceLocation TKL, EnumDecl *PrevDecl); static EnumDecl *Create(ASTContext &C, EmptyShell Empty); - virtual void Destroy(ASTContext& C); - /// completeDefinition - When created, the EnumDecl corresponds to a /// forward-declared enum. This method is used to mark the /// declaration as being defined; it's enumerators have already been @@ -2167,7 +2155,6 @@ protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, RecordDecl *PrevDecl, SourceLocation TKL); - virtual ~RecordDecl(); public: static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, @@ -2183,8 +2170,6 @@ public: return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); } - virtual void Destroy(ASTContext& C); - bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } @@ -2307,9 +2292,6 @@ protected: IsVariadic(false), ParamInfo(0), NumParams(0), Body(0), SignatureAsWritten(0) {} - virtual ~BlockDecl(); - virtual void Destroy(ASTContext& C); - public: static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index be30b8ed296b..1369c2b5955a 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -222,11 +222,13 @@ protected: // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum unsigned Access : 2; friend class CXXClassMemberWrapper; - - // PCHLevel - the "level" of precompiled header/AST file from which this - // declaration was built. - unsigned PCHLevel : 3; - + + /// PCHLevel - the "level" of AST file from which this declaration was built. + unsigned PCHLevel : 2; + + /// ChangedAfterLoad - if this declaration has changed since being loaded + bool ChangedAfterLoad : 1; + /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. unsigned IdentifierNamespace : 15; @@ -243,7 +245,7 @@ protected: : NextDeclInContext(0), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), - Access(AS_none), PCHLevel(0), + Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { if (Decl::CollectingStats()) add(DK); } @@ -251,7 +253,7 @@ protected: Decl(Kind DK, EmptyShell Empty) : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), - Access(AS_none), PCHLevel(0), + Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { if (Decl::CollectingStats()) add(DK); } @@ -305,24 +307,52 @@ public: } bool hasAttrs() const { return HasAttrs; } - void initAttrs(Attr *attrs); - void addAttr(Attr *attr); - const Attr *getAttrs() const { - if (!HasAttrs) return 0; // common case, no attributes. - return getAttrsImpl(); // Uncommon case, out of line hash lookup. + void setAttrs(const AttrVec& Attrs); + AttrVec& getAttrs() { + return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs()); } + const AttrVec &getAttrs() const; void swapAttrs(Decl *D); - void invalidateAttrs(); + void dropAttrs(); + + void addAttr(Attr *A) { + if (hasAttrs()) + getAttrs().push_back(A); + else + setAttrs(AttrVec(1, A)); + } + + typedef AttrVec::const_iterator attr_iterator; + + // FIXME: Do not rely on iterators having comparable singular values. + // Note that this should error out if they do not. + attr_iterator attr_begin() const { + return hasAttrs() ? getAttrs().begin() : 0; + } + attr_iterator attr_end() const { + return hasAttrs() ? getAttrs().end() : 0; + } - template<typename T> const T *getAttr() const { - for (const Attr *attr = getAttrs(); attr; attr = attr->getNext()) - if (const T *V = dyn_cast<T>(attr)) - return V; - return 0; + template <typename T> + specific_attr_iterator<T> specific_attr_begin() const { + return specific_attr_iterator<T>(attr_begin()); + } + template <typename T> + specific_attr_iterator<T> specific_attr_end() const { + return specific_attr_iterator<T>(attr_end()); } + template<typename T> T *getAttr() const { + return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0; + } template<typename T> bool hasAttr() const { - return getAttr<T>() != 0; + return hasAttrs() && hasSpecificAttr<T>(getAttrs()); + } + + /// getMaxAlignment - return the maximum alignment specified by attributes + /// on this decl, 0 if there are none. + unsigned getMaxAlignment() const { + return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0; } /// setInvalidDecl - Indicates the Decl had a semantic error. This @@ -343,22 +373,21 @@ public: /// (in addition to the "used" bit set by \c setUsed()) when determining /// whether the function is used. bool isUsed(bool CheckUsedAttr = true) const; - + void setUsed(bool U = true) { Used = U; } /// \brief Retrieve the level of precompiled header from which this /// declaration was generated. /// /// The PCH level of a declaration describes where the declaration originated - /// from. A PCH level of 0 indicates that the declaration was not from a - /// precompiled header. A PCH level of 1 indicates that the declaration was - /// from a top-level precompiled header; 2 indicates that the declaration - /// comes from a precompiled header on which the top-level precompiled header - /// depends, and so on. + /// from. A PCH level of 0 indicates that the declaration was parsed from + /// source. A PCH level of 1 indicates that the declaration was loaded from + /// a top-level AST file. A PCH level 2 indicates that the declaration was + /// loaded from a PCH file the AST file depends on, and so on. unsigned getPCHLevel() const { return PCHLevel; } /// \brief The maximum PCH level that any declaration may have. - static const unsigned MaxPCHLevel = 7; + static const unsigned MaxPCHLevel = 3; /// \brief Set the PCH level of this declaration. void setPCHLevel(unsigned Level) { @@ -366,6 +395,19 @@ public: PCHLevel = Level; } + /// \brief Query whether this declaration was changed in a significant way + /// since being loaded from an AST file. + /// + /// In an epic violation of layering, what is "significant" is entirely + /// up to the serialization system, but implemented in AST and Sema. + bool isChangedSinceDeserialization() const { return ChangedAfterLoad; } + + /// \brief Mark this declaration as having changed since deserialization, or + /// reset the flag. + void setChangedSinceDeserialization(bool Changed) { + ChangedAfterLoad = Changed; + } + unsigned getIdentifierNamespace() const { return IdentifierNamespace; } @@ -411,10 +453,10 @@ public: void setLexicalDeclContext(DeclContext *DC); - // isDefinedOutsideFunctionOrMethod - This predicate returns true if this - // scoped decl is defined outside the current function or method. This is - // roughly global variables and functions, but also handles enums (which could - // be defined inside or outside a function etc). + /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this + /// scoped decl is defined outside the current function or method. This is + /// roughly global variables and functions, but also handles enums (which + /// could be defined inside or outside a function etc). bool isDefinedOutsideFunctionOrMethod() const; /// \brief Retrieves the "canonical" declaration of the given declaration. @@ -572,9 +614,6 @@ public: static DeclContext *castToDeclContext(const Decl *); static Decl *castFromDeclContext(const DeclContext *); - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const; void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0) const; @@ -603,6 +642,29 @@ public: virtual void print(llvm::raw_ostream &OS) const; }; +class DeclContextLookupResult + : public std::pair<NamedDecl**,NamedDecl**> { +public: + DeclContextLookupResult(NamedDecl **I, NamedDecl **E) + : std::pair<NamedDecl**,NamedDecl**>(I, E) {} + DeclContextLookupResult() + : std::pair<NamedDecl**,NamedDecl**>() {} + + using std::pair<NamedDecl**,NamedDecl**>::operator=; +}; + +class DeclContextLookupConstResult + : public std::pair<NamedDecl*const*, NamedDecl*const*> { +public: + DeclContextLookupConstResult(std::pair<NamedDecl**,NamedDecl**> R) + : std::pair<NamedDecl*const*, NamedDecl*const*>(R) {} + DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E) + : std::pair<NamedDecl*const*, NamedDecl*const*>(I, E) {} + DeclContextLookupConstResult() + : std::pair<NamedDecl*const*, NamedDecl*const*>() {} + + using std::pair<NamedDecl*const*,NamedDecl*const*>::operator=; +}; /// DeclContext - This is used only as base class of specific decl types that /// can act as declaration contexts. These decls are (only the top classes @@ -654,8 +716,6 @@ protected: ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), LastDecl(0) { } - void DestroyDecls(ASTContext &C); - public: ~DeclContext(); @@ -724,6 +784,8 @@ public: return DeclKind == Decl::Namespace; } + bool isInlineNamespace() const; + /// \brief Determines whether this context is dependent on a /// template parameter. bool isDependentContext() const; @@ -742,19 +804,18 @@ public: /// Here, E is a transparent context, so its enumerator (Val1) will /// appear (semantically) that it is in the same context of E. /// Examples of transparent contexts include: enumerations (except for - /// C++0x scoped enums), C++ linkage specifications, and C++0x - /// inline namespaces. + /// C++0x scoped enums), and C++ linkage specifications. bool isTransparentContext() const; /// \brief Determine whether this declaration context is equivalent /// to the declaration context DC. - bool Equals(DeclContext *DC) { + bool Equals(const DeclContext *DC) const { return DC && this->getPrimaryContext() == DC->getPrimaryContext(); } /// \brief Determine whether this declaration context encloses the /// declaration context DC. - bool Encloses(DeclContext *DC); + bool Encloses(const DeclContext *DC) const; /// getPrimaryContext - There may be many different /// declarations of the same entity (including forward declarations @@ -767,13 +828,12 @@ public: return const_cast<DeclContext*>(this)->getPrimaryContext(); } - /// getLookupContext - Retrieve the innermost non-transparent - /// context of this context, which corresponds to the innermost - /// location from which name lookup can find the entities in this - /// context. - DeclContext *getLookupContext(); - const DeclContext *getLookupContext() const { - return const_cast<DeclContext *>(this)->getLookupContext(); + /// getRedeclContext - Retrieve the context in which an entity conflicts with + /// other entities of the same name, or where it is a redeclaration if the + /// two entities are compatible. This skips through transparent contexts. + DeclContext *getRedeclContext(); + const DeclContext *getRedeclContext() const { + return const_cast<DeclContext *>(this)->getRedeclContext(); } /// \brief Retrieve the nearest enclosing namespace context. @@ -782,6 +842,14 @@ public: return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext(); } + /// \brief Test if this context is part of the enclosing namespace set of + /// the context NS, as defined in C++0x [namespace.def]p9. If either context + /// isn't a namespace, this is equivalent to Equals(). + /// + /// The enclosing namespace set of a namespace is the namespace and, if it is + /// inline, its enclosing namespace, recursively. + bool InEnclosingNamespaceSetOf(const DeclContext *NS) const; + /// getNextContext - If this is a DeclContext that may have other /// DeclContexts that are semantically connected but syntactically /// different, such as C++ namespaces, this routine retrieves the @@ -845,6 +913,12 @@ public: decl_iterator decls_end() const; bool decls_empty() const; + /// noload_decls_begin/end - Iterate over the declarations stored in this + /// context that are currently loaded; don't attempt to retrieve anything + /// from an external source. + decl_iterator noload_decls_begin() const; + decl_iterator noload_decls_end() const; + /// specific_decl_iterator - Iterates over a subrange of /// declarations stored in a DeclContext, providing only those that /// are of type SpecificDecl (or a class derived from it). This @@ -1020,9 +1094,8 @@ public: /// access to the results of lookup up a name within this context. typedef NamedDecl * const * lookup_const_iterator; - typedef std::pair<lookup_iterator, lookup_iterator> lookup_result; - typedef std::pair<lookup_const_iterator, lookup_const_iterator> - lookup_const_result; + typedef DeclContextLookupResult lookup_result; + typedef DeclContextLookupConstResult lookup_const_result; /// lookup - Find the declarations (if any) with the given Name in /// this context. Returns a range of iterators that contains all of @@ -1052,6 +1125,14 @@ public: /// the declaration chains. void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true); + /// \brief Deserialize all the visible declarations from external storage. + /// + /// Name lookup deserializes visible declarations lazily, thus a DeclContext + /// may not have a complete name lookup table. This function deserializes + /// the rest of visible declarations from the external storage and completes + /// the name lookup table. + void MaterializeVisibleDeclsFromExternalStorage(); + /// udir_iterator - Iterates through the using-directives stored /// within this context. typedef UsingDirectiveDecl * const * udir_iterator; @@ -1109,7 +1190,6 @@ public: private: void LoadLexicalDeclsFromExternalStorage() const; - void LoadVisibleDeclsFromExternalStorage() const; friend class DependentDiagnostic; StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; @@ -1123,7 +1203,6 @@ inline bool Decl::isTemplateParameter() const { getKind() == TemplateTemplateParm; } - // Specialization selected when ToTy is not a known subclass of DeclContext. template <class ToTy, bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value> diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 41474ab21e32..a9802bfcaf4e 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -17,6 +17,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/Decl.h" +#include "clang/AST/TypeLoc.h" #include "clang/AST/UnresolvedSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -159,7 +160,6 @@ class CXXBaseSpecifier { /// Range - The source code range that covers the full base /// specifier, including the "virtual" (if present) and access /// specifier (if present). - // FIXME: Move over to a TypeLoc! SourceRange Range; /// Virtual - Whether this is a virtual base class or not. @@ -177,15 +177,17 @@ class CXXBaseSpecifier { /// VC++ bug. unsigned Access : 2; - /// BaseType - The type of the base class. This will be a class or - /// struct (or a typedef of such). - QualType BaseType; + /// BaseTypeInfo - The type of the base class. This will be a class or struct + /// (or a typedef of such). The source code range does not include the + /// "virtual" or access specifier. + TypeSourceInfo *BaseTypeInfo; public: CXXBaseSpecifier() { } - CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T) - : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { } + CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, + TypeSourceInfo *TInfo) + : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { } /// getSourceRange - Retrieves the source range that contains the /// entire base specifier. @@ -195,7 +197,7 @@ public: /// class (or not). bool isVirtual() const { return Virtual; } - /// \brief Determine whether this base class if a base of a class declared + /// \brief Determine whether this base class is a base of a class declared /// with the 'class' keyword (vs. one declared with the 'struct' keyword). bool isBaseOfClass() const { return BaseOfClass; } @@ -221,7 +223,10 @@ public: /// getType - Retrieves the type of the base class. This type will /// always be an unqualified class type. - QualType getType() const { return BaseType; } + QualType getType() const { return BaseTypeInfo->getType(); } + + /// getTypeLoc - Retrieves the type and source location of the base class. + TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; /// CXXRecordDecl - Represents a C++ struct/union/class. @@ -400,8 +405,6 @@ protected: CXXRecordDecl *PrevDecl, SourceLocation TKL = SourceLocation()); - ~CXXRecordDecl(); - public: /// base_class_iterator - Iterator that traverses the base classes /// of a class. @@ -449,8 +452,6 @@ public: bool DelayTypeCreation = false); static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty); - virtual void Destroy(ASTContext& C); - bool isDynamicClass() const { return data().Polymorphic || data().NumVBases != 0; } @@ -1056,29 +1057,30 @@ public: return true; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// CXXMethodDecl - Represents a static or instance method of a /// struct/union/class. class CXXMethodDecl : public FunctionDecl { protected: - CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo, + CXXMethodDecl(Kind DK, CXXRecordDecl *RD, + const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, bool isStatic, StorageClass SCAsWritten, bool isInline) - : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None), + : FunctionDecl(DK, RD, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_None), SCAsWritten, isInline) {} public: static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation L, DeclarationName N, - QualType T, TypeSourceInfo *TInfo, - bool isStatic = false, - StorageClass SCAsWritten = FunctionDecl::None, - bool isInline = false); + const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, + bool isStatic = false, + StorageClass SCAsWritten = SC_None, + bool isInline = false); - bool isStatic() const { return getStorageClass() == Static; } + bool isStatic() const { return getStorageClass() == SC_Static; } bool isInstance() const { return !isStatic(); } bool isVirtual() const { @@ -1249,9 +1251,6 @@ public: VarDecl **Indices, unsigned NumIndices); - /// \brief Destroy the base or member initializer. - void Destroy(ASTContext &Context); - /// isBaseInitializer - Returns true when this initializer is /// initializing a base class. bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); } @@ -1285,7 +1284,7 @@ public: /// getMember - If this is a member initializer, returns the /// declaration of the non-static data member being /// initialized. Otherwise, returns NULL. - FieldDecl *getMember() { + FieldDecl *getMember() const { if (isMemberInitializer()) return BaseOrMember.get<FieldDecl*>(); else @@ -1363,7 +1362,7 @@ public: reinterpret_cast<VarDecl **>(this + 1)[I] = Index; } - Expr *getInit() { return static_cast<Expr *>(Init); } + Expr *getInit() const { return static_cast<Expr *>(Init); } }; /// CXXConstructorDecl - Represents a C++ constructor within a @@ -1394,22 +1393,21 @@ class CXXConstructorDecl : public CXXMethodDecl { CXXBaseOrMemberInitializer **BaseOrMemberInitializers; unsigned NumBaseOrMemberInitializers; - CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo, + CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, - FunctionDecl::None, isInline), + : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false, + SC_None, isInline), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { setImplicit(isImplicitlyDeclared); } - virtual void Destroy(ASTContext& C); public: static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation L, DeclarationName N, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicit, bool isInline, bool isImplicitlyDeclared); @@ -1519,8 +1517,8 @@ public: static bool classof(const CXXConstructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConstructor; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// CXXDestructorDecl - Represents a C++ destructor within a @@ -1543,11 +1541,10 @@ class CXXDestructorDecl : public CXXMethodDecl { FunctionDecl *OperatorDelete; - CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, - bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false, - FunctionDecl::None, isInline), + CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + QualType T, bool isInline, bool isImplicitlyDeclared) + : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, /*TInfo=*/0, false, + SC_None, isInline), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } @@ -1555,7 +1552,7 @@ class CXXDestructorDecl : public CXXMethodDecl { public: static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation L, DeclarationName N, + const DeclarationNameInfo &NameInfo, QualType T, bool isInline, bool isImplicitlyDeclared); @@ -1585,8 +1582,8 @@ public: static bool classof(const CXXDestructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXDestructor; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// CXXConversionDecl - Represents a C++ conversion function within a @@ -1604,17 +1601,17 @@ class CXXConversionDecl : public CXXMethodDecl { /// explicitly wrote a cast. This is a C++0x feature. bool IsExplicitSpecified : 1; - CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo, + CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicitSpecified) - : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, - FunctionDecl::None, isInline), + : CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false, + SC_None, isInline), IsExplicitSpecified(isExplicitSpecified) { } public: static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation L, DeclarationName N, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicit); @@ -1642,8 +1639,8 @@ public: static bool classof(const CXXConversionDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConversion; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// LinkageSpecDecl - This represents a linkage specification. For example: @@ -1710,7 +1707,9 @@ public: // artificial name, for all using-directives in order to store // them in DeclContext effectively. class UsingDirectiveDecl : public NamedDecl { - + /// \brief The location of the "using" keyword. + SourceLocation UsingLoc; + /// SourceLocation - Location of 'namespace' token. SourceLocation NamespaceLoc; @@ -1722,10 +1721,6 @@ class UsingDirectiveDecl : public NamedDecl { /// name, if any. NestedNameSpecifier *Qualifier; - /// IdentLoc - Location of nominated namespace-name identifier. - // FIXME: We don't store location of scope specifier. - SourceLocation IdentLoc; - /// NominatedNamespace - Namespace nominated by using-directive. NamedDecl *NominatedNamespace; @@ -1740,17 +1735,16 @@ class UsingDirectiveDecl : public NamedDecl { return DeclarationName::getUsingDirectiveName(); } - UsingDirectiveDecl(DeclContext *DC, SourceLocation L, + UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc, SourceLocation NamespcLoc, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, NamedDecl *Nominated, DeclContext *CommonAncestor) - : NamedDecl(UsingDirective, DC, L, getName()), + : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc), NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), - Qualifier(Qualifier), IdentLoc(IdentLoc), - NominatedNamespace(Nominated), + Qualifier(Qualifier), NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { } @@ -1759,18 +1753,10 @@ public: /// that qualifies the namespace name. SourceRange getQualifierRange() const { return QualifierRange; } - /// \brief Set the source range of the nested-name-specifier that - /// qualifies the namespace name. - void setQualifierRange(SourceRange R) { QualifierRange = R; } - /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace. NestedNameSpecifier *getQualifier() const { return Qualifier; } - /// \brief Set the nested-name-specifier that qualifes the name of the - /// namespace. - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } - NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; } const NamedDecl *getNominatedNamespaceAsWritten() const { return NominatedNamespace; @@ -1783,34 +1769,23 @@ public: return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace(); } - /// setNominatedNamespace - Set the namespace nominataed by the - /// using-directive. - void setNominatedNamespace(NamedDecl* NS); - /// \brief Returns the common ancestor context of this using-directive and /// its nominated namespace. DeclContext *getCommonAncestor() { return CommonAncestor; } const DeclContext *getCommonAncestor() const { return CommonAncestor; } - /// \brief Set the common ancestor context of this using-directive and its - /// nominated namespace. - void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; } - + /// \brief Return the location of the "using" keyword. + SourceLocation getUsingLoc() const { return UsingLoc; } + // FIXME: Could omit 'Key' in name. /// getNamespaceKeyLocation - Returns location of namespace keyword. SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } - /// setNamespaceKeyLocation - Set the the location of the namespacekeyword. - void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; } - /// getIdentLocation - Returns location of identifier. - SourceLocation getIdentLocation() const { return IdentLoc; } - - /// setIdentLocation - set the location of the identifier. - void setIdentLocation(SourceLocation L) { IdentLoc = L; } + SourceLocation getIdentLocation() const { return getLocation(); } static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, + SourceLocation UsingLoc, SourceLocation NamespaceLoc, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, @@ -1818,12 +1793,18 @@ public: NamedDecl *Nominated, DeclContext *CommonAncestor); + SourceRange getSourceRange() const { + return SourceRange(UsingLoc, getLocation()); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingDirectiveDecl *D) { return true; } static bool classofKind(Kind K) { return K == UsingDirective; } // Friend for getUsingDirectiveName. friend class DeclContext; + + friend class ASTDeclReader; }; /// NamespaceAliasDecl - Represents a C++ namespace alias. For example: @@ -1832,7 +1813,8 @@ public: /// namespace Foo = Bar; /// @endcode class NamespaceAliasDecl : public NamedDecl { - SourceLocation AliasLoc; + /// \brief The location of the "namespace" keyword. + SourceLocation NamespaceLoc; /// \brief The source range that covers the nested-name-specifier /// preceding the namespace name. @@ -1849,15 +1831,17 @@ class NamespaceAliasDecl : public NamedDecl { /// NamespaceDecl or a NamespaceAliasDecl. NamedDecl *Namespace; - NamespaceAliasDecl(DeclContext *DC, SourceLocation L, + NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, NamedDecl *Namespace) - : NamedDecl(NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc), - QualifierRange(QualifierRange), Qualifier(Qualifier), - IdentLoc(IdentLoc), Namespace(Namespace) { } + : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), + NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange), + Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { } + friend class ASTDeclReader; + public: /// \brief Retrieve the source range of the nested-name-specifier /// that qualifiers the namespace name. @@ -1889,41 +1873,31 @@ public: /// Returns the location of the alias name, i.e. 'foo' in /// "namespace foo = ns::bar;". - SourceLocation getAliasLoc() const { return AliasLoc; } - - /// Set the location o;f the alias name, e.e., 'foo' in - /// "namespace foo = ns::bar;". - void setAliasLoc(SourceLocation L) { AliasLoc = L; } + SourceLocation getAliasLoc() const { return getLocation(); } /// Returns the location of the 'namespace' keyword. - SourceLocation getNamespaceLoc() const { return getLocation(); } + SourceLocation getNamespaceLoc() const { return NamespaceLoc; } /// Returns the location of the identifier in the named namespace. SourceLocation getTargetNameLoc() const { return IdentLoc; } - /// Set the location of the identifier in the named namespace. - void setTargetNameLoc(SourceLocation L) { IdentLoc = L; } - /// \brief Retrieve the namespace that this alias refers to, which /// may either be a NamespaceDecl or a NamespaceAliasDecl. NamedDecl *getAliasedNamespace() const { return Namespace; } - /// \brief Set the namespace or namespace alias pointed to by this - /// alias decl. - void setAliasedNamespace(NamedDecl *ND) { - assert((isa<NamespaceAliasDecl>(ND) || isa<NamespaceDecl>(ND)) && - "expecting namespace or namespace alias decl"); - Namespace = ND; - } - static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, SourceLocation AliasLoc, + SourceLocation NamespaceLoc, + SourceLocation AliasLoc, IdentifierInfo *Alias, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, NamedDecl *Namespace); + virtual SourceRange getSourceRange() const { + return SourceRange(NamespaceLoc, IdentLoc); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamespaceAliasDecl *D) { return true; } static bool classofKind(Kind K) { return K == NamespaceAlias; } @@ -2002,6 +1976,10 @@ class UsingDecl : public NamedDecl { /// \brief Target nested name specifier. NestedNameSpecifier* TargetNestedName; + /// DNLoc - Provides source/type location info for the + /// declaration name embedded in the ValueDecl base class. + DeclarationNameLoc DNLoc; + /// \brief The collection of shadow declarations associated with /// this using declaration. This set can change as a class is /// processed. @@ -2010,34 +1988,31 @@ class UsingDecl : public NamedDecl { // \brief Has 'typename' keyword. bool IsTypeName; - UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR, + UsingDecl(DeclContext *DC, SourceRange NNR, SourceLocation UL, NestedNameSpecifier* TargetNNS, - DeclarationName Name, bool IsTypeNameArg) - : NamedDecl(Using, DC, L, Name), + const DeclarationNameInfo &NameInfo, bool IsTypeNameArg) + : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), - IsTypeName(IsTypeNameArg) { + DNLoc(NameInfo.getInfo()), IsTypeName(IsTypeNameArg) { } public: - // FIXME: Should be const? /// \brief Returns the source range that covers the nested-name-specifier /// preceding the namespace name. - SourceRange getNestedNameRange() { return NestedNameRange; } + SourceRange getNestedNameRange() const { return NestedNameRange; } /// \brief Set the source range of the nested-name-specifier. void setNestedNameRange(SourceRange R) { NestedNameRange = R; } - // FIXME; Should be const? // FIXME: Naming is inconsistent with other get*Loc functions. /// \brief Returns the source location of the "using" keyword. - SourceLocation getUsingLocation() { return UsingLocation; } + SourceLocation getUsingLocation() const { return UsingLocation; } /// \brief Set the source location of the 'using' keyword. void setUsingLocation(SourceLocation L) { UsingLocation = L; } - /// \brief Get the target nested name declaration. - NestedNameSpecifier* getTargetNestedNameDecl() { + NestedNameSpecifier* getTargetNestedNameDecl() const { return TargetNestedName; } @@ -2046,6 +2021,10 @@ public: TargetNestedName = NNS; } + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); + } + /// \brief Return true if the using declaration has 'typename'. bool isTypeName() const { return IsTypeName; } @@ -2076,15 +2055,21 @@ public: } static UsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL, - NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg); + SourceRange NNR, SourceLocation UsingL, + NestedNameSpecifier* TargetNNS, + const DeclarationNameInfo &NameInfo, + bool IsTypeNameArg); + + SourceRange getSourceRange() const { + return SourceRange(UsingLocation, getNameInfo().getEndLoc()); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingDecl *D) { return true; } static bool classofKind(Kind K) { return K == Using; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// UnresolvedUsingValueDecl - Represents a dependent using @@ -2105,14 +2090,18 @@ class UnresolvedUsingValueDecl : public ValueDecl { NestedNameSpecifier *TargetNestedNameSpecifier; + /// DNLoc - Provides source/type location info for the + /// declaration name embedded in the ValueDecl base class. + DeclarationNameLoc DNLoc; + UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, SourceLocation UsingLoc, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, - DeclarationName TargetName) - : ValueDecl(UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty), - TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), - TargetNestedNameSpecifier(TargetNNS) + const DeclarationNameInfo &NameInfo) + : ValueDecl(UnresolvedUsingValue, DC, + NameInfo.getLoc(), NameInfo.getName(), Ty), + TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), + TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo()) { } public: @@ -2125,7 +2114,7 @@ public: void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } /// \brief Get target nested name declaration. - NestedNameSpecifier* getTargetNestedNameSpecifier() { + NestedNameSpecifier* getTargetNestedNameSpecifier() const { return TargetNestedNameSpecifier; } @@ -2140,10 +2129,18 @@ public: /// \brief Set the source location of the 'using' keyword. void setUsingLoc(SourceLocation L) { UsingLocation = L; } + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); + } + static UnresolvedUsingValueDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, DeclarationName TargetName); + const DeclarationNameInfo &NameInfo); + + SourceRange getSourceRange() const { + return SourceRange(UsingLocation, getNameInfo().getEndLoc()); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingValueDecl *D) { return true; } @@ -2181,43 +2178,34 @@ class UnresolvedUsingTypenameDecl : public TypeDecl { TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS) { } + friend class ASTDeclReader; + public: /// \brief Returns the source range that covers the nested-name-specifier /// preceding the namespace name. SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } - /// \brief Set the source range coverting the nested-name-specifier preceding - /// the namespace name. - void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } - /// \brief Get target nested name declaration. NestedNameSpecifier* getTargetNestedNameSpecifier() { return TargetNestedNameSpecifier; } - /// \brief Set the nested name declaration. - void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) { - TargetNestedNameSpecifier = NNS; - } - /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } - /// \brief Set the source location of the 'using' keyword. - void setUsingLoc(SourceLocation L) { UsingLocation = L; } - /// \brief Returns the source location of the 'typename' keyword. SourceLocation getTypenameLoc() const { return TypenameLocation; } - /// \brief Set the source location of the 'typename' keyword. - void setTypenameLoc(SourceLocation L) { TypenameLocation = L; } - static UnresolvedUsingTypenameDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, SourceLocation TargetNameLoc, DeclarationName TargetName); + SourceRange getSourceRange() const { + return SourceRange(UsingLocation, getLocation()); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; } static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } @@ -2243,12 +2231,11 @@ public: StringLiteral *getMessage() { return Message; } const StringLiteral *getMessage() const { return Message; } - virtual ~StaticAssertDecl(); - virtual void Destroy(ASTContext& C); - static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(StaticAssertDecl *D) { return true; } static bool classofKind(Kind K) { return K == StaticAssert; } + + friend class ASTDeclReader; }; /// Insertion operator for diagnostics. This allows sending AccessSpecifier's diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 9602b677fca5..97da6ca9a1ef 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -29,108 +29,54 @@ class DependentDiagnostic; /// StoredDeclsList - This is an array of decls optimized a common case of only /// containing one entry. struct StoredDeclsList { - /// The kind of data encoded in this list. - enum DataKind { - /// \brief The data is a NamedDecl*. - DK_Decl = 0, - /// \brief The data is a declaration ID (an unsigned value), - /// shifted left by 2 bits. - DK_DeclID = 1, - /// \brief The data is a pointer to a vector (of type VectorTy) - /// that contains declarations. - DK_Decl_Vector = 2, - /// \brief The data is a pointer to a vector (of type VectorTy) - /// that contains declaration ID. - DK_ID_Vector = 3 - }; - - /// VectorTy - When in vector form, this is what the Data pointer points to. - typedef llvm::SmallVector<uintptr_t, 4> VectorTy; - - /// \brief The stored data, which will be either a declaration ID, a - /// pointer to a NamedDecl, or a pointer to a vector. - uintptr_t Data; + + /// DeclsTy - When in vector form, this is what the Data pointer points to. + typedef llvm::SmallVector<NamedDecl *, 4> DeclsTy; + + /// \brief The stored data, which will be either a pointer to a NamedDecl, + /// or a pointer to a vector. + llvm::PointerUnion<NamedDecl *, DeclsTy *> Data; public: - StoredDeclsList() : Data(0) {} + StoredDeclsList() {} StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { - if (VectorTy *RHSVec = RHS.getAsVector()) { - VectorTy *New = new VectorTy(*RHSVec); - Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); - } + if (DeclsTy *RHSVec = RHS.getAsVector()) + Data = new DeclsTy(*RHSVec); } ~StoredDeclsList() { // If this is a vector-form, free the vector. - if (VectorTy *Vector = getAsVector()) + if (DeclsTy *Vector = getAsVector()) delete Vector; } StoredDeclsList &operator=(const StoredDeclsList &RHS) { - if (VectorTy *Vector = getAsVector()) + if (DeclsTy *Vector = getAsVector()) delete Vector; Data = RHS.Data; - if (VectorTy *RHSVec = RHS.getAsVector()) { - VectorTy *New = new VectorTy(*RHSVec); - Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); - } + if (DeclsTy *RHSVec = RHS.getAsVector()) + Data = new DeclsTy(*RHSVec); return *this; } - bool isNull() const { return (Data & ~0x03) == 0; } + bool isNull() const { return Data.isNull(); } NamedDecl *getAsDecl() const { - if ((Data & 0x03) != DK_Decl) - return 0; - - return reinterpret_cast<NamedDecl *>(Data & ~0x03); + return Data.dyn_cast<NamedDecl *>(); } - VectorTy *getAsVector() const { - if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector) - return 0; - - return reinterpret_cast<VectorTy *>(Data & ~0x03); + DeclsTy *getAsVector() const { + return Data.dyn_cast<DeclsTy *>(); } void setOnlyValue(NamedDecl *ND) { assert(!getAsVector() && "Not inline"); - Data = reinterpret_cast<uintptr_t>(ND); - } - - void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) { - if (Vec.size() > 1) { - VectorTy *Vector = getAsVector(); - if (!Vector) { - Vector = new VectorTy; - Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector; - } - - Vector->resize(Vec.size()); - std::copy(Vec.begin(), Vec.end(), Vector->begin()); - return; - } - - if (VectorTy *Vector = getAsVector()) - delete Vector; - - if (Vec.empty()) - Data = 0; - else - Data = (Vec[0] << 2) | DK_DeclID; - } - - /// \brief Force the stored declarations list to contain actual - /// declarations. - /// - /// This routine will resolve any declaration IDs for declarations - /// that may not yet have been loaded from external storage. - void materializeDecls(ASTContext &Context); - - bool hasDeclarationIDs() const { - DataKind DK = (DataKind)(Data & 0x03); - return DK == DK_DeclID || DK == DK_ID_Vector; + Data = ND; + // Make sure that Data is a plain NamedDecl* so we can use its address + // at getLookupResult. + assert(*(NamedDecl **)&Data == ND && + "PointerUnion mangles the NamedDecl pointer!"); } void remove(NamedDecl *D) { @@ -138,30 +84,26 @@ public: if (NamedDecl *Singleton = getAsDecl()) { assert(Singleton == D && "list is different singleton"); (void)Singleton; - Data = 0; + Data = (NamedDecl *)0; return; } - VectorTy &Vec = *getAsVector(); - VectorTy::iterator I = std::find(Vec.begin(), Vec.end(), - reinterpret_cast<uintptr_t>(D)); + DeclsTy &Vec = *getAsVector(); + DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D); assert(I != Vec.end() && "list does not contain decl"); Vec.erase(I); - assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D)) + assert(std::find(Vec.begin(), Vec.end(), D) == Vec.end() && "list still contains decl"); } /// getLookupResult - Return an array of all the decls that this list /// represents. - DeclContext::lookup_result getLookupResult(ASTContext &Context) { + DeclContext::lookup_result getLookupResult() { if (isNull()) return DeclContext::lookup_result(DeclContext::lookup_iterator(0), DeclContext::lookup_iterator(0)); - if (hasDeclarationIDs()) - materializeDecls(Context); - // If we have a single NamedDecl, return it. if (getAsDecl()) { assert(!isNull() && "Empty list isn't allowed"); @@ -172,19 +114,15 @@ public: } assert(getAsVector() && "Must have a vector at this point"); - VectorTy &Vector = *getAsVector(); + DeclsTy &Vector = *getAsVector(); // Otherwise, we have a range result. - return DeclContext::lookup_result((NamedDecl **)&Vector[0], - (NamedDecl **)&Vector[0]+Vector.size()); + return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size()); } /// HandleRedeclaration - If this is a redeclaration of an existing decl, /// replace the old one with D and return true. Otherwise return false. - bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) { - if (hasDeclarationIDs()) - materializeDecls(Context); - + bool HandleRedeclaration(NamedDecl *D) { // Most decls only have one entry in their list, special case it. if (NamedDecl *OldD = getAsDecl()) { if (!D->declarationReplaces(OldD)) @@ -194,12 +132,12 @@ public: } // Determine if this declaration is actually a redeclaration. - VectorTy &Vec = *getAsVector(); - for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); + DeclsTy &Vec = *getAsVector(); + for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); OD != ODEnd; ++OD) { - NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD); + NamedDecl *OldD = *OD; if (D->declarationReplaces(OldD)) { - *OD = reinterpret_cast<uintptr_t>(D); + *OD = D; return true; } } @@ -211,17 +149,15 @@ public: /// not a redeclaration to merge it into the appropriate place in our list. /// void AddSubsequentDecl(NamedDecl *D) { - assert(!hasDeclarationIDs() && "Must materialize before adding decls"); - // If this is the second decl added to the list, convert this to vector // form. if (NamedDecl *OldD = getAsDecl()) { - VectorTy *VT = new VectorTy(); - VT->push_back(reinterpret_cast<uintptr_t>(OldD)); - Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector; + DeclsTy *VT = new DeclsTy(); + VT->push_back(OldD); + Data = VT; } - VectorTy &Vec = *getAsVector(); + DeclsTy &Vec = *getAsVector(); // Using directives end up in a special entry which contains only // other using directives, so all this logic is wasted for them. @@ -232,32 +168,30 @@ public: // iterator which points at the first tag will start a span of // decls that only contains tags. if (D->hasTagIdentifierNamespace()) - Vec.push_back(reinterpret_cast<uintptr_t>(D)); + Vec.push_back(D); // Resolved using declarations go at the front of the list so that // they won't show up in other lookup results. Unresolved using // declarations (which are always in IDNS_Using | IDNS_Ordinary) // follow that so that the using declarations will be contiguous. else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { - VectorTy::iterator I = Vec.begin(); + DeclsTy::iterator I = Vec.begin(); if (D->getIdentifierNamespace() != Decl::IDNS_Using) { while (I != Vec.end() && - reinterpret_cast<NamedDecl *>(*I) - ->getIdentifierNamespace() == Decl::IDNS_Using) + (*I)->getIdentifierNamespace() == Decl::IDNS_Using) ++I; } - Vec.insert(I, reinterpret_cast<uintptr_t>(D)); + Vec.insert(I, D); // All other declarations go at the end of the list, but before any // tag declarations. But we can be clever about tag declarations // because there can only ever be one in a scope. - } else if (reinterpret_cast<NamedDecl *>(Vec.back()) - ->hasTagIdentifierNamespace()) { - uintptr_t TagD = Vec.back(); - Vec.back() = reinterpret_cast<uintptr_t>(D); + } else if (Vec.back()->hasTagIdentifierNamespace()) { + NamedDecl *TagD = Vec.back(); + Vec.back() = D; Vec.push_back(TagD); } else - Vec.push_back(reinterpret_cast<uintptr_t>(D)); + Vec.push_back(D); } }; diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 2807d16379ae..4b5e6fd48bb3 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -68,16 +68,16 @@ public: SourceLocation FriendL); static FriendDecl *Create(ASTContext &C, EmptyShell Empty); - /// If this friend declaration names an (untemplated but - /// possibly dependent) type, return the type; otherwise - /// return null. This is used only for C++0x's unelaborated - /// friend type declarations. + /// If this friend declaration names an (untemplated but possibly + /// dependent) type, return the type; otherwise return null. This + /// is used for elaborated-type-specifiers and, in C++0x, for + /// arbitrary friend type declarations. TypeSourceInfo *getFriendType() const { return Friend.dyn_cast<TypeSourceInfo*>(); } - /// If this friend declaration doesn't name an unelaborated - /// type, return the inner declaration. + /// If this friend declaration doesn't name a type, return the inner + /// declaration. NamedDecl *getFriendDecl() const { return Friend.dyn_cast<NamedDecl*>(); } @@ -92,8 +92,8 @@ public: static bool classof(const FriendDecl *D) { return true; } static bool classofKind(Kind K) { return K == Decl::Friend; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// An iterator over the friend declarations of a class. diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h index e1fae8f2ae67..030291ea7345 100644 --- a/include/clang/AST/DeclGroup.h +++ b/include/clang/AST/DeclGroup.h @@ -34,7 +34,6 @@ private: public: static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); - void Destroy(ASTContext& C); unsigned size() const { return NumDecls; } diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 30f63d895959..ad26748e1343 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -21,7 +21,6 @@ namespace clang { class Expr; class Stmt; class FunctionDecl; -class AttributeList; class RecordDecl; class ObjCIvarDecl; class ObjCMethodDecl; @@ -41,12 +40,6 @@ protected: public: ObjCListBase() : List(0), NumElts(0) {} - ~ObjCListBase() { - assert(List == 0 && "Destroy should have been called before dtor"); - } - - void Destroy(ASTContext &Ctx); - unsigned size() const { return NumElts; } bool empty() const { return NumElts == 0; } @@ -92,7 +85,6 @@ public: void set(ObjCProtocolDecl* const* InList, unsigned Elts, const SourceLocation *Locs, ASTContext &Ctx); - void Destroy(ASTContext &Ctx); }; @@ -128,6 +120,9 @@ private: // Synthesized declaration method for a property setter/getter bool IsSynthesized : 1; + + // Method has a definition. + bool IsDefined : 1; // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum /// @required/@optional @@ -171,29 +166,25 @@ private: bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, + bool isDefined = false, ImplementationControl impControl = None, unsigned numSelectorArgs = 0) : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), DeclContext(ObjCMethod), IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), + IsDefined(isDefined), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), NumSelectorArgs(numSelectorArgs), MethodDeclType(T), ResultTInfo(ResultTInfo), EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} - virtual ~ObjCMethodDecl() {} - /// \brief A definition will return its interface declaration. /// An interface declaration will return its definition. /// Otherwise it will return itself. virtual ObjCMethodDecl *getNextRedeclaration(); public: - - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - static ObjCMethodDecl *Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, @@ -203,6 +194,7 @@ public: bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, + bool isDefined = false, ImplementationControl impControl = None, unsigned numSelectorArgs = 0); @@ -296,6 +288,9 @@ public: bool isSynthesized() const { return IsSynthesized; } void setSynthesized(bool isSynth) { IsSynthesized = isSynth; } + + bool isDefined() const { return IsDefined; } + void setDefined(bool isDefined) { IsDefined = isDefined; } // Related to protocols declared in @protocol void setDeclImplementation(ImplementationControl ic) { @@ -326,21 +321,6 @@ public: } }; -/// ObjCMethodList - a linked list of methods with different signatures. -struct ObjCMethodList { - ObjCMethodDecl *Method; - ObjCMethodList *Next; - - ObjCMethodList() { - Method = 0; - Next = 0; - } - ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) { - Method = M; - Next = C; - } -}; - /// ObjCContainerDecl - Represents a container for method declarations. /// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, /// ObjCProtocolDecl, and ObjCImplDecl. @@ -355,8 +335,6 @@ public: IdentifierInfo *Id) : NamedDecl(DK, DC, L, Id), DeclContext(DK) {} - virtual ~ObjCContainerDecl() {} - // Iterator access to properties. typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; prop_iterator prop_begin() const { @@ -465,12 +443,19 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { /// Class's super class. ObjCInterfaceDecl *SuperClass; - /// Protocols referenced in interface header declaration + /// Protocols referenced in the @interface declaration ObjCProtocolList ReferencedProtocols; + + /// Protocols reference in both the @interface and class extensions. + ObjCList<ObjCProtocolDecl> AllReferencedProtocols; /// List of categories defined for this class. /// FIXME: Why is this a linked list?? ObjCCategoryDecl *CategoryList; + + /// IvarList - List of all ivars defined by this class; including class + /// extensions and implementation. This list is built lazily. + ObjCIvarDecl *IvarList; bool ForwardDecl:1; // declared with @class. bool InternalInterface:1; // true - no @interface for @implementation @@ -482,13 +467,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, SourceLocation CLoc, bool FD, bool isInternal); - virtual ~ObjCInterfaceDecl() {} - public: - - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, @@ -513,25 +492,49 @@ public: } typedef ObjCProtocolList::iterator protocol_iterator; - protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} - protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } + + protocol_iterator protocol_begin() const { + return ReferencedProtocols.begin(); + } + protocol_iterator protocol_end() const { + return ReferencedProtocols.end(); + } + typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; + protocol_loc_iterator protocol_loc_begin() const { return ReferencedProtocols.loc_begin(); } + protocol_loc_iterator protocol_loc_end() const { return ReferencedProtocols.loc_end(); } - unsigned protocol_size() const { return ReferencedProtocols.size(); } + + typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator; + + all_protocol_iterator all_referenced_protocol_begin() const { + return AllReferencedProtocols.empty() ? protocol_begin() + : AllReferencedProtocols.begin(); + } + all_protocol_iterator all_referenced_protocol_end() const { + return AllReferencedProtocols.empty() ? protocol_end() + : AllReferencedProtocols.end(); + } typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); } + unsigned ivar_size() const { return std::distance(ivar_begin(), ivar_end()); } + bool ivar_empty() const { return ivar_begin() == ivar_end(); } - + + ObjCIvarDecl *all_declared_ivar_begin(); + void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; } + /// setProtocolList - Set the list of protocols that this interface /// implements. void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num, @@ -543,7 +546,6 @@ public: /// into the protocol list for this class. void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, unsigned Num, - const SourceLocation *Locs, ASTContext &C); bool isForwardDecl() const { return ForwardDecl; } @@ -625,6 +627,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCInterfaceDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCInterface; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC @@ -650,21 +655,26 @@ public: private: ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW) + QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, + bool synthesized) : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), - DeclAccess(ac) {} + NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} public: static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - AccessControl ac, Expr *BW = NULL); + AccessControl ac, Expr *BW = NULL, + bool synthesized=false); /// \brief Return the class interface that this ivar is logically contained /// in; this is either the interface where the ivar was declared, or the /// interface the ivar is conceptually a part of in the case of synthesized /// ivars. const ObjCInterfaceDecl *getContainingInterface() const; + + ObjCIvarDecl *getNextIvar() { return NextIvar; } + void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; } void setAccessControl(AccessControl ac) { DeclAccess = ac; } @@ -674,13 +684,21 @@ public: return DeclAccess == None ? Protected : AccessControl(DeclAccess); } + void setSynthesize(bool synth) { Synthesized = synth; } + bool getSynthesize() const { return Synthesized; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCIvarDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCIvar; } private: + /// NextIvar - Next Ivar in the list of ivars declared in class; class's + /// extensions and class's implementation + ObjCIvarDecl *NextIvar; + // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum unsigned DeclAccess : 3; + unsigned Synthesized : 1; }; @@ -700,8 +718,6 @@ public: IdentifierInfo *Id, QualType T, Expr *BW); - virtual void Destroy(ASTContext& C); - // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCAtDefsFieldDecl *D) { return true; } @@ -745,15 +761,10 @@ class ObjCProtocolDecl : public ObjCContainerDecl { isForwardProtoDecl(true) { } - virtual ~ObjCProtocolDecl() {} - public: static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - const ObjCProtocolList &getReferencedProtocols() const { return ReferencedProtocols; } @@ -822,12 +833,7 @@ private: ObjCClassDecl(DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs, unsigned nElts, ASTContext &C); - virtual ~ObjCClassDecl() {} public: - - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts = 0, const SourceLocation *Locs = 0, @@ -860,7 +866,6 @@ class ObjCForwardProtocolDecl : public Decl { ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L, ObjCProtocolDecl *const *Elts, unsigned nElts, const SourceLocation *Locs, ASTContext &C); - virtual ~ObjCForwardProtocolDecl() {} public: static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC, @@ -874,9 +879,6 @@ public: return Create(C, DC, L, 0, 0, 0); } - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - typedef ObjCProtocolList::iterator protocol_iterator; protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } @@ -928,6 +930,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl { /// FIXME: this should not be a singly-linked list. Move storage elsewhere. ObjCCategoryDecl *NextClassCategory; + /// true of class extension has at least one bitfield ivar. + bool HasSynthBitfield : 1; + /// \brief The location of the '@' in '@interface' SourceLocation AtLoc; @@ -938,8 +943,8 @@ class ObjCCategoryDecl : public ObjCContainerDecl { SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, IdentifierInfo *Id) : ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id), - ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc), - CategoryNameLoc(CategoryNameLoc) { + ClassInterface(0), NextClassCategory(0), HasSynthBitfield(false), + AtLoc(AtLoc), CategoryNameLoc(CategoryNameLoc) { } public: @@ -991,6 +996,9 @@ public: bool IsClassExtension() const { return getIdentifier() == 0; } const ObjCCategoryDecl *getNextClassExtension() const; + bool hasSynthBitfield() const { return HasSynthBitfield; } + void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); @@ -1032,8 +1040,6 @@ protected: ClassInterface(classInterface) {} public: - virtual ~ObjCImplDecl() {} - const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } void setClassInterface(ObjCInterfaceDecl *IFace); @@ -1165,11 +1171,15 @@ class ObjCImplementationDecl : public ObjCImplDecl { CXXBaseOrMemberInitializer **IvarInitializers; unsigned NumIvarInitializers; + /// true of class extension has at least one bitfield ivar. + bool HasSynthBitfield : 1; + ObjCImplementationDecl(DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl) : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), - SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {} + SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0), + HasSynthBitfield(false) {} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -1207,6 +1217,9 @@ public: void setIvarInitializers(ASTContext &C, CXXBaseOrMemberInitializer ** initializers, unsigned numInitializers); + + bool hasSynthBitfield() const { return HasSynthBitfield; } + void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. @@ -1262,6 +1275,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCImplementationDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCImplementation; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 135dd3ae78d3..b532668242fd 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -23,6 +23,7 @@ namespace clang { class TemplateParameterList; class TemplateDecl; +class RedeclarableTemplateDecl; class FunctionTemplateDecl; class ClassTemplateDecl; class ClassTemplatePartialSpecializationDecl; @@ -193,13 +194,6 @@ public: TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { } - /// Used to release the memory associated with a TemplateArgumentList - /// object. FIXME: This is currently not called anywhere, but the - /// memory will still be freed when using a BumpPtrAllocator. - void Destroy(ASTContext &C); - - ~TemplateArgumentList(); - /// \brief Copies the template arguments into a locally new[]'d array. void init(ASTContext &Context, const TemplateArgument *Args, unsigned NumArgs); @@ -255,8 +249,6 @@ protected: : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(Params) { } public: - ~TemplateDecl(); - /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { return TemplateParams; @@ -268,6 +260,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TemplateDecl *D) { return true; } + static bool classof(const RedeclarableTemplateDecl *D) { return true; } static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const TemplateTemplateParmDecl *D) { return true; } @@ -490,122 +483,179 @@ public: } }; -/// Declaration of a template function. -class FunctionTemplateDecl : public TemplateDecl { - static void DeallocateCommon(void *Ptr); - +/// Declaration of a redeclarable template. +class RedeclarableTemplateDecl : public TemplateDecl { + + RedeclarableTemplateDecl *getPreviousDeclarationImpl() { + return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>(); + } + + RedeclarableTemplateDecl *getCanonicalDeclImpl(); + + void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev); + + RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() { + return getCommonPtr()->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) { + assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); + getCommonPtr()->InstantiatedFromMember.setPointer(TD); + } + protected: - /// \brief Data that is common to all of the declarations of a given - /// function template. - struct Common { - Common() : InstantiatedFromMember(0, false) { } + template <typename EntryType> struct SpecEntryTraits { + typedef EntryType DeclType; - /// \brief The function template specializations for this function - /// template, including explicit specializations and instantiations. - llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + static DeclType *getMostRecentDeclaration(EntryType *D) { + return D->getMostRecentDeclaration(); + } + }; + + template <typename EntryType, + typename _SETraits = SpecEntryTraits<EntryType>, + typename _DeclType = typename _SETraits::DeclType> + class SpecIterator : public std::iterator<std::forward_iterator_tag, + _DeclType*, ptrdiff_t, + _DeclType*, _DeclType*> { + typedef _SETraits SETraits; + typedef _DeclType DeclType; + + typedef typename llvm::FoldingSet<EntryType>::iterator SetIteratorType; + + SetIteratorType SetIter; + + public: + SpecIterator() : SetIter() {} + SpecIterator(SetIteratorType SetIter) : SetIter(SetIter) {} + + DeclType *operator*() const { + return SETraits::getMostRecentDeclaration(&*SetIter); + } + DeclType *operator->() const { return **this; } + + SpecIterator &operator++() { ++SetIter; return *this; } + SpecIterator operator++(int) { + SpecIterator tmp(*this); + ++(*this); + return tmp; + } + + bool operator==(SpecIterator Other) const { + return SetIter == Other.SetIter; + } + bool operator!=(SpecIterator Other) const { + return SetIter != Other.SetIter; + } + }; + + template <typename EntryType> + SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSet<EntryType> &Specs, + bool isEnd) { + return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin()); + } + + template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType* + findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs, + const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); + + struct CommonBase { + CommonBase() : InstantiatedFromMember(0, false) { } - /// \brief The member function template from which this was most + /// \brief The template from which this was most /// directly instantiated (or null). /// - /// The boolean value indicates whether this member function template + /// The boolean value indicates whether this template /// was explicitly specialized. - llvm::PointerIntPair<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember; + llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool> + InstantiatedFromMember; + + /// \brief The latest declaration of this template. + RedeclarableTemplateDecl *Latest; }; /// \brief A pointer to the previous declaration (if this is a redeclaration) - /// or to the data that is common to all declarations of this function - /// template. - llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev; + /// or to the data that is common to all declarations of this template. + llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev; - /// \brief Retrieves the "common" pointer shared by all - /// (re-)declarations of the same function template. Calling this routine - /// may implicitly allocate memory for the common pointer. - Common *getCommonPtr(); + /// \brief Retrieves the "common" pointer shared by all (re-)declarations of + /// the same template. Calling this routine may implicitly allocate memory + /// for the common pointer. + CommonBase *getCommonPtr(); - FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl), - CommonOrPrev((Common*)0) { } + virtual CommonBase *newCommon() = 0; -public: - void Destroy(ASTContext &C); + // Construct a template decl with name, parameters, and templated element. + RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : TemplateDecl(DK, DC, L, Name, Params, Decl), + CommonOrPrev((CommonBase*)0) { } - /// Get the underlying function declaration of the template. - FunctionDecl *getTemplatedDecl() const { - return static_cast<FunctionDecl*>(TemplatedDecl); - } +public: + template <class decl_type> friend class RedeclarableTemplate; - /// \brief Retrieve the set of function template specializations of this - /// function template. - llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { - return getCommonPtr()->Specializations; + RedeclarableTemplateDecl *getCanonicalDecl() { + return getCanonicalDeclImpl(); } - /// \brief Retrieve the previous declaration of this function template, or + /// \brief Retrieve the previous declaration of this template, or /// NULL if no such declaration exists. - const FunctionTemplateDecl *getPreviousDeclaration() const { - return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>(); + RedeclarableTemplateDecl *getPreviousDeclaration() { + return getPreviousDeclarationImpl(); } - /// \brief Retrieve the previous declaration of this function template, or + /// \brief Retrieve the previous declaration of this template, or /// NULL if no such declaration exists. - FunctionTemplateDecl *getPreviousDeclaration() { - return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>(); + const RedeclarableTemplateDecl *getPreviousDeclaration() const { + return + const_cast<RedeclarableTemplateDecl*>(this)->getPreviousDeclaration(); } - /// \brief Set the previous declaration of this function template. - void setPreviousDeclaration(FunctionTemplateDecl *Prev) { - if (Prev) - CommonOrPrev = Prev; + /// \brief Retrieve the first declaration of this template, or itself + /// if this the first one. + RedeclarableTemplateDecl *getFirstDeclaration() { + return getCanonicalDecl(); } - virtual FunctionTemplateDecl *getCanonicalDecl(); + /// \brief Retrieve the first declaration of this template, or itself + /// if this the first one. + const RedeclarableTemplateDecl *getFirstDeclaration() const { + return + const_cast<RedeclarableTemplateDecl*>(this)->getFirstDeclaration(); + } - /// \brief Retrieve the member function template that this function template - /// was instantiated from. - /// - /// This routine will return non-NULL for member function templates of - /// class templates. For example, given: - /// - /// \code - /// template <typename T> - /// struct X { - /// template <typename U> void f(); - /// }; - /// \endcode - /// - /// X<int>::A<float> is a CXXMethodDecl (whose parent is X<int>, a - /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will - /// return X<int>::f, a FunctionTemplateDecl (whose parent is again - /// X<int>) for which getInstantiatedFromMemberTemplate() will return - /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a - /// ClassTemplateDecl). - /// - /// \returns NULL if this is not an instantiation of a member function - /// template. - FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { - return getCommonPtr()->InstantiatedFromMember.getPointer(); + /// \brief Retrieve the most recent declaration of this template, or itself + /// if this the most recent one. + RedeclarableTemplateDecl *getMostRecentDeclaration() { + return getCommonPtr()->Latest; } - void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) { - assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); - getCommonPtr()->InstantiatedFromMember.setPointer(FTD); + /// \brief Retrieve the most recent declaration of this template, or itself + /// if this the most recent one. + const RedeclarableTemplateDecl *getMostRecentDeclaration() const { + return + const_cast<RedeclarableTemplateDecl*>(this)->getMostRecentDeclaration(); } /// \brief Determines whether this template was a specialization of a /// member template. /// - /// In the following example, the function template \c X<int>::f is a - /// member specialization. + /// In the following example, the function template \c X<int>::f and the + /// member template \c X<int>::Inner are member specializations. /// /// \code /// template<typename T> /// struct X { /// template<typename U> void f(T, U); + /// template<typename U> struct Inner; /// }; /// /// template<> template<typename T> /// void X<int>::f(int, T); + /// template<> template<typename T> + /// struct X<int>::Inner { /* ... */ }; /// \endcode bool isMemberSpecialization() { return getCommonPtr()->InstantiatedFromMember.getInt(); @@ -618,6 +668,197 @@ public: getCommonPtr()->InstantiatedFromMember.setInt(true); } + /// \brief Retrieve the previous declaration of this template, or + /// NULL if no such declaration exists. + RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() { + return getInstantiatedFromMemberTemplateImpl(); + } + + virtual RedeclarableTemplateDecl *getNextRedeclaration(); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const RedeclarableTemplateDecl *D) { return true; } + static bool classof(const FunctionTemplateDecl *D) { return true; } + static bool classof(const ClassTemplateDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; + } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + +template <class decl_type> +class RedeclarableTemplate { + RedeclarableTemplateDecl *thisDecl() { + return static_cast<decl_type*>(this); + } + +public: + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + decl_type *getPreviousDeclaration() { + return static_cast<decl_type*>(thisDecl()->getPreviousDeclarationImpl()); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + const decl_type *getPreviousDeclaration() const { + return const_cast<RedeclarableTemplate*>(this)->getPreviousDeclaration(); + } + + /// \brief Set the previous declaration of this function template. + void setPreviousDeclaration(decl_type *Prev) { + thisDecl()->setPreviousDeclarationImpl(Prev); + } + + decl_type *getCanonicalDecl() { + return static_cast<decl_type*>(thisDecl()->getCanonicalDeclImpl()); + } + + const decl_type *getCanonicalDecl() const { + return const_cast<RedeclarableTemplate*>(this)->getCanonicalDecl(); + } + + /// \brief Retrieve the member template that this template was instantiated + /// from. + /// + /// This routine will return non-NULL for member templates of + /// class templates. For example, given: + /// + /// \code + /// template <typename T> + /// struct X { + /// template <typename U> void f(); + /// template <typename U> struct A {}; + /// }; + /// \endcode + /// + /// X<int>::f<float> is a CXXMethodDecl (whose parent is X<int>, a + /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will + /// return X<int>::f, a FunctionTemplateDecl (whose parent is again + /// X<int>) for which getInstantiatedFromMemberTemplate() will return + /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a + /// ClassTemplateDecl). + /// + /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent + /// is X<int>, also a CTSD) for which getSpecializedTemplate() will + /// return X<int>::A<U>, a ClassTemplateDecl (whose parent is again + /// X<int>) for which getInstantiatedFromMemberTemplate() will return + /// X<T>::A<U>, a ClassTemplateDecl (whose parent is X<T>, also a CTD). + /// + /// \returns NULL if this is not an instantiation of a member template. + decl_type *getInstantiatedFromMemberTemplate() { + return static_cast<decl_type*>( + thisDecl()->getInstantiatedFromMemberTemplateImpl()); + } + + void setInstantiatedFromMemberTemplate(decl_type *TD) { + thisDecl()->setInstantiatedFromMemberTemplateImpl(TD); + } +}; + +template <> struct RedeclarableTemplateDecl:: +SpecEntryTraits<FunctionTemplateSpecializationInfo> { + typedef FunctionDecl DeclType; + + static DeclType * + getMostRecentDeclaration(FunctionTemplateSpecializationInfo *I) { + return I->Function->getMostRecentDeclaration(); + } +}; + +/// Declaration of a template function. +class FunctionTemplateDecl : public RedeclarableTemplateDecl, + public RedeclarableTemplate<FunctionTemplateDecl> { + static void DeallocateCommon(void *Ptr); + +protected: + typedef RedeclarableTemplate<FunctionTemplateDecl> redeclarable_base; + + /// \brief Data that is common to all of the declarations of a given + /// function template. + struct Common : CommonBase { + /// \brief The function template specializations for this function + /// template, including explicit specializations and instantiations. + llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + }; + + FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } + + CommonBase *newCommon(); + + Common *getCommonPtr() { + return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); + } + + friend void FunctionDecl::setFunctionTemplateSpecialization( + FunctionTemplateDecl *Template, + const TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation); + + /// \brief Retrieve the set of function template specializations of this + /// function template. + llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { + return getCommonPtr()->Specializations; + } + +public: + /// Get the underlying function declaration of the template. + FunctionDecl *getTemplatedDecl() const { + return static_cast<FunctionDecl*>(TemplatedDecl); + } + + /// Returns whether this template declaration defines the primary + /// pattern. + bool isThisDeclarationADefinition() const { + return getTemplatedDecl()->isThisDeclarationADefinition(); + } + + /// \brief Return the specialization with the provided arguments if it exists, + /// otherwise return the insertion point. + FunctionDecl *findSpecialization(const TemplateArgument *Args, + unsigned NumArgs, void *&InsertPos); + + FunctionTemplateDecl *getCanonicalDecl() { + return redeclarable_base::getCanonicalDecl(); + } + const FunctionTemplateDecl *getCanonicalDecl() const { + return redeclarable_base::getCanonicalDecl(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + FunctionTemplateDecl *getPreviousDeclaration() { + return redeclarable_base::getPreviousDeclaration(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + const FunctionTemplateDecl *getPreviousDeclaration() const { + return redeclarable_base::getPreviousDeclaration(); + } + + FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { + return redeclarable_base::getInstantiatedFromMemberTemplate(); + } + + typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator; + + spec_iterator spec_begin() { + return makeSpecIterator(getSpecializations(), false); + } + + spec_iterator spec_end() { + return makeSpecIterator(getSpecializations(), true); + } + /// Create a template function node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -630,8 +871,8 @@ public: static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K == FunctionTemplate; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; //===----------------------------------------------------------------------===// @@ -781,8 +1022,7 @@ class NonTypeTemplateParmDecl NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo) - : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None, - VarDecl::None), + : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None), TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false) { } @@ -904,13 +1144,20 @@ public: DefaultArgumentWasInherited = false; } + SourceRange getSourceRange() const { + SourceLocation End = getLocation(); + if (hasDefaultArgument() && !defaultArgumentWasInherited()) + End = getDefaultArgument().getSourceRange().getEnd(); + return SourceRange(getTemplateParameters()->getTemplateLoc(), End); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TemplateTemplateParmDecl *D) { return true; } static bool classofKind(Kind K) { return K == TemplateTemplateParm; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// \brief Represents a class template specialization, which refers to @@ -991,12 +1238,21 @@ public: static ClassTemplateSpecializationDecl * Create(ASTContext &Context, EmptyShell Empty); - virtual void Destroy(ASTContext& C); - virtual void getNameForDiagnostic(std::string &S, const PrintingPolicy &Policy, bool Qualified) const; + ClassTemplateSpecializationDecl *getMostRecentDeclaration() { + CXXRecordDecl *Recent + = cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDeclaration()); + if (!isa<ClassTemplateSpecializationDecl>(Recent)) { + // FIXME: Does injected class name need to be in the redeclarations chain? + assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration()); + Recent = Recent->getPreviousDeclaration(); + } + return cast<ClassTemplateSpecializationDecl>(Recent); + } + /// \brief Retrieve the template that this specialization specializes. ClassTemplateDecl *getSpecializedTemplate() const; @@ -1044,7 +1300,8 @@ public: if (getSpecializationKind() != TSK_ImplicitInstantiation && getSpecializationKind() != TSK_ExplicitInstantiationDefinition && getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) - return (ClassTemplateDecl*)0; + return llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *>(); if (SpecializedPartialSpecialization *PartialSpec = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) @@ -1123,7 +1380,8 @@ public: /// \brief Sets the type of this specialization as it was written by /// the user. This will be a class template specialization type. void setTypeAsWritten(TypeSourceInfo *T) { - if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TypeAsWritten = T; } /// \brief Gets the type of this specialization as it was written by @@ -1138,13 +1396,15 @@ public: } /// \brief Sets the location of the extern keyword. void setExternLoc(SourceLocation Loc) { - if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->ExternLoc = Loc; } /// \brief Sets the location of the template keyword. void setTemplateKeywordLoc(SourceLocation Loc) { - if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TemplateKeywordLoc = Loc; } /// \brief Gets the location of the template keyword, if present. @@ -1242,6 +1502,11 @@ public: static ClassTemplatePartialSpecializationDecl * Create(ASTContext &Context, EmptyShell Empty); + ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() { + return cast<ClassTemplatePartialSpecializationDecl>( + ClassTemplateSpecializationDecl::getMostRecentDeclaration()); + } + /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { return TemplateParams; @@ -1355,15 +1620,16 @@ public: }; /// Declaration of a class template. -class ClassTemplateDecl : public TemplateDecl { +class ClassTemplateDecl : public RedeclarableTemplateDecl, + public RedeclarableTemplate<ClassTemplateDecl> { static void DeallocateCommon(void *Ptr); protected: + typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base; + /// \brief Data that is common to all of the declarations of a given /// class template. - struct Common { - Common() : InstantiatedFromMember(0, 0) {} - + struct Common : CommonBase { /// \brief The class template specializations for this class /// template, including explicit specializations and instantiations. llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations; @@ -1375,28 +1641,29 @@ protected: /// \brief The injected-class-name type for this class template. QualType InjectedClassNameType; - - /// \brief The templated member class from which this was most - /// directly instantiated (or null). - /// - /// The boolean value indicates whether this member class template - /// was explicitly specialized. - llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember; }; - /// \brief A pointer to the previous declaration (if this is a redeclaration) - /// or to the data that is common to all declarations of this class template. - llvm::PointerUnion<Common*, ClassTemplateDecl*> CommonOrPrev; + /// \brief Retrieve the set of specializations of this class template. + llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { + return getCommonPtr()->Specializations; + } - /// \brief Retrieves the "common" pointer shared by all - /// (re-)declarations of the same class template. Calling this routine - /// may implicitly allocate memory for the common pointer. - Common *getCommonPtr(); + /// \brief Retrieve the set of partial specializations of this class + /// template. + llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> & + getPartialSpecializations() { + return getCommonPtr()->PartialSpecializations; + } ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl), - CommonOrPrev((Common*)0) { } + : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } + + CommonBase *newCommon(); + + Common *getCommonPtr() { + return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); + } public: /// Get the underlying class declarations of the template. @@ -1404,48 +1671,71 @@ public: return static_cast<CXXRecordDecl *>(TemplatedDecl); } - /// \brief Retrieve the previous declaration of this class template, or - /// NULL if no such declaration exists. - const ClassTemplateDecl *getPreviousDeclaration() const { - return CommonOrPrev.dyn_cast<ClassTemplateDecl*>(); + /// Returns whether this template declaration defines the primary + /// class pattern. + bool isThisDeclarationADefinition() const { + return getTemplatedDecl()->isThisDeclarationADefinition(); } - /// \brief Retrieve the previous declaration of this function template, or + /// Create a class template node. + static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl, + ClassTemplateDecl *PrevDecl); + + /// \brief Return the specialization with the provided arguments if it exists, + /// otherwise return the insertion point. + ClassTemplateSpecializationDecl * + findSpecialization(const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); + + /// \brief Insert the specified specialization knowing that it is not already + /// in. InsertPos must be obtained from findSpecialization. + void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) { + getSpecializations().InsertNode(D, InsertPos); + } + + ClassTemplateDecl *getCanonicalDecl() { + return redeclarable_base::getCanonicalDecl(); + } + const ClassTemplateDecl *getCanonicalDecl() const { + return redeclarable_base::getCanonicalDecl(); + } + + /// \brief Retrieve the previous declaration of this class template, or /// NULL if no such declaration exists. ClassTemplateDecl *getPreviousDeclaration() { - return CommonOrPrev.dyn_cast<ClassTemplateDecl*>(); + return redeclarable_base::getPreviousDeclaration(); } - /// \brief Set the previous declaration of this class template. - void setPreviousDeclaration(ClassTemplateDecl *Prev) { - if (Prev) - CommonOrPrev = Prev; + /// \brief Retrieve the previous declaration of this class template, or + /// NULL if no such declaration exists. + const ClassTemplateDecl *getPreviousDeclaration() const { + return redeclarable_base::getPreviousDeclaration(); } - virtual ClassTemplateDecl *getCanonicalDecl(); - - const ClassTemplateDecl *getCanonicalDecl() const { - return const_cast<ClassTemplateDecl*>(this)->getCanonicalDecl(); + ClassTemplateDecl *getInstantiatedFromMemberTemplate() { + return redeclarable_base::getInstantiatedFromMemberTemplate(); } - /// Create a class template node. - static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - DeclarationName Name, - TemplateParameterList *Params, - NamedDecl *Decl, - ClassTemplateDecl *PrevDecl); + /// \brief Return the partial specialization with the provided arguments if it + /// exists, otherwise return the insertion point. + ClassTemplatePartialSpecializationDecl * + findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); - /// \brief Retrieve the set of specializations of this class template. - llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { - return getCommonPtr()->Specializations; + /// \brief Insert the specified partial specialization knowing that it is not + /// already in. InsertPos must be obtained from findPartialSpecialization. + void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D, + void *InsertPos) { + getPartialSpecializations().InsertNode(D, InsertPos); } - /// \brief Retrieve the set of partial specializations of this class - /// template. - llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> & - getPartialSpecializations() { - return getCommonPtr()->PartialSpecializations; + /// \brief Return the next partial specialization sequence number. + unsigned getNextPartialSpecSequenceNumber() { + return getPartialSpecializations().size(); } /// \brief Retrieve the partial specializations as an ordered list. @@ -1455,12 +1745,24 @@ public: /// \brief Find a class template partial specialization with the given /// type T. /// - /// \brief A dependent type that names a specialization of this class + /// \param T a dependent type that names a specialization of this class /// template. /// /// \returns the class template partial specialization that exactly matches /// the type \p T, or NULL if no such partial specialization exists. ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T); + + /// \brief Find a class template partial specialization which was instantiated + /// from the given member partial specialization. + /// + /// \param D a member class template partial specialization. + /// + /// \returns the class template partial specialization which was instantiated + /// from the given member partial specialization, or NULL if no such partial + /// specialization exists. + ClassTemplatePartialSpecializationDecl * + findPartialSpecInstantiatedFromMember( + ClassTemplatePartialSpecializationDecl *D); /// \brief Retrieve the template specialization type of the /// injected-class-name for this class template. @@ -1478,78 +1780,45 @@ public: /// \endcode QualType getInjectedClassNameSpecialization(); - /// \brief Retrieve the member class template that this class template was - /// derived from. - /// - /// This routine will return non-NULL for templated member classes of - /// class templates. For example, given: - /// - /// \code - /// template <typename T> - /// struct X { - /// template <typename U> struct A {}; - /// }; - /// \endcode - /// - /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent - /// is X<int>, also a CTSD) for which getSpecializedTemplate() will - /// return X<int>::A<U>, a TemplateClassDecl (whose parent is again - /// X<int>) for which getInstantiatedFromMemberTemplate() will return - /// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD). - /// - /// \returns null if this is not an instantiation of a member class template. - ClassTemplateDecl *getInstantiatedFromMemberTemplate() { - return getCommonPtr()->InstantiatedFromMember.getPointer(); + typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator; + + spec_iterator spec_begin() { + return makeSpecIterator(getSpecializations(), false); } - void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) { - assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); - getCommonPtr()->InstantiatedFromMember.setPointer(CTD); + spec_iterator spec_end() { + return makeSpecIterator(getSpecializations(), true); } - /// \brief Determines whether this template was a specialization of a - /// member template. - /// - /// In the following example, the member template \c X<int>::Inner is a - /// member specialization. - /// - /// \code - /// template<typename T> - /// struct X { - /// template<typename U> struct Inner; - /// }; - /// - /// template<> template<typename T> - /// struct X<int>::Inner { /* ... */ }; - /// \endcode - bool isMemberSpecialization() { - return getCommonPtr()->InstantiatedFromMember.getInt(); + typedef SpecIterator<ClassTemplatePartialSpecializationDecl> + partial_spec_iterator; + + partial_spec_iterator partial_spec_begin() { + return makeSpecIterator(getPartialSpecializations(), false); } - - /// \brief Note that this member template is a specialization. - void setMemberSpecialization() { - assert(getCommonPtr()->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - getCommonPtr()->InstantiatedFromMember.setInt(true); + + partial_spec_iterator partial_spec_end() { + return makeSpecIterator(getPartialSpecializations(), true); } - + // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ClassTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K == ClassTemplate; } - virtual void Destroy(ASTContext& C); - - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// Declaration of a friend template. For example: /// /// template <typename T> class A { /// friend class MyVector<T>; // not a friend template -/// template <typename U> friend class B; // friend template +/// template <typename U> friend class B; // not a friend template /// template <typename U> friend class Foo<T>::Nested; // friend template +/// }; +/// NOTE: This class is not currently in use. All of the above +/// will yield a FriendDecl, not a FriendTemplateDecl. class FriendTemplateDecl : public Decl { public: typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; @@ -1580,6 +1849,12 @@ private: FriendLoc(FriendLoc) {} + FriendTemplateDecl(EmptyShell Empty) + : Decl(Decl::FriendTemplate, Empty), + NumParams(0), + Params(0) + {} + public: static FriendTemplateDecl *Create(ASTContext &Context, DeclContext *DC, SourceLocation Loc, @@ -1588,6 +1863,8 @@ public: FriendUnion Friend, SourceLocation FriendLoc); + static FriendTemplateDecl *Create(ASTContext &Context, EmptyShell Empty); + /// If this friend declaration names a templated type (or /// a dependent member type of a templated type), return that /// type; otherwise return null. @@ -1620,6 +1897,8 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decl::FriendTemplate; } static bool classof(const FriendTemplateDecl *D) { return true; } + + friend class ASTDeclReader; }; /// Implementation of inline functions that require the template declarations diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 8a771d513c42..8bb627597520 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -30,6 +30,7 @@ namespace clang { class IdentifierInfo; class MultiKeywordSelector; class UsingDirectiveDecl; + class TypeSourceInfo; /// DeclarationName - The name of a declaration. In the common case, /// this just stores an IdentifierInfo pointer to a normal @@ -367,6 +368,146 @@ public: DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II); }; +/// DeclarationNameLoc - Additional source/type location info +/// for a declaration name. Needs a DeclarationName in order +/// to be interpreted correctly. +struct DeclarationNameLoc { + 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; + }; + + DeclarationNameLoc(DeclarationName Name); + // FIXME: this should go away once all DNLocs are properly initialized. + DeclarationNameLoc() { NamedType.TInfo = 0; } +}; // struct DeclarationNameLoc + + +/// DeclarationNameInfo - A collector data type for bundling together +/// a DeclarationName and the correspnding source/type location info. +struct DeclarationNameInfo { +private: + /// Name - The declaration name, also encoding name kind. + DeclarationName Name; + /// Loc - The main source location for the declaration name. + SourceLocation NameLoc; + /// Info - Further source/type location info for special kinds of names. + DeclarationNameLoc LocInfo; + +public: + // FIXME: remove it. + DeclarationNameInfo() {} + + DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc) + : Name(Name), NameLoc(NameLoc), LocInfo(Name) {} + + DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc, + DeclarationNameLoc LocInfo) + : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {} + + /// getName - Returns the embedded declaration name. + DeclarationName getName() const { return Name; } + /// setName - Sets the embedded declaration name. + void setName(DeclarationName N) { Name = N; } + + /// getLoc - Returns the main location of the declaration name. + SourceLocation getLoc() const { return NameLoc; } + /// setLoc - Sets the main location of the declaration name. + void setLoc(SourceLocation L) { NameLoc = L; } + + const DeclarationNameLoc &getInfo() const { return LocInfo; } + DeclarationNameLoc &getInfo() { return LocInfo; } + void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; } + + /// getNamedTypeInfo - Returns the source type info associated to + /// the name. Assumes it is a constructor, destructor or conversion. + TypeSourceInfo *getNamedTypeInfo() const { + assert(Name.getNameKind() == DeclarationName::CXXConstructorName || + Name.getNameKind() == DeclarationName::CXXDestructorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName); + return LocInfo.NamedType.TInfo; + } + /// setNamedTypeInfo - Sets the source type info associated to + /// the name. Assumes it is a constructor, destructor or conversion. + void setNamedTypeInfo(TypeSourceInfo *TInfo) { + assert(Name.getNameKind() == DeclarationName::CXXConstructorName || + Name.getNameKind() == DeclarationName::CXXDestructorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName); + LocInfo.NamedType.TInfo = TInfo; + } + + /// getCXXOperatorNameRange - Gets the range of the operator name + /// (without the operator keyword). Assumes it is a (non-literal) operator. + SourceRange getCXXOperatorNameRange() const { + assert(Name.getNameKind() == DeclarationName::CXXOperatorName); + return SourceRange( + SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc), + SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc) + ); + } + /// setCXXOperatorNameRange - Sets the range of the operator name + /// (without the operator keyword). Assumes it is a C++ operator. + void setCXXOperatorNameRange(SourceRange R) { + assert(Name.getNameKind() == DeclarationName::CXXOperatorName); + LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding(); + LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding(); + } + + /// getCXXLiteralOperatorNameLoc - Returns the location of the literal + /// operator name (not the operator keyword). + /// Assumes it is a literal operator. + SourceLocation getCXXLiteralOperatorNameLoc() const { + assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName); + return SourceLocation:: + getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc); + } + /// setCXXLiteralOperatorNameLoc - Sets the location of the literal + /// operator name (not the operator keyword). + /// Assumes it is a literal operator. + void setCXXLiteralOperatorNameLoc(SourceLocation Loc) { + assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName); + LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding(); + } + + /// getAsString - Retrieve the human-readable string for this name. + std::string getAsString() const; + + /// printName - Print the human-readable name to a stream. + void printName(llvm::raw_ostream &OS) const; + + /// getBeginLoc - Retrieve the location of the first token. + SourceLocation getBeginLoc() const { return NameLoc; } + /// getEndLoc - Retrieve the location of the last token. + SourceLocation getEndLoc() const; + /// getSourceRange - The range of the declaration name. + SourceRange getSourceRange() const { + return SourceRange(getBeginLoc(), getEndLoc()); + } +}; + /// Insertion operator for diagnostics. This allows sending DeclarationName's /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, @@ -385,6 +526,12 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, return PD; } +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + DeclarationNameInfo DNInfo) { + DNInfo.printName(OS); + return OS; +} + } // end namespace clang namespace llvm { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index ade2b09c80c2..48130becf3b5 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -18,6 +18,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" #include "clang/AST/DeclAccessPair.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/ASTVector.h" #include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/APSInt.h" @@ -42,7 +43,7 @@ namespace clang { class TemplateArgumentListInfo; /// \brief A simple array of base specifiers. -typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray; +typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt @@ -61,8 +62,14 @@ protected: /// (C++ [temp.dep.constexpr]). bool ValueDependent : 1; + /// ValueKind - The value classification of this expression. + /// Only actually used by certain subclasses. + unsigned ValueKind : 2; + + enum { BitsRemaining = 28 }; + Expr(StmtClass SC, QualType T, bool TD, bool VD) - : Stmt(SC), TypeDependent(TD), ValueDependent(VD) { + : Stmt(SC), TypeDependent(TD), ValueDependent(VD), ValueKind(0) { setType(T); } @@ -258,7 +265,6 @@ public: /// function returning an rvalue reference. /// lvalues and xvalues are collectively referred to as glvalues, while /// prvalues and xvalues together form rvalues. - /// If a Classification Classify(ASTContext &Ctx) const { return ClassifyImpl(Ctx, 0); } @@ -310,7 +316,7 @@ public: } /// isConstantInitializer - Returns true if this expression is a constant /// initializer, which can be emitted at compile-time. - bool isConstantInitializer(ASTContext &Ctx) const; + bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const; /// EvalResult is a struct with detailed info about an evaluated expression. struct EvalResult { @@ -521,10 +527,14 @@ class DeclRefExpr : public Expr { // (2) the declaration's name was followed by an explicit template // argument list. llvm::PointerIntPair<ValueDecl *, 2> DecoratedD; - + // Loc - The location of the declaration name itself. SourceLocation Loc; + /// DNLoc - Provides source/type location info for the + /// declaration name embedded in DecoratedD. + DeclarationNameLoc DNLoc; + /// \brief Retrieve the qualifier that preceded the declaration name, if any. NameQualifier *getNameQualifier() { if ((DecoratedD.getInt() & HasQualifierFlag) == 0) @@ -537,31 +547,17 @@ class DeclRefExpr : public Expr { const NameQualifier *getNameQualifier() const { return const_cast<DeclRefExpr *>(this)->getNameQualifier(); } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { - if ((DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag) == 0) - return 0; - - if ((DecoratedD.getInt() & HasQualifierFlag) == 0) - return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); - - return reinterpret_cast<ExplicitTemplateArgumentList *>( - getNameQualifier() + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { - return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgumentList(); - } - + DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, ValueDecl *D, SourceLocation NameLoc, const TemplateArgumentListInfo *TemplateArgs, QualType T); + DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + ValueDecl *D, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, + QualType T); + /// \brief Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) { } @@ -584,6 +580,14 @@ public: QualType T, const TemplateArgumentListInfo *TemplateArgs = 0); + static DeclRefExpr *Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + ValueDecl *D, + const DeclarationNameInfo &NameInfo, + QualType T, + const TemplateArgumentListInfo *TemplateArgs = 0); + /// \brief Construct an empty declaration reference expression. static DeclRefExpr *CreateEmpty(ASTContext &Context, bool HasQualifier, unsigned NumTemplateArgs); @@ -592,6 +596,10 @@ public: const ValueDecl *getDecl() const { return DecoratedD.getPointer(); } void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); } + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc); + } + SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } virtual SourceRange getSourceRange() const; @@ -619,53 +627,77 @@ public: return getNameQualifier()->NNS; } - /// \brief Determines whether this member expression actually had a C++ - /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgumentList() const { - return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag; + bool hasExplicitTemplateArgs() const { + return (DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + + if ((DecoratedD.getInt() & HasQualifierFlag) == 0) + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + + return *reinterpret_cast<ExplicitTemplateArgumentList *>( + getNameQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs(); } + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getExplicitTemplateArgsOpt() const { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); + } + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgumentList()) - getExplicitTemplateArgumentList()->copyInto(List); + if (hasExplicitTemplateArgs()) + getExplicitTemplateArgs().copyInto(List); } /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { - if (!hasExplicitTemplateArgumentList()) + if (!hasExplicitTemplateArgs()) return SourceLocation(); - return getExplicitTemplateArgumentList()->LAngleLoc; + return getExplicitTemplateArgs().LAngleLoc; } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - if (!hasExplicitTemplateArgumentList()) + if (!hasExplicitTemplateArgs()) return 0; - return getExplicitTemplateArgumentList()->getTemplateArgs(); + return getExplicitTemplateArgs().getTemplateArgs(); } /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { - if (!hasExplicitTemplateArgumentList()) + if (!hasExplicitTemplateArgs()) return 0; - return getExplicitTemplateArgumentList()->NumTemplateArgs; + return getExplicitTemplateArgs().NumTemplateArgs; } /// \brief Retrieve the location of the right angle bracket following the /// template arguments ('>'). SourceLocation getRAngleLoc() const { - if (!hasExplicitTemplateArgumentList()) + if (!hasExplicitTemplateArgs()) return SourceLocation(); - return getExplicitTemplateArgumentList()->RAngleLoc; + return getExplicitTemplateArgs().RAngleLoc; } static bool classof(const Stmt *T) { @@ -677,8 +709,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; - friend class PCHStmtWriter; + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__. @@ -725,28 +757,84 @@ public: virtual child_iterator child_end(); }; +/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without +/// leaking memory. +/// +/// For large floats/integers, APFloat/APInt will allocate memory from the heap +/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator +/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with +/// the APFloat/APInt values will never get freed. APNumericStorage uses +/// ASTContext's allocator for memory allocation. +class APNumericStorage { + unsigned BitWidth; + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + + bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; } + + APNumericStorage(const APNumericStorage&); // do not implement + APNumericStorage& operator=(const APNumericStorage&); // do not implement + +protected: + APNumericStorage() : BitWidth(0), VAL(0) { } + + llvm::APInt getIntValue() const { + unsigned NumWords = llvm::APInt::getNumWords(BitWidth); + if (NumWords > 1) + return llvm::APInt(BitWidth, NumWords, pVal); + else + return llvm::APInt(BitWidth, VAL); + } + void setIntValue(ASTContext &C, const llvm::APInt &Val); +}; + +class APIntStorage : public APNumericStorage { +public: + llvm::APInt getValue() const { return getIntValue(); } + void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); } +}; + +class APFloatStorage : public APNumericStorage { +public: + llvm::APFloat getValue() const { return llvm::APFloat(getIntValue()); } + void setValue(ASTContext &C, const llvm::APFloat &Val) { + setIntValue(C, Val.bitcastToAPInt()); + } +}; + class IntegerLiteral : public Expr { - llvm::APInt Value; + APIntStorage Num; SourceLocation Loc; + + /// \brief Construct an empty integer literal. + explicit IntegerLiteral(EmptyShell Empty) + : Expr(IntegerLiteralClass, Empty) { } + public: // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, // or UnsignedLongLongTy - IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l) - : Expr(IntegerLiteralClass, type, false, false), Value(V), Loc(l) { + IntegerLiteral(ASTContext &C, const llvm::APInt &V, + QualType type, SourceLocation l) + : Expr(IntegerLiteralClass, type, false, false), Loc(l) { assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); + setValue(C, V); } - /// \brief Construct an empty integer literal. - explicit IntegerLiteral(EmptyShell Empty) - : Expr(IntegerLiteralClass, Empty) { } + // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, + // or UnsignedLongLongTy + static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V, + QualType type, SourceLocation l); + static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty); - const llvm::APInt &getValue() const { return Value; } + llvm::APInt getValue() const { return Num.getValue(); } virtual SourceRange getSourceRange() const { return SourceRange(Loc); } /// \brief Retrieve the location of the literal. SourceLocation getLocation() const { return Loc; } - void setValue(const llvm::APInt &Val) { Value = Val; } + void setValue(ASTContext &C, const llvm::APInt &Val) { Num.setValue(C, Val); } void setLocation(SourceLocation Location) { Loc = Location; } static bool classof(const Stmt *T) { @@ -795,21 +883,30 @@ public: }; class FloatingLiteral : public Expr { - llvm::APFloat Value; + APFloatStorage Num; bool IsExact : 1; SourceLocation Loc; -public: - FloatingLiteral(const llvm::APFloat &V, bool isexact, + + FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) - : Expr(FloatingLiteralClass, Type, false, false), Value(V), - IsExact(isexact), Loc(L) {} + : Expr(FloatingLiteralClass, Type, false, false), + IsExact(isexact), Loc(L) { + setValue(C, V); + } /// \brief Construct an empty floating-point literal. explicit FloatingLiteral(EmptyShell Empty) - : Expr(FloatingLiteralClass, Empty), Value(0.0) { } + : Expr(FloatingLiteralClass, Empty), IsExact(false) { } - const llvm::APFloat &getValue() const { return Value; } - void setValue(const llvm::APFloat &Val) { Value = Val; } +public: + static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V, + bool isexact, QualType Type, SourceLocation L); + static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty); + + llvm::APFloat getValue() const { return Num.getValue(); } + void setValue(ASTContext &C, const llvm::APFloat &Val) { + Num.setValue(C, Val); + } bool isExact() const { return IsExact; } void setExact(bool E) { IsExact = E; } @@ -889,9 +986,6 @@ class StringLiteral : public Expr { StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {} -protected: - virtual void DoDestroy(ASTContext &C); - public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. @@ -912,8 +1006,7 @@ public: llvm::StringRef getString() const { return llvm::StringRef(StrData, ByteLength); } - // FIXME: These are deprecated, replace with StringRef. - const char *getStrData() const { return StrData; } + unsigned getByteLength() const { return ByteLength; } /// \brief Sets the string data to the given string data. @@ -1009,40 +1102,27 @@ public: /// applied to a non-complex value, the former returns its operand and the /// later returns zero in the type of the operand. /// -/// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose -/// subexpression is a compound literal with the various MemberExpr and -/// ArraySubscriptExpr's applied to it. (This is only used in C) -/// class UnaryOperator : public Expr { public: - // Note that additions to this should also update the StmtVisitor class. - enum Opcode { - PostInc, PostDec, // [C99 6.5.2.4] Postfix increment and decrement operators - PreInc, PreDec, // [C99 6.5.3.1] Prefix increment and decrement operators. - AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators. - Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators. - Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators. - Real, Imag, // "__real expr"/"__imag expr" Extension. - Extension, // __extension__ marker. - OffsetOf // __builtin_offsetof - }; + typedef UnaryOperatorKind Opcode; + private: - Stmt *Val; - Opcode Opc; + unsigned Opc : 5; SourceLocation Loc; + Stmt *Val; public: UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l) : Expr(UnaryOperatorClass, type, - input->isTypeDependent() && opc != OffsetOf, + input->isTypeDependent() || type->isDependentType(), input->isValueDependent()), - Val(input), Opc(opc), Loc(l) {} + Opc(opc), Loc(l), Val(input) {} /// \brief Build an empty unary operator. explicit UnaryOperator(EmptyShell Empty) - : Expr(UnaryOperatorClass, Empty), Opc(AddrOf) { } + : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { } - Opcode getOpcode() const { return Opc; } + Opcode getOpcode() const { return static_cast<Opcode>(Opc); } void setOpcode(Opcode O) { Opc = O; } Expr *getSubExpr() const { return cast<Expr>(Val); } @@ -1054,21 +1134,26 @@ public: /// isPostfix - Return true if this is a postfix operation, like x++. static bool isPostfix(Opcode Op) { - return Op == PostInc || Op == PostDec; + return Op == UO_PostInc || Op == UO_PostDec; } /// isPostfix - Return true if this is a prefix operation, like --x. static bool isPrefix(Opcode Op) { - return Op == PreInc || Op == PreDec; + return Op == UO_PreInc || Op == UO_PreDec; } - bool isPrefix() const { return isPrefix(Opc); } - bool isPostfix() const { return isPostfix(Opc); } - bool isIncrementOp() const {return Opc==PreInc || Opc==PostInc; } - bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; } - bool isOffsetOfOp() const { return Opc == OffsetOf; } - static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; } - bool isArithmeticOp() const { return isArithmeticOp(Opc); } + bool isPrefix() const { return isPrefix(getOpcode()); } + bool isPostfix() const { return isPostfix(getOpcode()); } + bool isIncrementOp() const { + return Opc == UO_PreInc || Opc == UO_PostInc; + } + bool isIncrementDecrementOp() const { + return Opc <= UO_PreDec; + } + static bool isArithmeticOp(Opcode Op) { + return Op >= UO_Plus && Op <= UO_LNot; + } + bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); } /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "sizeof" or "[pre]++" @@ -1310,9 +1395,6 @@ class SizeOfAlignOfExpr : public Expr { } Argument; SourceLocation OpLoc, RParenLoc; -protected: - virtual void DoDestroy(ASTContext& C); - public: SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo, QualType resultType, SourceLocation op, @@ -1485,8 +1567,6 @@ protected: CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc); - virtual void DoDestroy(ASTContext& C); - public: CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc); @@ -1494,8 +1574,6 @@ public: /// \brief Build an empty call expression. CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty); - ~CallExpr() {} - const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); } Expr *getCallee() { return cast<Expr>(SubExprs[FN]); } void setCallee(Expr *F) { SubExprs[FN] = F; } @@ -1594,6 +1672,10 @@ class MemberExpr : public Expr { /// MemberLoc - This is the location of the member name. SourceLocation MemberLoc; + /// MemberDNLoc - Provides source/type location info for the + /// declaration name embedded in MemberDecl. + DeclarationNameLoc MemberDNLoc; + /// IsArrow - True if this is "X->F", false if this is "X.F". bool IsArrow : 1; @@ -1621,37 +1703,33 @@ class MemberExpr : public Expr { return const_cast<MemberExpr *>(this)->getMemberQualifier(); } - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { - if (!HasExplicitTemplateArgumentList) - return 0; - - if (!HasQualifierOrFoundDecl) - return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); - - return reinterpret_cast<ExplicitTemplateArgumentList *>( - getMemberQualifier() + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { - return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList(); +public: + MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, + const DeclarationNameInfo &NameInfo, QualType ty) + : Expr(MemberExprClass, ty, + base->isTypeDependent(), base->isValueDependent()), + Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()), + MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow), + HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) { + assert(memberdecl->getDeclName() == NameInfo.getName()); } -public: + // NOTE: this constructor should be used only when it is known that + // the member name can not provide additional syntactic info + // (i.e., source locations for C++ operator names or type source info + // for constructors, destructors and conversion oeprators). MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, SourceLocation l, QualType ty) : Expr(MemberExprClass, ty, base->isTypeDependent(), base->isValueDependent()), - Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), + Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(), + IsArrow(isarrow), HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, ValueDecl *memberdecl, DeclAccessPair founddecl, - SourceLocation l, + DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *targs, QualType ty); @@ -1700,15 +1778,42 @@ public: /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgumentList() const { + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgumentList; } /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgumentList()) - getExplicitTemplateArgumentList()->copyInto(List); + if (hasExplicitTemplateArgs()) + getExplicitTemplateArgs().copyInto(List); + } + + /// \brief Retrieve the explicit template argument list that + /// follow the member template name. This must only be called on an + /// expression with explicit template arguments. + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { + assert(HasExplicitTemplateArgumentList); + if (!HasQualifierOrFoundDecl) + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + + return *reinterpret_cast<ExplicitTemplateArgumentList *>( + getMemberQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that + /// followed the member template name. This must only be called on + /// an expression with explicit template arguments. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs(); + } + + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() const { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); } /// \brief Retrieve the location of the left angle bracket following the @@ -1717,7 +1822,7 @@ public: if (!HasExplicitTemplateArgumentList) return SourceLocation(); - return getExplicitTemplateArgumentList()->LAngleLoc; + return getExplicitTemplateArgs().LAngleLoc; } /// \brief Retrieve the template arguments provided as part of this @@ -1726,7 +1831,7 @@ public: if (!HasExplicitTemplateArgumentList) return 0; - return getExplicitTemplateArgumentList()->getTemplateArgs(); + return getExplicitTemplateArgs().getTemplateArgs(); } /// \brief Retrieve the number of template arguments provided as part of this @@ -1735,7 +1840,7 @@ public: if (!HasExplicitTemplateArgumentList) return 0; - return getExplicitTemplateArgumentList()->NumTemplateArgs; + return getExplicitTemplateArgs().NumTemplateArgs; } /// \brief Retrieve the location of the right angle bracket following the @@ -1744,7 +1849,13 @@ public: if (!HasExplicitTemplateArgumentList) return SourceLocation(); - return getExplicitTemplateArgumentList()->RAngleLoc; + return getExplicitTemplateArgs().RAngleLoc; + } + + /// \brief Retrieve the member declaration name info. + DeclarationNameInfo getMemberNameInfo() const { + return DeclarationNameInfo(MemberDecl->getDeclName(), + MemberLoc, MemberDNLoc); } bool isArrow() const { return IsArrow; } @@ -1758,9 +1869,8 @@ public: virtual SourceRange getSourceRange() const { // If we have an implicit base (like a C++ implicit this), // make sure not to return its location - SourceLocation EndLoc = MemberLoc; - if (HasExplicitTemplateArgumentList) - EndLoc = getRAngleLoc(); + SourceLocation EndLoc = (HasExplicitTemplateArgumentList) + ? getRAngleLoc() : getMemberNameInfo().getEndLoc(); SourceLocation BaseLoc = getBase()->getLocStart(); if (BaseLoc.isInvalid()) @@ -1843,110 +1953,13 @@ public: /// classes). class CastExpr : public Expr { public: - /// CastKind - the kind of cast this represents. - enum CastKind { - /// CK_Unknown - Unknown cast kind. - /// FIXME: The goal is to get rid of this and make all casts have a - /// kind so that the AST client doesn't have to try to figure out what's - /// going on. - CK_Unknown, - - /// CK_BitCast - Used for reinterpret_cast. - CK_BitCast, - - /// CK_LValueBitCast - Used for reinterpret_cast of expressions to - /// a reference type. - CK_LValueBitCast, - - /// CK_NoOp - Used for const_cast. - CK_NoOp, - - /// CK_BaseToDerived - Base to derived class casts. - CK_BaseToDerived, - - /// CK_DerivedToBase - Derived to base class casts. - CK_DerivedToBase, - - /// CK_UncheckedDerivedToBase - Derived to base class casts that - /// assume that the derived pointer is not null. - CK_UncheckedDerivedToBase, - - /// CK_Dynamic - Dynamic cast. - CK_Dynamic, - - /// CK_ToUnion - Cast to union (GCC extension). - CK_ToUnion, - - /// CK_ArrayToPointerDecay - Array to pointer decay. - CK_ArrayToPointerDecay, - - // CK_FunctionToPointerDecay - Function to pointer decay. - CK_FunctionToPointerDecay, - - /// CK_NullToMemberPointer - Null pointer to member pointer. - CK_NullToMemberPointer, - - /// CK_BaseToDerivedMemberPointer - Member pointer in base class to - /// member pointer in derived class. - CK_BaseToDerivedMemberPointer, - - /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to - /// member pointer in base class. - CK_DerivedToBaseMemberPointer, - - /// CK_UserDefinedConversion - Conversion using a user defined type - /// conversion function. - CK_UserDefinedConversion, - - /// CK_ConstructorConversion - Conversion by constructor - CK_ConstructorConversion, - - /// CK_IntegralToPointer - Integral to pointer - CK_IntegralToPointer, - - /// CK_PointerToIntegral - Pointer to integral - CK_PointerToIntegral, - - /// CK_ToVoid - Cast to void. - CK_ToVoid, - - /// CK_VectorSplat - Casting from an integer/floating type to an extended - /// vector type with the same element type as the src type. Splats the - /// src expression into the destination expression. - CK_VectorSplat, - - /// CK_IntegralCast - Casting between integral types of different size. - CK_IntegralCast, - - /// CK_IntegralToFloating - Integral to floating point. - CK_IntegralToFloating, - - /// CK_FloatingToIntegral - Floating point to integral. - CK_FloatingToIntegral, - - /// CK_FloatingCast - Casting between floating types of different size. - CK_FloatingCast, - - /// CK_MemberPointerToBoolean - Member pointer to boolean - CK_MemberPointerToBoolean, - - /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c - /// pointer - CK_AnyPointerToObjCPointerCast, - /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block - /// pointer - CK_AnyPointerToBlockPointerCast - - }; + typedef clang::CastKind CastKind; private: - CastKind Kind; + unsigned Kind : 5; + unsigned BasePathSize : BitsRemaining - 5; Stmt *Op; - /// BasePath - For derived-to-base and base-to-derived casts, the base array - /// contains the inheritance path. - CXXBaseSpecifierArray BasePath; - void CheckBasePath() const { #ifndef NDEBUG switch (getCastKind()) { @@ -1955,7 +1968,7 @@ private: case CK_DerivedToBaseMemberPointer: case CK_BaseToDerived: case CK_BaseToDerivedMemberPointer: - assert(!BasePath.empty() && "Cast kind should have a base path!"); + assert(!path_empty() && "Cast kind should have a base path!"); break; // These should not have an inheritance path. @@ -1981,15 +1994,21 @@ private: case CK_MemberPointerToBoolean: case CK_AnyPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: - assert(BasePath.empty() && "Cast kind should not have a base path!"); + case CK_ObjCObjectLValueCast: + assert(path_empty() && "Cast kind should not have a base path!"); break; } #endif } + const CXXBaseSpecifier * const *path_buffer() const { + return const_cast<CastExpr*>(this)->path_buffer(); + } + CXXBaseSpecifier **path_buffer(); + protected: CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath) : + unsigned BasePathSize) : Expr(SC, ty, // Cast expressions are type-dependent if the type is // dependent (C++ [temp.dep.expr]p3). @@ -1997,18 +2016,16 @@ protected: // Cast expressions are value-dependent if the type is // dependent or if the subexpression is value-dependent. ty->isDependentType() || (op && op->isValueDependent())), - Kind(kind), Op(op), BasePath(BasePath) { - CheckBasePath(); - } + Kind(kind), BasePathSize(BasePathSize), Op(op) { + CheckBasePath(); + } /// \brief Construct an empty cast. - CastExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty) { } - - virtual void DoDestroy(ASTContext &C); + CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) + : Expr(SC, Empty), BasePathSize(BasePathSize) { } public: - CastKind getCastKind() const { return Kind; } + CastKind getCastKind() const { return static_cast<CastKind>(Kind); } void setCastKind(CastKind K) { Kind = K; } const char *getCastKindName() const; @@ -2024,8 +2041,16 @@ public: return const_cast<CastExpr *>(this)->getSubExprAsWritten(); } - const CXXBaseSpecifierArray& getBasePath() const { return BasePath; } - CXXBaseSpecifierArray& getBasePath() { return BasePath; } + typedef CXXBaseSpecifier **path_iterator; + typedef const CXXBaseSpecifier * const *path_const_iterator; + bool path_empty() const { return BasePathSize == 0; } + unsigned path_size() const { return BasePathSize; } + path_iterator path_begin() { return path_buffer(); } + path_iterator path_end() { return path_buffer() + path_size(); } + path_const_iterator path_begin() const { return path_buffer(); } + path_const_iterator path_end() const { return path_buffer() + path_size(); } + + void setCastPath(const CXXCastPath &Path); static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCastExprConstant && @@ -2045,38 +2070,57 @@ public: /// /// In C, implicit casts always produce rvalues. However, in C++, an /// implicit cast whose result is being bound to a reference will be -/// an lvalue. For example: +/// an lvalue or xvalue. For example: /// /// @code /// class Base { }; /// class Derived : public Base { }; +/// Derived &&ref(); /// void f(Derived d) { -/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base +/// Base& b = d; // initializer is an ImplicitCastExpr +/// // to an lvalue of type Base +/// Base&& r = ref(); // initializer is an ImplicitCastExpr +/// // to an xvalue of type Base /// } /// @endcode class ImplicitCastExpr : public CastExpr { - /// LvalueCast - Whether this cast produces an lvalue. - bool LvalueCast; +private: + ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, + unsigned BasePathLength, ExprValueKind VK) + : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePathLength) { + ValueKind = VK; + } + + /// \brief Construct an empty implicit cast. + explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize) + : CastExpr(ImplicitCastExprClass, Shell, PathSize) { } public: - ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, bool Lvalue) - : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath), - LvalueCast(Lvalue) { } + enum OnStack_t { OnStack }; + ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op, + ExprValueKind VK) + : CastExpr(ImplicitCastExprClass, ty, kind, op, 0) { + ValueKind = VK; + } - /// \brief Construct an empty implicit cast. - explicit ImplicitCastExpr(EmptyShell Shell) - : CastExpr(ImplicitCastExprClass, Shell) { } + static ImplicitCastExpr *Create(ASTContext &Context, QualType T, + CastKind Kind, Expr *Operand, + const CXXCastPath *BasePath, + ExprValueKind Cat); + + static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); virtual SourceRange getSourceRange() const { return getSubExpr()->getSourceRange(); } - /// isLvalueCast - Whether this cast produces an lvalue. - bool isLvalueCast() const { return LvalueCast; } + /// getValueKind - The value kind that this cast produces. + ExprValueKind getValueKind() const { + return static_cast<ExprValueKind>(ValueKind); + } - /// setLvalueCast - Set whether this cast produces an lvalue. - void setLvalueCast(bool Lvalue) { LvalueCast = Lvalue; } + /// setValueKind - Set the value kind this cast produces. + void setValueKind(ExprValueKind Cat) { ValueKind = Cat; } static bool classof(const Stmt *T) { return T->getStmtClass() == ImplicitCastExprClass; @@ -2098,8 +2142,8 @@ public: /// actual type of the expression as determined by semantic /// analysis. These types may differ slightly. For example, in C++ one /// can cast to a reference type, which indicates that the resulting -/// expression will be an lvalue. The reference type, however, will -/// not be used as the type of the expression. +/// expression will be an lvalue or xvalue. The reference type, however, +/// will not be used as the type of the expression. class ExplicitCastExpr : public CastExpr { /// TInfo - Source type info for the (written) type /// this expression is casting to. @@ -2107,13 +2151,12 @@ class ExplicitCastExpr : public CastExpr { protected: ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind, - Expr *op, CXXBaseSpecifierArray BasePath, - TypeSourceInfo *writtenTy) - : CastExpr(SC, exprTy, kind, op, BasePath), TInfo(writtenTy) {} + Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy) + : CastExpr(SC, exprTy, kind, op, PathSize), TInfo(writtenTy) {} /// \brief Construct an empty explicit cast. - ExplicitCastExpr(StmtClass SC, EmptyShell Shell) - : CastExpr(SC, Shell) { } + ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) + : CastExpr(SC, Shell, PathSize) { } public: /// getTypeInfoAsWritten - Returns the type source info for the type @@ -2138,16 +2181,24 @@ public: class CStyleCastExpr : public ExplicitCastExpr { SourceLocation LPLoc; // the location of the left paren SourceLocation RPLoc; // the location of the right paren -public: + CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + unsigned PathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation r) - : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, BasePath, + : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, PathSize, writtenTy), LPLoc(l), RPLoc(r) {} /// \brief Construct an empty C-style explicit cast. - explicit CStyleCastExpr(EmptyShell Shell) - : ExplicitCastExpr(CStyleCastExprClass, Shell) { } + explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize) + : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } + +public: + static CStyleCastExpr *Create(ASTContext &Context, QualType T, CastKind K, + Expr *Op, const CXXCastPath *BasePath, + TypeSourceInfo *WrittenTy, SourceLocation L, + SourceLocation R); + + static CStyleCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); SourceLocation getLParenLoc() const { return LPLoc; } void setLParenLoc(SourceLocation L) { LPLoc = L; } @@ -2184,33 +2235,14 @@ public: /// be used to express the computation. class BinaryOperator : public Expr { public: - enum Opcode { - // Operators listed in order of precedence. - // Note that additions to this should also update the StmtVisitor class. - PtrMemD, PtrMemI, // [C++ 5.5] Pointer-to-member operators. - Mul, Div, Rem, // [C99 6.5.5] Multiplicative operators. - Add, Sub, // [C99 6.5.6] Additive operators. - Shl, Shr, // [C99 6.5.7] Bitwise shift operators. - LT, GT, LE, GE, // [C99 6.5.8] Relational operators. - EQ, NE, // [C99 6.5.9] Equality operators. - And, // [C99 6.5.10] Bitwise AND operator. - Xor, // [C99 6.5.11] Bitwise XOR operator. - Or, // [C99 6.5.12] Bitwise OR operator. - LAnd, // [C99 6.5.13] Logical AND operator. - LOr, // [C99 6.5.14] Logical OR operator. - Assign, MulAssign,// [C99 6.5.16] Assignment operators. - DivAssign, RemAssign, - AddAssign, SubAssign, - ShlAssign, ShrAssign, - AndAssign, XorAssign, - OrAssign, - Comma // [C99 6.5.17] Comma operator. - }; + typedef BinaryOperatorKind Opcode; + private: + unsigned Opc : 6; + SourceLocation OpLoc; + enum { LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; - Opcode Opc; - SourceLocation OpLoc; public: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, @@ -2227,12 +2259,12 @@ public: /// \brief Construct an empty binary operator. explicit BinaryOperator(EmptyShell Empty) - : Expr(BinaryOperatorClass, Empty), Opc(Comma) { } + : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { } SourceLocation getOperatorLoc() const { return OpLoc; } void setOperatorLoc(SourceLocation L) { OpLoc = L; } - Opcode getOpcode() const { return Opc; } + Opcode getOpcode() const { return static_cast<Opcode>(Opc); } void setOpcode(Opcode O) { Opc = O; } Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } @@ -2248,6 +2280,8 @@ public: /// corresponds to, e.g. "<<=". static const char *getOpcodeStr(Opcode Op); + const char *getOpcodeStr() const { return getOpcodeStr(getOpcode()); } + /// \brief Retrieve the binary opcode that corresponds to the given /// overloaded operator. static Opcode getOverloadedOpcode(OverloadedOperatorKind OO); @@ -2257,30 +2291,34 @@ public: static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); /// predicates to categorize the respective opcodes. - bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; } - static bool isAdditiveOp(Opcode Opc) { return Opc == Add || Opc == Sub; } - bool isAdditiveOp() const { return isAdditiveOp(Opc); } - static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; } - bool isShiftOp() const { return isShiftOp(Opc); } + bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; } + static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; } + bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); } + static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; } + bool isShiftOp() const { return isShiftOp(getOpcode()); } - static bool isBitwiseOp(Opcode Opc) { return Opc >= And && Opc <= Or; } - bool isBitwiseOp() const { return isBitwiseOp(Opc); } + static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; } + bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); } - static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; } - bool isRelationalOp() const { return isRelationalOp(Opc); } + static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; } + bool isRelationalOp() const { return isRelationalOp(getOpcode()); } - static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; } - bool isEqualityOp() const { return isEqualityOp(Opc); } + static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; } + bool isEqualityOp() const { return isEqualityOp(getOpcode()); } - static bool isComparisonOp(Opcode Opc) { return Opc >= LT && Opc <= NE; } - bool isComparisonOp() const { return isComparisonOp(Opc); } + static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; } + bool isComparisonOp() const { return isComparisonOp(getOpcode()); } - static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; } - bool isLogicalOp() const { return isLogicalOp(Opc); } + static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; } + bool isLogicalOp() const { return isLogicalOp(getOpcode()); } - bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; } - bool isCompoundAssignmentOp() const { return Opc > Assign && Opc <= OrAssign;} - bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; } + bool isAssignmentOp() const { return Opc >= BO_Assign && Opc <= BO_OrAssign; } + bool isCompoundAssignmentOp() const { + return Opc > BO_Assign && Opc <= BO_OrAssign; + } + bool isShiftAssignOp() const { + return Opc == BO_ShlAssign || Opc == BO_ShrAssign; + } static bool classof(const Stmt *S) { return S->getStmtClass() >= firstBinaryOperatorConstant && @@ -2304,7 +2342,7 @@ protected: } BinaryOperator(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Opc(MulAssign) { } + : Expr(SC, Empty), Opc(BO_MulAssign) { } }; /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep @@ -2353,10 +2391,11 @@ public: class ConditionalOperator : public Expr { enum { COND, LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. + Stmt* Save; SourceLocation QuestionLoc, ColonLoc; public: ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, - SourceLocation CLoc, Expr *rhs, QualType t) + SourceLocation CLoc, Expr *rhs, Expr *save, QualType t) : Expr(ConditionalOperatorClass, t, // FIXME: the type of the conditional operator doesn't // depend on the type of the conditional, but the standard @@ -2370,6 +2409,7 @@ public: SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; + Save = save; } /// \brief Build an empty conditional operator. @@ -2382,25 +2422,31 @@ public: void setCond(Expr *E) { SubExprs[COND] = E; } // getTrueExpr - Return the subexpression representing the value of the ?: - // expression if the condition evaluates to true. In most cases this value - // will be the same as getLHS() except a GCC extension allows the left - // subexpression to be omitted, and instead of the condition be returned. - // e.g: x ?: y is shorthand for x ? x : y, except that the expression "x" - // is only evaluated once. + // expression if the condition evaluates to true. Expr *getTrueExpr() const { - return cast<Expr>(SubExprs[LHS] ? SubExprs[LHS] : SubExprs[COND]); + return cast<Expr>(!Save ? SubExprs[LHS] : SubExprs[COND]); } - // getTrueExpr - Return the subexpression representing the value of the ?: + // getFalseExpr - Return the subexpression representing the value of the ?: // expression if the condition evaluates to false. This is the same as getRHS. Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } - - Expr *getLHS() const { return cast_or_null<Expr>(SubExprs[LHS]); } + + // getSaveExpr - In most cases this value will be null. Except a GCC extension + // allows the left subexpression to be omitted, and instead of that condition + // be returned. e.g: x ?: y is shorthand for x ? x : y, except that the + // expression "x" is only evaluated once. Under this senario, this function + // returns the original, non-converted condition expression for the ?:operator + Expr *getSaveExpr() const { return Save? cast<Expr>(Save) : (Expr*)0; } + + Expr *getLHS() const { return Save ? 0 : cast<Expr>(SubExprs[LHS]); } void setLHS(Expr *E) { SubExprs[LHS] = E; } Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } + Expr *getSAVE() const { return Save? cast<Expr>(Save) : (Expr*)0; } + void setSAVE(Expr *E) { Save = E; } + SourceLocation getQuestionLoc() const { return QuestionLoc; } void setQuestionLoc(SourceLocation L) { QuestionLoc = L; } @@ -2500,23 +2546,27 @@ public: /// expressions) are compatible. The result of this built-in function can be /// used in integer constant expressions. class TypesCompatibleExpr : public Expr { - QualType Type1; - QualType Type2; + TypeSourceInfo *TInfo1; + TypeSourceInfo *TInfo2; SourceLocation BuiltinLoc, RParenLoc; public: TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc, - QualType t1, QualType t2, SourceLocation RP) : + TypeSourceInfo *tinfo1, TypeSourceInfo *tinfo2, + SourceLocation RP) : Expr(TypesCompatibleExprClass, ReturnType, false, false), - Type1(t1), Type2(t2), BuiltinLoc(BLoc), RParenLoc(RP) {} + TInfo1(tinfo1), TInfo2(tinfo2), BuiltinLoc(BLoc), RParenLoc(RP) {} /// \brief Build an empty __builtin_type_compatible_p expression. explicit TypesCompatibleExpr(EmptyShell Empty) : Expr(TypesCompatibleExprClass, Empty) { } - QualType getArgType1() const { return Type1; } - void setArgType1(QualType T) { Type1 = T; } - QualType getArgType2() const { return Type2; } - void setArgType2(QualType T) { Type2 = T; } + TypeSourceInfo *getArgTInfo1() const { return TInfo1; } + void setArgTInfo1(TypeSourceInfo *TInfo) { TInfo1 = TInfo; } + TypeSourceInfo *getArgTInfo2() const { return TInfo2; } + void setArgTInfo2(TypeSourceInfo *TInfo) { TInfo2 = TInfo; } + + QualType getArgType1() const { return TInfo1->getType(); } + QualType getArgType2() const { return TInfo2->getType(); } SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } @@ -2553,9 +2603,6 @@ class ShuffleVectorExpr : public Expr { Stmt **SubExprs; unsigned NumExprs; -protected: - virtual void DoDestroy(ASTContext &C); - public: // FIXME: Can a shufflevector be value-dependent? Does type-dependence need // to be computed differently? @@ -2588,8 +2635,6 @@ public: } static bool classof(const ShuffleVectorExpr *) { return true; } - ~ShuffleVectorExpr() {} - /// getNumSubExprs - Return the size of the SubExprs array. This includes the /// constant expression, the actual arguments passed in, and the function /// pointers. @@ -2716,11 +2761,13 @@ public: /// VAArgExpr, used for the builtin function __builtin_va_arg. class VAArgExpr : public Expr { Stmt *Val; + TypeSourceInfo *TInfo; SourceLocation BuiltinLoc, RParenLoc; public: - VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc) + VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo, + SourceLocation RPLoc, QualType t) : Expr(VAArgExprClass, t, t->isDependentType(), false), - Val(e), + Val(e), TInfo(TInfo), BuiltinLoc(BLoc), RParenLoc(RPLoc) { } @@ -2731,6 +2778,9 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } + TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; } + void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; } + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } @@ -2896,12 +2946,18 @@ public: virtual child_iterator child_end(); typedef InitExprsTy::iterator iterator; + typedef InitExprsTy::const_iterator const_iterator; typedef InitExprsTy::reverse_iterator reverse_iterator; + typedef InitExprsTy::const_reverse_iterator const_reverse_iterator; iterator begin() { return InitExprs.begin(); } + const_iterator begin() const { return InitExprs.begin(); } iterator end() { return InitExprs.end(); } + const_iterator end() const { return InitExprs.end(); } reverse_iterator rbegin() { return InitExprs.rbegin(); } + const_reverse_iterator rbegin() const { return InitExprs.rbegin(); } reverse_iterator rend() { return InitExprs.rend(); } + const_reverse_iterator rend() const { return InitExprs.rend(); } }; /// @brief Represents a C99 designated initializer expression. @@ -2961,11 +3017,6 @@ private: : Expr(DesignatedInitExprClass, EmptyShell()), NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { } -protected: - virtual void DoDestroy(ASTContext &C); - - void DestroyDesignators(ASTContext &C); - public: /// A field designator, e.g., ".x". struct FieldDesignator { @@ -3233,15 +3284,10 @@ class ParenListExpr : public Expr { unsigned NumExprs; SourceLocation LParenLoc, RParenLoc; -protected: - virtual void DoDestroy(ASTContext& C); - public: ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, unsigned numexprs, SourceLocation rparenloc); - ~ParenListExpr() {} - /// \brief Build an empty paren list. explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } @@ -3274,8 +3320,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; - friend class PCHStmtWriter; + friend class ASTStmtReader; + friend class ASTStmtWriter; }; diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index b9553815d8eb..0a9435479d93 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -121,12 +121,12 @@ private: protected: CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + unsigned PathSize, TypeSourceInfo *writtenTy, SourceLocation l) - : ExplicitCastExpr(SC, ty, kind, op, BasePath, writtenTy), Loc(l) {} + : ExplicitCastExpr(SC, ty, kind, op, PathSize, writtenTy), Loc(l) {} - explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell) - : ExplicitCastExpr(SC, Shell) { } + explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) + : ExplicitCastExpr(SC, Shell, PathSize) { } public: const char *getCastName() const; @@ -158,14 +158,22 @@ public: /// This expression node represents a C++ static cast, e.g., /// @c static_cast<int>(1.0). class CXXStaticCastExpr : public CXXNamedCastExpr { -public: CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, BasePath, writtenTy, l) {} + : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, pathSize, + writtenTy, l) {} - explicit CXXStaticCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { } + explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) + : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { } + +public: + static CXXStaticCastExpr *Create(ASTContext &Context, QualType T, + CastKind K, Expr *Op, + const CXXCastPath *Path, + TypeSourceInfo *Written, SourceLocation L); + static CXXStaticCastExpr *CreateEmpty(ASTContext &Context, + unsigned PathSize); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXStaticCastExprClass; @@ -180,15 +188,23 @@ public: /// This expression node represents a dynamic cast, e.g., /// @c dynamic_cast<Derived*>(BasePtr). class CXXDynamicCastExpr : public CXXNamedCastExpr { -public: CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, BasePath, + : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, pathSize, writtenTy, l) {} - explicit CXXDynamicCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { } + explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) + : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { } + +public: + static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T, + CastKind Kind, Expr *Op, + const CXXCastPath *Path, + TypeSourceInfo *Written, SourceLocation L); + + static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context, + unsigned pathSize); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDynamicCastExprClass; @@ -203,15 +219,22 @@ public: /// This expression node represents a reinterpret cast, e.g., /// @c reinterpret_cast<int>(VoidPtr). class CXXReinterpretCastExpr : public CXXNamedCastExpr { -public: CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, + unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, BasePath, + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, pathSize, writtenTy, l) {} - explicit CXXReinterpretCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty) { } + CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) + : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { } + +public: + static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T, + CastKind Kind, Expr *Op, + const CXXCastPath *Path, + TypeSourceInfo *WrittenTy, SourceLocation L); + static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context, + unsigned pathSize); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXReinterpretCastExprClass; @@ -225,14 +248,18 @@ public: /// This expression node represents a const cast, e.g., /// @c const_cast<char*>(PtrToConstChar). class CXXConstCastExpr : public CXXNamedCastExpr { -public: CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l) : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, - CXXBaseSpecifierArray(), writtenTy, l) {} + 0, writtenTy, l) {} explicit CXXConstCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXConstCastExprClass, Empty) { } + : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { } + +public: + static CXXConstCastExpr *Create(ASTContext &Context, QualType T, Expr *Op, + TypeSourceInfo *WrittenTy, SourceLocation L); + static CXXConstCastExpr *CreateEmpty(ASTContext &Context); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstCastExprClass; @@ -479,9 +506,6 @@ class CXXDefaultArgExpr : public Expr { *reinterpret_cast<Expr **>(this + 1) = SubExpr; } -protected: - virtual void DoDestroy(ASTContext &C); - public: CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} @@ -535,8 +559,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; - friend class PCHStmtWriter; + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// CXXTemporary - Represents a C++ temporary. @@ -546,14 +570,11 @@ class CXXTemporary { CXXTemporary(const CXXDestructorDecl *destructor) : Destructor(destructor) { } - ~CXXTemporary() { } public: static CXXTemporary *Create(ASTContext &C, const CXXDestructorDecl *Destructor); - void Destroy(ASTContext &Ctx); - const CXXDestructorDecl *getDestructor() const { return Destructor; } }; @@ -579,10 +600,6 @@ class CXXBindTemporaryExpr : public Expr { CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr) : Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false), Temp(temp), SubExpr(subexpr) { } - ~CXXBindTemporaryExpr() { } - -protected: - virtual void DoDestroy(ASTContext &C); public: CXXBindTemporaryExpr(EmptyShell Empty) @@ -614,73 +631,6 @@ public: virtual child_iterator child_end(); }; -/// CXXBindReferenceExpr - Represents binding an expression to a reference. -/// In the example: -/// -/// const int &i = 10; -/// -/// a bind reference expression is inserted to indicate that 10 is bound to -/// a reference, and that a temporary needs to be created to hold the -/// value. -class CXXBindReferenceExpr : public Expr { - // SubExpr - The expression being bound. - Stmt *SubExpr; - - // ExtendsLifetime - Whether binding this reference extends the lifetime of - // the expression being bound. FIXME: Add C++ reference. - bool ExtendsLifetime; - - /// RequiresTemporaryCopy - Whether binding the subexpression requires a - /// temporary copy. - bool RequiresTemporaryCopy; - - CXXBindReferenceExpr(Expr *subexpr, bool ExtendsLifetime, - bool RequiresTemporaryCopy) - : Expr(CXXBindReferenceExprClass, subexpr->getType(), false, false), - SubExpr(subexpr), ExtendsLifetime(ExtendsLifetime), - RequiresTemporaryCopy(RequiresTemporaryCopy) { } - ~CXXBindReferenceExpr() { } - -protected: - virtual void DoDestroy(ASTContext &C); - -public: - static CXXBindReferenceExpr *Create(ASTContext &C, Expr *SubExpr, - bool ExtendsLifetime, - bool RequiresTemporaryCopy); - - explicit CXXBindReferenceExpr(EmptyShell Empty) - : Expr(CXXBindReferenceExprClass, Empty) { } - - const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } - Expr *getSubExpr() { return cast<Expr>(SubExpr); } - void setSubExpr(Expr *E) { SubExpr = E; } - - virtual SourceRange getSourceRange() const { - return SubExpr->getSourceRange(); - } - - /// requiresTemporaryCopy - Whether binding the subexpression requires a - /// temporary copy. - bool requiresTemporaryCopy() const { return RequiresTemporaryCopy; } - - // extendsLifetime - Whether binding this reference extends the lifetime of - // the expression being bound. FIXME: Add C++ reference. - bool extendsLifetime() const { return ExtendsLifetime; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXBindReferenceExprClass; - } - static bool classof(const CXXBindReferenceExpr *) { return true; } - - // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); - - friend class PCHStmtReader; -}; - /// CXXConstructExpr - Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { public: @@ -707,15 +657,12 @@ protected: Expr **args, unsigned numargs, bool ZeroInitialization = false, ConstructionKind ConstructKind = CK_Complete); - ~CXXConstructExpr() { } /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty), Constructor(0), Elidable(0), ZeroInitialization(0), ConstructKind(0), Args(0), NumArgs(0) { } - virtual void DoDestroy(ASTContext &C); - public: /// \brief Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) @@ -796,7 +743,7 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; + friend class ASTStmtReader; }; /// CXXFunctionalCastExpr - Represents an explicit C++ type conversion @@ -805,17 +752,27 @@ public: class CXXFunctionalCastExpr : public ExplicitCastExpr { SourceLocation TyBeginLoc; SourceLocation RParenLoc; -public: + CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy, SourceLocation tyBeginLoc, CastKind kind, - Expr *castExpr, CXXBaseSpecifierArray BasePath, + Expr *castExpr, unsigned pathSize, SourceLocation rParenLoc) : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, - BasePath, writtenTy), + pathSize, writtenTy), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} - explicit CXXFunctionalCastExpr(EmptyShell Shell) - : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell) { } + explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) + : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { } + +public: + static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T, + TypeSourceInfo *Written, + SourceLocation TyBeginLoc, + CastKind Kind, Expr *Op, + const CXXCastPath *Path, + SourceLocation RPLoc); + static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context, + unsigned PathSize); SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } @@ -859,8 +816,6 @@ public: explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { } - ~CXXTemporaryObjectExpr() { } - SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -872,7 +827,7 @@ public: } static bool classof(const CXXTemporaryObjectExpr *) { return true; } - friend class PCHStmtReader; + friend class ASTStmtReader; }; /// CXXScalarValueInitExpr - [C++ 5.2.3p2] @@ -952,7 +907,7 @@ class CXXNewExpr : public Expr { SourceLocation StartLoc; SourceLocation EndLoc; - friend class PCHStmtReader; + friend class ASTStmtReader; public: CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs, unsigned numPlaceArgs, @@ -967,8 +922,6 @@ public: void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, unsigned numConsArgs); - virtual void DoDestroy(ASTContext &C); - QualType getAllocatedType() const { assert(getType()->isPointerType()); return getType()->getAs<PointerType>()->getPointeeType(); @@ -1381,7 +1334,7 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; + friend class ASTStmtReader; }; /// \brief A reference to an overloaded function set, either an @@ -1395,7 +1348,7 @@ class OverloadExpr : public Expr { unsigned NumResults; /// The common name of these declarations. - DeclarationName Name; + DeclarationNameInfo NameInfo; /// The scope specifier, if any. NestedNameSpecifier *Qualifier; @@ -1403,16 +1356,13 @@ class OverloadExpr : public Expr { /// The source range of the scope specifier. SourceRange QualifierRange; - /// The location of the name. - SourceLocation NameLoc; - protected: /// True if the name was a template-id. bool HasExplicitTemplateArgs; OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent, NestedNameSpecifier *Qualifier, SourceRange QRange, - DeclarationName Name, SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool HasTemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -1427,19 +1377,38 @@ public: UnresolvedSetIterator End, const TemplateArgumentListInfo *Args); + struct FindResult { + OverloadExpr *Expression; + bool IsAddressOfOperand; + bool HasFormOfMemberPointer; + }; + /// Finds the overloaded expression in the given expression of /// OverloadTy. /// - /// \return the expression (which must be there) and true if it is - /// within an address-of operator. - static llvm::PointerIntPair<OverloadExpr*,1> find(Expr *E) { + /// \return the expression (which must be there) and true if it has + /// the particular form of a member pointer expression + static FindResult find(Expr *E) { assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload)); - bool op = false; + FindResult Result; + E = E->IgnoreParens(); - if (isa<UnaryOperator>(E)) - op = true, E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); - return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op); + if (isa<UnaryOperator>(E)) { + assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf); + E = cast<UnaryOperator>(E)->getSubExpr(); + OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens()); + + Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier()); + Result.IsAddressOfOperand = true; + Result.Expression = Ovl; + } else { + Result.HasFormOfMemberPointer = false; + Result.IsAddressOfOperand = false; + Result.Expression = cast<OverloadExpr>(E); + } + + return Result; } /// Gets the naming class of this lookup, if any. @@ -1457,13 +1426,17 @@ public: /// Gets the number of declarations in the unresolved set. unsigned getNumDecls() const { return NumResults; } + /// Gets the full name info. + const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; } + /// Gets the name looked up. - DeclarationName getName() const { return Name; } - void setName(DeclarationName N) { Name = N; } + DeclarationName getName() const { return NameInfo.getName(); } + void setName(DeclarationName N) { NameInfo.setName(N); } /// Gets the location of the name. - SourceLocation getNameLoc() const { return NameLoc; } - void setNameLoc(SourceLocation Loc) { NameLoc = Loc; } + SourceLocation getNameLoc() const { return NameInfo.getLoc(); } + void setNameLoc(SourceLocation Loc) { NameInfo.setLoc(Loc); } /// Fetches the nested-name qualifier, if one was given. NestedNameSpecifier *getQualifier() const { return Qualifier; } @@ -1483,10 +1456,12 @@ public: return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs(); } - ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { - if (hasExplicitTemplateArgs()) - return &getExplicitTemplateArgs(); - return 0; + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); } static bool classof(const Stmt *T) { @@ -1526,11 +1501,11 @@ class UnresolvedLookupExpr : public OverloadExpr { UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent, CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QRange, - DeclarationName Name, SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, bool HasTemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) : OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier, - QRange, Name, NameLoc, HasTemplateArgs, Begin, End), + QRange, NameInfo, HasTemplateArgs, Begin, End), RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) {} @@ -1545,16 +1520,15 @@ public: CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool ADL, bool Overloaded, UnresolvedSetIterator Begin, UnresolvedSetIterator End) { return new(C) UnresolvedLookupExpr(C, Dependent ? C.DependentTy : C.OverloadTy, Dependent, NamingClass, - Qualifier, QualifierRange, - Name, NameLoc, ADL, Overloaded, false, + Qualifier, QualifierRange, NameInfo, + ADL, Overloaded, false, Begin, End); } @@ -1563,8 +1537,7 @@ public: CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool ADL, const TemplateArgumentListInfo &Args, UnresolvedSetIterator Begin, @@ -1603,6 +1576,14 @@ public: return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); } + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); + } + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { @@ -1626,7 +1607,7 @@ public: } virtual SourceRange getSourceRange() const { - SourceRange Range(getNameLoc()); + SourceRange Range(getNameInfo().getSourceRange()); if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); return Range; @@ -1657,10 +1638,7 @@ public: /// declaration can be found. class DependentScopeDeclRefExpr : public Expr { /// The name of the entity we will be referencing. - DeclarationName Name; - - /// Location of the name of the declaration we're referencing. - SourceLocation Loc; + DeclarationNameInfo NameInfo; /// QualifierRange - The source range that covers the /// nested-name-specifier. @@ -1676,12 +1654,10 @@ class DependentScopeDeclRefExpr : public Expr { DependentScopeDeclRefExpr(QualType T, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool HasExplicitTemplateArgs) : Expr(DependentScopeDeclRefExprClass, T, true, true), - Name(Name), Loc(NameLoc), - QualifierRange(QualifierRange), Qualifier(Qualifier), + NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier), HasExplicitTemplateArgs(HasExplicitTemplateArgs) {} @@ -1689,20 +1665,23 @@ public: static DependentScopeDeclRefExpr *Create(ASTContext &C, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs = 0); static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C, unsigned NumTemplateArgs); /// \brief Retrieve the name that this expression refers to. - DeclarationName getDeclName() const { return Name; } - void setDeclName(DeclarationName N) { Name = N; } + const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; } + + /// \brief Retrieve the name that this expression refers to. + DeclarationName getDeclName() const { return NameInfo.getName(); } + void setDeclName(DeclarationName N) { NameInfo.setName(N); } /// \brief Retrieve the location of the name within the expression. - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } + SourceLocation getLocation() const { return NameInfo.getLoc(); } + void setLocation(SourceLocation L) { NameInfo.setLoc(L); } /// \brief Retrieve the source range of the nested-name-specifier. SourceRange getQualifierRange() const { return QualifierRange; } @@ -1731,6 +1710,14 @@ public: return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); } + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); + } + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { @@ -1777,10 +1764,6 @@ class CXXExprWithTemporaries : public Expr { CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); - ~CXXExprWithTemporaries(); - -protected: - virtual void DoDestroy(ASTContext &C); public: CXXExprWithTemporaries(EmptyShell Empty) @@ -1991,10 +1974,7 @@ class CXXDependentScopeMemberExpr : public Expr { /// \brief The member to which this member expression refers, which /// can be name, overloaded operator, or destructor. /// FIXME: could also be a template-id - DeclarationName Member; - - /// \brief The location of the member name. - SourceLocation MemberLoc; + DeclarationNameInfo MemberNameInfo; CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, @@ -2002,8 +1982,7 @@ class CXXDependentScopeMemberExpr : public Expr { NestedNameSpecifier *Qualifier, SourceRange QualifierRange, NamedDecl *FirstQualifierFoundInScope, - DeclarationName Member, - SourceLocation MemberLoc, + DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); public: @@ -2014,14 +1993,13 @@ public: NestedNameSpecifier *Qualifier, SourceRange QualifierRange, NamedDecl *FirstQualifierFoundInScope, - DeclarationName Member, - SourceLocation MemberLoc) + DeclarationNameInfo MemberNameInfo) : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), Base(Base), BaseType(BaseType), IsArrow(IsArrow), HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), Qualifier(Qualifier), QualifierRange(QualifierRange), FirstQualifierFoundInScope(FirstQualifierFoundInScope), - Member(Member), MemberLoc(MemberLoc) { } + MemberNameInfo(MemberNameInfo) { } static CXXDependentScopeMemberExpr * Create(ASTContext &C, @@ -2030,8 +2008,7 @@ public: NestedNameSpecifier *Qualifier, SourceRange QualifierRange, NamedDecl *FirstQualifierFoundInScope, - DeclarationName Member, - SourceLocation MemberLoc, + DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); static CXXDependentScopeMemberExpr * @@ -2092,13 +2069,20 @@ public: /// \brief Retrieve the name of the member that this expression /// refers to. - DeclarationName getMember() const { return Member; } - void setMember(DeclarationName N) { Member = N; } + const DeclarationNameInfo &getMemberNameInfo() const { + return MemberNameInfo; + } + void setMemberNameInfo(const DeclarationNameInfo &N) { MemberNameInfo = N; } + + /// \brief Retrieve the name of the member that this expression + /// refers to. + DeclarationName getMember() const { return MemberNameInfo.getName(); } + void setMember(DeclarationName N) { MemberNameInfo.setName(N); } // \brief Retrieve the location of the name of the member that this // expression refers to. - SourceLocation getMemberLoc() const { return MemberLoc; } - void setMemberLoc(SourceLocation L) { MemberLoc = L; } + SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); } + void setMemberLoc(SourceLocation L) { MemberNameInfo.setLoc(L); } /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. @@ -2108,57 +2092,59 @@ public: /// \brief Retrieve the explicit template argument list that followed the /// member template name, if any. - ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { assert(HasExplicitTemplateArgs); - return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); } /// \brief Retrieve the explicit template argument list that followed the /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { return const_cast<CXXDependentScopeMemberExpr *>(this) - ->getExplicitTemplateArgumentList(); + ->getExplicitTemplateArgs(); + } + + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); } /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - assert(HasExplicitTemplateArgs); - getExplicitTemplateArgumentList()->copyInto(List); + getExplicitTemplateArgs().copyInto(List); } /// \brief Initializes the template arguments using the given structure. void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) { - assert(HasExplicitTemplateArgs); - getExplicitTemplateArgumentList()->initializeFrom(List); + getExplicitTemplateArgs().initializeFrom(List); } /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { - assert(HasExplicitTemplateArgs); - return getExplicitTemplateArgumentList()->LAngleLoc; + return getExplicitTemplateArgs().LAngleLoc; } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - assert(HasExplicitTemplateArgs); - return getExplicitTemplateArgumentList()->getTemplateArgs(); + return getExplicitTemplateArgs().getTemplateArgs(); } /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { - assert(HasExplicitTemplateArgs); - return getExplicitTemplateArgumentList()->NumTemplateArgs; + return getExplicitTemplateArgs().NumTemplateArgs; } /// \brief Retrieve the location of the right angle bracket following the /// template arguments ('>'). SourceLocation getRAngleLoc() const { - assert(HasExplicitTemplateArgs); - return getExplicitTemplateArgumentList()->RAngleLoc; + return getExplicitTemplateArgs().RAngleLoc; } virtual SourceRange getSourceRange() const { @@ -2168,12 +2154,12 @@ public: else if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); else - Range.setBegin(MemberLoc); + Range.setBegin(MemberNameInfo.getBeginLoc()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); else - Range.setEnd(MemberLoc); + Range.setEnd(MemberNameInfo.getEndLoc()); return Range; } @@ -2226,8 +2212,7 @@ class UnresolvedMemberExpr : public OverloadExpr { SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Member, - SourceLocation MemberLoc, + const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2242,8 +2227,7 @@ public: SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Member, - SourceLocation MemberLoc, + const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2287,6 +2271,11 @@ public: /// \brief Retrieves the naming class of this lookup. CXXRecordDecl *getNamingClass() const; + /// \brief Retrieve the full name info for the member that this expression + /// refers to. + const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); } + void setMemberNameInfo(const DeclarationNameInfo &N) { setNameInfo(N); } + /// \brief Retrieve the name of the member that this expression /// refers to. DeclarationName getMemberName() const { return getName(); } @@ -2311,6 +2300,14 @@ public: return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1); } + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); + } + /// \brief Copies the template arguments into the given structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { getExplicitTemplateArgs().copyInto(List); @@ -2341,18 +2338,14 @@ public: } virtual SourceRange getSourceRange() const { - SourceRange Range; + SourceRange Range = getMemberNameInfo().getSourceRange(); if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); else if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); - else - Range.setBegin(getMemberLoc()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); - else - Range.setEnd(getMemberLoc()); return Range; } diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index def9ced94c29..a8ef0053a442 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -14,31 +14,25 @@ #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Type.h" -#include "llvm/ADT/SmallVector.h" #include <cassert> #include <vector> + +namespace llvm { +template <class T> class SmallVectorImpl; +} + namespace clang { class ASTConsumer; class Decl; class DeclContext; +class DeclContextLookupResult; +class DeclarationName; class ExternalSemaSource; // layering violation required for downcasting +class NamedDecl; +class Selector; class Stmt; -/// \brief The deserialized representation of a set of declarations -/// with the same name that are visible in a given context. -struct VisibleDeclaration { - /// \brief The name of the declarations. - DeclarationName Name; - - /// \brief The ID numbers of all of the declarations with this name. - /// - /// These declarations have not necessarily been de-serialized. - llvm::SmallVector<unsigned, 4> Declarations; -}; - /// \brief Abstract interface for external sources of AST nodes. /// /// External AST sources provide AST nodes constructed from some @@ -58,6 +52,20 @@ public: virtual ~ExternalASTSource(); + /// \brief RAII class for safely pairing a StartedDeserializing call + /// with FinishedDeserializing. + class Deserializing { + ExternalASTSource *Source; + public: + explicit Deserializing(ExternalASTSource *source) : Source(source) { + assert(Source); + Source->StartedDeserializing(); + } + ~Deserializing() { + Source->FinishedDeserializing(); + } + }; + /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. /// @@ -89,10 +97,18 @@ public: /// Generally the final step of this method is either to call /// SetExternalVisibleDeclsForName or to recursively call lookup on /// the DeclContext after calling SetExternalVisibleDecls. - virtual DeclContext::lookup_result + virtual DeclContextLookupResult FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) = 0; + /// \brief Deserialize all the visible declarations from external storage. + /// + /// Name lookup deserializes visible declarations lazily, thus a DeclContext + /// may not have a complete name lookup table. This function deserializes + /// the rest of visible declarations from the external storage and completes + /// the name lookup table of the DeclContext. + virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0; + /// \brief Finds all declarations lexically contained within the given /// DeclContext. /// @@ -100,6 +116,19 @@ public: virtual bool FindExternalLexicalDecls(const DeclContext *DC, llvm::SmallVectorImpl<Decl*> &Result) = 0; + /// \brief Notify ExternalASTSource that we started deserialization of + /// a decl or type so until FinishedDeserializing is called there may be + /// decls that are initializing. Must be paired with FinishedDeserializing. + /// + /// The default implementation of this method is a no-op. + virtual void StartedDeserializing() { } + + /// \brief Notify ExternalASTSource that we finished the deserialization of + /// a decl or type. Must be paired with StartedDeserializing. + /// + /// The default implementation of this method is a no-op. + virtual void FinishedDeserializing() { } + /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. /// @@ -113,30 +142,18 @@ public: virtual void PrintStats(); protected: - /// \brief Initialize the context's lookup map with the given decls. - /// It is assumed that none of the declarations are redeclarations of - /// each other. - static void SetExternalVisibleDecls(const DeclContext *DC, - const llvm::SmallVectorImpl<VisibleDeclaration> &Decls); - - /// \brief Initialize the context's lookup map with the given decls. - /// It is assumed that none of the declarations are redeclarations of - /// each other. - static void SetExternalVisibleDecls(const DeclContext *DC, - const llvm::SmallVectorImpl<NamedDecl*> &Decls); - - static DeclContext::lookup_result - SetExternalVisibleDeclsForName(const DeclContext *DC, - const VisibleDeclaration &VD); - - static DeclContext::lookup_result + static DeclContextLookupResult SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, llvm::SmallVectorImpl<NamedDecl*> &Decls); - static DeclContext::lookup_result + static DeclContextLookupResult SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name); + + void MaterializeVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name, + llvm::SmallVectorImpl<NamedDecl*> &Decls); }; /// \brief A lazy pointer to an AST node (of base type T) that resides @@ -145,7 +162,7 @@ protected: /// The AST node is identified within the external AST source by a /// 63-bit offset, and can be retrieved via an operation on the /// external AST source itself. -template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)> +template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)> struct LazyOffsetPtr { /// \brief Either a pointer to an AST node or the offset within the /// external AST source where the AST node can be found. @@ -203,9 +220,13 @@ public: }; /// \brief A lazy pointer to a statement. -typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetExternalDeclStmt> +typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> LazyDeclStmtPtr; +/// \brief A lazy pointer to a declaration. +typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> + LazyDeclPtr; + } // end namespace clang #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H diff --git a/include/clang/AST/FullExpr.h b/include/clang/AST/FullExpr.h index bb81bf0fe7c8..6ceefed8a63a 100644 --- a/include/clang/AST/FullExpr.h +++ b/include/clang/AST/FullExpr.h @@ -47,7 +47,6 @@ class FullExpr { public: static FullExpr Create(ASTContext &Context, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); - void Destroy(ASTContext &Context); Expr *getExpr() { if (Expr *E = SubExpr.dyn_cast<Expr *>()) diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile index 00a1e1bf7977..6ba6e897d186 100644 --- a/include/clang/AST/Makefile +++ b/include/clang/AST/Makefile @@ -1,6 +1,6 @@ CLANG_LEVEL := ../../.. TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic -BUILT_SOURCES = Attrs.inc StmtNodes.inc DeclNodes.inc +BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc TABLEGEN_INC_FILES_COMMON = 1 @@ -12,6 +12,12 @@ $(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \ $(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \ -I $(PROJ_SRC_DIR)/../../ $< +$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang attribute implementations with tblgen" + $(Verb) $(TableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \ + -I $(PROJ_SRC_DIR)/../../ $< + $(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \ $(ObjDir)/.dir $(Echo) "Building Clang statement node tables with tblgen" diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 1594b090fea5..3b25f3bb403f 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -181,8 +181,6 @@ public: ID.AddPointer(Specifier); } - void Destroy(ASTContext &Context); - /// \brief Dump the nested name specifier to standard output to aid /// in debugging. void dump(const LangOptions &LO); diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h new file mode 100644 index 000000000000..804531192971 --- /dev/null +++ b/include/clang/AST/OperationKinds.h @@ -0,0 +1,158 @@ +//===- OperationKinds.h - Operation enums -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates the different kinds of operations that can be +// performed by various expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H +#define LLVM_CLANG_AST_OPERATION_KINDS_H + +namespace clang { + +/// CastKind - the kind of cast this represents. +enum CastKind { + /// CK_Unknown - Unknown cast kind. + /// FIXME: The goal is to get rid of this and make all casts have a + /// kind so that the AST client doesn't have to try to figure out what's + /// going on. + CK_Unknown, + + /// CK_BitCast - Used for reinterpret_cast. + CK_BitCast, + + /// CK_LValueBitCast - Used for reinterpret_cast of expressions to + /// a reference type. + CK_LValueBitCast, + + /// CK_NoOp - Used for const_cast. + CK_NoOp, + + /// CK_BaseToDerived - Base to derived class casts. + CK_BaseToDerived, + + /// CK_DerivedToBase - Derived to base class casts. + CK_DerivedToBase, + + /// CK_UncheckedDerivedToBase - Derived to base class casts that + /// assume that the derived pointer is not null. + CK_UncheckedDerivedToBase, + + /// CK_Dynamic - Dynamic cast. + CK_Dynamic, + + /// CK_ToUnion - Cast to union (GCC extension). + CK_ToUnion, + + /// CK_ArrayToPointerDecay - Array to pointer decay. + CK_ArrayToPointerDecay, + + // CK_FunctionToPointerDecay - Function to pointer decay. + CK_FunctionToPointerDecay, + + /// CK_NullToMemberPointer - Null pointer to member pointer. + CK_NullToMemberPointer, + + /// CK_BaseToDerivedMemberPointer - Member pointer in base class to + /// member pointer in derived class. + CK_BaseToDerivedMemberPointer, + + /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to + /// member pointer in base class. + CK_DerivedToBaseMemberPointer, + + /// CK_UserDefinedConversion - Conversion using a user defined type + /// conversion function. + CK_UserDefinedConversion, + + /// CK_ConstructorConversion - Conversion by constructor + CK_ConstructorConversion, + + /// CK_IntegralToPointer - Integral to pointer + CK_IntegralToPointer, + + /// CK_PointerToIntegral - Pointer to integral + CK_PointerToIntegral, + + /// CK_ToVoid - Cast to void. + CK_ToVoid, + + /// CK_VectorSplat - Casting from an integer/floating type to an extended + /// vector type with the same element type as the src type. Splats the + /// src expression into the destination expression. + CK_VectorSplat, + + /// CK_IntegralCast - Casting between integral types of different size. + CK_IntegralCast, + + /// CK_IntegralToFloating - Integral to floating point. + CK_IntegralToFloating, + + /// CK_FloatingToIntegral - Floating point to integral. + CK_FloatingToIntegral, + + /// CK_FloatingCast - Casting between floating types of different size. + CK_FloatingCast, + + /// CK_MemberPointerToBoolean - Member pointer to boolean + CK_MemberPointerToBoolean, + + /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c + /// pointer + CK_AnyPointerToObjCPointerCast, + + /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block + /// pointer + CK_AnyPointerToBlockPointerCast, + + /// \brief Converting between two Objective-C object types, which + /// can occur when performing reference binding to an Objective-C + /// object. + CK_ObjCObjectLValueCast +}; + + +enum BinaryOperatorKind { + // Operators listed in order of precedence. + // Note that additions to this should also update the StmtVisitor class. + BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators. + BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators. + BO_Add, BO_Sub, // [C99 6.5.6] Additive operators. + BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators. + BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators. + BO_EQ, BO_NE, // [C99 6.5.9] Equality operators. + BO_And, // [C99 6.5.10] Bitwise AND operator. + BO_Xor, // [C99 6.5.11] Bitwise XOR operator. + BO_Or, // [C99 6.5.12] Bitwise OR operator. + BO_LAnd, // [C99 6.5.13] Logical AND operator. + BO_LOr, // [C99 6.5.14] Logical OR operator. + BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators. + BO_DivAssign, BO_RemAssign, + BO_AddAssign, BO_SubAssign, + BO_ShlAssign, BO_ShrAssign, + BO_AndAssign, BO_XorAssign, + BO_OrAssign, + BO_Comma // [C99 6.5.17] Comma operator. +}; + +enum UnaryOperatorKind { + // Note that additions to this should also update the StmtVisitor class. + UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement + UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement + UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection + UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic + UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic + UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension. + UO_Extension // __extension__ marker. +}; + +} + +#endif diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 0853dddbe9e5..232e47b03ae5 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -42,7 +42,7 @@ OPERATOR(Plus) OPERATOR(Minus) \ OPERATOR(Not) OPERATOR(LNot) \ OPERATOR(Real) OPERATOR(Imag) \ - OPERATOR(Extension) OPERATOR(OffsetOf) + OPERATOR(Extension) // All binary operators (excluding compound assign operators). #define BINOP_LIST() \ @@ -123,12 +123,27 @@ namespace clang { /// users may override Traverse* and WalkUpFrom* to implement custom /// traversal strategies. Returning false from one of these overridden /// functions will abort the entire traversal. +/// +/// By default, this visitor tries to visit every part of the explicit +/// source code exactly once. The default policy towards templates +/// is to descend into the 'pattern' class or function body, not any +/// explicit or implicit instantiations. Explicit specializations +/// are still visited, and the patterns of partial specializations +/// are visited separately. This behavior can be changed by +/// overriding shouldVisitTemplateInstantiations() in the derived class +/// to return true, in which case all known implicit and explicit +/// instantiations will be visited at the same time as the pattern +/// from which they were produced. template<typename Derived> class RecursiveASTVisitor { public: /// \brief Return a reference to the derived class. Derived &getDerived() { return *static_cast<Derived*>(this); } + /// \brief Return whether this visitor should recurse into + /// template instantiations. + bool shouldVisitTemplateInstantiations() const { return false; } + /// \brief Recursively visit a statement or expression, by /// dispatching to Traverse*() based on the argument's dynamic type. /// @@ -351,8 +366,11 @@ public: private: // These are helper methods used by more than one Traverse* method. bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); - bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, + bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern); + bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ; + bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, unsigned Count); + bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); bool TraverseRecordHelper(RecordDecl *D); bool TraverseCXXRecordHelper(CXXRecordDecl *D); bool TraverseDeclaratorHelper(DeclaratorDecl *D); @@ -375,14 +393,14 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { #define OPERATOR(NAME) \ - case BinaryOperator::NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S); + case BO_##NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S); BINOP_LIST() #undef OPERATOR #undef BINOP_LIST #define OPERATOR(NAME) \ - case BinaryOperator::NAME##Assign: \ + case BO_##NAME##Assign: \ DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S); CAO_LIST() @@ -392,7 +410,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { switch (UnOp->getOpcode()) { #define OPERATOR(NAME) \ - case UnaryOperator::NAME: DISPATCH(Unary##NAME, UnaryOperator, S); + case UO_##NAME: DISPATCH(Unary##NAME, UnaryOperator, S); UNARYOP_LIST() #undef OPERATOR @@ -540,8 +558,11 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( return true; case TemplateArgument::Type: { - TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo(); - return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); + // FIXME: how can TSI ever be NULL? + if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) + return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); + else + return true; } case TemplateArgument::Template: @@ -796,23 +817,31 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { + // This isn't available for ArrayType, but is for the ArrayTypeLoc. + TRY_TO(TraverseStmt(TL.getSizeExpr())); + return true; +} + DEF_TRAVERSE_TYPELOC(ConstantArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); }) DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); }) DEF_TRAVERSE_TYPELOC(VariableArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + return TraverseArrayTypeLocHelper(TL); }) DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - if (TL.getTypePtr()->getSizeExpr()) - TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + return TraverseArrayTypeLocHelper(TL); }) // FIXME: order? why not size expr first? @@ -1083,19 +1112,124 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( return true; } +// A helper method for traversing the implicit instantiations of a +// class. +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations( + ClassTemplateDecl* D, Decl *Pattern) { + assert(isa<ClassTemplateDecl>(Pattern) || + isa<ClassTemplatePartialSpecializationDecl>(Pattern)); + + ClassTemplateDecl::spec_iterator end = D->spec_end(); + for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { + ClassTemplateSpecializationDecl* SD = *it; + + switch (SD->getSpecializationKind()) { + // Visit the implicit instantiations with the requested pattern. + case TSK_ImplicitInstantiation: { + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> U + = SD->getInstantiatedFrom(); + + bool ShouldVisit; + if (U.is<ClassTemplateDecl*>()) + ShouldVisit = (U.get<ClassTemplateDecl*>() == Pattern); + else + ShouldVisit + = (U.get<ClassTemplatePartialSpecializationDecl*>() == Pattern); + + if (ShouldVisit) + TRY_TO(TraverseClassTemplateSpecializationDecl(SD)); + break; + } + + // We don't need to do anything on an explicit instantiation + // or explicit specialization because there will be an explicit + // node for it elsewhere. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + break; + + // We don't need to do anything for an uninstantiated + // specialization. + case TSK_Undeclared: + break; + } + } + + return true; +} + DEF_TRAVERSE_DECL(ClassTemplateDecl, { - TRY_TO(TraverseDecl(D->getTemplatedDecl())); + CXXRecordDecl* TempDecl = D->getTemplatedDecl(); + TRY_TO(TraverseDecl(TempDecl)); TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - // We should not traverse the specializations/partial - // specializations. Those will show up in other contexts. - // getInstantiatedFromMemberTemplate() is just a link from a - // template instantiation back to the template from which it was - // instantiated, and thus should not be traversed either. + + // By default, we do not traverse the instantiations of + // class templates since they do not apprear in the user code. The + // following code optionally traverses them. + if (getDerived().shouldVisitTemplateInstantiations()) { + // If this is the definition of the primary template, visit + // instantiations which were formed from this pattern. + if (D->isThisDeclarationADefinition()) + TRY_TO(TraverseClassInstantiations(D, D)); + } + + // Note that getInstantiatedFromMemberTemplate() is just a link + // from a template instantiation back to the template from which + // it was instantiated, and thus should not be traversed. }) +// A helper method for traversing the instantiations of a +// function while skipping its specializations. +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( + FunctionTemplateDecl* D) { + FunctionTemplateDecl::spec_iterator end = D->spec_end(); + for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { + FunctionDecl* FD = *it; + switch (FD->getTemplateSpecializationKind()) { + case TSK_ImplicitInstantiation: + // We don't know what kind of FunctionDecl this is. + TRY_TO(TraverseDecl(FD)); + break; + + // No need to visit explicit instantiations, we'll find the node + // eventually. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + break; + + case TSK_Undeclared: // Declaration of the template definition. + case TSK_ExplicitSpecialization: + break; + default: + assert(false && "Unknown specialization kind."); + } + } + + return true; +} + DEF_TRAVERSE_DECL(FunctionTemplateDecl, { TRY_TO(TraverseDecl(D->getTemplatedDecl())); TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + + // By default, we do not traverse the instantiations of + // function templates since they do not apprear in the user code. The + // following code optionally traverses them. + if (getDerived().shouldVisitTemplateInstantiations()) { + // Explicit function specializations will be traversed from the + // context of their declaration. There is therefore no need to + // traverse them for here. + // + // In addition, we only traverse the function instantiations when + // the function template is a function template definition. + if (D->isThisDeclarationADefinition()) { + TRY_TO(TraverseFunctionInstantiations(D)); + } + } }) DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { @@ -1110,10 +1244,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { // D is the "T" in something like "template<typename T> class vector;" - if (D->hasDefaultArgument()) - TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); if (D->getTypeForDecl()) TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); + if (D->hasDefaultArgument()) + TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); }) DEF_TRAVERSE_DECL(TypedefDecl, { @@ -1166,7 +1300,7 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper( for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { - TRY_TO(TraverseType(I->getType())); + TRY_TO(TraverseTypeLoc(I->getTypeSourceInfo()->getTypeLoc())); } // We don't traverse the friends or the conversions, as they are // already in decls_begin()/decls_end(). @@ -1191,10 +1325,16 @@ DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, { // ("template set<int>;"), we do need a callback, since this // is the only callback that's made for this instantiation. // We use getTypeAsWritten() to distinguish. - // FIXME: see how we want to handle template specializations. if (TypeSourceInfo *TSI = D->getTypeAsWritten()) TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); - return true; + + if (!getDerived().shouldVisitTemplateInstantiations() && + D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + // Returning from here skips traversing the + // declaration context of the ClassTemplateSpecializationDecl + // (embedded in the DEF_TRAVERSE_DECL() macro) + // which contains the instantiated members of the class. + return true; }) template <typename Derived> @@ -1222,6 +1362,12 @@ DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, { // though that's our parent class -- we already visit all the // template args here. TRY_TO(TraverseCXXRecordHelper(D)); + + // If we're visiting instantiations, visit the instantiations of + // this template now. + if (getDerived().shouldVisitTemplateInstantiations() && + D->isThisDeclarationADefinition()) + TRY_TO(TraverseClassInstantiations(D->getSpecializedTemplate(), D)); }) DEF_TRAVERSE_DECL(EnumConstantDecl, { @@ -1304,7 +1450,45 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { } TRY_TO(TraverseType(D->getResultType())); - TRY_TO(TraverseDeclContextHelper(D)); // Parameters. + + // If we're an explicit template specialization, iterate over the + // template args that were explicitly specified. + if (const FunctionTemplateSpecializationInfo *FTSI = + D->getTemplateSpecializationInfo()) { + if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared && + FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { + // A specialization might not have explicit template arguments if it has + // a templated return type and concrete arguments. + if (const TemplateArgumentListInfo *TALI = + FTSI->TemplateArgumentsAsWritten) { + TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getArgumentArray(), + TALI->size())); + } + } + } + + for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + + if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) { + if (D->isThisDeclarationADefinition()) { + // This would be visited if we called TraverseType(D->getType()) + // above, but we don't (at least, not in the + // declaration-is-a-definition case), in order to avoid duplicate + // visiting for parameters. (We need to check parameters here, + // rather than letting D->getType() do it, so we visit default + // parameter values). So we need to re-do some of the work the + // type would do. + for (FunctionProtoType::exception_iterator + E = FuncProto->exception_begin(), + EEnd = FuncProto->exception_end(); + E != EEnd; ++E) { + TRY_TO(TraverseType(*E)); + } + } + } if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { // Constructor initializers. @@ -1356,9 +1540,6 @@ DEF_TRAVERSE_DECL(CXXDestructorDecl, { template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { TRY_TO(TraverseDeclaratorHelper(D)); - // FIXME: This often double-counts -- for instance, for all local - // vars, though not for global vars -- because the initializer is - // also captured when the var-decl is in a DeclStmt. TRY_TO(TraverseStmt(D->getInit())); return true; } @@ -1373,11 +1554,13 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, { DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { // A non-type template parameter, e.g. "S" in template<int S> class Foo ... - TRY_TO(TraverseStmt(D->getDefaultArgument())); TRY_TO(TraverseVarHelper(D)); + TRY_TO(TraverseStmt(D->getDefaultArgument())); }) DEF_TRAVERSE_DECL(ParmVarDecl, { + TRY_TO(TraverseVarHelper(D)); + if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() && !D->hasUnparsedDefaultArg()) @@ -1387,8 +1570,6 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { !D->hasUninstantiatedDefaultArg() && !D->hasUnparsedDefaultArg()) TRY_TO(TraverseStmt(D->getDefaultArg())); - - TRY_TO(TraverseVarHelper(D)); }) #undef DEF_TRAVERSE_DECL @@ -1431,35 +1612,36 @@ DEF_TRAVERSE_STMT(AsmStmt, { }) DEF_TRAVERSE_STMT(CXXCatchStmt, { - // We don't traverse S->getCaughtType(), as we are already - // traversing the exception object, which has this type. + TRY_TO(TraverseDecl(S->getExceptionDecl())); // child_begin()/end() iterates over the handler block. }) -DEF_TRAVERSE_STMT(ForStmt, { - TRY_TO(TraverseDecl(S->getConditionVariable())); - // child_begin()/end() iterates over init, cond, inc, and body stmts. - }) - -DEF_TRAVERSE_STMT(IfStmt, { - TRY_TO(TraverseDecl(S->getConditionVariable())); - // child_begin()/end() iterates over cond, then, and else stmts. +DEF_TRAVERSE_STMT(DeclStmt, { + for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + // Suppress the default iteration over child_begin/end by + // returning. Here's why: A DeclStmt looks like 'type var [= + // initializer]'. The decls above already traverse over the + // initializers, so we don't have to do it again (which + // child_begin/end would do). + return true; }) -DEF_TRAVERSE_STMT(WhileStmt, { - TRY_TO(TraverseDecl(S->getConditionVariable())); - // child_begin()/end() iterates over cond, then, and else stmts. - }) // These non-expr stmts (most of them), do not need any action except // iterating over the children. DEF_TRAVERSE_STMT(BreakStmt, { }) +DEF_TRAVERSE_STMT(CXXTryStmt, { }) +DEF_TRAVERSE_STMT(CaseStmt, { }) DEF_TRAVERSE_STMT(CompoundStmt, { }) DEF_TRAVERSE_STMT(ContinueStmt, { }) -DEF_TRAVERSE_STMT(CXXTryStmt, { }) -DEF_TRAVERSE_STMT(DeclStmt, { }) +DEF_TRAVERSE_STMT(DefaultStmt, { }) DEF_TRAVERSE_STMT(DoStmt, { }) +DEF_TRAVERSE_STMT(ForStmt, { }) DEF_TRAVERSE_STMT(GotoStmt, { }) +DEF_TRAVERSE_STMT(IfStmt, { }) DEF_TRAVERSE_STMT(IndirectGotoStmt, { }) DEF_TRAVERSE_STMT(LabelStmt, { }) DEF_TRAVERSE_STMT(NullStmt, { }) @@ -1470,10 +1652,10 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) DEF_TRAVERSE_STMT(ReturnStmt, { }) -DEF_TRAVERSE_STMT(SwitchStmt, { }) DEF_TRAVERSE_STMT(SwitchCase, { }) -DEF_TRAVERSE_STMT(CaseStmt, { }) -DEF_TRAVERSE_STMT(DefaultStmt, { }) +DEF_TRAVERSE_STMT(SwitchStmt, { }) +DEF_TRAVERSE_STMT(WhileStmt, { }) + DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { if (S->hasExplicitTemplateArgs()) { @@ -1565,6 +1747,37 @@ DEF_TRAVERSE_STMT(CXXNewExpr, { TRY_TO(TraverseType(S->getAllocatedType())); }) +DEF_TRAVERSE_STMT(OffsetOfExpr, { + // The child-iterator will pick up the expression representing + // the field. + // FIMXE: for code like offsetof(Foo, a.b.c), should we get + // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c? + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isArgumentType()) + TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(CXXTypeidExpr, { + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isTypeOperand()) + TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(TypesCompatibleExpr, { + TRY_TO(TraverseTypeLoc(S->getArgTInfo1()->getTypeLoc())); + TRY_TO(TraverseTypeLoc(S->getArgTInfo2()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { + TRY_TO(TraverseType(S->getQueriedType())); + }) + // These exprs (most of them), do not need any action except iterating // over the children. DEF_TRAVERSE_STMT(AddrLabelExpr, { }) @@ -1573,7 +1786,6 @@ DEF_TRAVERSE_STMT(BlockDeclRefExpr, { }) DEF_TRAVERSE_STMT(BlockExpr, { }) DEF_TRAVERSE_STMT(ChooseExpr, { }) DEF_TRAVERSE_STMT(CompoundLiteralExpr, { }) -DEF_TRAVERSE_STMT(CXXBindReferenceExpr, { }) DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { }) @@ -1583,7 +1795,6 @@ DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { }) DEF_TRAVERSE_STMT(CXXThisExpr, { }) DEF_TRAVERSE_STMT(CXXThrowExpr, { }) -DEF_TRAVERSE_STMT(CXXTypeidExpr, { }) DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { }) DEF_TRAVERSE_STMT(DesignatedInitExpr, { }) DEF_TRAVERSE_STMT(ExtVectorElementExpr, { }) @@ -1598,18 +1809,17 @@ DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { }) DEF_TRAVERSE_STMT(ObjCProtocolExpr, { }) DEF_TRAVERSE_STMT(ObjCSelectorExpr, { }) DEF_TRAVERSE_STMT(ObjCSuperExpr, { }) -DEF_TRAVERSE_STMT(OffsetOfExpr, { }) DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) -DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) -DEF_TRAVERSE_STMT(TypesCompatibleExpr, { }) -DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { }) DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { }) -DEF_TRAVERSE_STMT(VAArgExpr, { }) +DEF_TRAVERSE_STMT(VAArgExpr, { + // The child-iterator will pick up the expression argument. + TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); + }) DEF_TRAVERSE_STMT(CXXConstructExpr, { }) DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 55e1f8477992..ba778293ba2d 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -177,6 +177,9 @@ public: static_cast<const decl_type*>(this))); } redecl_iterator redecls_end() const { return redecl_iterator(); } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index a0c95b1fce8c..62a6b6463df5 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -151,22 +151,11 @@ public: struct EmptyShell { }; protected: - /// DestroyChildren - Invoked by destructors of subclasses of Stmt to - /// recursively release child AST nodes. - void DestroyChildren(ASTContext& Ctx); - /// \brief Construct an empty statement. explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) { if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); } - /// \brief Virtual method that performs the actual destruction of - /// this statement. - /// - /// Subclasses should override this method (not Destroy()) to - /// provide class-specific destruction. - virtual void DoDestroy(ASTContext &Ctx); - public: Stmt(StmtClass SC) : sClass(SC), RefCount(1) { if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); @@ -181,13 +170,6 @@ public: } #endif - /// \brief Destroy the current statement and its children. - void Destroy(ASTContext &Ctx) { - assert(RefCount >= 1); - if (--RefCount == 0) - DoDestroy(Ctx); - } - /// \brief Increases the reference count for this statement. /// /// Invoke the Retain() operation when this statement or expression @@ -221,6 +203,7 @@ public: /// This is useful in a debugger. void dump() const; void dump(SourceManager &SM) const; + void dump(llvm::raw_ostream &OS, SourceManager &SM) const; /// dumpAll - This does a dump of the specified AST fragment and all subtrees. void dumpAll() const; @@ -295,9 +278,6 @@ class DeclStmt : public Stmt { DeclGroupRef DG; SourceLocation StartLoc, EndLoc; -protected: - virtual void DoDestroy(ASTContext &Ctx); - public: DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), @@ -671,9 +651,6 @@ public: // over the initialization expression referenced by the condition variable. virtual child_iterator child_begin(); virtual child_iterator child_end(); - -protected: - virtual void DoDestroy(ASTContext &Ctx); }; /// SwitchStmt - This represents a 'switch' stmt. @@ -685,9 +662,6 @@ class SwitchStmt : public Stmt { SwitchCase *FirstCase; SourceLocation SwitchLoc; -protected: - virtual void DoDestroy(ASTContext &Ctx); - public: SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond); @@ -794,9 +768,6 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); - -protected: - virtual void DoDestroy(ASTContext &Ctx); }; /// DoStmt - This represents a 'do/while' stmt. @@ -910,9 +881,6 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); - -protected: - virtual void DoDestroy(ASTContext &Ctx); }; /// GotoStmt - This represents a direct goto. @@ -1113,9 +1081,6 @@ class AsmStmt : public Stmt { StringLiteral **Constraints; Stmt **Exprs; StringLiteral **Clobbers; - -protected: - virtual void DoDestroy(ASTContext &Ctx); public: AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 4e87c2701c26..0508f35e48e8 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -29,14 +29,14 @@ class CXXCatchStmt : public Stmt { /// The handler block. Stmt *HandlerBlock; -protected: - virtual void DoDestroy(ASTContext& Ctx); - public: CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), HandlerBlock(handlerBlock) {} + CXXCatchStmt(EmptyShell Empty) + : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {} + virtual SourceRange getSourceRange() const { return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); } @@ -53,6 +53,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class ASTStmtReader; }; /// CXXTryStmt - A C++ try block, including all handlers. @@ -64,38 +66,46 @@ class CXXTryStmt : public Stmt { CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, unsigned numHandlers); + CXXTryStmt(EmptyShell Empty, unsigned numHandlers) + : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } + + Stmt const * const *getStmts() const { + return reinterpret_cast<Stmt const * const*>(this + 1); + } + Stmt **getStmts() { + return reinterpret_cast<Stmt **>(this + 1); + } + public: static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, unsigned numHandlers); + static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty, + unsigned numHandlers); + virtual SourceRange getSourceRange() const { return SourceRange(getTryLoc(), getEndLoc()); } SourceLocation getTryLoc() const { return TryLoc; } SourceLocation getEndLoc() const { - Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); - return Stmts[NumHandlers]->getLocEnd(); + return getStmts()[NumHandlers]->getLocEnd(); } CompoundStmt *getTryBlock() { - Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); - return llvm::cast<CompoundStmt>(Stmts[0]); + return llvm::cast<CompoundStmt>(getStmts()[0]); } const CompoundStmt *getTryBlock() const { - Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); - return llvm::cast<CompoundStmt>(Stmts[0]); + return llvm::cast<CompoundStmt>(getStmts()[0]); } unsigned getNumHandlers() const { return NumHandlers; } CXXCatchStmt *getHandler(unsigned i) { - Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); - return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); + return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]); } const CXXCatchStmt *getHandler(unsigned i) const { - Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); - return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); + return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]); } static bool classof(const Stmt *T) { @@ -105,6 +115,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class ASTStmtReader; }; diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index 8078451fa31f..b8c141d7ef8e 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -37,68 +37,57 @@ public: if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { default: assert(0 && "Unknown binary operator!"); - case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); - case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); - case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator); - case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator); - case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator); - case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator); - case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator); - case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator); - case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator); - - case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator); - case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator); - case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator); - case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator); - case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator); - case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator); - - case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator); - case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator); - case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator); - case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator); - case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator); - case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator); - case BinaryOperator::MulAssign: - DISPATCH(BinMulAssign, CompoundAssignOperator); - case BinaryOperator::DivAssign: - DISPATCH(BinDivAssign, CompoundAssignOperator); - case BinaryOperator::RemAssign: - DISPATCH(BinRemAssign, CompoundAssignOperator); - case BinaryOperator::AddAssign: - DISPATCH(BinAddAssign, CompoundAssignOperator); - case BinaryOperator::SubAssign: - DISPATCH(BinSubAssign, CompoundAssignOperator); - case BinaryOperator::ShlAssign: - DISPATCH(BinShlAssign, CompoundAssignOperator); - case BinaryOperator::ShrAssign: - DISPATCH(BinShrAssign, CompoundAssignOperator); - case BinaryOperator::AndAssign: - DISPATCH(BinAndAssign, CompoundAssignOperator); - case BinaryOperator::OrAssign: - DISPATCH(BinOrAssign, CompoundAssignOperator); - case BinaryOperator::XorAssign: - DISPATCH(BinXorAssign, CompoundAssignOperator); - case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator); + case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); + case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); + case BO_Mul: DISPATCH(BinMul, BinaryOperator); + case BO_Div: DISPATCH(BinDiv, BinaryOperator); + case BO_Rem: DISPATCH(BinRem, BinaryOperator); + case BO_Add: DISPATCH(BinAdd, BinaryOperator); + case BO_Sub: DISPATCH(BinSub, BinaryOperator); + case BO_Shl: DISPATCH(BinShl, BinaryOperator); + case BO_Shr: DISPATCH(BinShr, BinaryOperator); + + case BO_LT: DISPATCH(BinLT, BinaryOperator); + case BO_GT: DISPATCH(BinGT, BinaryOperator); + case BO_LE: DISPATCH(BinLE, BinaryOperator); + case BO_GE: DISPATCH(BinGE, BinaryOperator); + case BO_EQ: DISPATCH(BinEQ, BinaryOperator); + case BO_NE: DISPATCH(BinNE, BinaryOperator); + + case BO_And: DISPATCH(BinAnd, BinaryOperator); + case BO_Xor: DISPATCH(BinXor, BinaryOperator); + case BO_Or : DISPATCH(BinOr, BinaryOperator); + case BO_LAnd: DISPATCH(BinLAnd, BinaryOperator); + case BO_LOr : DISPATCH(BinLOr, BinaryOperator); + case BO_Assign: DISPATCH(BinAssign, BinaryOperator); + case BO_MulAssign: DISPATCH(BinMulAssign, CompoundAssignOperator); + case BO_DivAssign: DISPATCH(BinDivAssign, CompoundAssignOperator); + case BO_RemAssign: DISPATCH(BinRemAssign, CompoundAssignOperator); + case BO_AddAssign: DISPATCH(BinAddAssign, CompoundAssignOperator); + case BO_SubAssign: DISPATCH(BinSubAssign, CompoundAssignOperator); + case BO_ShlAssign: DISPATCH(BinShlAssign, CompoundAssignOperator); + case BO_ShrAssign: DISPATCH(BinShrAssign, CompoundAssignOperator); + case BO_AndAssign: DISPATCH(BinAndAssign, CompoundAssignOperator); + case BO_OrAssign: DISPATCH(BinOrAssign, CompoundAssignOperator); + case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator); + case BO_Comma: DISPATCH(BinComma, BinaryOperator); } } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { switch (UnOp->getOpcode()) { default: assert(0 && "Unknown unary operator!"); - case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator); - case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator); - case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator); - case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator); - case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator); - case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator); - case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator); - case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator); - case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator); - case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator); - case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator); - case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator); - case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator); - case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator); + case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator); + case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator); + case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator); + case UO_PreDec: DISPATCH(UnaryPreDec, UnaryOperator); + case UO_AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator); + case UO_Deref: DISPATCH(UnaryDeref, UnaryOperator); + case UO_Plus: DISPATCH(UnaryPlus, UnaryOperator); + case UO_Minus: DISPATCH(UnaryMinus, UnaryOperator); + case UO_Not: DISPATCH(UnaryNot, UnaryOperator); + case UO_LNot: DISPATCH(UnaryLNot, UnaryOperator); + case UO_Real: DISPATCH(UnaryReal, UnaryOperator); + case UO_Imag: DISPATCH(UnaryImag, UnaryOperator); + case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator); } } @@ -163,7 +152,7 @@ public: UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) - UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf) + UNARYOP_FALLBACK(Extension) #undef UNARYOP_FALLBACK // Base case, ignore it. :) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 4c148e8fa221..92e62a58d42c 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -289,7 +289,18 @@ public: L += R; return L; } + + Qualifiers &operator-=(Qualifiers R) { + Mask = Mask & ~(R.Mask); + return *this; + } + /// \brief Compute the difference between two qualifier sets. + friend Qualifiers operator-(Qualifiers L, Qualifiers R) { + L -= R; + return L; + } + std::string getAsString() const; std::string getAsString(const PrintingPolicy &Policy) const { std::string Buffer; @@ -399,7 +410,8 @@ enum CallingConv { CC_C, // __attribute__((cdecl)) CC_X86StdCall, // __attribute__((stdcall)) CC_X86FastCall, // __attribute__((fastcall)) - CC_X86ThisCall // __attribute__((thiscall)) + CC_X86ThisCall, // __attribute__((thiscall)) + CC_X86Pascal // __attribute__((pascal)) }; @@ -787,12 +799,12 @@ private: /// \brief Linkage of this type. mutable unsigned CachedLinkage : 2; - /// \brief FromPCH - Whether this type comes from a PCH file. - mutable bool FromPCH : 1; + /// \brief FromAST - Whether this type comes from an AST file. + mutable bool FromAST : 1; - /// \brief Set whether this type comes from a PCH file. - void setFromPCH(bool V = true) const { - FromPCH = V; + /// \brief Set whether this type comes from an AST file. + void setFromAST(bool V = true) const { + FromAST = V; } protected: @@ -806,16 +818,15 @@ protected: Type(TypeClass tc, QualType Canonical, bool dependent) : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical), TC(tc), Dependent(dependent), LinkageKnown(false), - CachedLinkage(NoLinkage), FromPCH(false) {} - virtual ~Type() {} - virtual void Destroy(ASTContext& C); + CachedLinkage(NoLinkage), FromAST(false) {} + virtual ~Type(); friend class ASTContext; public: TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); } - /// \brief Whether this type comes from a PCH file. - bool isFromPCH() const { return FromPCH; } + /// \brief Whether this type comes from an AST file. + bool isFromAST() const { return FromAST; } bool isCanonicalUnqualified() const { return CanonicalType.getTypePtr() == this; @@ -824,14 +835,6 @@ public: /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. - /// \brief Determines whether the type describes an object in memory. - /// - /// Note that this definition of object type corresponds to the C++ - /// definition of object type, which includes incomplete types, as - /// opposed to the C definition (which does not include incomplete - /// types). - bool isObjectType() const; - /// isIncompleteType - Return true if this is an incomplete type. /// A type that can describe objects, but which lacks information needed to /// determine its size (e.g. void, or a fwd declared struct). Clients of this @@ -906,6 +909,7 @@ public: bool isFunctionPointerType() const; bool isMemberPointerType() const; bool isMemberFunctionPointerType() const; + bool isMemberDataPointerType() const; bool isArrayType() const; bool isConstantArrayType() const; bool isIncompleteArrayType() const; @@ -926,6 +930,7 @@ public: bool isObjCQualifiedInterfaceType() const; // NSString<foo> bool isObjCQualifiedIdType() const; // id<foo> bool isObjCQualifiedClassType() const; // Class<foo> + bool isObjCObjectOrInterfaceType() const; bool isObjCIdType() const; // id bool isObjCClassType() const; // Class bool isObjCSelType() const; // Class @@ -952,10 +957,22 @@ public: /// an objective pointer type for the purpose of GC'ability bool hasObjCPointerRepresentation() const; + /// \brief Determine whether this type has an integer representation + /// of some sort, e.g., it is an integer type or a vector. + bool hasIntegerRepresentation() const; + + /// \brief Determine whether this type has an signed integer representation + /// of some sort, e.g., it is an signed integer type or a vector. + bool hasSignedIntegerRepresentation() const; + + /// \brief Determine whether this type has an unsigned integer representation + /// of some sort, e.g., it is an unsigned integer type or a vector. + bool hasUnsignedIntegerRepresentation() const; + /// \brief Determine whether this type has a floating-point representation /// of some sort, e.g., it is a floating-point type or a vector thereof. bool hasFloatingRepresentation() const; - + // Type Checking Functions: Check to see if this type is structurally the // specified type, ignoring typedefs and qualifiers, and return a pointer to // the best type we can. @@ -975,7 +992,8 @@ public: /// type of a class template or class template partial specialization. CXXRecordDecl *getAsCXXRecordDecl() const; - // Member-template getAs<specific type>'. This scheme will eventually + // Member-template getAs<specific type>'. Look through sugar for + // an instance of <specific type>. This scheme will eventually // replace the specific getAsXXXX methods above. // // There are some specializations of this member template listed @@ -1035,8 +1053,8 @@ public: void dump() const; static bool classof(const Type *) { return true; } - friend class PCHReader; - friend class PCHWriter; + friend class ASTReader; + friend class ASTWriter; }; template <> inline const TypedefType *Type::getAs() const { @@ -1353,9 +1371,20 @@ protected: virtual Linkage getLinkageImpl() const; public: - QualType getPointeeType() const { return PointeeType; } + /// Returns true if the member type (i.e. the pointee type) is a + /// function type rather than a data-member type. + bool isMemberFunctionPointer() const { + return PointeeType->isFunctionProtoType(); + } + + /// Returns true if the member type (i.e. the pointee type) is a + /// data type rather than a function type. + bool isMemberDataPointer() const { + return !PointeeType->isFunctionProtoType(); + } + const Type *getClass() const { return Class; } bool isSugared() const { return false; } @@ -1454,6 +1483,17 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + + /// \brief Determine the number of bits required to address a member of + // an array with the given element type and number of elements. + static unsigned getNumAddressingBits(ASTContext &Context, + QualType ElementType, + const llvm::APInt &NumElements); + + /// \brief Determine the maximum number of active bits that an array's size + /// can require, which limits the maximum size of the array. + static unsigned getMaxSizeBits(ASTContext &Context); + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getElementType(), getSize(), getSizeModifier(), getIndexTypeCVRQualifiers()); @@ -1533,7 +1573,6 @@ class VariableArrayType : public ArrayType { : ArrayType(VariableArray, et, can, sm, tq), SizeExpr((Stmt*) e), Brackets(brackets) {} friend class ASTContext; // ASTContext creates these. - virtual void Destroy(ASTContext& C); public: Expr *getSizeExpr() const { @@ -1592,7 +1631,6 @@ class DependentSizedArrayType : public ArrayType { : ArrayType(DependentSizedArray, et, can, sm, tq), Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {} friend class ASTContext; // ASTContext creates these. - virtual void Destroy(ASTContext& C); public: Expr *getSizeExpr() const { @@ -1646,7 +1684,6 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { Context(Context), SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) {} friend class ASTContext; - virtual void Destroy(ASTContext& C); public: Expr *getSizeExpr() const { return SizeExpr; } @@ -1844,13 +1881,13 @@ class FunctionType : public Type { // * FunctionNoProtoType::Profile // * FunctionProtoType::Profile // * TypePrinter::PrintFunctionProto - // * PCH read and write + // * AST read and write // * Codegen class ExtInfo { public: // Constructor with no defaults. Use this when you know that you - // have all the elements (when reading a PCH file for example). + // have all the elements (when reading an AST file for example). ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) : NoReturn(noReturn), RegParm(regParm), CC(cc) {} @@ -1892,7 +1929,7 @@ class FunctionType : public Type { // The value passed to __attribute__((regparm(x))) unsigned RegParm; // The calling convention as specified via - // __attribute__((cdecl|stdcall|fastcall|thiscall)) + // __attribute__((cdecl|stdcall|fastcall|thiscall|pascal)) CallingConv CC; }; @@ -2259,14 +2296,9 @@ public: }; class TagType : public Type { - /// Stores the TagDecl associated with this type. The decl will - /// point to the TagDecl that actually defines the entity (or is a - /// definition in progress), if there is such a definition. The - /// single-bit value will be non-zero when this tag is in the - /// process of being defined. - mutable llvm::PointerIntPair<TagDecl *, 1> decl; - friend class ASTContext; - friend class TagDecl; + /// Stores the TagDecl associated with this type. The decl may point to any + /// TagDecl that declares the entity. + TagDecl * decl; protected: TagType(TypeClass TC, const TagDecl *D, QualType can); @@ -2274,12 +2306,11 @@ protected: virtual Linkage getLinkageImpl() const; public: - TagDecl *getDecl() const { return decl.getPointer(); } + TagDecl *getDecl() const; /// @brief Determines whether this type is in the process of being /// defined. - bool isBeingDefined() const { return decl.getInt(); } - void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); } + bool isBeingDefined() const; static bool classof(const Type *T) { return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; @@ -2468,8 +2499,6 @@ class TemplateSpecializationType const TemplateArgument *Args, unsigned NumArgs, QualType Canon); - virtual void Destroy(ASTContext& C); - friend class ASTContext; // ASTContext creates these public: @@ -2574,9 +2603,8 @@ class InjectedClassNameType : public Type { QualType InjectedType; friend class ASTContext; // ASTContext creates these. - friend class TagDecl; // TagDecl mutilates the Decl - friend class PCHReader; // FIXME: ASTContext::getInjectedClassNameType is not - // currently suitable for PCH reading, too much + friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not + // currently suitable for AST reading, too much // interdependencies. InjectedClassNameType(CXXRecordDecl *D, QualType TST) : Type(InjectedClassName, QualType(), true), @@ -2592,7 +2620,7 @@ public: return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); } - CXXRecordDecl *getDecl() const { return Decl; } + CXXRecordDecl *getDecl() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2836,8 +2864,6 @@ class DependentTemplateSpecializationType : const TemplateArgument *Args, QualType Canon); - virtual void Destroy(ASTContext& C); - friend class ASTContext; // ASTContext creates these public: @@ -3014,8 +3040,6 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {} public: - void Destroy(ASTContext& C); // key function - void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, QualType Base, @@ -3049,8 +3073,6 @@ class ObjCInterfaceType : public ObjCObjectType { Decl(const_cast<ObjCInterfaceDecl*>(D)) {} friend class ASTContext; // ASTContext creates these. public: - void Destroy(ASTContext& C); // key function - /// getDecl - Get the declaration of this interface. ObjCInterfaceDecl *getDecl() const { return Decl; } @@ -3103,8 +3125,6 @@ protected: virtual Linkage getLinkageImpl() const; public: - void Destroy(ASTContext& C); - /// getPointeeType - Gets the type pointed to by this ObjC pointer. /// The result will always be an ObjCObjectType or sugar thereof. QualType getPointeeType() const { return PointeeType; } @@ -3486,7 +3506,13 @@ inline bool Type::isMemberPointerType() const { } inline bool Type::isMemberFunctionPointerType() const { if (const MemberPointerType* T = getAs<MemberPointerType>()) - return T->getPointeeType()->isFunctionType(); + return T->isMemberFunctionPointer(); + else + return false; +} +inline bool Type::isMemberDataPointerType() const { + if (const MemberPointerType* T = getAs<MemberPointerType>()) + return T->isMemberDataPointer(); else return false; } @@ -3523,6 +3549,11 @@ inline bool Type::isObjCObjectPointerType() const { inline bool Type::isObjCObjectType() const { return isa<ObjCObjectType>(CanonicalType); } +inline bool Type::isObjCObjectOrInterfaceType() const { + return isa<ObjCInterfaceType>(CanonicalType) || + isa<ObjCObjectType>(CanonicalType); +} + inline bool Type::isObjCQualifiedIdType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCQualifiedIdType(); diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 842c06878453..f1c64bd95977 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -341,6 +341,10 @@ private: template <class Base, class Derived, class TypeClass> class InheritingConcreteTypeLoc : public Base { public: + static bool classofType(const Type *Ty) { + return TypeClass::classof(Ty); + } + static bool classof(const TypeLoc *TL) { return Derived::classofType(TL->getTypePtr()); } diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index 1a050d29c860..7cf0d5e999b6 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -17,6 +17,7 @@ #define LLVM_CLANG_TYPE_ORDERING_H #include "clang/AST/Type.h" +#include "clang/AST/CanonicalType.h" #include <functional> namespace clang { @@ -51,6 +52,26 @@ namespace llvm { return LHS == RHS; } }; + + template<> struct DenseMapInfo<clang::CanQualType> { + static inline clang::CanQualType getEmptyKey() { + return clang::CanQualType(); + } + + static inline clang::CanQualType getTombstoneKey() { + using clang::CanQualType; + return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1)); + } + + static unsigned getHashValue(clang::CanQualType Val) { + return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^ + ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9)); + } + + static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) { + return LHS == RHS; + } + }; } #endif diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h new file mode 100644 index 000000000000..280b1260ac26 --- /dev/null +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -0,0 +1,595 @@ +//= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines APIs for analyzing the format strings of printf, fscanf, +// and friends. +// +// The structure of format strings for fprintf are described in C99 7.19.6.1. +// +// The structure of format strings for fscanf are described in C99 7.19.6.2. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FORMAT_H +#define LLVM_CLANG_FORMAT_H + +#include "clang/AST/CanonicalType.h" + +namespace clang { + +//===----------------------------------------------------------------------===// +/// Common components of both fprintf and fscanf format strings. +namespace analyze_format_string { + +/// Class representing optional flags with location and representation +/// information. +class OptionalFlag { +public: + OptionalFlag(const char *Representation) + : representation(Representation), flag(false) {} + bool isSet() { return flag; } + void set() { flag = true; } + void clear() { flag = false; } + void setPosition(const char *position) { + assert(position); + this->position = position; + } + const char *getPosition() const { + assert(position); + return position; + } + const char *toString() const { return representation; } + + // Overloaded operators for bool like qualities + operator bool() const { return flag; } + OptionalFlag& operator=(const bool &rhs) { + flag = rhs; + return *this; // Return a reference to myself. + } +private: + const char *representation; + const char *position; + bool flag; +}; + +/// Represents the length modifier in a format string in scanf/printf. +class LengthModifier { +public: + enum Kind { + None, + AsChar, // 'hh' + AsShort, // 'h' + AsLong, // 'l' + AsLongLong, // 'll', 'q' (BSD, deprecated) + AsIntMax, // 'j' + AsSizeT, // 'z' + AsPtrDiff, // 't' + AsLongDouble, // 'L' + AsWideChar = AsLong // for '%ls', only makes sense for printf + }; + + LengthModifier() + : Position(0), kind(None) {} + LengthModifier(const char *pos, Kind k) + : Position(pos), kind(k) {} + + const char *getStart() const { + return Position; + } + + unsigned getLength() const { + switch (kind) { + default: + return 1; + case AsLongLong: + case AsChar: + return 2; + case None: + return 0; + } + } + + Kind getKind() const { return kind; } + void setKind(Kind k) { kind = k; } + + const char *toString() const; + +private: + const char *Position; + Kind kind; +}; + +class ConversionSpecifier { +public: + enum Kind { + InvalidSpecifier = 0, + // C99 conversion specifiers. + cArg, + dArg, + iArg, + IntArgBeg = cArg, IntArgEnd = iArg, + + oArg, + uArg, + xArg, + XArg, + UIntArgBeg = oArg, UIntArgEnd = XArg, + + fArg, + FArg, + eArg, + EArg, + gArg, + GArg, + aArg, + AArg, + DoubleArgBeg = fArg, DoubleArgEnd = AArg, + + sArg, + pArg, + nArg, + PercentArg, + CArg, + SArg, + + // ** Printf-specific ** + + // Objective-C specific specifiers. + ObjCObjArg, // '@' + ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg, + + // GlibC specific specifiers. + PrintErrno, // 'm' + + PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno, + + // ** Scanf-specific ** + ScanListArg, // '[' + ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg + }; + + ConversionSpecifier(bool isPrintf) + : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {} + + ConversionSpecifier(bool isPrintf, const char *pos, Kind k) + : IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {} + + const char *getStart() const { + return Position; + } + + llvm::StringRef getCharacters() const { + return llvm::StringRef(getStart(), getLength()); + } + + bool consumesDataArgument() const { + switch (kind) { + case PrintErrno: + assert(IsPrintf); + case PercentArg: + return false; + default: + return true; + } + } + + Kind getKind() const { return kind; } + void setKind(Kind k) { kind = k; } + unsigned getLength() const { + return EndScanList ? EndScanList - Position : 1; + } + + const char *toString() const; + + bool isPrintfKind() const { return IsPrintf; } + +protected: + bool IsPrintf; + const char *Position; + const char *EndScanList; + Kind kind; +}; + +class ArgTypeResult { +public: + enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, + CStrTy, WCStrTy, WIntTy }; +private: + const Kind K; + QualType T; + ArgTypeResult(bool) : K(InvalidTy) {} +public: + ArgTypeResult(Kind k = UnknownTy) : K(k) {} + ArgTypeResult(QualType t) : K(SpecificTy), T(t) {} + ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {} + + static ArgTypeResult Invalid() { return ArgTypeResult(true); } + + bool isValid() const { return K != InvalidTy; } + + const QualType *getSpecificType() const { + return K == SpecificTy ? &T : 0; + } + + bool matchesType(ASTContext &C, QualType argTy) const; + + bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; } + + QualType getRepresentativeType(ASTContext &C) const; +}; + +class OptionalAmount { +public: + enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; + + OptionalAmount(HowSpecified howSpecified, + unsigned amount, + const char *amountStart, + unsigned amountLength, + bool usesPositionalArg) + : start(amountStart), length(amountLength), hs(howSpecified), amt(amount), + UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {} + + OptionalAmount(bool valid = true) + : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0), + UsesPositionalArg(0), UsesDotPrefix(0) {} + + bool isInvalid() const { + return hs == Invalid; + } + + HowSpecified getHowSpecified() const { return hs; } + void setHowSpecified(HowSpecified h) { hs = h; } + + bool hasDataArgument() const { return hs == Arg; } + + unsigned getArgIndex() const { + assert(hasDataArgument()); + return amt; + } + + unsigned getConstantAmount() const { + assert(hs == Constant); + return amt; + } + + const char *getStart() const { + // We include the . character if it is given. + return start - UsesDotPrefix; + } + + unsigned getConstantLength() const { + assert(hs == Constant); + return length + UsesDotPrefix; + } + + ArgTypeResult getArgType(ASTContext &Ctx) const; + + void toString(llvm::raw_ostream &os) const; + + bool usesPositionalArg() const { return (bool) UsesPositionalArg; } + unsigned getPositionalArgIndex() const { + assert(hasDataArgument()); + return amt + 1; + } + + bool usesDotPrefix() const { return UsesDotPrefix; } + void setUsesDotPrefix() { UsesDotPrefix = true; } + +private: + const char *start; + unsigned length; + HowSpecified hs; + unsigned amt; + bool UsesPositionalArg : 1; + bool UsesDotPrefix; +}; + + +class FormatSpecifier { +protected: + LengthModifier LM; + OptionalAmount FieldWidth; + ConversionSpecifier CS; + /// Positional arguments, an IEEE extension: + /// IEEE Std 1003.1, 2004 Edition + /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html + bool UsesPositionalArg; + unsigned argIndex; +public: + FormatSpecifier(bool isPrintf) + : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {} + + void setLengthModifier(LengthModifier lm) { + LM = lm; + } + + void setUsesPositionalArg() { UsesPositionalArg = true; } + + void setArgIndex(unsigned i) { + argIndex = i; + } + + unsigned getArgIndex() const { + return argIndex; + } + + unsigned getPositionalArgIndex() const { + return argIndex + 1; + } + + const LengthModifier &getLengthModifier() const { + return LM; + } + + const OptionalAmount &getFieldWidth() const { + return FieldWidth; + } + + void setFieldWidth(const OptionalAmount &Amt) { + FieldWidth = Amt; + } + + bool usesPositionalArg() const { return UsesPositionalArg; } + + bool hasValidLengthModifier() const; +}; + +} // end analyze_format_string namespace + +//===----------------------------------------------------------------------===// +/// Pieces specific to fprintf format strings. + +namespace analyze_printf { + +class PrintfConversionSpecifier : + public analyze_format_string::ConversionSpecifier { +public: + PrintfConversionSpecifier() + : ConversionSpecifier(true, 0, InvalidSpecifier) {} + + PrintfConversionSpecifier(const char *pos, Kind k) + : ConversionSpecifier(true, pos, k) {} + + bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } + bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; } + bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } + bool isDoubleArg() const { return kind >= DoubleArgBeg && + kind <= DoubleArgBeg; } + unsigned getLength() const { + // Conversion specifiers currently only are represented by + // single characters, but we be flexible. + return 1; + } + + static bool classof(const analyze_format_string::ConversionSpecifier *CS) { + return CS->isPrintfKind(); + } +}; + +using analyze_format_string::ArgTypeResult; +using analyze_format_string::LengthModifier; +using analyze_format_string::OptionalAmount; +using analyze_format_string::OptionalFlag; + +class PrintfSpecifier : public analyze_format_string::FormatSpecifier { + OptionalFlag IsLeftJustified; // '-' + OptionalFlag HasPlusPrefix; // '+' + OptionalFlag HasSpacePrefix; // ' ' + OptionalFlag HasAlternativeForm; // '#' + OptionalFlag HasLeadingZeroes; // '0' + OptionalAmount Precision; +public: + PrintfSpecifier() : + FormatSpecifier(/* isPrintf = */ true), + IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "), + HasAlternativeForm("#"), HasLeadingZeroes("0") {} + + static PrintfSpecifier Parse(const char *beg, const char *end); + + // Methods for incrementally constructing the PrintfSpecifier. + void setConversionSpecifier(const PrintfConversionSpecifier &cs) { + CS = cs; + } + void setIsLeftJustified(const char *position) { + IsLeftJustified = true; + IsLeftJustified.setPosition(position); + } + void setHasPlusPrefix(const char *position) { + HasPlusPrefix = true; + HasPlusPrefix.setPosition(position); + } + void setHasSpacePrefix(const char *position) { + HasSpacePrefix = true; + HasSpacePrefix.setPosition(position); + } + void setHasAlternativeForm(const char *position) { + HasAlternativeForm = true; + HasAlternativeForm.setPosition(position); + } + void setHasLeadingZeros(const char *position) { + HasLeadingZeroes = true; + HasLeadingZeroes.setPosition(position); + } + void setUsesPositionalArg() { UsesPositionalArg = true; } + + // Methods for querying the format specifier. + + const PrintfConversionSpecifier &getConversionSpecifier() const { + return cast<PrintfConversionSpecifier>(CS); + } + + void setPrecision(const OptionalAmount &Amt) { + Precision = Amt; + Precision.setUsesDotPrefix(); + } + + const OptionalAmount &getPrecision() const { + return Precision; + } + + bool consumesDataArgument() const { + return getConversionSpecifier().consumesDataArgument(); + } + + /// \brief Returns the builtin type that a data argument + /// paired with this format specifier should have. This method + /// will return null if the format specifier does not have + /// a matching data argument or the matching argument matches + /// more than one type. + ArgTypeResult getArgType(ASTContext &Ctx) const; + + const OptionalFlag &isLeftJustified() const { return IsLeftJustified; } + const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; } + const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; } + const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; } + const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; } + bool usesPositionalArg() const { return UsesPositionalArg; } + + /// Changes the specifier and length according to a QualType, retaining any + /// flags or options. Returns true on success, or false when a conversion + /// was not successful. + bool fixType(QualType QT); + + void toString(llvm::raw_ostream &os) const; + + // Validation methods - to check if any element results in undefined behavior + bool hasValidPlusPrefix() const; + bool hasValidAlternativeForm() const; + bool hasValidLeadingZeros() const; + bool hasValidSpacePrefix() const; + bool hasValidLeftJustified() const; + + bool hasValidPrecision() const; + bool hasValidFieldWidth() const; +}; +} // end analyze_printf namespace + +//===----------------------------------------------------------------------===// +/// Pieces specific to fscanf format strings. + +namespace analyze_scanf { + +class ScanfConversionSpecifier : + public analyze_format_string::ConversionSpecifier { +public: + ScanfConversionSpecifier() + : ConversionSpecifier(false, 0, InvalidSpecifier) {} + + ScanfConversionSpecifier(const char *pos, Kind k) + : ConversionSpecifier(false, pos, k) {} + + void setEndScanList(const char *pos) { EndScanList = pos; } + + static bool classof(const analyze_format_string::ConversionSpecifier *CS) { + return !CS->isPrintfKind(); + } +}; + +using analyze_format_string::LengthModifier; +using analyze_format_string::OptionalAmount; +using analyze_format_string::OptionalFlag; + +class ScanfSpecifier : public analyze_format_string::FormatSpecifier { + OptionalFlag SuppressAssignment; // '*' +public: + ScanfSpecifier() : + FormatSpecifier(/* isPrintf = */ false), + SuppressAssignment("*") {} + + void setSuppressAssignment(const char *position) { + SuppressAssignment = true; + SuppressAssignment.setPosition(position); + } + + const OptionalFlag &getSuppressAssignment() const { + return SuppressAssignment; + } + + void setConversionSpecifier(const ScanfConversionSpecifier &cs) { + CS = cs; + } + + const ScanfConversionSpecifier &getConversionSpecifier() const { + return cast<ScanfConversionSpecifier>(CS); + } + + bool consumesDataArgument() const { + return CS.consumesDataArgument() && !SuppressAssignment; + } + + static ScanfSpecifier Parse(const char *beg, const char *end); +}; + +} // end analyze_scanf namespace + +//===----------------------------------------------------------------------===// +// Parsing and processing of format strings (both fprintf and fscanf). + +namespace analyze_format_string { + +enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; + +class FormatStringHandler { +public: + FormatStringHandler() {} + virtual ~FormatStringHandler(); + + virtual void HandleNullChar(const char *nullCharacter) {} + + virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, + PositionContext p) {} + + virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {} + + virtual void HandleIncompleteSpecifier(const char *startSpecifier, + unsigned specifierLen) {} + + // Printf-specific handlers. + + virtual bool HandleInvalidPrintfConversionSpecifier( + const analyze_printf::PrintfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + return true; + } + + virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + return true; + } + + // Scanf-specific handlers. + + virtual bool HandleInvalidScanfConversionSpecifier( + const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + return true; + } + + virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + return true; + } + + virtual void HandleIncompleteScanList(const char *start, const char *end) {} +}; + +bool ParsePrintfString(FormatStringHandler &H, + const char *beg, const char *end); + +bool ParseScanfString(FormatStringHandler &H, + const char *beg, const char *end); + +} // end analyze_format_string namespace +} // end clang namespace +#endif diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 44ab080acbf3..237fe14aed4f 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -41,8 +41,9 @@ struct LiveVariables_ValueTypes { ObserverTy* Observer; ValTy AlwaysLive; AnalysisContext *AC; + bool killAtAssign; - AnalysisDataTy() : Observer(NULL), AC(NULL) {} + AnalysisDataTy() : Observer(NULL), AC(NULL), killAtAssign(true) {} }; //===-----------------------------------------------------===// @@ -68,7 +69,7 @@ class LiveVariables : public DataflowValues<LiveVariables_ValueTypes, public: typedef LiveVariables_ValueTypes::ObserverTy ObserverTy; - LiveVariables(AnalysisContext &AC); + LiveVariables(AnalysisContext &AC, bool killAtAssign = true); /// IsLive - Return true if a variable is live at the end of a /// specified block. diff --git a/include/clang/Analysis/Analyses/PrintfFormatString.h b/include/clang/Analysis/Analyses/PrintfFormatString.h deleted file mode 100644 index d907637d39c5..000000000000 --- a/include/clang/Analysis/Analyses/PrintfFormatString.h +++ /dev/null @@ -1,445 +0,0 @@ -//==- PrintfFormatStrings.h - Analysis of printf format strings --*- C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Handling of format string in printf and friends. The structure of format -// strings for fprintf() are described in C99 7.19.6.1. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_FPRINTF_FORMAT_H -#define LLVM_CLANG_FPRINTF_FORMAT_H - -#include "clang/AST/CanonicalType.h" - -namespace clang { - -class ASTContext; - -namespace analyze_printf { - -class ArgTypeResult { -public: - enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, - CStrTy, WCStrTy }; -private: - const Kind K; - QualType T; - ArgTypeResult(bool) : K(InvalidTy) {} -public: - ArgTypeResult(Kind k = UnknownTy) : K(k) {} - ArgTypeResult(QualType t) : K(SpecificTy), T(t) {} - ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {} - - static ArgTypeResult Invalid() { return ArgTypeResult(true); } - - bool isValid() const { return K != InvalidTy; } - - const QualType *getSpecificType() const { - return K == SpecificTy ? &T : 0; - } - - bool matchesType(ASTContext &C, QualType argTy) const; - - bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; } - - QualType getRepresentativeType(ASTContext &C) const; -}; - -class ConversionSpecifier { -public: - enum Kind { - InvalidSpecifier = 0, - // C99 conversion specifiers. - dArg, // 'd' - IntAsCharArg, // 'c' - iArg, // 'i', - oArg, // 'o', - uArg, // 'u', - xArg, // 'x', - XArg, // 'X', - fArg, // 'f', - FArg, // 'F', - eArg, // 'e', - EArg, // 'E', - gArg, // 'g', - GArg, // 'G', - aArg, // 'a', - AArg, // 'A', - CStrArg, // 's' - VoidPtrArg, // 'p' - OutIntPtrArg, // 'n' - PercentArg, // '%' - // MacOS X unicode extensions. - CArg, // 'C' - UnicodeStrArg, // 'S' - // Objective-C specific specifiers. - ObjCObjArg, // '@' - // GlibC specific specifiers. - PrintErrno, // 'm' - // Specifier ranges. - IntArgBeg = dArg, - IntArgEnd = iArg, - UIntArgBeg = oArg, - UIntArgEnd = XArg, - DoubleArgBeg = fArg, - DoubleArgEnd = AArg, - C99Beg = IntArgBeg, - C99End = DoubleArgEnd, - ObjCBeg = ObjCObjArg, - ObjCEnd = ObjCObjArg - }; - - ConversionSpecifier() - : Position(0), kind(InvalidSpecifier) {} - - ConversionSpecifier(const char *pos, Kind k) - : Position(pos), kind(k) {} - - const char *getStart() const { - return Position; - } - - llvm::StringRef getCharacters() const { - return llvm::StringRef(getStart(), getLength()); - } - - bool consumesDataArgument() const { - switch (kind) { - case PercentArg: - case PrintErrno: - return false; - default: - return true; - } - } - - bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } - bool isIntArg() const { return kind >= dArg && kind <= iArg; } - bool isUIntArg() const { return kind >= oArg && kind <= XArg; } - bool isDoubleArg() const { return kind >= fArg && kind <= AArg; } - Kind getKind() const { return kind; } - void setKind(Kind k) { kind = k; } - unsigned getLength() const { - // Conversion specifiers currently only are represented by - // single characters, but we be flexible. - return 1; - } - const char *toString() const; - -private: - const char *Position; - Kind kind; -}; - -class LengthModifier { -public: - enum Kind { - None, - AsChar, // 'hh' - AsShort, // 'h' - AsLong, // 'l' - AsLongLong, // 'll', 'q' (BSD, deprecated) - AsIntMax, // 'j' - AsSizeT, // 'z' - AsPtrDiff, // 't' - AsLongDouble, // 'L' - AsWideChar = AsLong // for '%ls' - }; - - LengthModifier() - : Position(0), kind(None) {} - LengthModifier(const char *pos, Kind k) - : Position(pos), kind(k) {} - - const char *getStart() const { - return Position; - } - - unsigned getLength() const { - switch (kind) { - default: - return 1; - case AsLongLong: - case AsChar: - return 2; - case None: - return 0; - } - } - - Kind getKind() const { return kind; } - void setKind(Kind k) { kind = k; } - - const char *toString() const; - -private: - const char *Position; - Kind kind; -}; - -class OptionalAmount { -public: - enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; - - OptionalAmount(HowSpecified howSpecified, - unsigned amount, - const char *amountStart, - unsigned amountLength, - bool usesPositionalArg) - : start(amountStart), length(amountLength), hs(howSpecified), amt(amount), - UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {} - - OptionalAmount(bool valid = true) - : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0), - UsesPositionalArg(0), UsesDotPrefix(0) {} - - bool isInvalid() const { - return hs == Invalid; - } - - HowSpecified getHowSpecified() const { return hs; } - void setHowSpecified(HowSpecified h) { hs = h; } - - bool hasDataArgument() const { return hs == Arg; } - - unsigned getArgIndex() const { - assert(hasDataArgument()); - return amt; - } - - unsigned getConstantAmount() const { - assert(hs == Constant); - return amt; - } - - const char *getStart() const { - // We include the . character if it is given. - return start - UsesDotPrefix; - } - - unsigned getConstantLength() const { - assert(hs == Constant); - return length + UsesDotPrefix; - } - - ArgTypeResult getArgType(ASTContext &Ctx) const; - - void toString(llvm::raw_ostream &os) const; - - bool usesPositionalArg() const { return (bool) UsesPositionalArg; } - unsigned getPositionalArgIndex() const { - assert(hasDataArgument()); - return amt + 1; - } - - bool usesDotPrefix() const { return UsesDotPrefix; } - void setUsesDotPrefix() { UsesDotPrefix = true; } - -private: - const char *start; - unsigned length; - HowSpecified hs; - unsigned amt; - bool UsesPositionalArg : 1; - bool UsesDotPrefix; -}; - -// Class representing optional flags with location and representation -// information. -class OptionalFlag { -public: - OptionalFlag(const char *Representation) - : representation(Representation), flag(false) {} - bool isSet() { return flag; } - void set() { flag = true; } - void clear() { flag = false; } - void setPosition(const char *position) { - assert(position); - this->position = position; - } - const char *getPosition() const { - assert(position); - return position; - } - const char *toString() const { return representation; } - - // Overloaded operators for bool like qualities - operator bool() const { return flag; } - OptionalFlag& operator=(const bool &rhs) { - flag = rhs; - return *this; // Return a reference to myself. - } -private: - const char *representation; - const char *position; - bool flag; -}; - -class FormatSpecifier { - LengthModifier LM; - OptionalFlag IsLeftJustified; // '-' - OptionalFlag HasPlusPrefix; // '+' - OptionalFlag HasSpacePrefix; // ' ' - OptionalFlag HasAlternativeForm; // '#' - OptionalFlag HasLeadingZeroes; // '0' - /// Positional arguments, an IEEE extension: - /// IEEE Std 1003.1, 2004 Edition - /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html - bool UsesPositionalArg; - unsigned argIndex; - ConversionSpecifier CS; - OptionalAmount FieldWidth; - OptionalAmount Precision; -public: - FormatSpecifier() : - IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "), - HasAlternativeForm("#"), HasLeadingZeroes("0"), UsesPositionalArg(false), - argIndex(0) {} - - static FormatSpecifier Parse(const char *beg, const char *end); - - // Methods for incrementally constructing the FormatSpecifier. - void setConversionSpecifier(const ConversionSpecifier &cs) { - CS = cs; - } - void setLengthModifier(LengthModifier lm) { - LM = lm; - } - void setIsLeftJustified(const char *position) { - IsLeftJustified = true; - IsLeftJustified.setPosition(position); - } - void setHasPlusPrefix(const char *position) { - HasPlusPrefix = true; - HasPlusPrefix.setPosition(position); - } - void setHasSpacePrefix(const char *position) { - HasSpacePrefix = true; - HasSpacePrefix.setPosition(position); - } - void setHasAlternativeForm(const char *position) { - HasAlternativeForm = true; - HasAlternativeForm.setPosition(position); - } - void setHasLeadingZeros(const char *position) { - HasLeadingZeroes = true; - HasLeadingZeroes.setPosition(position); - } - void setUsesPositionalArg() { UsesPositionalArg = true; } - - void setArgIndex(unsigned i) { - assert(CS.consumesDataArgument()); - argIndex = i; - } - - unsigned getArgIndex() const { - assert(CS.consumesDataArgument()); - return argIndex; - } - - unsigned getPositionalArgIndex() const { - assert(CS.consumesDataArgument()); - return argIndex + 1; - } - - // Methods for querying the format specifier. - - const ConversionSpecifier &getConversionSpecifier() const { - return CS; - } - - const LengthModifier &getLengthModifier() const { - return LM; - } - - const OptionalAmount &getFieldWidth() const { - return FieldWidth; - } - - void setFieldWidth(const OptionalAmount &Amt) { - FieldWidth = Amt; - } - - void setPrecision(const OptionalAmount &Amt) { - Precision = Amt; - Precision.setUsesDotPrefix(); - } - - const OptionalAmount &getPrecision() const { - return Precision; - } - - /// \brief Returns the builtin type that a data argument - /// paired with this format specifier should have. This method - /// will return null if the format specifier does not have - /// a matching data argument or the matching argument matches - /// more than one type. - ArgTypeResult getArgType(ASTContext &Ctx) const; - - const OptionalFlag &isLeftJustified() const { return IsLeftJustified; } - const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; } - const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; } - const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; } - const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; } - bool usesPositionalArg() const { return UsesPositionalArg; } - - /// Changes the specifier and length according to a QualType, retaining any - /// flags or options. Returns true on success, or false when a conversion - /// was not successful. - bool fixType(QualType QT); - - void toString(llvm::raw_ostream &os) const; - - // Validation methods - to check if any element results in undefined behavior - bool hasValidPlusPrefix() const; - bool hasValidAlternativeForm() const; - bool hasValidLeadingZeros() const; - bool hasValidSpacePrefix() const; - bool hasValidLeftJustified() const; - - bool hasValidLengthModifier() const; - bool hasValidPrecision() const; - bool hasValidFieldWidth() const; -}; - -enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; - -class FormatStringHandler { -public: - FormatStringHandler() {} - virtual ~FormatStringHandler(); - - virtual void HandleIncompleteFormatSpecifier(const char *startSpecifier, - unsigned specifierLen) {} - - virtual void HandleNullChar(const char *nullCharacter) {} - - virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, - PositionContext p) {} - - virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {} - - virtual bool - HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS, - const char *startSpecifier, - unsigned specifierLen) { return true; } - - virtual bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS, - const char *startSpecifier, - unsigned specifierLen) { - return true; - } -}; - -bool ParseFormatString(FormatStringHandler &H, - const char *beg, const char *end); - -} // end printf namespace -} // end clang namespace -#endif diff --git a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h new file mode 100644 index 000000000000..cb73850b08c7 --- /dev/null +++ b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h @@ -0,0 +1,45 @@ +//== PseudoConstantAnalysis.h - Find Pseudo-constants in the AST -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tracks the usage of variables in a Decl body to see if they are +// never written to, implying that they constant. This is useful in static +// analysis to see if a developer might have intended a variable to be const. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS +#define LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS + +#include "clang/AST/Stmt.h" + +namespace clang { + +class PseudoConstantAnalysis { +public: + PseudoConstantAnalysis(const Stmt *DeclBody); + ~PseudoConstantAnalysis(); + + bool isPseudoConstant(const VarDecl *VD); + bool wasReferenced(const VarDecl *VD); + +private: + void RunAnalysis(); + inline static const Decl *getDecl(const Expr *E); + + // for storing the result of analyzed ValueDecls + void *NonConstantsImpl; + void *UsedVarsImpl; + + const Stmt *DeclBody; + bool Analyzed; +}; + +} + +#endif diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 9ebd93b75b38..7d4d25f8b0d8 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -30,41 +30,67 @@ class CFG; class CFGBlock; class LiveVariables; class ParentMap; +class PseudoConstantAnalysis; class ImplicitParamDecl; class LocationContextManager; class StackFrameContext; +namespace idx { class TranslationUnit; } + /// AnalysisContext contains the context data for the function or method under /// analysis. class AnalysisContext { const Decl *D; + // TranslationUnit is NULL if we don't have multiple translation units. + idx::TranslationUnit *TU; + // AnalysisContext owns the following data. - CFG *cfg; - bool builtCFG; + CFG *cfg, *completeCFG; + bool builtCFG, builtCompleteCFG; LiveVariables *liveness; + LiveVariables *relaxedLiveness; ParentMap *PM; + PseudoConstantAnalysis *PCA; llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; llvm::BumpPtrAllocator A; + bool UseUnoptimizedCFG; bool AddEHEdges; public: - AnalysisContext(const Decl *d, bool addehedges = false) - : D(d), cfg(0), builtCFG(false), liveness(0), PM(0), - ReferencedBlockVars(0), AddEHEdges(addehedges) {} + AnalysisContext(const Decl *d, idx::TranslationUnit *tu, + bool useUnoptimizedCFG = false, + bool addehedges = false) + : D(d), TU(tu), cfg(0), completeCFG(0), + builtCFG(false), builtCompleteCFG(false), + liveness(0), relaxedLiveness(0), PM(0), PCA(0), + ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG), + AddEHEdges(addehedges) {} ~AnalysisContext(); ASTContext &getASTContext() { return D->getASTContext(); } - const Decl *getDecl() { return D; } + const Decl *getDecl() const { return D; } + + idx::TranslationUnit *getTranslationUnit() const { return TU; } + /// getAddEHEdges - Return true iff we are adding exceptional edges from /// callExprs. If this is false, then try/catch statements and blocks /// reachable from them can appear to be dead in the CFG, analysis passes must /// cope with that. bool getAddEHEdges() const { return AddEHEdges; } + + bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; } + Stmt *getBody(); CFG *getCFG(); + + /// Return a version of the CFG without any edges pruned. + CFG *getUnoptimizedCFG(); + ParentMap &getParentMap(); + PseudoConstantAnalysis *getPseudoConstantAnalysis(); LiveVariables *getLiveVariables(); + LiveVariables *getRelaxedLiveVariables(); typedef const VarDecl * const * referenced_decls_iterator; @@ -79,10 +105,16 @@ public: class AnalysisContextManager { typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap; ContextMap Contexts; + bool UseUnoptimizedCFG; public: + AnalysisContextManager(bool useUnoptimizedCFG = false) + : UseUnoptimizedCFG(useUnoptimizedCFG) {} + ~AnalysisContextManager(); - AnalysisContext *getContext(const Decl *D); + AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0); + + bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; } // Discard all previously created AnalysisContexts. void clear(); @@ -94,7 +126,10 @@ public: private: ContextKind Kind; + + // AnalysisContext can't be const since some methods may modify its member. AnalysisContext *Ctx; + const LocationContext *Parent; protected: @@ -109,6 +144,10 @@ public: AnalysisContext *getAnalysisContext() const { return Ctx; } + idx::TranslationUnit *getTranslationUnit() const { + return Ctx->getTranslationUnit(); + } + const LocationContext *getParent() const { return Parent; } bool isParentOf(const LocationContext *LC) const; diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index b7256c9dc3db..b7a8e1159693 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -35,22 +35,6 @@ namespace clang { class LangOptions; class ASTContext; -namespace { -// An element of the CFG for implicit descructor calls implied by the language -// rules. -class Dtor { - // Statement that introduces the variable. - Stmt *S; - // A token which ends the scope, return, goto, throw, }. - SourceLocation Loc; -public: - Dtor(Stmt *s, SourceLocation l) : S(s), Loc(l) { - } - SourceLocation getLoc() { return Loc; } - Stmt *getStmt() { return S; } -}; -} - /// CFGElement - Represents a top-level expression in a basic block. class CFGElement { llvm::PointerIntPair<Stmt *, 2> Data; @@ -59,7 +43,6 @@ public: explicit CFGElement() {} CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {} CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {} - // CFGElement(Dtor *S, Type t) : Data(reinterpret_cast<Stmt*>(S), 4) {} Stmt *getStmt() const { return Data.getPointer(); } bool asLValue() const { return Data.getInt() == 1; } bool asStartScope() const { return Data.getInt() == 2; } @@ -67,7 +50,6 @@ public: bool asDtor() const { return Data.getInt() == 4; } operator Stmt*() const { return getStmt(); } operator bool() const { return getStmt() != 0; } - operator Dtor*() const { return reinterpret_cast<Dtor*>(getStmt()); } }; /// CFGBlock - Represents a single basic block in a source-level CFG. @@ -285,6 +267,7 @@ public: /// buildCFG - Builds a CFG from an AST. The responsibility to free the /// constructed CFG belongs to the caller. static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C, + bool pruneTriviallyFalseEdges = true, bool AddEHEdges = false, bool AddScopes = false /* NOT FULLY IMPLEMENTED. NOT READY FOR GENERAL USE. */); diff --git a/include/clang/Analysis/CFGStmtMap.h b/include/clang/Analysis/CFGStmtMap.h new file mode 100644 index 000000000000..6e8e140afb23 --- /dev/null +++ b/include/clang/Analysis/CFGStmtMap.h @@ -0,0 +1,52 @@ +//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the CFGStmtMap class, which defines a mapping from +// Stmt* to CFGBlock* +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CFGSTMTMAP_H +#define LLVM_CLANG_CFGSTMTMAP_H + +#include "clang/Analysis/CFG.h" + +namespace clang { + +class CFG; +class CFGBlock; +class ParentMap; +class Stmt; + +class CFGStmtMap { + ParentMap *PM; + void *M; + + CFGStmtMap(ParentMap *pm, void *m) : PM(pm), M(m) {} + +public: + ~CFGStmtMap(); + + /// Returns a new CFGMap for the given CFG. It is the caller's + /// responsibility to 'delete' this object when done using it. + static CFGStmtMap *Build(CFG* C, ParentMap *PM); + + /// Returns the CFGBlock the specified Stmt* appears in. For Stmt* that + /// are terminators, the CFGBlock is the block they appear as a terminator, + /// and not the block they appear as a block-level expression (e.g, '&&'). + /// CaseStmts and LabelStmts map to the CFGBlock they label. + CFGBlock *getBlock(Stmt * S); + + const CFGBlock *getBlock(const Stmt * S) const { + return const_cast<CFGStmtMap*>(this)->getBlock(const_cast<Stmt*>(S)); + } +}; + +} // end clang namespace +#endif diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h index 3c762011a657..9375db06be72 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -231,7 +231,7 @@ private: EdgeDataMapTy& M = D.getEdgeDataMap(); bool firstMerge = true; - + bool noEdges = true; for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){ CFGBlock *PrevBlk = *I; @@ -243,6 +243,7 @@ private: M.find(ItrTraits::PrevEdge(B, PrevBlk)); if (EI != M.end()) { + noEdges = false; if (firstMerge) { firstMerge = false; V.copyValues(EI->second); @@ -252,8 +253,20 @@ private: } } + bool isInitialized = true; + typename BlockDataMapTy::iterator BI = D.getBlockDataMap().find(B); + if(BI == D.getBlockDataMap().end()) { + isInitialized = false; + BI = D.getBlockDataMap().insert( std::make_pair(B,ValTy()) ).first; + } + // If no edges have been found, it means this is the first time the solver + // has been called on block B, we copy the initialization values (if any) + // as current value for V (which will be used as edge data) + if(noEdges && isInitialized) + Merge(V, BI->second); + // Set the data for the block. - D.getBlockDataMap()[B].copyValues(V); + BI->second.copyValues(V); } /// ProcessBlock - Process the transfer functions for a given block. diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 075838d45e5c..ba303de7a8da 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT #define LLVM_CLANG_ANALYSIS_PROGRAM_POINT +#include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" #include "llvm/System/DataTypes.h" #include "llvm/ADT/DenseMap.h" @@ -26,6 +27,7 @@ namespace clang { class LocationContext; +class AnalysisContext; class FunctionDecl; class ProgramPoint { @@ -45,7 +47,7 @@ public: CallEnterKind, CallExitKind, MinPostStmtKind = PostStmtKind, - MaxPostStmtKind = PostLValueKind }; + MaxPostStmtKind = CallExitKind }; private: std::pair<const void *, const void *> Data; @@ -107,16 +109,16 @@ public: const void *tag = 0) : ProgramPoint(B, BlockEntranceKind, L, tag) {} - CFGBlock* getBlock() const { - return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); + const CFGBlock* getBlock() const { + return reinterpret_cast<const CFGBlock*>(getData1()); } - CFGElement getFirstElement() const { + const CFGElement getFirstElement() const { const CFGBlock* B = getBlock(); return B->empty() ? CFGElement() : B->front(); } - Stmt *getFirstStmt() const { + const Stmt *getFirstStmt() const { return getFirstElement().getStmt(); } @@ -130,16 +132,16 @@ public: BlockExit(const CFGBlock* B, const LocationContext *L) : ProgramPoint(B, BlockExitKind, L) {} - CFGBlock* getBlock() const { - return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); + const CFGBlock* getBlock() const { + return reinterpret_cast<const CFGBlock*>(getData1()); } - Stmt* getLastStmt() const { + const Stmt* getLastStmt() const { const CFGBlock* B = getBlock(); return B->empty() ? CFGElement() : B->back(); } - Stmt* getTerminator() const { + const Stmt* getTerminator() const { return getBlock()->getTerminator(); } @@ -298,12 +300,12 @@ public: BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L) : ProgramPoint(B1, B2, BlockEdgeKind, L) {} - CFGBlock* getSrc() const { - return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData1())); + const CFGBlock* getSrc() const { + return static_cast<const CFGBlock*>(getData1()); } - CFGBlock* getDst() const { - return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData2())); + const CFGBlock* getDst() const { + return static_cast<const CFGBlock*>(getData2()); } static bool classof(const ProgramPoint* Location) { @@ -313,16 +315,17 @@ public: class CallEnter : public StmtPoint { public: - // CallEnter uses the caller's location context. - CallEnter(const Stmt *S, const FunctionDecl *fd, const LocationContext *L) - : StmtPoint(S, fd, CallEnterKind, L, 0) {} + // L is caller's location context. AC is callee's AnalysisContext. + CallEnter(const Stmt *S, const AnalysisContext *AC, const LocationContext *L) + : StmtPoint(S, AC, CallEnterKind, L, 0) {} const Stmt *getCallExpr() const { return static_cast<const Stmt *>(getData1()); } - const FunctionDecl *getCallee() const { - return static_cast<const FunctionDecl *>(getData2()); + AnalysisContext *getCalleeContext() const { + return const_cast<AnalysisContext *>( + static_cast<const AnalysisContext *>(getData2())); } static bool classof(const ProgramPoint *Location) { diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h index 8a85ec15cdce..6421f185ff7f 100644 --- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -86,7 +86,7 @@ public: BinaryOperator* B = cast<BinaryOperator>(S); if (B->isLogicalOp()) return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B); - else if (B->getOpcode() == BinaryOperator::Comma) + else if (B->getOpcode() == BO_Comma) return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B); // Fall through. } @@ -149,7 +149,7 @@ public: case Stmt::BinaryOperatorClass: { BinaryOperator* B = cast<BinaryOperator>(S); - if (B->getOpcode() != BinaryOperator::Comma) break; + if (B->getOpcode() != BO_Comma) break; static_cast<ImplClass*>(this)->Visit(B->getRHS()); return; } diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 98871d26204f..2f2267f7f79f 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -33,8 +33,8 @@ class SubsetSubject<AttrSubject base, string description, code check> // a possible subject. def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable", [{S->getStorageClass() != VarDecl::Register && - S->getKind() != Decl::ImplicitParam - S->getKind() != Decl::ParmVar + S->getKind() != Decl::ImplicitParam && + S->getKind() != Decl::ParmVar && S->getKind() != Decl::NonTypeTemplateParm}]>; def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function", [{S->isVirtual()}]>; @@ -51,18 +51,27 @@ class IntArgument<string name> : Argument<name>; class StringArgument<string name> : Argument<name>; class ExprArgument<string name> : Argument<name>; class FunctionArgument<string name> : Argument<name>; -class ObjCInterfaceArgument<string name> : Argument<name>; -class UnsignedIntArgument<string name> : Argument<name>; -class UnsignedIntOrTypeArgument<string name> : Argument<name>; +class TypeArgument<string name> : Argument<name>; +class UnsignedArgument<string name> : Argument<name>; +class VariadicUnsignedArgument<string name> : Argument<name>; + +// This one's a doozy, so it gets its own special type +// It can be an unsigned integer, or a type. Either can +// be dependent. +class AlignedArgument<string name> : Argument<name>; // An integer argument with a default value class DefaultIntArgument<string name, int default> : IntArgument<name> { int Default = default; } -// Zero or more arguments of a type -class VariadicArgument<Argument arg> : Argument<arg.Name> { - Argument VariadicArg = arg; +// This argument is more complex, it includes the enumerator type name, +// a list of strings to accept, and a list of enumerators to map them to. +class EnumArgument<string name, string type, list<string> values, + list<string> enums> : Argument<name> { + string Type = type; + list<string> Values = values; + list<string> Enums = enums; } class Attr { @@ -76,9 +85,8 @@ class Attr { // The attribute will not be permitted in C++0x attribute-specifiers if // this is empty; the empty string can be used as a namespace. list<string> Namespaces = []; - // A temporary development bit to tell TableGen not to emit certain - // information about the attribute. - bit DoNotEmit = 1; + // Any additional text that should be included verbatim in the class. + code AdditionalMembers = [{}]; } // @@ -87,13 +95,13 @@ class Attr { def Alias : Attr { let Spellings = ["alias"]; - let Args = [StringArgument<"AliasName">]; + let Args = [StringArgument<"Aliasee">]; } def Aligned : Attr { let Spellings = ["align", "aligned"]; let Subjects = [NonBitField, NormalVar, Tag]; - let Args = [UnsignedIntOrTypeArgument<"Alignment">]; + let Args = [AlignedArgument<"Alignment">]; let Namespaces = ["", "std"]; } @@ -123,19 +131,17 @@ def BaseCheck : Attr { let Spellings = ["base_check"]; let Subjects = [CXXRecord]; let Namespaces = ["", "std"]; - let DoNotEmit = 0; } def Blocks : Attr { let Spellings = ["blocks"]; - let Args = [IdentifierArgument<"Type">]; + let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>]; } def CarriesDependency : Attr { let Spellings = ["carries_dependency"]; let Subjects = [ParmVar, Function]; let Namespaces = ["", "std"]; - let DoNotEmit = 0; } def CDecl : Attr { @@ -189,7 +195,6 @@ def Final : Attr { let Spellings = ["final"]; let Subjects = [CXXRecord, CXXVirtualMethod]; let Namespaces = ["", "std"]; - let DoNotEmit = 0; } def Format : Attr { @@ -211,7 +216,6 @@ def Hiding : Attr { let Spellings = ["hiding"]; let Subjects = [Field, CXXMethod]; let Namespaces = ["", "std"]; - let DoNotEmit = 0; } def IBAction : Attr { @@ -224,7 +228,7 @@ def IBOutlet : Attr { def IBOutletCollection : Attr { let Spellings = ["iboutletcollection"]; - let Args = [ObjCInterfaceArgument<"Class">]; + let Args = [TypeArgument<"Interface">]; } def Malloc : Attr { @@ -233,12 +237,12 @@ def Malloc : Attr { def MaxFieldAlignment : Attr { let Spellings = []; - let Args = [UnsignedIntArgument<"Alignment">]; + let Args = [UnsignedArgument<"Alignment">]; } def MSP430Interrupt : Attr { let Spellings = []; - let Args = [UnsignedIntArgument<"Number">]; + let Args = [UnsignedArgument<"Number">]; } def NoDebug : Attr { @@ -251,7 +255,15 @@ def NoInline : Attr { def NonNull : Attr { let Spellings = ["nonnull"]; - let Args = [VariadicArgument<UnsignedIntArgument<"Args">>]; + let Args = [VariadicUnsignedArgument<"Args">]; + let AdditionalMembers = +[{bool isNonNull(unsigned idx) const { + for (args_iterator i = args_begin(), e = args_end(); + i != e; ++i) + if (*i == idx) + return true; + return false; + } }]; } def NoReturn : Attr { @@ -290,13 +302,20 @@ def Override : Attr { let Spellings = ["override"]; let Subjects = [CXXVirtualMethod]; let Namespaces = ["", "std"]; - let DoNotEmit = 0; } def Overloadable : Attr { let Spellings = ["overloadable"]; } +def Ownership : Attr { + let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"]; + let Args = [EnumArgument<"OwnKind", "OwnershipKind", + ["ownership_holds", "ownership_returns", "ownership_takes"], + ["Holds", "Returns", "Takes"]>, + StringArgument<"Module">, VariadicUnsignedArgument<"Args">]; +} + def Packed : Attr { let Spellings = ["packed"]; } @@ -307,18 +326,18 @@ def Pure : Attr { def Regparm : Attr { let Spellings = ["regparm"]; - let Args = [UnsignedIntArgument<"NumParams">]; + let Args = [UnsignedArgument<"NumParams">]; } def ReqdWorkGroupSize : Attr { let Spellings = ["reqd_work_group_size"]; - let Args = [UnsignedIntArgument<"XDim">, UnsignedIntArgument<"YDim">, - UnsignedIntArgument<"ZDim">]; + let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">, + UnsignedArgument<"ZDim">]; } def InitPriority : Attr { let Spellings = ["init_priority"]; - let Args = [UnsignedIntArgument<"Priority">]; + let Args = [UnsignedArgument<"Priority">]; } def Section : Attr { @@ -328,8 +347,8 @@ def Section : Attr { def Sentinel : Attr { let Spellings = ["sentinel"]; - let Args = [DefaultIntArgument<"NulPos", 0>, - DefaultIntArgument<"Sentinel", 0>]; + let Args = [DefaultIntArgument<"Sentinel", 0>, + DefaultIntArgument<"NullPos", 0>]; } def StdCall : Attr { @@ -340,6 +359,10 @@ def ThisCall : Attr { let Spellings = ["thiscall", "__thiscall"]; } +def Pascal : Attr { + let Spellings = ["pascal", "__pascal"]; +} + def TransparentUnion : Attr { let Spellings = ["transparent_union"]; } @@ -358,7 +381,14 @@ def Used : Attr { def Visibility : Attr { let Spellings = ["visibility"]; - let Args = [StringArgument<"Visibility">]; + let Args = [EnumArgument<"Visibility", "VisibilityType", + ["default", "hidden", "internal", "protected"], + ["Default", "Hidden", "Hidden", "Protected"]>]; +} + +def VecReturn : Attr { + let Spellings = ["vecreturn"]; + let Subjects = [CXXRecord]; } def WarnUnusedResult : Attr { diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index eff4f5e6727b..0da893899b0b 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -66,6 +66,11 @@ // P:N: -> similar to the p:N: attribute, but the function is like vprintf // in that it accepts its arguments as a va_list rather than // through an ellipsis +// s:N: -> this is a scanf-like function whose Nth argument is the format +// string. +// S:N: -> similar to the s:N: attribute, but the function is like vscanf +// in that it accepts its arguments as a va_list rather than +// through an ellipsis // e -> const, but only when -fmath-errno=0 // FIXME: gcc has nonnull @@ -193,9 +198,9 @@ BUILTIN(__builtin_cexpl, "XLdXLd", "Fnc") BUILTIN(__builtin_cimag, "dXd", "Fnc") BUILTIN(__builtin_cimagf, "fXf", "Fnc") BUILTIN(__builtin_cimagl, "LdXLd", "Fnc") -BUILTIN(__builtin_conj, "dXd", "Fnc") -BUILTIN(__builtin_conjf, "fXf", "Fnc") -BUILTIN(__builtin_conjl, "LdXLd", "Fnc") +BUILTIN(__builtin_conj, "XdXd", "Fnc") +BUILTIN(__builtin_conjf, "XfXf", "Fnc") +BUILTIN(__builtin_conjl, "XLdXLd", "Fnc") BUILTIN(__builtin_clog, "XdXd", "Fnc") BUILTIN(__builtin_clogf, "XfXf", "Fnc") BUILTIN(__builtin_clogl, "XLdXLd", "Fnc") @@ -281,12 +286,14 @@ BUILTIN(__builtin_stdarg_start, "vA.", "n") BUILTIN(__builtin_bcmp, "iv*v*z", "n") BUILTIN(__builtin_bcopy, "vv*v*z", "n") BUILTIN(__builtin_bzero, "vv*z", "nF") +BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:") BUILTIN(__builtin_memchr, "v*vC*iz", "nF") BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF") BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF") BUILTIN(__builtin_memmove, "v*v*vC*z", "nF") BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF") BUILTIN(__builtin_memset, "v*v*iz", "nF") +BUILTIN(__builtin_printf, "icC*.", "Fp:0:") BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF") BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF") BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF") @@ -319,7 +326,7 @@ BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:") BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:") // GCC exception builtins -BUILTIN(__builtin_eh_return, "vzv*", "") // FIXME: Takes intptr_t, not size_t! +BUILTIN(__builtin_eh_return, "vzv*", "r") // FIXME: Takes intptr_t, not size_t! BUILTIN(__builtin_frob_return_addr, "v*v*", "n") BUILTIN(__builtin_dwarf_cfa, "v*", "n") BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n") @@ -363,75 +370,75 @@ BUILTIN(__builtin_alloca, "v*z" , "n") // long long -> i64. BUILTIN(__sync_fetch_and_add, "v.", "") -BUILTIN(__sync_fetch_and_add_1, "cc*c.", "n") -BUILTIN(__sync_fetch_and_add_2, "ss*s.", "n") -BUILTIN(__sync_fetch_and_add_4, "ii*i.", "n") -BUILTIN(__sync_fetch_and_add_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_fetch_and_add_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_fetch_and_add_1, "ccD*c.", "n") +BUILTIN(__sync_fetch_and_add_2, "ssD*s.", "n") +BUILTIN(__sync_fetch_and_add_4, "iiD*i.", "n") +BUILTIN(__sync_fetch_and_add_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_fetch_and_add_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_fetch_and_sub, "v.", "") -BUILTIN(__sync_fetch_and_sub_1, "cc*c.", "n") -BUILTIN(__sync_fetch_and_sub_2, "ss*s.", "n") -BUILTIN(__sync_fetch_and_sub_4, "ii*i.", "n") -BUILTIN(__sync_fetch_and_sub_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_fetch_and_sub_1, "ccD*c.", "n") +BUILTIN(__sync_fetch_and_sub_2, "ssD*s.", "n") +BUILTIN(__sync_fetch_and_sub_4, "iiD*i.", "n") +BUILTIN(__sync_fetch_and_sub_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_fetch_and_or, "v.", "") -BUILTIN(__sync_fetch_and_or_1, "cc*c.", "n") -BUILTIN(__sync_fetch_and_or_2, "ss*s.", "n") -BUILTIN(__sync_fetch_and_or_4, "ii*i.", "n") -BUILTIN(__sync_fetch_and_or_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_fetch_and_or_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_fetch_and_or_1, "ccD*c.", "n") +BUILTIN(__sync_fetch_and_or_2, "ssD*s.", "n") +BUILTIN(__sync_fetch_and_or_4, "iiD*i.", "n") +BUILTIN(__sync_fetch_and_or_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_fetch_and_or_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_fetch_and_and, "v.", "") -BUILTIN(__sync_fetch_and_and_1, "cc*c.", "n") -BUILTIN(__sync_fetch_and_and_2, "ss*s.", "n") -BUILTIN(__sync_fetch_and_and_4, "ii*i.", "n") -BUILTIN(__sync_fetch_and_and_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_fetch_and_and_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_fetch_and_and_1, "ccD*c.", "n") +BUILTIN(__sync_fetch_and_and_2, "ssD*s.", "n") +BUILTIN(__sync_fetch_and_and_4, "iiD*i.", "n") +BUILTIN(__sync_fetch_and_and_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_fetch_and_and_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_fetch_and_xor, "v.", "") -BUILTIN(__sync_fetch_and_xor_1, "cc*c.", "n") -BUILTIN(__sync_fetch_and_xor_2, "ss*s.", "n") -BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n") -BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_fetch_and_xor_1, "ccD*c.", "n") +BUILTIN(__sync_fetch_and_xor_2, "ssD*s.", "n") +BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "n") +BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_add_and_fetch, "v.", "") -BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n") -BUILTIN(__sync_add_and_fetch_2, "ss*s.", "n") -BUILTIN(__sync_add_and_fetch_4, "ii*i.", "n") -BUILTIN(__sync_add_and_fetch_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_add_and_fetch_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "n") +BUILTIN(__sync_add_and_fetch_2, "ssD*s.", "n") +BUILTIN(__sync_add_and_fetch_4, "iiD*i.", "n") +BUILTIN(__sync_add_and_fetch_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_add_and_fetch_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_sub_and_fetch, "v.", "") -BUILTIN(__sync_sub_and_fetch_1, "cc*c.", "n") -BUILTIN(__sync_sub_and_fetch_2, "ss*s.", "n") -BUILTIN(__sync_sub_and_fetch_4, "ii*i.", "n") -BUILTIN(__sync_sub_and_fetch_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_sub_and_fetch_1, "ccD*c.", "n") +BUILTIN(__sync_sub_and_fetch_2, "ssD*s.", "n") +BUILTIN(__sync_sub_and_fetch_4, "iiD*i.", "n") +BUILTIN(__sync_sub_and_fetch_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_or_and_fetch, "v.", "") -BUILTIN(__sync_or_and_fetch_1, "cc*c.", "n") -BUILTIN(__sync_or_and_fetch_2, "ss*s.", "n") -BUILTIN(__sync_or_and_fetch_4, "ii*i.", "n") -BUILTIN(__sync_or_and_fetch_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_or_and_fetch_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_or_and_fetch_1, "ccD*c.", "n") +BUILTIN(__sync_or_and_fetch_2, "ssD*s.", "n") +BUILTIN(__sync_or_and_fetch_4, "iiD*i.", "n") +BUILTIN(__sync_or_and_fetch_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_or_and_fetch_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_and_and_fetch, "v.", "") -BUILTIN(__sync_and_and_fetch_1, "cc*c.", "n") -BUILTIN(__sync_and_and_fetch_2, "ss*s.", "n") -BUILTIN(__sync_and_and_fetch_4, "ii*i.", "n") -BUILTIN(__sync_and_and_fetch_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_and_and_fetch_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_and_and_fetch_1, "ccD*c.", "n") +BUILTIN(__sync_and_and_fetch_2, "ssD*s.", "n") +BUILTIN(__sync_and_and_fetch_4, "iiD*i.", "n") +BUILTIN(__sync_and_and_fetch_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_and_and_fetch_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_xor_and_fetch, "v.", "") -BUILTIN(__sync_xor_and_fetch_1, "cc*c.", "n") -BUILTIN(__sync_xor_and_fetch_2, "ss*s.", "n") -BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n") -BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_xor_and_fetch_1, "ccD*c.", "n") +BUILTIN(__sync_xor_and_fetch_2, "ssD*s.", "n") +BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "n") +BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_bool_compare_and_swap, "v.", "") BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n") @@ -448,18 +455,18 @@ BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "n") BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "n") BUILTIN(__sync_lock_test_and_set, "v.", "") -BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n") -BUILTIN(__sync_lock_test_and_set_2, "ss*s.", "n") -BUILTIN(__sync_lock_test_and_set_4, "ii*i.", "n") -BUILTIN(__sync_lock_test_and_set_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLi*LLLi.", "n") +BUILTIN(__sync_lock_test_and_set_1, "ccD*c.", "n") +BUILTIN(__sync_lock_test_and_set_2, "ssD*s.", "n") +BUILTIN(__sync_lock_test_and_set_4, "iiD*i.", "n") +BUILTIN(__sync_lock_test_and_set_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLiD*LLLi.", "n") BUILTIN(__sync_lock_release, "v.", "") -BUILTIN(__sync_lock_release_1, "vc*.", "n") -BUILTIN(__sync_lock_release_2, "vs*.", "n") -BUILTIN(__sync_lock_release_4, "vi*.", "n") -BUILTIN(__sync_lock_release_8, "vLLi*.", "n") -BUILTIN(__sync_lock_release_16, "vLLLi*.", "n") +BUILTIN(__sync_lock_release_1, "vcD*.", "n") +BUILTIN(__sync_lock_release_2, "vsD*.", "n") +BUILTIN(__sync_lock_release_4, "viD*.", "n") +BUILTIN(__sync_lock_release_8, "vLLiD*.", "n") +BUILTIN(__sync_lock_release_16, "vLLLiD*.", "n") @@ -468,10 +475,10 @@ BUILTIN(__sync_synchronize, "v.", "n") // LLVM instruction builtin [Clang extension]. BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n") // GCC does not support these, they are a Clang extension. -BUILTIN(__sync_fetch_and_min, "ii*i", "n") -BUILTIN(__sync_fetch_and_max, "ii*i", "n") -BUILTIN(__sync_fetch_and_umin, "UiUi*Ui", "n") -BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n") +BUILTIN(__sync_fetch_and_min, "iiD*i", "n") +BUILTIN(__sync_fetch_and_max, "iiD*i", "n") +BUILTIN(__sync_fetch_and_umin, "UiUiD*Ui", "n") +BUILTIN(__sync_fetch_and_umax, "UiUiD*Ui", "n") // Random libc builtins. BUILTIN(__builtin_abort, "v", "Fnr") @@ -516,6 +523,7 @@ LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h") LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h") LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h") LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h") +LIBBUILTIN(scanf, "icC*.", "fs:0:", "stdio.h") // C99 LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h") @@ -560,5 +568,10 @@ LIBBUILTIN(cos, "dd", "fe", "math.h") LIBBUILTIN(cosl, "LdLd", "fe", "math.h") LIBBUILTIN(cosf, "ff", "fe", "math.h") +// Blocks runtime Builtin math library functions +LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h") +LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h") +// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock. + #undef BUILTIN #undef LIBBUILTIN diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 07f091a58a4e..94d5e6955a24 100644 --- a/include/clang/Basic/Builtins.h +++ b/include/clang/Basic/Builtins.h @@ -119,6 +119,11 @@ public: /// argument and whether this function as a va_list argument. bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); + /// \brief Determine whether this builtin is like scanf in its + /// formatting rules and, if so, set the index to the format string + /// argument and whether this function as a va_list argument. + bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); + /// hasVAListUse - Return true of the specified builtin uses __builtin_va_list /// as an operand or return type. bool hasVAListUse(unsigned ID) const { diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def index 54e4c2b2083a..080d17fa1e32 100644 --- a/include/clang/Basic/BuiltinsARM.def +++ b/include/clang/Basic/BuiltinsARM.def @@ -15,9 +15,21 @@ // The format of this database matches clang/Basic/Builtins.def. // In libgcc -BUILTIN(__clear_cache, "vc*c*", "") +BUILTIN(__clear_cache, "v.", "") BUILTIN(__builtin_thread_pointer, "v*", "") +// Saturating arithmetic +BUILTIN(__builtin_arm_qadd, "iii", "nc") +BUILTIN(__builtin_arm_qsub, "iii", "nc") +BUILTIN(__builtin_arm_ssat, "iiUi", "nc") +BUILTIN(__builtin_arm_usat, "UiUiUi", "nc") + +// VFP +BUILTIN(__builtin_arm_get_fpscr, "Ui", "nc") +BUILTIN(__builtin_arm_set_fpscr, "vUi", "nc") +BUILTIN(__builtin_arm_vcvtr_f, "ffi", "nc") +BUILTIN(__builtin_arm_vcvtr_d, "fdi", "nc") + // NEON #define GET_NEON_BUILTINS #include "clang/Basic/arm_neon.inc" diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index a878dd1bd1a3..5ad64b9b49d1 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -22,10 +22,81 @@ // definition anyway, since code generation will lower to the // intrinsic if one exists. -BUILTIN(__builtin_ia32_emms , "v", "") - // FIXME: Are these nothrow/const? +// MMX +BUILTIN(__builtin_ia32_emms, "v", "") +BUILTIN(__builtin_ia32_femms, "v", "") +BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "") +BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "") +BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "") +BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "") +BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "") +BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "") +BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "") +BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "") +BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "") +BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "") +BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "") +BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "") +BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "") +BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "") +BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "") +BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "") +BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "") +BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "") +BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "") +BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "") +BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "") +BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "") +BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "") +BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "") // FIXME: Correct type? +BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "") +BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "") +BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "") +BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "") + // SSE intrinsics. BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "") BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "") @@ -57,29 +128,6 @@ BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "") -BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "") -BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "") -BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "") -BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "") -BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "") BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "") BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "") BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "") @@ -147,18 +195,6 @@ BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "") BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "") BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "") BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "") -BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "") -BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "") -BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "") -BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "") -BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "") -BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "") -BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "") -BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "") -BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "") -BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "") -BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "") -BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "") BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "") BUILTIN(__builtin_ia32_stmxcsr, "Ui", "") BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "") @@ -166,17 +202,13 @@ BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "") BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "") BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "") BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "") -BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "") BUILTIN(__builtin_ia32_loadups, "V4ffC*", "") BUILTIN(__builtin_ia32_storeups, "vf*V4f", "") BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "") BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "") BUILTIN(__builtin_ia32_movmskps, "iV4f", "") -BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "") BUILTIN(__builtin_ia32_movntps, "vf*V4f", "") -BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "") BUILTIN(__builtin_ia32_sfence, "v", "") -BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "") BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "") BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "") BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "") @@ -212,15 +244,6 @@ BUILTIN(__builtin_ia32_lfence, "v", "") BUILTIN(__builtin_ia32_mfence, "v", "") BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "") BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "") -BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "") -BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "") -BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "") -BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "") -BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "") -BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "") -BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "") -BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "") -BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "") BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "") BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "") @@ -244,8 +267,7 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "") BUILTIN(__builtin_ia32_mwait, "vUiUi", "") BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") -BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") -BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "") +BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") // FIXME: Correct type? BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "") BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "") @@ -324,5 +346,98 @@ BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "") -BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLii", "") +BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLic", "") + +// AVX +BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "") +BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "") +BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "") +BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "") +BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "") +BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "") +BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "") +BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "") +BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "") +BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "") +BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "") +BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "") +BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "") +BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "") +BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4di", "") +BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fi", "") +BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "") +BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "") +BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fi", "") +BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dc", "") +BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fc", "") +BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dc", "") +BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fc", "") +BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8ic", "") +BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "") +BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "") +BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "") +BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "") +BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "") +BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "") +BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "") +BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "") +BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dc", "") +BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fc", "") +BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8ic", "") +BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dc", "") +BUILTIN(__builtin_ia32_vpermilps, "V4fV4fc", "") +BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dc", "") +BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fc", "") +BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dc", "") +BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fc", "") +BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4ic", "") +BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "") +BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "") +BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "") +BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "") +BUILTIN(__builtin_ia32_roundpd256, "V4dV4di", "") +BUILTIN(__builtin_ia32_roundps256, "V8fV8fi", "") +BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "") +BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "") +BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "") +BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "") +BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "") +BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "") +BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "") +BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "") +BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "") +BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "") +BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "") +BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "") +BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "") +BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "") +BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "") +BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "") +BUILTIN(__builtin_ia32_movmskps256, "iV8f", "") +BUILTIN(__builtin_ia32_vzeroall, "v", "") +BUILTIN(__builtin_ia32_vzeroupper, "v", "") +BUILTIN(__builtin_ia32_vbroadcastss, "V4ffC*", "") +BUILTIN(__builtin_ia32_vbroadcastsd256, "V4ddC*", "") +BUILTIN(__builtin_ia32_vbroadcastss256, "V8ffC*", "") +BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "") +BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "") +BUILTIN(__builtin_ia32_loadupd256, "V4ddC*", "") +BUILTIN(__builtin_ia32_loadups256, "V8ffC*", "") +BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "") +BUILTIN(__builtin_ia32_storeups256, "vf*V8f", "") +BUILTIN(__builtin_ia32_loaddqu256, "V32ccC*", "") +BUILTIN(__builtin_ia32_storedqu256, "vc*V32c", "") +BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "") +BUILTIN(__builtin_ia32_movntdq256, "vV4LLi*V4LLi", "") +BUILTIN(__builtin_ia32_movntpd256, "vd*V4d", "") +BUILTIN(__builtin_ia32_movntps256, "vf*V8f", "") +BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2d", "") +BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4f", "") +BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4d", "") +BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8f", "") +BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2dV2d", "") +BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4fV4f", "") +BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4dV4d", "") +BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8fV8f", "") + #undef BUILTIN diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td index 203fb451e38b..e2f93e02c525 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -43,8 +43,9 @@ def Named : Decl<1>; def ParmVar : DDecl<Var>; def NonTypeTemplateParm : DDecl<Var>; def Template : DDecl<Named, 1>; - def FunctionTemplate : DDecl<Template>; - def ClassTemplate : DDecl<Template>; + def RedeclarableTemplate : DDecl<Template, 1>; + def FunctionTemplate : DDecl<RedeclarableTemplate>; + def ClassTemplate : DDecl<RedeclarableTemplate>; def TemplateTemplateParm : DDecl<Template>; def Using : DDecl<Named>; def UsingShadow : DDecl<Named>; diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 1fe0d8154cd4..37d26947c335 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -16,6 +16,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/type_traits.h" #include <string> @@ -95,23 +96,20 @@ namespace clang { /// compilation. class FixItHint { public: - /// \brief Code that should be removed to correct the error. + /// \brief Code that should be replaced to correct the error. Empty for an + /// insertion hint. CharSourceRange RemoveRange; - /// \brief The location at which we should insert code to correct - /// the error. - SourceLocation InsertionLoc; - /// \brief The actual code to insert at the insertion location, as a /// string. std::string CodeToInsert; /// \brief Empty code modification hint, indicating that no code /// modification is known. - FixItHint() : RemoveRange(), InsertionLoc() { } + FixItHint() : RemoveRange() { } bool isNull() const { - return !RemoveRange.isValid() && !InsertionLoc.isValid(); + return !RemoveRange.isValid(); } /// \brief Create a code modification hint that inserts the given @@ -119,7 +117,8 @@ public: static FixItHint CreateInsertion(SourceLocation InsertionLoc, llvm::StringRef Code) { FixItHint Hint; - Hint.InsertionLoc = InsertionLoc; + Hint.RemoveRange = + CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false); Hint.CodeToInsert = Code; return Hint; } @@ -141,7 +140,6 @@ public: llvm::StringRef Code) { FixItHint Hint; Hint.RemoveRange = RemoveRange; - Hint.InsertionLoc = RemoveRange.getBegin(); Hint.CodeToInsert = Code; return Hint; } @@ -205,16 +203,32 @@ private: unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack, // 0 -> no limit. ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? - DiagnosticClient *Client; - + llvm::OwningPtr<DiagnosticClient> Client; + /// DiagMappings - Mapping information for diagnostics. Mapping info is /// packed into four bits per diagnostic. The low three bits are the mapping /// (an instance of diag::Mapping), or zero if unset. The high bit is set /// when the mapping was established as a user mapping. If the high bit is /// clear, then the low bits are set to the default value, and should be /// mapped with -pedantic, -Werror, etc. + class DiagMappings { + unsigned char Values[diag::DIAG_UPPER_LIMIT/2]; + + public: + DiagMappings() { + memset(Values, 0, diag::DIAG_UPPER_LIMIT/2); + } + + void setMapping(diag::kind Diag, unsigned Map) { + size_t Shift = (Diag & 1)*4; + Values[Diag/2] = (Values[Diag/2] & ~(15 << Shift)) | (Map << Shift); + } + + diag::Mapping getMapping(diag::kind Diag) const { + return (diag::Mapping)((Values[Diag/2] >> (Diag & 1)*4) & 15); + } + }; - typedef std::vector<unsigned char> DiagMappings; mutable std::vector<DiagMappings> DiagMappingsStack; /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or @@ -272,8 +286,12 @@ public: // Diagnostic characterization methods, used by a client to customize how // - DiagnosticClient *getClient() { return Client; } - const DiagnosticClient *getClient() const { return Client; } + DiagnosticClient *getClient() { return Client.get(); } + const DiagnosticClient *getClient() const { return Client.get(); } + + /// \brief Return the current diagnostic client along with ownership of that + /// client. + DiagnosticClient *takeClient() { return Client.take(); } /// pushMappings - Copies the current DiagMappings and pushes the new copy /// onto the top of the stack. @@ -285,7 +303,10 @@ public: /// stack. bool popMappings(); - void setClient(DiagnosticClient* client) { Client = client; } + /// \brief Set the diagnostic client associated with this diagnostic object. + /// + /// The diagnostic object takes ownership of \c client. + void setClient(DiagnosticClient* client) { Client.reset(client); } /// setErrorLimit - Specify a limit for the number of errors we should /// emit before giving up. Zero disables the limit. @@ -382,6 +403,10 @@ public: unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; } unsigned getNumWarnings() const { return NumWarnings; } + void setNumWarnings(unsigned NumWarnings) { + this->NumWarnings = NumWarnings; + } + /// getCustomDiagID - Return an ID for a diagnostic with the specified message /// and level. If this is the first request for this diagnosic, it is /// registered and created, otherwise the existing ID is returned. @@ -404,6 +429,10 @@ public: ArgToStringCookie = Cookie; } + /// \brief Reset the state of the diagnostic object to its initial + /// configuration. + void Reset(); + //===--------------------------------------------------------------------===// // Diagnostic classification and reporting interfaces. // @@ -535,17 +564,13 @@ private: /// specified builtin diagnostic. This returns the high bit encoding, or zero /// if the field is completely uninitialized. diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const { - const DiagMappings ¤tMappings = DiagMappingsStack.back(); - return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15); + return DiagMappingsStack.back().getMapping(Diag); } void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map, bool isUser) const { if (isUser) Map |= 8; // Set the high bit for user mappings. - unsigned char &Slot = DiagMappingsStack.back()[DiagId/2]; - unsigned Shift = (DiagId & 1)*4; - Slot &= ~(15 << Shift); - Slot |= Map << Shift; + DiagMappingsStack.back().setMapping((diag::kind)DiagId, Map); } /// getDiagnosticLevel - This is an internal implementation helper used when @@ -927,7 +952,9 @@ public: Diagnostic::Level getLevel() const { return Level; } const FullSourceLoc &getLocation() const { return Loc; } llvm::StringRef getMessage() const { return Message; } - + + void setLocation(FullSourceLoc Loc) { this->Loc = Loc; } + typedef std::vector<CharSourceRange>::const_iterator range_iterator; range_iterator range_begin() const { return Ranges.begin(); } range_iterator range_end() const { return Ranges.end(); } diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 4b0bf57bef63..98ea9d4bd6d9 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -41,7 +41,8 @@ def err_expected_colon_after_setter_name : Error< "must end with ':'">; // Parse && Sema -def ext_no_declarators : ExtWarn<"declaration does not declare anything">; +def ext_no_declarators : ExtWarn<"declaration does not declare anything">, + InGroup<MissingDeclarations>; def err_param_redefinition : Error<"redefinition of parameter %0">; def err_invalid_storage_class_in_func_decl : Error< "invalid storage class specifier in function declarator">; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index f4a31cc5766c..34cd6004edee 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -68,6 +68,8 @@ def err_drv_invalid_gcc_output_type : Error< "invalid output type '%0' for use with gcc tool">; def err_drv_cc_print_options_failure : Error< "unable to open CC_PRINT_OPTIONS file: %0">; +def err_drv_preamble_format : Error< + "incorrect format for -preamble-bytes=N,END">; def warn_drv_input_file_unused : Warning< "%0: '%1' input unused when '%2' is present">; diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 989ec38d2950..7c74bf458e58 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -99,7 +99,7 @@ def warn_fixit_no_changes : Note< def err_fe_invoking : Error<"error invoking%0: %1">, DefaultFatal; // PCH reader -def err_relocatable_without_without_isysroot : Error< +def err_relocatable_without_isysroot : Error< "must specify system root with -isysroot when building a relocatable " "PCH file">; def warn_pch_target_triple : Error< diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 49077513c137..d4b7f1f55743 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -25,15 +25,19 @@ def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">; def : DiagGroup<"attributes">; def : DiagGroup<"bad-function-cast">; def BoolConversions : DiagGroup<"bool-conversions">; -def : DiagGroup<"c++-compat">; -def : DiagGroup<"cast-align">; +def CXXCompat: DiagGroup<"c++-compat">; +def CastAlign : DiagGroup<"cast-align">; def : DiagGroup<"cast-qual">; def : DiagGroup<"char-align">; def Comment : DiagGroup<"comment">; def : DiagGroup<"ctor-dtor-privacy">; def : DiagGroup<"declaration-after-statement">; def GNUDesignator : DiagGroup<"gnu-designator">; -def Deprecated : DiagGroup<"deprecated">; + +def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">; +def Deprecated : DiagGroup<"deprecated", [ DeprecatedDeclarations] >, + DiagCategory<"Deprecations">; + def : DiagGroup<"disabled-optimization">; def : DiagGroup<"discard-qual">; def : DiagGroup<"div-by-zero">; @@ -46,7 +50,9 @@ def FormatZeroLength : DiagGroup<"format-zero-length">; def CXXHexFloats : DiagGroup<"c++-hex-floats">; def : DiagGroup<"c++0x-compat", [CXXHexFloats]>; +def : DiagGroup<"effc++">; def FourByteMultiChar : DiagGroup<"four-char-constants">; +def GlobalConstructors : DiagGroup<"global-constructors">; def : DiagGroup<"idiomatic-parentheses">; def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; def : DiagGroup<"import">; @@ -55,9 +61,10 @@ def : DiagGroup<"inline">; def : DiagGroup<"int-to-pointer-cast">; def : DiagGroup<"invalid-pch">; def LiteralRange : DiagGroup<"literal-range">; +def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">; def : DiagGroup<"main">; def MissingBraces : DiagGroup<"missing-braces">; -def : DiagGroup<"missing-declarations">; +def MissingDeclarations: DiagGroup<"missing-declarations">; def : DiagGroup<"missing-format-attribute">; def : DiagGroup<"missing-include-dirs">; def : DiagGroup<"missing-noreturn">; @@ -71,8 +78,11 @@ def InitializerOverrides : DiagGroup<"initializer-overrides">; def NonNull : DiagGroup<"nonnull">; def : DiagGroup<"nonportable-cfstrings">; def : DiagGroup<"non-virtual-dtor">; +def : DiagGroup<"old-style-cast">; def : DiagGroup<"old-style-definition">; +def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">; def : DiagGroup<"overflow">; +def OverlengthStrings : DiagGroup<"overlength-strings">; def : DiagGroup<"overloaded-virtual">; def : DiagGroup<"packed">; def PointerArith : DiagGroup<"pointer-arith">; @@ -88,6 +98,8 @@ def Shadow : DiagGroup<"shadow">; def : DiagGroup<"shorten-64-to-32">; def : DiagGroup<"sign-promo">; def SignCompare : DiagGroup<"sign-compare">; +def : DiagGroup<"stack-protector">; +def : DiagGroup<"switch-default">; def : DiagGroup<"synth">; // Preprocessor warnings. @@ -110,7 +122,7 @@ def : DiagGroup<"strict-overflow">; def InvalidOffsetof : DiagGroup<"invalid-offsetof">; def : DiagGroup<"strict-prototypes">; -def : DiagGroup<"strict-selector-match">; +def StrictSelector : DiagGroup<"strict-selector-match">; def SwitchEnum : DiagGroup<"switch-enum">; def Switch : DiagGroup<"switch", [SwitchEnum]>; def Trigraphs : DiagGroup<"trigraphs">; @@ -119,9 +131,11 @@ def : DiagGroup<"type-limits">; def Uninitialized : DiagGroup<"uninitialized">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; def UnknownAttributes : DiagGroup<"unknown-attributes">; +def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">; def UnusedArgument : DiagGroup<"unused-argument">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; def UnusedFunction : DiagGroup<"unused-function">; +def UnusedMemberFunction : DiagGroup<"unused-member-function">; def UnusedLabel : DiagGroup<"unused-label">; def UnusedParameter : DiagGroup<"unused-parameter">; def UnusedValue : DiagGroup<"unused-value">; @@ -129,6 +143,8 @@ def UnusedVariable : DiagGroup<"unused-variable">; def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">; def Reorder : DiagGroup<"reorder">; def UndeclaredSelector : DiagGroup<"undeclared-selector">; +def Selector : DiagGroup<"selector">; +def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">; def Protocol : DiagGroup<"protocol">; def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def : DiagGroup<"variadic-macros">; @@ -154,6 +170,7 @@ def Conversion : DiagGroup<"conversion", def Unused : DiagGroup<"unused", [UnusedArgument, UnusedFunction, UnusedLabel, // UnusedParameter, (matches GCC's behavior) + // UnusedMemberFunction, (clean-up llvm before enabling) UnusedValue, UnusedVariable]>, DiagCategory<"Unused Entity Issue">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 21c93e7e8fa2..dcb05c8fcd45 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -51,6 +51,7 @@ def err_empty_character : Error<"empty character constant">; def err_unterminated_block_comment : Error<"unterminated /* comment">; def err_invalid_character_to_charify : Error< "invalid argument to convert to character">; +def err_unterminated___pragma : Error<"missing terminating ')' character">; def err_conflict_marker : Error<"version control conflict marker in file">; @@ -94,7 +95,10 @@ def ext_binary_literal : Extension< def err_pascal_string_too_long : Error<"Pascal string is too long">; def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">; def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">; - +def ext_string_too_long : Extension<"string literal of length %0 exceeds " + "maximum length %1 that %select{C90|ISO C99|C++}2 compilers are required to " + "support">, InGroup<OverlengthStrings>; + //===----------------------------------------------------------------------===// // PTH Diagnostics //===----------------------------------------------------------------------===// @@ -227,6 +231,10 @@ def err_pragma_comment_malformed : Error< "pragma comment requires parenthesized identifier and optional string">; def err_pragma_message_malformed : Error< "pragma message requires parenthesized string">; +def err_pragma_push_pop_macro_malformed : Error< + "pragma %0 requires a parenthesized string">; +def warn_pragma_pop_macro_no_push : Warning< + "pragma pop_macro could not pop '%0', no matching push_macro">; def warn_pragma_message : Warning<"%0">; def warn_pragma_ignored : Warning<"unknown pragma ignored">, InGroup<UnknownPragmas>, DefaultIgnore; @@ -241,15 +249,11 @@ def ext_stdc_pragma_syntax_eom : def warn_stdc_fenv_access_not_supported : Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">, InGroup<UnknownPragmas>; -def warn_pragma_diagnostic_gcc_invalid : - ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', or" - " 'fatal'">, - InGroup<UnknownPragmas>; -def warn_pragma_diagnostic_clang_invalid : - ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal'" +def warn_pragma_diagnostic_invalid : + ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal'," " 'push', or 'pop'">, InGroup<UnknownPragmas>; -def warn_pragma_diagnostic_clang_cannot_ppp : +def warn_pragma_diagnostic_cannot_pop : ExtWarn<"pragma diagnostic pop could not pop, no matching push">, InGroup<UnknownPragmas>; def warn_pragma_diagnostic_invalid_option : @@ -261,6 +265,9 @@ def warn_pragma_diagnostic_invalid_token : def warn_pragma_diagnostic_unknown_warning : ExtWarn<"unknown warning group '%0', ignored">, InGroup<UnknownPragmas>; +// - #pragma __debug +def warn_pragma_debug_unexpected_command : Warning< + "unexpected debug command '%0'">; def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">; def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">; @@ -277,6 +284,9 @@ def err_too_few_args_in_macro_invoc : Error< "too few arguments provided to function-like macro invocation">; def err_pp_bad_paste : Error< "pasting formed '%0', an invalid preprocessing token">; +def err_pp_bad_paste_ms : Warning< + "pasting formed '%0', an invalid preprocessing token">, DefaultError, + InGroup<DiagGroup<"invalid-token-paste">>; def err_pp_operator_used_as_macro_name : Error< "C++ operator '%0' cannot be used as a macro name">; def err_pp_illegal_floating_literal : Error< diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index ca761f9bf5e9..646fd0d1bfb6 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -35,8 +35,9 @@ def ext_integer_complex : Extension< "complex integer types are an extension">; def ext_thread_before : Extension<"'__thread' before 'static'">; -def ext_empty_struct_union_enum : Extension<"use of empty %0 extension">; - +def ext_empty_struct_union : Extension<"empty %select{struct|union}0 " + "(accepted as an extension) has size 0 in C, size 1 in C++">, + InGroup<CXXCompat>; def error_empty_enum : Error<"use of empty enum">; def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">; def err_invalid_short_spec : Error<"'short %0' is invalid">; @@ -102,6 +103,8 @@ def err_expected_member_name_or_semi : Error< "expected member name or ';' after declaration specifiers">; def err_function_declared_typedef : Error< "function definition declared 'typedef'">; +def err_iboutletcollection_builtintype : Error< + "type argument of iboutletcollection attribute cannot be a builtin type">; def err_expected_fn_body : Error< "expected function body after function declarator">; def err_expected_method_body : Error<"expected method body">; @@ -125,6 +128,7 @@ def err_expected_semi_after_namespace_name : Error< "expected ';' after namespace name">; def err_unexpected_namespace_attributes_alias : Error< "attributes can not be specified on namespace alias">; +def err_inline_namespace_alias : Error<"namespace alias cannot be inline">; def err_namespace_nonnamespace_scope : Error< "namespaces can only be defined in global or namespace scope">; def err_expected_semi_after_attribute_list : Error< @@ -150,6 +154,8 @@ def err_illegal_decl_reference_to_reference : Error< "%0 declared as a reference to a reference">; def err_rvalue_reference : Error< "rvalue references are only allowed in C++0x">; +def ext_inline_namespace : Extension< + "inline namespaces are a C++0x feature">; def err_argument_required_after_attribute : Error< "argument required after attribute">; def err_missing_param : Error<"expected parameter declarator">; @@ -270,6 +276,8 @@ def err_destructor_tilde_identifier : Error< "expected a class name after '~' to name a destructor">; def err_destructor_template_id : Error< "destructor name %0 does not refer to a template">; +def err_default_arg_unparsed : Error< + "unexpected end of default argument expression">; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; @@ -373,10 +381,10 @@ def warn_pragma_extra_tokens_at_eol : Warning< // - #pragma options def warn_pragma_options_expected_align : Warning< "expected 'align' following '#pragma options' - ignored">; -def warn_pragma_options_expected_equal : Warning< - "expected '=' following '#pragma options align' - ignored">; -def warn_pragma_options_invalid_option : Warning< - "invalid alignment option in '#pragma options align' - ignored">; +def warn_pragma_align_expected_equal : Warning< + "expected '=' following '#pragma %select{align|options align}0' - ignored">; +def warn_pragma_align_invalid_option : Warning< + "invalid alignment option in '#pragma %select{align|options align}0' - ignored">; // - #pragma pack def warn_pragma_pack_invalid_action : Warning< "unknown action for '#pragma pack' - ignored">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 01a37fb6f2c6..a25b2a341fc5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -104,6 +104,8 @@ def warn_decl_in_param_list : Warning< "declaration of %0 will not be visible outside of this function">; def warn_unused_function : Warning<"unused function %0">, InGroup<UnusedFunction>, DefaultIgnore; +def warn_unused_member_function : Warning<"unused member function %0">, + InGroup<UnusedMemberFunction>, DefaultIgnore; def warn_implicit_function_decl : Warning< "implicit declaration of function %0">, @@ -168,6 +170,13 @@ def warn_access_decl_deprecated : Warning< "access declarations are deprecated; use using declarations instead">, InGroup<Deprecated>; +def warn_global_constructor : Warning< + "declaration requires a global constructor">, + InGroup<GlobalConstructors>, DefaultIgnore; +def warn_global_destructor : Warning< + "declaration requires a global destructor">, + InGroup<GlobalConstructors>, DefaultIgnore; + def err_invalid_thread : Error< "'__thread' is only allowed on variable declarations">; def err_thread_non_global : Error< @@ -227,7 +236,8 @@ def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " "platform-specific data}0) must be of type %1">; /// parser diagnostics -def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">; +def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">, + InGroup<MissingDeclarations>; def err_typedef_not_identifier : Error<"typedef name must be an identifier">; def err_statically_allocated_object : Error< "interface type cannot be statically allocated">; @@ -322,6 +332,8 @@ def warn_implements_nscopying : Warning< "NSCopying protocol is not appropriate with -fobjc-gc[-only]">; def warn_multiple_method_decl : Warning<"multiple methods named %0 found">; +def warn_strict_multiple_method_decl : Warning< + "multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore; def warn_accessor_property_type_mismatch : Warning< "type of property %0 does not match type of accessor %1">; def note_declared_at : Note<"declared here">; @@ -399,6 +411,8 @@ def warn_objc_property_attr_mutually_exclusive : Warning< InGroup<ReadOnlySetterAttrs>, DefaultIgnore; def warn_undeclared_selector : Warning< "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore; +def warn_unimplemented_selector: Warning< + "unimplemented selector %0">, InGroup<Selector>, DefaultIgnore; def warn_unimplemented_protocol_method : Warning< "method in protocol not implemented">, InGroup<Protocol>; @@ -407,6 +421,10 @@ def err_static_assert_expression_is_not_constant : Error< "static_assert expression is not an integral constant expression">; def err_static_assert_failed : Error<"static_assert failed \"%0\"">; +def err_inline_namespace_mismatch : Error< + "%select{|non-}0inline namespace " + "cannot be reopened as %select{non-|}0inline">; + def err_unexpected_friend : Error< "friends can only be classes or functions">; def ext_enum_friend : ExtWarn< @@ -549,6 +567,8 @@ def note_access_natural : Note< def note_access_constrained_by_path : Note< "constrained by %select{|implicitly }1%select{private|protected}0" " inheritance here">; +def note_access_protected_restricted : Note< + "object type %select{|%1 }0must derive from context type %2">; // C++ name lookup def err_incomplete_nested_name_spec : Error< @@ -621,9 +641,9 @@ def err_missing_default_ctor : Error< "%select{|implicit default }0constructor for %1 must explicitly initialize " "the %select{base class|member}2 %3 which does not have a default " "constructor">; -def err_illegal_union_member : Error< - "union member %0 has a non-trivial %select{constructor|" - "copy constructor|copy assignment operator|destructor}1">; +def err_illegal_union_or_anon_struct_member : Error< + "%select{anonymous struct|union}0 member %1 has a non-trivial " + "%select{constructor|copy constructor|copy assignment operator|destructor}2">; def note_nontrivial_has_virtual : Note< "because type %0 has a virtual %select{member function|base class}1">; def note_nontrivial_has_nontrivial : Note< @@ -814,6 +834,11 @@ def err_attributes_are_not_compatible : Error< "%0 and %1 attributes are not compatible">; def err_attribute_wrong_number_arguments : Error< "attribute requires %0 argument(s)">; +def err_iboutletcollection_type : Error< + "invalid type %0 as argument of iboutletcollection attribute">; +def err_iboutletcollection_object_type : Error< + "%select{ivar|property}1 with iboutletcollection attribute must " + "have object type (invalid %0)">; def err_attribute_missing_parameter_name : Error< "attribute requires unquoted parameter">; def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; @@ -833,8 +858,10 @@ def err_attribute_argument_out_of_bounds : Error< "'%0' attribute parameter %1 is out of bounds">; def err_attribute_requires_objc_interface : Error< "attribute may only be applied to an Objective-C interface">; -def err_nonnull_pointers_only : Error< +def warn_nonnull_pointers_only : Warning< "nonnull attribute only applies to pointer arguments">; +def err_ownership_type : Error< + "%0 attribute only applies to %1 arguments">; def err_format_strftime_third_parameter : Error< "strftime format attribute requires 3rd parameter to be 0">; def err_format_attribute_requires_variadic : Error< @@ -957,6 +984,10 @@ def warn_impcast_integer_64_32 : Warning< "implicit conversion loses integer precision: %0 to %1">, InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore; +def warn_cast_align : Warning< + "cast from %0 to %1 increases required alignment from %2 to %3">, + InGroup<CastAlign>, DefaultIgnore; + def warn_attribute_ignored_for_field_of_type : Warning< "%0 attribute ignored for field of type %1">; def warn_transparent_union_attribute_field_size_align : Warning< @@ -976,7 +1007,7 @@ def warn_transparent_union_attribute_zero_fields : Warning< "transparent_union attribute ignored">; def warn_attribute_type_not_supported : Warning< "'%0' attribute argument not supported: %1">; -def warn_attribute_unknown_visibility : Warning<"unknown visibility '%1'">; +def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">; def err_unknown_machine_mode : Error<"unknown machine mode %0">; def err_unsupported_machine_mode : Error<"unsupported machine mode %0">; def err_mode_not_primitive : Error< @@ -1139,6 +1170,9 @@ def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note< def note_ovl_candidate_instantiation_depth : Note< "candidate template ignored: substitution exceeded maximum template " "instantiation depth">; +def note_ovl_candidate_underqualified : Note< + "candidate template ignored: can't deduce a type for %0 which would " + "make %2 equal %1">; def note_ovl_candidate_substitution_failure : Note< "candidate template ignored: substitution failure %0">; @@ -1195,7 +1229,7 @@ def note_ovl_candidate_bad_cvr_this : Note<"candidate " "%select{|function|||function||||" "function (the implicit copy assignment operator)}0 not viable: " "'this' argument has type %2, but method is not marked " - "%select{const|volatile|const or volatile|restrict|const or restrict|" + "%select{const|restrict|const or restrict|volatile|const or volatile|" "volatile or restrict|const, volatile, or restrict}3">; def note_ovl_candidate_bad_cvr : Note<"candidate " "%select{function|function|constructor|" @@ -1204,7 +1238,7 @@ def note_ovl_candidate_bad_cvr : Note<"candidate " "constructor (the implicit copy constructor)|" "function (the implicit copy assignment operator)}0%1 not viable: " "%ordinal4 argument (%2) would lose " - "%select{const|volatile|const and volatile|restrict|const and restrict|" + "%select{const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}3 qualifier" "%select{||s||s|s|s}3">; def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate " @@ -1258,6 +1292,8 @@ def err_addr_ovl_ambiguous : Error< "address of overloaded function %0 is ambiguous">; def err_addr_ovl_not_func_ptrref : Error< "address of overloaded function %0 cannot be converted to type %1">; +def err_addr_ovl_no_qualifier : Error< + "can't form member pointer of type %0 without '&' and class name">; // C++ Template Declarations def err_template_param_shadow : Error< @@ -1335,9 +1371,10 @@ def err_template_arg_nontype_ambig : Error< "template argument for non-type template parameter is treated as type %0">; def err_template_arg_must_be_template : Error< "template argument for template template parameter must be a class template">; -def err_template_arg_local_type : Error<"template argument uses local type %0">; -def err_template_arg_unnamed_type : Error< - "template argument uses unnamed type">; +def ext_template_arg_local_type : ExtWarn< + "template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>; +def ext_template_arg_unnamed_type : ExtWarn< + "template argument uses unnamed type">, InGroup<UnnamedTypeTemplateArgs>; def note_template_unnamed_type_here : Note< "unnamed type used in template argument was declared here">; def err_template_arg_overload_type : Error< @@ -1683,9 +1720,8 @@ def note_dependent_var_use : Note<"must qualify identifier to find this " "declaration in dependent base class">; def err_undeclared_use : Error<"use of undeclared %0">; def warn_deprecated : Warning<"%0 is deprecated">, - InGroup<DiagGroup<"deprecated-declarations">>; -def warn_unavailable : Warning<"%0 is unavailable">, - InGroup<DiagGroup<"unavailable-declarations">>; + InGroup<DeprecatedDeclarations>; +def err_unavailable : Error<"%0 is unavailable">; def note_unavailable_here : Note< "function has been explicitly marked %select{unavailable|deleted}0 here">; def warn_not_enough_argument : Warning< @@ -1706,6 +1742,8 @@ def warn_redefinition_of_typedef : Warning< "redefinition of typedef %0 is invalid in C">, InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError; +def err_inline_declaration_block_scope : Error< + "inline declaration of %0 not allowed in block scope">; def err_static_non_static : Error< "static declaration of %0 follows non-static declaration">; def err_non_static_static : Error< @@ -1768,6 +1806,8 @@ def err_typecheck_field_variable_size : Error< "extension will never be supported">; def err_vm_func_decl : Error< "function declaration cannot have variably modified type">; +def err_array_too_large : Error< + "array is too large (%0 elements)">; def err_typecheck_negative_array_size : Error<"array size is negative">; def warn_typecheck_function_qualifiers : Warning< @@ -1809,7 +1849,7 @@ def warn_missing_field_initializers : Warning< InGroup<MissingFieldInitializers>, DefaultIgnore; def warn_braces_around_scalar_init : Warning< "braces around scalar initializer">; -def err_many_braces_around_scalar_init : Error< +def warn_many_braces_around_scalar_init : ExtWarn< "too many braces around scalar initializer">; def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">; def err_illegal_initializer : Error< @@ -1844,9 +1884,9 @@ def warn_missing_braces : Warning< def err_redefinition_of_label : Error<"redefinition of label '%0'">; def err_undeclared_label_use : Error<"use of undeclared label '%0'">; -def err_goto_into_protected_scope : Error<"illegal goto into protected scope">; +def err_goto_into_protected_scope : Error<"goto into protected scope">; def err_switch_into_protected_scope : Error< - "illegal switch case into protected scope">; + "switch case is in protected scope">; def err_indirect_goto_without_addrlabel : Error< "indirect goto in function with no address-of-label expressions">; def warn_indirect_goto_in_protected_scope : Warning< @@ -1990,7 +2030,7 @@ def note_precedence_bitwise_silence : Note< def warn_logical_instead_of_bitwise : Warning< "use of logical %0 with constant operand; switch to bitwise %1 or " - "remove constant">, InGroup<DiagGroup<"logical-bitwise-confusion">>; + "remove constant">, InGroup<DiagGroup<"constant-logical-operand">>; def err_sizeof_nonfragile_interface : Error< "invalid application of '%select{alignof|sizeof}1' to interface %0 in " @@ -2048,8 +2088,9 @@ def err_qualified_typedef_declarator : Error< "typedef declarator cannot be qualified">; def err_qualified_param_declarator : Error< "parameter declarator cannot be qualified">; -def err_out_of_line_declaration : Error< - "out-of-line declaration of a member must be a definition">; +def ext_out_of_line_declaration : ExtWarn< + "out-of-line declaration of a member must be a definition">, + InGroup<OutOfLineDeclaration>, DefaultError; def note_member_def_close_match : Note<"member declaration nearly matches">; def err_typecheck_ivar_variable_size : Error< "instance variables must have a constant size">; @@ -2093,7 +2134,11 @@ def err_typecheck_address_of : Error<"address of %0 requested">; def ext_typecheck_addrof_void : Extension< "ISO C forbids taking the address of an expression of type 'void'">; def err_unqualified_pointer_member_function : Error< - "must explicitly qualify member function %0 when taking its address">; + "must explicitly qualify name of member function when taking its address">; +def err_invalid_form_pointer_member_function : Error< + "cannot create a non-constant pointer to member function">; +def err_parens_pointer_member_function : Error< + "cannot parenthesize the name of a method when forming a member pointer">; def err_typecheck_invalid_lvalue_addrof : Error< "address expression must be an lvalue or a function designator">; def ext_typecheck_addrof_class_temporary : ExtWarn< @@ -2110,8 +2155,8 @@ def warn_indirection_through_null : Warning< def note_indirection_through_null : Note< "consider using __builtin_trap() or qualifying pointer with 'volatile'">; -def err_indirection_requires_nonfragile_object : Error< - "indirection cannot be to an interface in non-fragile ABI (%0 invalid)">; +def err_assignment_requires_nonfragile_object : Error< + "cannot assign to class object in non-fragile ABI (%0 invalid)">; def err_direct_interface_unsupported : Error< "indirection to an interface is not supported (%0 invalid)">; def err_typecheck_invalid_operands : Error< @@ -2183,10 +2228,10 @@ def err_builtin_direct_init_more_than_one_arg : Error< "initializer of a builtin type can only take one argument">; def err_value_init_for_array_type : Error< "array types cannot be value-initialized">; -def warn_printf_nonliteral_noargs : Warning< +def warn_format_nonliteral_noargs : Warning< "format string is not a string literal (potentially insecure)">, InGroup<FormatSecurity>; -def warn_printf_nonliteral : Warning< +def warn_format_nonliteral : Warning< "format string is not a string literal">, InGroup<FormatNonLiteral>, DefaultIgnore; @@ -2215,7 +2260,7 @@ def ext_integer_complement_complex : Extension< def error_nosetter_property_assignment : Error< "setter method is needed to assign to object using property" " assignment syntax">; def error_no_subobject_property_setting : Error< - "expression is not assignable using property assignment syntax">; + "expression is not assignable">; def ext_freestanding_complex : Extension< "complex numbers are an extension in a freestanding C99 implementation">; @@ -2263,7 +2308,13 @@ def warn_register_objc_catch_parm : Warning< "'register' storage specifier on @catch parameter will be ignored">; def err_qualified_objc_catch_parm : Error< "@catch parameter declarator cannot be qualified">; - +def err_objc_pointer_cxx_catch_gnu : Error< + "can't catch Objective C exceptions in C++ in the GNU runtime">; +def err_objc_pointer_cxx_catch_fragile : Error< + "can't catch Objective C exceptions in C++ in the non-unified " + "exception model">; +def err_objc_object_catch : Error< + "can't catch an Objective C object by value">; def warn_setter_getter_impl_required : Warning< "property %0 requires method %1 to be defined - " @@ -2313,6 +2364,9 @@ def err_bad_static_cast_pointer_nonpointer : Error< "cannot cast from type %1 to pointer type %2">; def err_bad_static_cast_member_pointer_nonmp : Error< "cannot cast from type %1 to member pointer type %2">; +def err_bad_cxx_cast_member_pointer_size : Error< + "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer " + "type %1 to member pointer type %2 of different size">; def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">; // These messages don't adhere to the pattern. @@ -2378,8 +2432,12 @@ def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete " "expression of type %0 to a pointer">; def warn_delete_incomplete : Warning< "deleting pointer to incomplete type %0 may cause undefined behaviour">; +def err_delete_incomplete_class_type : Warning< + "deleting incomplete class type %0; no conversions to pointer type">; def err_no_suitable_delete_member_function_found : Error< "no suitable member %0 in %1">; +def err_ambiguous_suitable_delete_member_function_found : Error< + "multiple suitable %0 functions in %1">; def note_member_declared_here : Note< "member %0 declared here">; def err_decrement_bool : Error<"cannot decrement expression of type bool">; @@ -2486,8 +2544,11 @@ def note_condition_assign_to_comparison : Note< def note_condition_assign_silence : Note< "place parentheses around the assignment to silence this warning">; -def warn_value_always_zero : Warning< - "%0 is always %select{zero|false|NULL}1 in this context">; +def warn_ivar_variable_conflict : Warning< + "when default property synthesis is on, " + "%0 lookup will access property ivar instead of global variable">, + InGroup<NonfragileAbi2>; +def note_global_declared_at : Note<"global variable declared here">; // assignment related diagnostics (also for argument passing, returning, etc). // In most of these diagnostics the %2 is a value from the @@ -2648,6 +2709,8 @@ def err_typecheck_cond_expect_scalar : Error< "used type %0 where arithmetic or pointer type is required">; def ext_typecheck_cond_one_void : Extension< "C99 forbids conditional expressions with only one void side">; +def err_typecheck_cast_to_incomplete : Error< + "cast to incomplete type %0">; def ext_typecheck_cast_nonscalar : Extension< "C99 forbids casting nonscalar type %0 to the same type">; def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">; @@ -2885,7 +2948,7 @@ def err_operator_new_default_arg: Error< def err_operator_delete_dependent_param_type : Error< "%0 cannot take a dependent type as first parameter; use %1 instead">; def err_operator_delete_param_type : Error< - "%0 takes type %1 as first parameter">; + "first parameter of %0 must have type %1">; // C++ literal operators def err_literal_operator_outside_namespace : Error< @@ -2932,33 +2995,36 @@ def warn_printf_insufficient_data_args : Warning< "more '%%' conversions than data arguments">, InGroup<Format>; def warn_printf_data_arg_not_used : Warning< "data argument not used by format string">, InGroup<FormatExtraArgs>; -def warn_printf_invalid_conversion : Warning< +def warn_format_invalid_conversion : Warning< "invalid conversion specifier '%0'">, InGroup<Format>; def warn_printf_incomplete_specifier : Warning< "incomplete format specifier">, InGroup<Format>; -def warn_printf_missing_format_string : Warning< +def warn_missing_format_string : Warning< "format string missing">, InGroup<Format>; +def warn_scanf_nonzero_width : Warning< + "zero field width in scanf format string is unused">, + InGroup<Format>; def warn_printf_conversion_argument_type_mismatch : Warning< "conversion specifies type %0 but the argument has type %1">, InGroup<Format>; def warn_printf_positional_arg_exceeds_data_args : Warning < "data argument position '%0' exceeds the number of data arguments (%1)">, InGroup<Format>; -def warn_printf_zero_positional_specifier : Warning< +def warn_format_zero_positional_specifier : Warning< "position arguments in format strings start counting at 1 (not 0)">, InGroup<Format>; -def warn_printf_invalid_positional_specifier : Warning< +def warn_format_invalid_positional_specifier : Warning< "invalid position specified for %select{field width|field precision}0">, InGroup<Format>; -def warn_printf_mix_positional_nonpositional_args : Warning< +def warn_format_mix_positional_nonpositional_args : Warning< "cannot mix positional and non-positional arguments in format string">, InGroup<Format>; def warn_null_arg : Warning< "null passed to a callee which requires a non-null argument">, InGroup<NonNull>; -def warn_printf_empty_format_string : Warning< +def warn_empty_format_string : Warning< "format string is empty">, InGroup<FormatZeroLength>; -def warn_printf_format_string_is_wide_literal : Warning< +def warn_format_string_is_wide_literal : Warning< "format string should not be a wide string">, InGroup<Format>; def warn_printf_format_string_contains_null_char : Warning< "format string contains '\\0' within the string body">, InGroup<Format>; @@ -2973,12 +3039,15 @@ def warn_printf_nonsensical_optional_amount: Warning< def warn_printf_nonsensical_flag: Warning< "flag '%0' results in undefined behavior with '%1' conversion specifier">, InGroup<Format>; -def warn_printf_nonsensical_length: Warning< +def warn_format_nonsensical_length: Warning< "length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">, InGroup<Format>; def warn_printf_ignored_flag: Warning< "flag '%0' is ignored when flag '%1' is present">, InGroup<Format>; +def warn_scanf_scanlist_incomplete : Warning< + "no closing ']' for '%%[' in scanf format string">, + InGroup<Format>; // CHECK: returning address/reference of stack memory def warn_ret_stack_addr : Warning< @@ -2995,7 +3064,8 @@ def err_ret_local_block : Error< // should result in a warning, since these always evaluate to a constant. // Array comparisons have similar warnings def warn_comparison_always : Warning< - "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">; + "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">, + InGroup<DiagGroup<"tautological-compare">>; def warn_stringcompare : Warning< "result of comparison against %select{a string literal|@encode}0 is " @@ -3127,6 +3197,8 @@ def err_selector_element_type : Error< "selector element type %0 is not a valid object">; def err_collection_expr_type : Error< "collection expression type %0 is not a valid object">; +def warn_collection_expr_type : Warning< + "collection expression type %0 may not respond to %1">; def err_invalid_conversion_between_ext_vectors : Error< "invalid conversion between ext-vector type %0 and %1">; diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 6b8bcdc52f6f..24fe086a79e9 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -59,7 +59,11 @@ class IdentifierInfo { bool IsPoisoned : 1; // True if identifier is poisoned. bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword. bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier". - // 9 bits left in 32-bit word. + bool IsFromAST : 1; // True if identfier first appeared in an AST + // file and wasn't modified since. + bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was + // called. + // 7 bits left in 32-bit word. void *FETokenInfo; // Managed by the language front-end. llvm::StringMapEntry<IdentifierInfo*> *Entry; @@ -125,13 +129,28 @@ public: NeedsHandleIdentifier = 1; else RecomputeNeedsHandleIdentifier(); + IsFromAST = false; } - /// get/setTokenID - If this is a source-language token (e.g. 'for'), this API + /// getTokenID - If this is a source-language token (e.g. 'for'), this API /// can be used to cause the lexer to map identifiers to source-language /// tokens. tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; } - void setTokenID(tok::TokenKind ID) { TokenID = ID; } + + /// \brief True if RevertTokenIDToIdentifier() was called. + bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; } + + /// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2 + /// compatibility. + /// + /// TokenID is normally read-only but there are 2 instances where we revert it + /// to tok::identifier for libstdc++ 4.2. Keep track of when this happens + /// using this method so we can inform serialization about it. + void RevertTokenIDToIdentifier() { + assert(TokenID != tok::identifier && "Already at tok::identifier"); + TokenID = tok::identifier; + RevertedTokenID = true; + } /// getPPKeywordID - Return the preprocessor keyword ID for this identifier. /// For example, "define" will return tok::pp_define. @@ -186,6 +205,7 @@ public: NeedsHandleIdentifier = 1; else RecomputeNeedsHandleIdentifier(); + IsFromAST = false; } /// isPoisoned - Return true if this token has been poisoned. @@ -213,6 +233,12 @@ public: /// know that HandleIdentifier will not affect the token. bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; } + /// isFromAST - Return true if the identifier in its current state was loaded + /// from an AST file. + bool isFromAST() const { return IsFromAST; } + + void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; } + private: /// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does /// several special (but rare) things to identifiers of various sorts. For @@ -313,6 +339,12 @@ public: return *II; } + IdentifierInfo &get(llvm::StringRef Name, tok::TokenKind TokenCode) { + IdentifierInfo &II = get(Name); + II.TokenID = TokenCode; + return II; + } + IdentifierInfo &get(const char *NameStart, const char *NameEnd) { return get(llvm::StringRef(NameStart, NameEnd-NameStart)); } @@ -321,35 +353,33 @@ public: return get(llvm::StringRef(Name, NameLen)); } - /// \brief Creates a new IdentifierInfo from the given string. + /// \brief Gets an IdentifierInfo for the given name without consulting + /// external sources. /// - /// This is a lower-level version of get() that requires that this - /// identifier not be known previously and that does not consult an - /// external source for identifiers. In particular, external - /// identifier sources can use this routine to build IdentifierInfo - /// nodes and then introduce additional information about those - /// identifiers. - IdentifierInfo &CreateIdentifierInfo(const char *NameStart, - const char *NameEnd) { + /// This is a version of get() meant for external sources that want to + /// introduce or modify an identifier. If they called get(), they would + /// likely end up in a recursion. + IdentifierInfo &getOwn(const char *NameStart, const char *NameEnd) { llvm::StringMapEntry<IdentifierInfo*> &Entry = HashTable.GetOrCreateValue(NameStart, NameEnd); IdentifierInfo *II = Entry.getValue(); - assert(!II && "IdentifierInfo already exists"); + if (!II) { - // Lookups failed, make a new IdentifierInfo. - void *Mem = getAllocator().Allocate<IdentifierInfo>(); - II = new (Mem) IdentifierInfo(); - Entry.setValue(II); + // Lookups failed, make a new IdentifierInfo. + void *Mem = getAllocator().Allocate<IdentifierInfo>(); + II = new (Mem) IdentifierInfo(); + Entry.setValue(II); - // Make sure getName() knows how to find the IdentifierInfo - // contents. - II->Entry = &Entry; + // Make sure getName() knows how to find the IdentifierInfo + // contents. + II->Entry = &Entry; + } return *II; } - IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) { - return CreateIdentifierInfo(Name.begin(), Name.end()); + IdentifierInfo &getOwn(llvm::StringRef Name) { + return getOwn(Name.begin(), Name.end()); } typedef HashTableTy::const_iterator iterator; diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index bbcceb70ac91..5bd0d04a4eea 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -34,6 +34,7 @@ public: unsigned HexFloats : 1; // C99 Hexadecimal float constants. unsigned C99 : 1; // C99 Support unsigned Microsoft : 1; // Microsoft extensions. + unsigned Borland : 1; // Borland extensions. unsigned CPlusPlus : 1; // C++ Support unsigned CPlusPlus0x : 1; // C++0x Support unsigned CXXOperatorNames : 1; // Treat C++ operator names as keywords. @@ -140,7 +141,7 @@ public: HexFloats = 0; GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0; NoConstantCFStrings = 0; InlineVisibilityHidden = 0; - C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; + C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0; NeXTRuntime = 1; diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h index de0de348d351..01b6c790428a 100644 --- a/include/clang/Basic/Linkage.h +++ b/include/clang/Basic/Linkage.h @@ -41,6 +41,17 @@ enum Linkage { ExternalLinkage }; +/// \brief A more specific kind of linkage. This is relevant to CodeGen and +/// AST file reading. +enum GVALinkage { + GVA_Internal, + GVA_C99Inline, + GVA_CXXInline, + GVA_StrongExternal, + GVA_TemplateInstantiation, + GVA_ExplicitTemplateInstantiation +}; + /// \brief Determine whether the given linkage is semantically /// external. inline bool isExternalLinkage(Linkage L) { diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile index 7db3e2982af4..bc64f6aab555 100644 --- a/include/clang/Basic/Makefile +++ b/include/clang/Basic/Makefile @@ -16,6 +16,7 @@ INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td) # Compute the Clang version from the LLVM version, unless specified explicitly. ifndef CLANG_VERSION CLANG_VERSION := $(subst svn,,$(LLVMVersion)) +CLANG_VERSION := $(subst rc,,$(CLANG_VERSION)) endif CLANG_VERSION_COMPONENTS := $(subst ., ,$(CLANG_VERSION)) diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index 2019e27ce5de..8909e47146a7 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -124,8 +124,9 @@ class OnDiskChainedHashTableGenerator { Item *next; const uint32_t hash; - Item(typename Info::key_type_ref k, typename Info::data_type_ref d) - : key(k), data(d), next(0), hash(Info::ComputeHash(k)) {} + Item(typename Info::key_type_ref k, typename Info::data_type_ref d, + Info &InfoObj) + : key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {} }; class Bucket { @@ -168,10 +169,17 @@ public: void insert(typename Info::key_type_ref key, typename Info::data_type_ref data) { + Info InfoObj; + insert(key, data, InfoObj); + } + + void insert(typename Info::key_type_ref key, + typename Info::data_type_ref data, Info &InfoObj) { ++NumEntries; if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2); - insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data)); + insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data, + InfoObj)); } io::Offset Emit(llvm::raw_ostream &out) { @@ -278,8 +286,8 @@ public: InfoPtr = &InfoObj; using namespace io; - const internal_key_type& iKey = Info::GetInternalKey(eKey); - unsigned key_hash = Info::ComputeHash(iKey); + const internal_key_type& iKey = InfoObj.GetInternalKey(eKey); + unsigned key_hash = InfoObj.ComputeHash(iKey); // Each bucket is just a 32-bit offset into the hash table file. unsigned idx = key_hash & (NumBuckets - 1); @@ -326,6 +334,71 @@ public: iterator end() const { return iterator(); } + /// \brief Iterates over all the entries in the table, returning + /// a key/data pair. + class item_iterator { + const unsigned char* Ptr; + unsigned NumItemsInBucketLeft; + unsigned NumEntriesLeft; + Info *InfoObj; + public: + typedef std::pair<external_key_type, data_type> value_type; + + item_iterator(const unsigned char* const Ptr, unsigned NumEntries, + Info *InfoObj) + : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries), + InfoObj(InfoObj) { } + item_iterator() + : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { } + + bool operator==(const item_iterator& X) const { + return X.NumEntriesLeft == NumEntriesLeft; + } + bool operator!=(const item_iterator& X) const { + return X.NumEntriesLeft != NumEntriesLeft; + } + + item_iterator& operator++() { // Preincrement + if (!NumItemsInBucketLeft) { + // 'Items' starts with a 16-bit unsigned integer representing the + // number of items in this bucket. + NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr); + } + Ptr += 4; // Skip the hash. + // Determine the length of the key and the data. + const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr); + Ptr += L.first + L.second; + assert(NumItemsInBucketLeft); + --NumItemsInBucketLeft; + assert(NumEntriesLeft); + --NumEntriesLeft; + return *this; + } + item_iterator operator++(int) { // Postincrement + item_iterator tmp = *this; ++*this; return tmp; + } + + value_type operator*() const { + const unsigned char* LocalPtr = Ptr; + if (!NumItemsInBucketLeft) + LocalPtr += 2; // number of items in bucket + LocalPtr += 4; // Skip the hash. + + // Determine the length of the key and the data. + const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(LocalPtr); + + // Read the key. + const internal_key_type& Key = + InfoObj->ReadKey(LocalPtr, L.first); + return std::make_pair(InfoObj->GetExternalKey(Key), + InfoObj->ReadData(Key, LocalPtr + L.first, L.second)); + } + }; + + item_iterator item_begin() { + return item_iterator(Base + 4, getNumEntries(), &InfoObj); + } + item_iterator item_end() { return item_iterator(); } static OnDiskChainedHashTable* Create(const unsigned char* buckets, const unsigned char* const base, diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 6a4be4609433..7a66117f2076 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -50,13 +50,20 @@ namespace SrcMgr { C_User, C_System, C_ExternCSystem }; - /// ContentCache - Once instance of this struct is kept for every file + /// ContentCache - One instance of this struct is kept for every file /// loaded or used. This object owns the MemoryBuffer object. class ContentCache { + enum CCFlags { + /// \brief Whether the buffer is invalid. + InvalidFlag = 0x01, + /// \brief Whether the buffer should not be freed on destruction. + DoNotFreeFlag = 0x02 + }; + /// Buffer - The actual buffer containing the characters from the input /// file. This is owned by the ContentCache object. - /// The bit indicates whether the buffer is invalid. - mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 1, bool> Buffer; + /// The bits indicate indicates whether the buffer is invalid. + mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer; public: /// Reference to the file entry. This reference does not own @@ -103,11 +110,27 @@ namespace SrcMgr { Buffer.setPointer(B); Buffer.setInt(false); } + + /// \brief Get the underlying buffer, returning NULL if the buffer is not + /// yet available. + const llvm::MemoryBuffer *getRawBuffer() const { + return Buffer.getPointer(); + } /// \brief Replace the existing buffer (which will be deleted) /// with the given buffer. - void replaceBuffer(const llvm::MemoryBuffer *B); + void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false); + /// \brief Determine whether the buffer itself is invalid. + bool isBufferInvalid() const { + return Buffer.getInt() & InvalidFlag; + } + + /// \brief Determine whether the buffer should be freed. + bool shouldFreeBuffer() const { + return (Buffer.getInt() & DoNotFreeFlag) == 0; + } + ContentCache(const FileEntry *Ent = 0) : Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {} @@ -421,10 +444,9 @@ public: FileID getMainFileID() const { return MainFileID; } /// createMainFileID - Create the FileID for the main source file. - FileID createMainFileID(const FileEntry *SourceFile, - SourceLocation IncludePos) { + FileID createMainFileID(const FileEntry *SourceFile) { assert(MainFileID.isInvalid() && "MainFileID already set!"); - MainFileID = createFileID(SourceFile, IncludePos, SrcMgr::C_User); + MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User); return MainFileID; } @@ -435,7 +457,7 @@ public: /// createFileID - Create a new FileID that represents the specified file /// being #included from the specified IncludePosition. This returns 0 on /// error and translates NULL into standard input. - /// PreallocateID should be non-zero to specify which a pre-allocated, + /// PreallocateID should be non-zero to specify which pre-allocated, /// lazily computed source location is being filled in by this operation. FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, @@ -485,14 +507,18 @@ public: /// \brief Override the contents of the given source file by providing an /// already-allocated buffer. /// - /// \param SourceFile the source file whose contents will be override. + /// \param SourceFile the source file whose contents will be overriden. /// /// \param Buffer the memory buffer whose contents will be used as the /// data in the given source file. /// + /// \param DoNotFree If true, then the buffer will not be freed when the + /// source manager is destroyed. + /// /// \returns true if an error occurred, false otherwise. bool overrideFileContents(const FileEntry *SourceFile, - const llvm::MemoryBuffer *Buffer); + const llvm::MemoryBuffer *Buffer, + bool DoNotFree = false); //===--------------------------------------------------------------------===// // FileID manipulation methods. @@ -768,7 +794,7 @@ public: unsigned sloc_entry_size() const { return SLocEntryTable.size(); } // FIXME: Exposing this is a little gross; what we want is a good way - // to iterate the entries that were not defined in a PCH file (or + // to iterate the entries that were not defined in an AST file (or // any other external source). unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); } diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 9e54762add7d..e757a2f4a185 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -78,6 +78,68 @@ namespace clang { AS_none }; + /// ExprValueKind - The categorization of expression values, + /// currently following the C++0x scheme. + enum ExprValueKind { + /// An r-value expression (a gr-value in the C++0x taxonomy) + /// produces a temporary value. + VK_RValue, + + /// An l-value expression is a reference to an object with + /// independent storage. + VK_LValue, + + /// An x-value expression is a reference to an object with + /// independent storage but which can be "moved", i.e. + /// efficiently cannibalized for its resources. + VK_XValue + }; + + // \brief Describes the kind of template specialization that a + // particular template specialization declaration represents. + enum TemplateSpecializationKind { + /// This template specialization was formed from a template-id but + /// has not yet been declared, defined, or instantiated. + TSK_Undeclared = 0, + /// This template specialization was implicitly instantiated from a + /// template. (C++ [temp.inst]). + TSK_ImplicitInstantiation, + /// This template specialization was declared or defined by an + /// explicit specialization (C++ [temp.expl.spec]) or partial + /// specialization (C++ [temp.class.spec]). + TSK_ExplicitSpecialization, + /// This template specialization was instantiated from a template + /// due to an explicit instantiation declaration request + /// (C++0x [temp.explicit]). + TSK_ExplicitInstantiationDeclaration, + /// This template specialization was instantiated from a template + /// due to an explicit instantiation definition request + /// (C++ [temp.explicit]). + TSK_ExplicitInstantiationDefinition + }; + + /// \brief Storage classes. + enum StorageClass { + // These are legal on both functions and variables. + SC_None, + SC_Extern, + SC_Static, + SC_PrivateExtern, + + // These are only legal on variables. + SC_Auto, + SC_Register + }; + + /// Checks whether the given storage class is legal for functions. + inline bool isLegalForFunction(StorageClass SC) { + return SC <= SC_PrivateExtern; + } + + /// Checks whether the given storage class is legal for variables. + inline bool isLegalForVariable(StorageClass SC) { + return true; + } } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index a2f69730a010..4aa055e695e9 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -103,7 +103,6 @@ def UnaryTypeTraitExpr : DStmt<Expr>; def DependentScopeDeclRefExpr : DStmt<Expr>; def CXXConstructExpr : DStmt<Expr>; def CXXBindTemporaryExpr : DStmt<Expr>; -def CXXBindReferenceExpr : DStmt<Expr>; def CXXExprWithTemporaries : DStmt<Expr>; def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>; def CXXUnresolvedConstructExpr : DStmt<Expr>; diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 9f7debf9c500..40df9ba11da4 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -16,6 +16,7 @@ // FIXME: Daniel isn't smart enough to use a prototype for this. #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/System/DataTypes.h" #include <cassert> @@ -37,6 +38,22 @@ class TargetOptions; namespace Builtin { struct Info; } +/// TargetCXXABI - The types of C++ ABIs for which we can generate code. +enum TargetCXXABI { + /// The generic ("Itanium") C++ ABI, documented at: + /// http://www.codesourcery.com/public/cxx-abi/ + CXXABI_Itanium, + + /// The ARM C++ ABI, based largely on the Itanium ABI but with + /// significant differences. + /// http://infocenter.arm.com + /// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf + CXXABI_ARM, + + /// The Visual Studio ABI. Only scattered official documentation exists. + CXXABI_Microsoft +}; + /// TargetInfo - This class exposes information about the current target. /// class TargetInfo { @@ -58,7 +75,7 @@ protected: const char *UserLabelPrefix; const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat; unsigned char RegParmMax, SSERegParmMax; - std::string CXXABI; + TargetCXXABI CXXABI; unsigned HasAlignMac68kSupport : 1; unsigned RealTypeUsesObjCFPRet : 3; @@ -412,7 +429,7 @@ public: } /// getCXXABI - Get the C++ ABI in use. - virtual llvm::StringRef getCXXABI() const { + virtual TargetCXXABI getCXXABI() const { return CXXABI; } @@ -434,11 +451,23 @@ public: /// setCXXABI - Use this specific C++ ABI. /// - /// \return - False on error (invalid ABI name). - virtual bool setCXXABI(const std::string &Name) { - if (Name != "itanium" && Name != "microsoft") - return false; - CXXABI = Name; + /// \return - False on error (invalid C++ ABI name). + bool setCXXABI(const std::string &Name) { + static const TargetCXXABI Unknown = static_cast<TargetCXXABI>(-1); + TargetCXXABI ABI = llvm::StringSwitch<TargetCXXABI>(Name) + .Case("arm", CXXABI_ARM) + .Case("itanium", CXXABI_Itanium) + .Case("microsoft", CXXABI_Microsoft) + .Default(Unknown); + if (ABI == Unknown) return false; + return setCXXABI(ABI); + } + + /// setCXXABI - Set the C++ ABI to be used by this implementation. + /// + /// \return - False on error (ABI not valid on this target) + virtual bool setCXXABI(TargetCXXABI ABI) { + CXXABI = ABI; return true; } diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index 19b0cbbf5820..f3c206f2cc96 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -18,11 +18,6 @@ namespace clang { /// TargetOptions - Options for controlling the target. class TargetOptions { public: - - TargetOptions() { - CXXABI = "itanium"; - } - /// If given, the name of the target triple to compile for. If not given the /// target will be selected to match the host. std::string Triple; @@ -37,6 +32,9 @@ public: /// to "itanium". std::string CXXABI; + /// If given, the version string of the linker in use. + std::string LinkerVersion; + /// The list of target specific features to enable or disable -- this should /// be a list of strings starting with by '+' or '-'. std::vector<std::string> Features; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index b16b82854b1c..dc360adf8f19 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -96,6 +96,7 @@ TOK(unknown) // Not a token. TOK(eof) // End of file. TOK(eom) // End of macro (end of line inside a macro). TOK(code_completion) // Code completion marker +TOK(cxx_defaultarg_end) // C++ default argument end marker // C99 6.4.9: Comments. TOK(comment) // Comment (only in -E -C[C] mode) @@ -185,6 +186,7 @@ PUNCTUATOR(at, "@") // KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x // KEYGNU - This is a keyword if GNU extensions are enabled // KEYMS - This is a keyword if Microsoft extensions are enabled +// KEYBORLAND - This is a keyword if Borland extensions are enabled // KEYWORD(auto , KEYALL) KEYWORD(break , KEYALL) @@ -272,16 +274,11 @@ CXX_KEYWORD_OPERATOR(xor_eq , caretequal) // C++0x keywords KEYWORD(alignof , KEYCXX0X) -KEYWORD(axiom , KEYCXX0X) KEYWORD(char16_t , KEYCXX0X) KEYWORD(char32_t , KEYCXX0X) -KEYWORD(concept , KEYCXX0X) -KEYWORD(concept_map , KEYCXX0X) KEYWORD(constexpr , KEYCXX0X) KEYWORD(decltype , KEYCXX0X) -KEYWORD(late_check , KEYCXX0X) KEYWORD(nullptr , KEYCXX0X) -KEYWORD(requires , KEYCXX0X) KEYWORD(static_assert , KEYCXX0X) KEYWORD(thread_local , KEYCXX0X) @@ -339,6 +336,9 @@ KEYWORD(__fastcall , KEYALL) KEYWORD(__thiscall , KEYALL) KEYWORD(__forceinline , KEYALL) +// Borland Extension. +KEYWORD(__pascal , KEYALL) + // Altivec Extension. KEYWORD(__vector , KEYALTIVEC) KEYWORD(__pixel , KEYALTIVEC) @@ -375,6 +375,9 @@ ALIAS("_fastcall" , __fastcall , KEYMS) ALIAS("_stdcall" , __stdcall , KEYMS) ALIAS("_thiscall" , __thiscall , KEYMS) +// Borland Extensions which should be disabled in strict conformance mode. +ALIAS("_pascal" , __pascal , KEYBORLAND) + //===----------------------------------------------------------------------===// // Objective-C @-preceeded keywords. //===----------------------------------------------------------------------===// diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index b42755ca72ae..fa6ebb756ca3 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -64,6 +64,7 @@ class WInst<string p, string t> : Inst<p, t, OP_NONE> {} // u: unsigned integer (int/float args) // f: float (int args) // d: default +// g: default, ignore 'Q' size modifier. // w: double width elements, same num elts // n: double width elements, half num elts // h: half width elements, double num elts @@ -239,6 +240,7 @@ def VCREATE: Inst<"dl", "csihfUcUsUiUlPcPsl", OP_CAST>; // E.3.19 Set all lanes to same value def VDUP_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; def VMOV_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; +def VDUP_LANE : WInst<"dgi", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">; //////////////////////////////////////////////////////////////////////////////// // E.3.20 Combining vectors diff --git a/include/clang/CMakeLists.txt b/include/clang/CMakeLists.txt index c2880481a2e9..e82cf429eecc 100644 --- a/include/clang/CMakeLists.txt +++ b/include/clang/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(AST) add_subdirectory(Basic) add_subdirectory(Driver) +add_subdirectory(Serialization) diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h index 3749b43d7e23..370d96552c45 100644 --- a/include/clang/Checker/BugReporter/BugReporter.h +++ b/include/clang/Checker/BugReporter/BugReporter.h @@ -471,6 +471,9 @@ void registerFindLastStore(BugReporterContext& BRC, const void *memregion, void registerNilReceiverVisitor(BugReporterContext &BRC); +void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt, + const ExplodedNode *N); + } // end namespace clang::bugreporter //===----------------------------------------------------------------------===// diff --git a/include/clang/Checker/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h index 3c7cb68c0943..38550798b812 100644 --- a/include/clang/Checker/PathSensitive/AnalysisManager.h +++ b/include/clang/Checker/PathSensitive/AnalysisManager.h @@ -21,6 +21,11 @@ namespace clang { +namespace idx { + class Indexer; + class TranslationUnit; +} + class AnalysisManager : public BugReporterData { AnalysisContextManager AnaCtxMgr; LocationContextManager LocCtxMgr; @@ -35,6 +40,11 @@ class AnalysisManager : public BugReporterData { StoreManagerCreator CreateStoreMgr; ConstraintManagerCreator CreateConstraintMgr; + /// \brief Provide function definitions in other translation units. This is + /// NULL if we don't have multiple translation units. AnalysisManager does + /// not own the Indexer. + idx::Indexer *Idxer; + enum AnalysisScope { ScopeTU, ScopeDecl } AScope; // The maximum number of exploded nodes the analyzer will generate. @@ -62,13 +72,15 @@ public: AnalysisManager(ASTContext &ctx, Diagnostic &diags, const LangOptions &lang, PathDiagnosticClient *pd, StoreManagerCreator storemgr, - ConstraintManagerCreator constraintmgr, unsigned maxnodes, - unsigned maxloop, + ConstraintManagerCreator constraintmgr, + idx::Indexer *idxer, + unsigned maxnodes, unsigned maxloop, bool vizdot, bool vizubi, bool purge, bool eager, bool trim, - bool inlinecall) + bool inlinecall, bool useUnoptimizedCFG) - : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), - CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), + : AnaCtxMgr(useUnoptimizedCFG), Ctx(ctx), Diags(diags), LangInfo(lang), + PD(pd), + CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),Idxer(idxer), AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop), VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {} @@ -79,6 +91,10 @@ public: LocCtxMgr.clear(); AnaCtxMgr.clear(); } + + AnalysisContextManager& getAnalysisContextManager() { + return AnaCtxMgr; + } StoreManagerCreator getStoreManagerCreator() { return CreateStoreMgr; @@ -88,6 +104,8 @@ public: return CreateConstraintMgr; } + idx::Indexer *getIndexer() const { return Idxer; } + virtual ASTContext &getASTContext() { return Ctx; } @@ -133,6 +151,10 @@ public: bool shouldInlineCall() const { return InlineCall; } + bool hasIndexer() const { return Idxer != 0; } + + const AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D); + CFG *getCFG(Decl const *D) { return AnaCtxMgr.getContext(D)->getCFG(); } @@ -145,9 +167,25 @@ public: return AnaCtxMgr.getContext(D)->getParentMap(); } + AnalysisContext *getAnalysisContext(const Decl *D) { + return AnaCtxMgr.getContext(D); + } + + AnalysisContext *getAnalysisContext(const Decl *D, idx::TranslationUnit *TU) { + return AnaCtxMgr.getContext(D, TU); + } + + const StackFrameContext *getStackFrame(AnalysisContext *Ctx, + LocationContext const *Parent, + Stmt const *S, const CFGBlock *Blk, + unsigned Idx) { + return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx); + } + // Get the top level stack frame. - const StackFrameContext *getStackFrame(Decl const *D) { - return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0); + const StackFrameContext *getStackFrame(Decl const *D, + idx::TranslationUnit *TU) { + return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0); } // Get a stack frame with parent. diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h index 49dc3fa7dc44..136a29da5f2a 100644 --- a/include/clang/Checker/PathSensitive/Checker.h +++ b/include/clang/Checker/PathSensitive/Checker.h @@ -36,7 +36,6 @@ class CheckerContext { const GRState *ST; const Stmt *statement; const unsigned size; - bool DoneEvaluating; // FIXME: This is not a permanent API change. public: bool *respondsToCallback; public: @@ -166,6 +165,10 @@ public: Eng.getBugReporter().EmitReport(R); } + AnalysisContext *getCurrentAnalysisContext() const { + return Pred->getLocationContext()->getAnalysisContext(); + } + private: ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state, bool markAsSink) { @@ -223,7 +226,6 @@ private: // FIXME: Remove the 'tag' option. void GR_VisitBind(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, GRExprEngine &Eng, - const Stmt *AssignE, const Stmt *StoreE, ExplodedNode *Pred, void *tag, SVal location, SVal val, bool isPrevisit) { @@ -231,7 +233,7 @@ private: isPrevisit ? ProgramPoint::PreStmtKind : ProgramPoint::PostStmtKind, 0, StoreE); assert(isPrevisit && "Only previsit supported for now."); - PreVisitBind(C, AssignE, StoreE, location, val); + PreVisitBind(C, StoreE, location, val); } // FIXME: Remove the 'tag' option. @@ -261,15 +263,17 @@ public: virtual void _PreVisit(CheckerContext &C, const Stmt *S) {} virtual void _PostVisit(CheckerContext &C, const Stmt *S) {} virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {} - virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE, - const Stmt *StoreE, SVal location, SVal val) {} + virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE, + SVal location, SVal val) {} virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {} virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng) {} + virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {} + virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder, GRExprEngine &Eng, - Stmt *Condition, void *tag) {} + const Stmt *Condition, void *tag) {} virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) { return false; @@ -280,12 +284,23 @@ public: } virtual const GRState *EvalAssume(const GRState *state, SVal Cond, - bool Assumption) { + bool Assumption, bool *respondsToCallback) { + *respondsToCallback = false; + return state; + } + + virtual bool WantsRegionChangeUpdate(const GRState *state) { return false; } + + virtual const GRState *EvalRegionChanges(const GRState *state, + const MemRegion * const *Begin, + const MemRegion * const *End, + bool *respondsToCallback) { + *respondsToCallback = false; return state; } virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, - bool hasWorkRemaining) {} + GRExprEngine &Eng) {} }; } // end clang namespace diff --git a/include/clang/Checker/PathSensitive/CheckerHelpers.h b/include/clang/Checker/PathSensitive/CheckerHelpers.h new file mode 100644 index 000000000000..ea3c842ffc1f --- /dev/null +++ b/include/clang/Checker/PathSensitive/CheckerHelpers.h @@ -0,0 +1,40 @@ +//== CheckerHelpers.h - Helper functions for checkers ------------*- C++ -*--=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines CheckerVisitor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS +#define LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS + +#include "clang/AST/Stmt.h" + +namespace clang { + +bool containsMacro(const Stmt *S); +bool containsEnum(const Stmt *S); +bool containsStaticLocal(const Stmt *S); +bool containsBuiltinOffsetOf(const Stmt *S); +template <class T> bool containsStmt(const Stmt *S) { + if (isa<T>(S)) + return true; + + for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end(); + ++I) + if (const Stmt *child = *I) + if (containsStmt<T>(child)) + return true; + + return false; +} + +} + +#endif diff --git a/include/clang/Checker/PathSensitive/ConstraintManager.h b/include/clang/Checker/PathSensitive/ConstraintManager.h index ce7d1b381714..97535f55bfb9 100644 --- a/include/clang/Checker/PathSensitive/ConstraintManager.h +++ b/include/clang/Checker/PathSensitive/ConstraintManager.h @@ -34,9 +34,6 @@ public: virtual const GRState *Assume(const GRState *state, DefinedSVal Cond, bool Assumption) = 0; - virtual const GRState *AssumeInBound(const GRState *state, DefinedSVal Idx, - DefinedSVal UpperBound, bool Assumption) = 0; - std::pair<const GRState*, const GRState*> AssumeDual(const GRState *state, DefinedSVal Cond) { return std::make_pair(Assume(state, Cond, true), diff --git a/include/clang/Checker/PathSensitive/Environment.h b/include/clang/Checker/PathSensitive/Environment.h index 2981731f863c..611f5079452a 100644 --- a/include/clang/Checker/PathSensitive/Environment.h +++ b/include/clang/Checker/PathSensitive/Environment.h @@ -83,8 +83,14 @@ public: return Environment(F.GetEmptyMap()); } - Environment BindExpr(Environment Env, const Stmt *S, SVal V, + /// Bind the value 'V' to the statement 'S'. + Environment bindExpr(Environment Env, const Stmt *S, SVal V, bool Invalidate); + + /// Bind the location 'location' and value 'V' to the statement 'S'. This + /// is used when simulating loads/stores. + Environment bindExprAndLocation(Environment Env, const Stmt *S, SVal location, + SVal V); Environment RemoveDeadBindings(Environment Env, SymbolReaper &SymReaper, const GRState *ST, diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index 7f101dca97e5..216ecac73653 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -43,6 +43,11 @@ class GRCoreEngine { friend class GRCallEnterNodeBuilder; friend class GRCallExitNodeBuilder; +public: + typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> > + BlocksAborted; +private: + GRSubEngine& SubEngine; /// G - The simulation graph. Each node is a (location,state) pair. @@ -57,21 +62,21 @@ class GRCoreEngine { /// These are used to record for key nodes in the ExplodedGraph the /// number of times different CFGBlocks have been visited along a path. GRBlockCounter::Factory BCounterFactory; - - /// A flag that indicates whether paths were halted because - /// ProcessBlockEntrace returned false. - bool BlockAborted; + + /// The locations where we stopped doing work because we visited a location + /// too many times. + BlocksAborted blocksAborted; void GenerateNode(const ProgramPoint& Loc, const GRState* State, ExplodedNode* Pred); void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred); void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred); - void HandleBlockExit(CFGBlock* B, ExplodedNode* Pred); - void HandlePostStmt(const PostStmt& S, CFGBlock* B, + void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred); + void HandlePostStmt(const PostStmt& S, const CFGBlock* B, unsigned StmtIdx, ExplodedNode *Pred); - void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B, + void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B, ExplodedNode* Pred); void HandleCallEnter(const CallEnter &L, const CFGBlock *Block, unsigned Index, ExplodedNode *Pred); @@ -82,25 +87,42 @@ class GRCoreEngine { return SubEngine.getInitialState(InitLoc); } - void ProcessEndPath(GREndPathNodeBuilder& Builder); + void ProcessEndPath(GREndPathNodeBuilder& Builder) { + SubEngine.ProcessEndPath(Builder); + } - void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder); + void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& Builder) { + SubEngine.ProcessStmt(E, Builder); + } - bool ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred, - GRBlockCounter BC); + bool ProcessBlockEntrance(const CFGBlock* Blk, const ExplodedNode *Pred, + GRBlockCounter BC) { + return SubEngine.ProcessBlockEntrance(Blk, Pred, BC); + } - void ProcessBranch(Stmt* Condition, Stmt* Terminator, - GRBranchNodeBuilder& Builder); + void ProcessBranch(const Stmt* Condition, const Stmt* Terminator, + GRBranchNodeBuilder& Builder) { + SubEngine.ProcessBranch(Condition, Terminator, Builder); + } - void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder); + void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) { + SubEngine.ProcessIndirectGoto(Builder); + } - void ProcessSwitch(GRSwitchNodeBuilder& Builder); + void ProcessSwitch(GRSwitchNodeBuilder& Builder) { + SubEngine.ProcessSwitch(Builder); + } - void ProcessCallEnter(GRCallEnterNodeBuilder &Builder); - void ProcessCallExit(GRCallExitNodeBuilder &Builder); + void ProcessCallEnter(GRCallEnterNodeBuilder &Builder) { + SubEngine.ProcessCallEnter(Builder); + } + + void ProcessCallExit(GRCallExitNodeBuilder &Builder) { + SubEngine.ProcessCallExit(Builder); + } private: GRCoreEngine(const GRCoreEngine&); // Do not implement. @@ -112,16 +134,14 @@ public: GRCoreEngine(GRSubEngine& subengine) : SubEngine(subengine), G(new ExplodedGraph()), WList(GRWorkList::MakeBFS()), - BCounterFactory(G->getAllocator()), - BlockAborted(false) {} + BCounterFactory(G->getAllocator()) {} /// Construct a GRCoreEngine object to analyze the provided CFG and to /// use the provided worklist object to execute the worklist algorithm. /// The GRCoreEngine object assumes ownership of 'wlist'. GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine) : SubEngine(subengine), G(new ExplodedGraph()), WList(wlist), - BCounterFactory(G->getAllocator()), - BlockAborted(false) {} + BCounterFactory(G->getAllocator()) {} ~GRCoreEngine() { delete WList; @@ -136,12 +156,29 @@ public: /// ExecuteWorkList - Run the worklist algorithm for a maximum number of /// steps. Returns true if there is still simulation state on the worklist. - bool ExecuteWorkList(const LocationContext *L, unsigned Steps); + bool ExecuteWorkList(const LocationContext *L, unsigned Steps, + const GRState *InitState); + void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, + const GRState *InitState, + ExplodedNodeSet &Dst); + + // Functions for external checking of whether we have unfinished work + bool wasBlockAborted() const { return !blocksAborted.empty(); } + bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); } + + GRWorkList *getWorkList() const { return WList; } + + BlocksAborted::const_iterator blocks_aborted_begin() const { + return blocksAborted.begin(); + } + BlocksAborted::const_iterator blocks_aborted_end() const { + return blocksAborted.end(); + } }; class GRStmtNodeBuilder { GRCoreEngine& Eng; - CFGBlock& B; + const CFGBlock& B; const unsigned Idx; ExplodedNode* Pred; GRStateManager& Mgr; @@ -163,7 +200,7 @@ public: void GenerateAutoTransition(ExplodedNode* N); public: - GRStmtNodeBuilder(CFGBlock* b, unsigned idx, ExplodedNode* N, + GRStmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N, GRCoreEngine* e, GRStateManager &mgr); ~GRStmtNodeBuilder(); @@ -222,11 +259,11 @@ public: /// getStmt - Return the current block-level expression associated with /// this builder. - Stmt* getStmt() const { return B[Idx]; } + const Stmt* getStmt() const { return B[Idx]; } /// getBlock - Return the CFGBlock associated with the block-level expression /// of this builder. - CFGBlock* getBlock() const { return &B; } + const CFGBlock* getBlock() const { return &B; } unsigned getIndex() const { return Idx; } @@ -239,15 +276,15 @@ public: return Pred->getState(); } - ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, - const GRState* St) { + ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S, + ExplodedNode* Pred, const GRState* St) { return MakeNode(Dst, S, Pred, St, PointKind); } - ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, + ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,ExplodedNode* Pred, const GRState* St, ProgramPoint::Kind K); - ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, Stmt* S, + ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, const Stmt* S, ExplodedNode* Pred, const GRState* St) { bool Tmp = BuildSinks; BuildSinks = true; @@ -259,9 +296,9 @@ public: class GRBranchNodeBuilder { GRCoreEngine& Eng; - CFGBlock* Src; - CFGBlock* DstT; - CFGBlock* DstF; + const CFGBlock* Src; + const CFGBlock* DstT; + const CFGBlock* DstF; ExplodedNode* Pred; typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy; @@ -273,8 +310,8 @@ class GRBranchNodeBuilder { bool InFeasibleFalse; public: - GRBranchNodeBuilder(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF, - ExplodedNode* pred, GRCoreEngine* e) + GRBranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT, + const CFGBlock* dstF, ExplodedNode* pred, GRCoreEngine* e) : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred), GeneratedTrue(false), GeneratedFalse(false), InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {} @@ -289,7 +326,7 @@ public: ExplodedNode* generateNode(const GRState* State, bool branch); - CFGBlock* getTargetBlock(bool branch) const { + const CFGBlock* getTargetBlock(bool branch) const { return branch ? DstT : DstF; } @@ -311,31 +348,31 @@ public: class GRIndirectGotoNodeBuilder { GRCoreEngine& Eng; - CFGBlock* Src; - CFGBlock& DispatchBlock; - Expr* E; + const CFGBlock* Src; + const CFGBlock& DispatchBlock; + const Expr* E; ExplodedNode* Pred; public: - GRIndirectGotoNodeBuilder(ExplodedNode* pred, CFGBlock* src, Expr* e, - CFGBlock* dispatch, GRCoreEngine* eng) - : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} + GRIndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src, + const Expr* e, const CFGBlock* dispatch, GRCoreEngine* eng) + : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} class iterator { - CFGBlock::succ_iterator I; + CFGBlock::const_succ_iterator I; friend class GRIndirectGotoNodeBuilder; - iterator(CFGBlock::succ_iterator i) : I(i) {} + iterator(CFGBlock::const_succ_iterator i) : I(i) {} public: iterator& operator++() { ++I; return *this; } bool operator!=(const iterator& X) const { return I != X.I; } - LabelStmt* getLabel() const { + const LabelStmt* getLabel() const { return llvm::cast<LabelStmt>((*I)->getLabel()); } - CFGBlock* getBlock() const { + const CFGBlock* getBlock() const { return *I; } }; @@ -346,37 +383,38 @@ public: ExplodedNode* generateNode(const iterator& I, const GRState* State, bool isSink = false); - Expr* getTarget() const { return E; } + const Expr* getTarget() const { return E; } const GRState* getState() const { return Pred->State; } }; class GRSwitchNodeBuilder { GRCoreEngine& Eng; - CFGBlock* Src; - Expr* Condition; + const CFGBlock* Src; + const Expr* Condition; ExplodedNode* Pred; public: - GRSwitchNodeBuilder(ExplodedNode* pred, CFGBlock* src, - Expr* condition, GRCoreEngine* eng) + GRSwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src, + const Expr* condition, GRCoreEngine* eng) : Eng(*eng), Src(src), Condition(condition), Pred(pred) {} class iterator { - CFGBlock::succ_reverse_iterator I; + CFGBlock::const_succ_reverse_iterator I; friend class GRSwitchNodeBuilder; - iterator(CFGBlock::succ_reverse_iterator i) : I(i) {} + iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {} public: iterator& operator++() { ++I; return *this; } - bool operator!=(const iterator& X) const { return I != X.I; } + bool operator!=(const iterator &X) const { return I != X.I; } + bool operator==(const iterator &X) const { return I == X.I; } - CaseStmt* getCase() const { + const CaseStmt* getCase() const { return llvm::cast<CaseStmt>((*I)->getLabel()); } - CFGBlock* getBlock() const { + const CFGBlock* getBlock() const { return *I; } }; @@ -389,21 +427,21 @@ public: ExplodedNode* generateDefaultCaseNode(const GRState* State, bool isSink = false); - Expr* getCondition() const { return Condition; } + const Expr* getCondition() const { return Condition; } const GRState* getState() const { return Pred->State; } }; class GREndPathNodeBuilder { GRCoreEngine &Eng; - CFGBlock& B; + const CFGBlock& B; ExplodedNode* Pred; public: bool HasGeneratedNode; public: - GREndPathNodeBuilder(CFGBlock* b, ExplodedNode* N, GRCoreEngine* e) + GREndPathNodeBuilder(const CFGBlock* b, ExplodedNode* N, GRCoreEngine* e) : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {} ~GREndPathNodeBuilder(); @@ -427,7 +465,7 @@ public: void GenerateCallExitNode(const GRState *state); - CFGBlock* getBlock() const { return &B; } + const CFGBlock* getBlock() const { return &B; } const GRState* getState() const { return getPredecessor()->getState(); @@ -442,8 +480,8 @@ class GRCallEnterNodeBuilder { // The call site. const Stmt *CE; - // The definition of callee. - const FunctionDecl *FD; + // The AnalysisContext of the callee. + AnalysisContext *CalleeCtx; // The parent block of the CallExpr. const CFGBlock *Block; @@ -453,9 +491,9 @@ class GRCallEnterNodeBuilder { public: GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred, - const Stmt *s, const FunctionDecl *fd, + const Stmt *s, AnalysisContext *callee, const CFGBlock *blk, unsigned idx) - : Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {} + : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {} const GRState *getState() const { return Pred->getState(); } @@ -465,7 +503,7 @@ public: const Stmt *getCallExpr() const { return CE; } - const FunctionDecl *getCallee() const { return FD; } + AnalysisContext *getCalleeContext() const { return CalleeCtx; } const CFGBlock *getBlock() const { return Block; } diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 8eaf3f4a97d7..5ba0b36b315d 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -64,7 +64,7 @@ class GRExprEngine : public GRSubEngine { const GRState* CleanedState; /// CurrentStmt - The current block-level statement. - Stmt* CurrentStmt; + const Stmt* CurrentStmt; // Obj-C Class Identifiers. IdentifierInfo* NSExceptionII; @@ -75,10 +75,26 @@ class GRExprEngine : public GRSubEngine { llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor; + enum CallbackKind { + PreVisitStmtCallback, + PostVisitStmtCallback, + ProcessAssumeCallback, + EvalRegionChangesCallback + }; + + typedef uint32_t CallbackTag; + + /// GetCallbackTag - Create a tag for a certain kind of callback. The 'Sub' + /// argument can be used to differentiate callbacks that depend on another + /// value from a small set of possibilities, such as statement classes. + static inline CallbackTag GetCallbackTag(CallbackKind K, uint32_t Sub = 0) { + assert(Sub == ((Sub << 8) >> 8) && "Tag sub-kind must fit into 24 bits"); + return K | (Sub << 8); + } + typedef llvm::DenseMap<void *, unsigned> CheckerMap; typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered; - typedef llvm::DenseMap<std::pair<unsigned, unsigned>, CheckersOrdered *> - CheckersOrderedCache; + typedef llvm::DenseMap<CallbackTag, CheckersOrdered *> CheckersOrderedCache; /// A registration map from checker tag to the index into the /// ordered checkers vector. @@ -89,7 +105,7 @@ class GRExprEngine : public GRSubEngine { CheckersOrdered Checkers; /// A map used for caching the checkers that respond to the callback for - /// a particular statement and visitation order. + /// a particular callback tag. CheckersOrderedCache COCache; /// The BugReporter associated with this engine. It is important that @@ -101,10 +117,10 @@ class GRExprEngine : public GRSubEngine { class CallExprWLItem { public: - CallExpr::arg_iterator I; + CallExpr::const_arg_iterator I; ExplodedNode *N; - CallExprWLItem(const CallExpr::arg_iterator &i, ExplodedNode *n) + CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n) : I(i), N(n) {} }; @@ -114,13 +130,22 @@ public: ~GRExprEngine(); void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { - CoreEngine.ExecuteWorkList(L, Steps); + CoreEngine.ExecuteWorkList(L, Steps, 0); + } + + /// Execute the work list with an initial state. Nodes that reaches the exit + /// of the function are added into the Dst set, which represent the exit + /// state of the function call. + void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, + const GRState *InitState, + ExplodedNodeSet &Dst) { + CoreEngine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst); } /// getContext - Return the ASTContext associated with this analysis. ASTContext& getContext() const { return AMgr.getASTContext(); } - AnalysisManager &getAnalysisManager() const { return AMgr; } + virtual AnalysisManager &getAnalysisManager() { return AMgr; } SValuator &getSValuator() { return SVator; } @@ -166,17 +191,18 @@ public: /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. - void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder); + void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder); /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue /// exploring the given path, and false otherwise. - bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, + bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred, GRBlockCounter BC); /// ProcessBranch - Called by GRCoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. - void ProcessBranch(Stmt* Condition, Stmt* Term, GRBranchNodeBuilder& builder); + void ProcessBranch(const Stmt* Condition, const Stmt* Term, + GRBranchNodeBuilder& builder); /// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor /// nodes by processing the 'effects' of a computed goto jump. @@ -201,10 +227,19 @@ public: /// EvalAssume - Callback function invoked by the ConstraintManager when /// making assumptions about state values. - const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption); + const GRState *ProcessAssume(const GRState *state, SVal cond,bool assumption); + + /// WantsRegionChangeUpdate - Called by GRStateManager to determine if a + /// region change should trigger a ProcessRegionChanges update. + bool WantsRegionChangeUpdate(const GRState* state); - GRStateManager& getStateManager() { return StateMgr; } - const GRStateManager& getStateManager() const { return StateMgr; } + /// ProcessRegionChanges - Called by GRStateManager whenever a change is made + /// to the store. Used to update checkers that track region values. + const GRState* ProcessRegionChanges(const GRState *state, + const MemRegion * const *Begin, + const MemRegion * const *End); + + virtual GRStateManager& getStateManager() { return StateMgr; } StoreManager& getStoreManager() { return StateMgr.getStoreManager(); } @@ -227,21 +262,29 @@ public: SymbolManager& getSymbolManager() { return SymMgr; } const SymbolManager& getSymbolManager() const { return SymMgr; } + // Functions for external checking of whether we have unfinished work + bool wasBlockAborted() const { return CoreEngine.wasBlockAborted(); } + bool hasWorkRemaining() const { + return wasBlockAborted() || CoreEngine.getWorkList()->hasWork(); + } + + const GRCoreEngine &getCoreEngine() const { return CoreEngine; } + protected: const GRState* GetState(ExplodedNode* N) { return N == EntryNode ? CleanedState : N->getState(); } public: - ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, - const GRState* St, + ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S, + ExplodedNode* Pred, const GRState* St, ProgramPoint::Kind K = ProgramPoint::PostStmtKind, const void *tag = 0); /// CheckerVisit - Dispatcher for performing checker-specific logic /// at specific statements. - void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, - bool isPrevisit); + void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, + CallbackKind Kind); bool CheckerEvalCall(const CallExpr *CE, ExplodedNodeSet &Dst, @@ -252,125 +295,130 @@ public: const GRState *state, ExplodedNode *Pred); - void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE, - ExplodedNodeSet &Dst, ExplodedNodeSet &Src, - SVal location, SVal val, bool isPrevisit); - + void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst, + ExplodedNodeSet &Src, SVal location, SVal val, + bool isPrevisit); /// Visit - Transfer function logic for all statements. Dispatches to /// other functions that handle specific kinds of statements. - void Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is /// a DeclRefExpr, it evaluates to the MemRegionVal which represents its /// storage location. Note that not all kinds of expressions has lvalue. - void VisitLValue(Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitLValue(const Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitArraySubscriptExpr - Transfer function for array accesses. - void VisitArraySubscriptExpr(ArraySubscriptExpr* Ex, ExplodedNode* Pred, + void VisitArraySubscriptExpr(const ArraySubscriptExpr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); /// VisitAsmStmt - Transfer function logic for inline asm. - void VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst); - void VisitAsmStmtHelperOutputs(AsmStmt* A, - AsmStmt::outputs_iterator I, - AsmStmt::outputs_iterator E, + void VisitAsmStmtHelperOutputs(const AsmStmt* A, + AsmStmt::const_outputs_iterator I, + AsmStmt::const_outputs_iterator E, ExplodedNode* Pred, ExplodedNodeSet& Dst); - void VisitAsmStmtHelperInputs(AsmStmt* A, - AsmStmt::inputs_iterator I, - AsmStmt::inputs_iterator E, + void VisitAsmStmtHelperInputs(const AsmStmt* A, + AsmStmt::const_inputs_iterator I, + AsmStmt::const_inputs_iterator E, ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitBlockExpr - Transfer function logic for BlockExprs. - void VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst); + void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, + ExplodedNodeSet &Dst); /// VisitBinaryOperator - Transfer function logic for binary operators. - void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred, + void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); /// VisitCall - Transfer function for function calls. - void VisitCall(CallExpr* CE, ExplodedNode* Pred, - CallExpr::arg_iterator AI, CallExpr::arg_iterator AE, + void VisitCall(const CallExpr* CE, ExplodedNode* Pred, + CallExpr::const_arg_iterator AI, + CallExpr::const_arg_iterator AE, ExplodedNodeSet& Dst, bool asLValue); /// VisitCast - Transfer function logic for all casts (implicit and explicit). - void VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred, + void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst, bool asLValue); /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. - void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred, - ExplodedNodeSet& Dst, bool asLValue); + void VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL, + ExplodedNode* Pred, ExplodedNodeSet& Dst, + bool asLValue); /// VisitDeclRefExpr - Transfer function logic for DeclRefExprs. - void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred, + void VisitDeclRefExpr(const DeclRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); /// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs. - void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred, + void VisitBlockDeclRefExpr(const BlockDeclRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); - void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred, - ExplodedNodeSet& Dst, bool asLValue); + void VisitCommonDeclRefExpr(const Expr* DR, const NamedDecl *D, + ExplodedNode* Pred, ExplodedNodeSet& Dst, + bool asLValue); /// VisitDeclStmt - Transfer function logic for DeclStmts. - void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitDeclStmt(const DeclStmt* DS, ExplodedNode* Pred, + ExplodedNodeSet& Dst); /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose - void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, - ExplodedNodeSet& Dst); + void VisitGuardedExpr(const Expr* Ex, const Expr* L, const Expr* R, + ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitCondInit - Transfer function for handling the initialization /// of a condition variable in an IfStmt, SwitchStmt, etc. - void VisitCondInit(VarDecl *VD, Stmt *S, ExplodedNode *Pred, + void VisitCondInit(const VarDecl *VD, const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet& Dst); - void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, + void VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitLogicalExpr - Transfer function logic for '&&', '||' - void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, + void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitMemberExpr - Transfer function for member expressions. - void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst, - bool asLValue); + void VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); /// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs. - void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred, + void VisitObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); /// VisitObjCForCollectionStmt - Transfer function logic for /// ObjCForCollectionStmt. - void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred, - ExplodedNodeSet& Dst); + void VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S, + ExplodedNode* Pred, ExplodedNodeSet& Dst); - void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, + void VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst, SVal ElementV); /// VisitObjCMessageExpr - Transfer function for ObjC message expressions. - void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, + void VisitObjCMessageExpr(const ObjCMessageExpr* ME, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); /// VisitReturnStmt - Transfer function logic for return statements. - void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitReturnStmt(const ReturnStmt* R, ExplodedNode* Pred, + ExplodedNodeSet& Dst); /// VisitOffsetOfExpr - Transfer function for offsetof. - void VisitOffsetOfExpr(OffsetOfExpr* Ex, ExplodedNode* Pred, + void VisitOffsetOfExpr(const OffsetOfExpr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitSizeOfAlignOfExpr - Transfer function for sizeof. - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, ExplodedNode* Pred, + void VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitUnaryOperator - Transfer function logic for unary operators. - void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, + void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); - void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, + void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet & Dst); void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest, @@ -380,17 +428,17 @@ public: void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred, + void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred, + void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, ExplodedNodeSet &Dst); void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred, ExplodedNodeSet &Dst); /// Create a C++ temporary object for an rvalue. - void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred, + void CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst); /// Synthesize CXXThisRegion. @@ -398,14 +446,15 @@ public: const StackFrameContext *SFC); /// Evaluate arguments with a work list algorithm. - void EvalArguments(ExprIterator AI, ExprIterator AE, + void EvalArguments(ConstExprIterator AI, ConstExprIterator AE, const FunctionProtoType *FnType, ExplodedNode *Pred, ExplodedNodeSet &Dst); /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) /// with those assumptions. - void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src, Expr *Ex); + void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src, + const Expr *Ex); SVal EvalMinus(SVal X) { return X.isValid() ? SVator.EvalMinus(cast<NonLoc>(X)) : X; @@ -433,42 +482,41 @@ public: } protected: - void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, + void EvalObjCMessageExpr(ExplodedNodeSet& Dst, const ObjCMessageExpr* ME, ExplodedNode* Pred, const GRState *state) { assert (Builder && "GRStmtNodeBuilder must be defined."); getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state); } - const GRState* MarkBranch(const GRState* St, Stmt* Terminator, + const GRState* MarkBranch(const GRState* St, const Stmt* Terminator, bool branchTaken); /// EvalBind - Handle the semantics of binding a value to a specific location. /// This method is used by EvalStore, VisitDeclStmt, and others. - void EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE, - Stmt* StoreE, ExplodedNode* Pred, + void EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred, const GRState* St, SVal location, SVal Val, bool atDeclInit = false); public: // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. - void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, + void EvalLoad(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred, const GRState* St, SVal location, const void *tag = 0, QualType LoadTy = QualType()); // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. - void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE, + void EvalStore(ExplodedNodeSet& Dst, const Expr* AssignE, const Expr* StoreE, ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val, const void *tag = 0); private: - void EvalLoadCommon(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, + void EvalLoadCommon(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred, const GRState* St, SVal location, const void *tag, QualType LoadTy); // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. - void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred, + void EvalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred, const GRState* St, SVal location, const void *tag, bool isLoad); diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h index 67a2caf06a13..d72d63ab3c98 100644 --- a/include/clang/Checker/PathSensitive/GRState.h +++ b/include/clang/Checker/PathSensitive/GRState.h @@ -77,6 +77,10 @@ private: Store St; GenericDataMap GDM; + /// makeWithStore - Return a GRState with the same values as the current + /// state with the exception of using the specified Store. + const GRState *makeWithStore(Store store) const; + public: /// This ctor is used when creating the first GRState object. @@ -134,10 +138,6 @@ public: return Env.LookupExpr(E); } - /// makeWithStore - Return a GRState with the same values as the current - /// state with the exception of using the specified Store. - const GRState *makeWithStore(Store store) const; - BasicValueFactory &getBasicVals() const; SymbolManager &getSymbolManager() const; @@ -201,8 +201,15 @@ public: const LocationContext *LC, SVal V) const; + /// Create a new state by binding the value 'V' to the statement 'S' in the + /// state's environment. const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const; + /// Create a new state by binding the value 'V' and location 'locaton' to the + /// statement 'S' in the state's environment. + const GRState *bindExprAndLocation(const Stmt *S, SVal location, SVal V) + const; + const GRState *bindDecl(const VarRegion *VR, SVal V) const; const GRState *bindDeclWithNoInit(const VarRegion *VR) const; @@ -215,6 +222,28 @@ public: const GRState *unbindLoc(Loc LV) const; + /// InvalidateRegion - Returns the state with bindings for the given region + /// cleared from the store. See InvalidateRegions. + const GRState *InvalidateRegion(const MemRegion *R, + const Expr *E, unsigned BlockCount, + StoreManager::InvalidatedSymbols *IS = NULL) + const { + return InvalidateRegions(&R, &R+1, E, BlockCount, IS, false); + } + + /// InvalidateRegions - Returns the state with bindings for the given regions + /// cleared from the store. The regions are provided as a continuous array + /// from Begin to End. Optionally invalidates global regions as well. + const GRState *InvalidateRegions(const MemRegion * const *Begin, + const MemRegion * const *End, + const Expr *E, unsigned BlockCount, + StoreManager::InvalidatedSymbols *IS, + bool invalidateGlobals) const; + + /// EnterStackFrame - Returns the state for entry to the given stack frame, + /// preserving the current state. + const GRState *EnterStackFrame(const StackFrameContext *frame) const; + /// Get the lvalue for a variable reference. Loc getLValue(const VarDecl *D, const LocationContext *LC) const; @@ -235,11 +264,18 @@ public: const llvm::APSInt *getSymVal(SymbolRef sym) const; - SVal getSVal(const Stmt* Ex) const; - + /// Returns the SVal bound to the statement 'S' in the state's environment. + SVal getSVal(const Stmt* S) const; + SVal getSValAsScalarOrLoc(const Stmt *Ex) const; SVal getSVal(Loc LV, QualType T = QualType()) const; + + /// Returns a "simplified" SVal bound to the location 'LV' in the state's + /// store. A simplified SVal will include optimizations such as + /// if the SVal is a symbol whose value is perfectly constrained then that + /// constant value is returned instead. + SVal getSimplifiedSVal(Loc LV, QualType T= QualType()) const; SVal getSVal(const MemRegion* R) const; @@ -375,6 +411,9 @@ class GRStateManager { friend class GRState; friend class GRExprEngine; // FIXME: Remove. private: + /// Eng - The GRSubEngine that owns this state manager. + GRSubEngine &Eng; + EnvironmentManager EnvMgr; llvm::OwningPtr<StoreManager> StoreMgr; llvm::OwningPtr<ConstraintManager> ConstraintMgr; @@ -404,7 +443,8 @@ public: ConstraintManagerCreator CreateConstraintManager, llvm::BumpPtrAllocator& alloc, GRSubEngine &subeng) - : EnvMgr(alloc), + : Eng(subeng), + EnvMgr(alloc), GDMFactory(alloc), ValueMgr(alloc, Ctx, *this), Alloc(alloc) { @@ -447,11 +487,16 @@ public: StoreManager& getStoreManager() { return *StoreMgr; } ConstraintManager& getConstraintManager() { return *ConstraintMgr; } + GRSubEngine& getOwningEngine() { return Eng; } const GRState* RemoveDeadBindings(const GRState* St, const StackFrameContext *LCtx, SymbolReaper& SymReaper); + /// Marshal a new state for the callee in another translation unit. + /// 'state' is owned by the caller's engine. + const GRState *MarshalState(const GRState *state, const StackFrameContext *L); + public: SVal ArrayToPointer(Loc Array) { @@ -581,50 +626,10 @@ GRState::Assume(DefinedOrUnknownSVal Cond) const { cast<DefinedSVal>(Cond)); } -inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx, - DefinedOrUnknownSVal UpperBound, - bool Assumption) const { - if (Idx.isUnknown() || UpperBound.isUnknown()) - return this; - - ConstraintManager &CM = *getStateManager().ConstraintMgr; - return CM.AssumeInBound(this, cast<DefinedSVal>(Idx), - cast<DefinedSVal>(UpperBound), Assumption); -} - -inline const GRState * -GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL, - const LocationContext *LC, SVal V) const { - Store new_store = - getStateManager().StoreMgr->BindCompoundLiteral(St, CL, LC, V); - return makeWithStore(new_store); -} - -inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const { - Store new_store = getStateManager().StoreMgr->BindDecl(St, VR, IVal); - return makeWithStore(new_store); -} - -inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const { - Store new_store = getStateManager().StoreMgr->BindDeclWithNoInit(St, VR); - return makeWithStore(new_store); -} - -inline const GRState *GRState::bindLoc(Loc LV, SVal V) const { - Store new_store = getStateManager().StoreMgr->Bind(St, LV, V); - return makeWithStore(new_store); -} - inline const GRState *GRState::bindLoc(SVal LV, SVal V) const { return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V); } -inline const GRState *GRState::bindDefault(SVal loc, SVal V) const { - const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion(); - Store new_store = getStateManager().StoreMgr->BindDefault(St, R, V); - return makeWithStore(new_store); -} - inline Loc GRState::getLValue(const VarDecl* VD, const LocationContext *LC) const { return getStateManager().StoreMgr->getLValueVar(VD, LC); diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h index 90a41d7c093f..1904835fbc34 100644 --- a/include/clang/Checker/PathSensitive/GRSubEngine.h +++ b/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -17,7 +17,7 @@ namespace clang { -class Stmt; +class AnalysisManager; class CFGBlock; class CFGElement; class ExplodedNode; @@ -32,6 +32,8 @@ class GREndPathNodeBuilder; class GRCallEnterNodeBuilder; class GRCallExitNodeBuilder; class LocationContext; +class MemRegion; +class Stmt; class GRSubEngine { public: @@ -39,21 +41,23 @@ public: virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0; - virtual GRStateManager& getStateManager() = 0; + virtual AnalysisManager &getAnalysisManager() = 0; + + virtual GRStateManager &getStateManager() = 0; /// Called by GRCoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. - virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0; + virtual void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder) = 0; /// Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue /// exploring the given path, and false otherwise. - virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, + virtual bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred, GRBlockCounter BC) = 0; /// Called by GRCoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. - virtual void ProcessBranch(Stmt* Condition, Stmt* Term, + virtual void ProcessBranch(const Stmt* Condition, const Stmt* Term, GRBranchNodeBuilder& builder) = 0; /// Called by GRCoreEngine. Used to generate successor @@ -73,12 +77,27 @@ public: // Generate the first post callsite node. virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0; - + /// Called by ConstraintManager. Used to call checker-specific /// logic for handling assumptions on symbolic values. virtual const GRState* ProcessAssume(const GRState *state, SVal cond, bool assumption) = 0; - + + /// WantsRegionChangeUpdate - Called by GRStateManager to determine if a + /// region change should trigger a ProcessRegionChanges update. + virtual bool WantsRegionChangeUpdate(const GRState* state) = 0; + + /// ProcessRegionChanges - Called by GRStateManager whenever a change is made + /// to the store. Used to update checkers that track region values. + virtual const GRState* ProcessRegionChanges(const GRState* state, + const MemRegion* const *Begin, + const MemRegion* const *End) = 0; + + inline const GRState* ProcessRegionChange(const GRState* state, + const MemRegion* MR) { + return ProcessRegionChanges(state, &MR, &MR+1); + } + /// Called by GRCoreEngine when the analysis worklist is either empty or the // maximum number of analysis steps have been reached. virtual void ProcessEndWorklist(bool hasWorkRemaining) = 0; diff --git a/include/clang/Checker/PathSensitive/GRTransferFuncs.h b/include/clang/Checker/PathSensitive/GRTransferFuncs.h index 374f99820bd0..320b7f7b8abd 100644 --- a/include/clang/Checker/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Checker/PathSensitive/GRTransferFuncs.h @@ -42,13 +42,13 @@ public: virtual void EvalCall(ExplodedNodeSet& Dst, GRExprEngine& Engine, GRStmtNodeBuilder& Builder, - CallExpr* CE, SVal L, + const CallExpr* CE, SVal L, ExplodedNode* Pred) {} virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst, GRExprEngine& Engine, GRStmtNodeBuilder& Builder, - ObjCMessageExpr* ME, + const ObjCMessageExpr* ME, ExplodedNode* Pred, const GRState *state) {} @@ -73,7 +73,7 @@ public: virtual void EvalReturn(ExplodedNodeSet& Dst, GRExprEngine& Engine, GRStmtNodeBuilder& Builder, - ReturnStmt* S, + const ReturnStmt* S, ExplodedNode* Pred) {} // Assumptions. diff --git a/include/clang/Checker/PathSensitive/GRWorkList.h b/include/clang/Checker/PathSensitive/GRWorkList.h index b8f90fa1eea1..315b614043d4 100644 --- a/include/clang/Checker/PathSensitive/GRWorkList.h +++ b/include/clang/Checker/PathSensitive/GRWorkList.h @@ -27,12 +27,12 @@ class ExplodedNodeImpl; class GRWorkListUnit { ExplodedNode* Node; GRBlockCounter Counter; - CFGBlock* Block; + const CFGBlock* Block; unsigned BlockIdx; // This is the index of the next statement. public: GRWorkListUnit(ExplodedNode* N, GRBlockCounter C, - CFGBlock* B, unsigned idx) + const CFGBlock* B, unsigned idx) : Node(N), Counter(C), Block(B), @@ -46,7 +46,7 @@ public: ExplodedNode* getNode() const { return Node; } GRBlockCounter getBlockCounter() const { return Counter; } - CFGBlock* getBlock() const { return Block; } + const CFGBlock* getBlock() const { return Block; } unsigned getIndex() const { return BlockIdx; } }; @@ -58,8 +58,8 @@ public: virtual void Enqueue(const GRWorkListUnit& U) = 0; - void Enqueue(ExplodedNode* N, CFGBlock& B, unsigned idx) { - Enqueue(GRWorkListUnit(N, CurrentCounter, &B, idx)); + void Enqueue(ExplodedNode* N, const CFGBlock* B, unsigned idx) { + Enqueue(GRWorkListUnit(N, CurrentCounter, B, idx)); } void Enqueue(ExplodedNode* N) { diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index feb4b7218a7e..96f906af28e1 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -20,6 +20,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/Checker/PathSensitive/SVals.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/ADT/FoldingSet.h" #include <string> @@ -38,6 +39,22 @@ class ValueManager; class VarRegion; class CodeTextRegion; +/// Represent a region's offset within the top level base region. +class RegionOffset { + /// The base region. + const MemRegion *R; + + /// The bit offset within the base region. It shouldn't be negative. + int64_t Offset; + +public: + RegionOffset(const MemRegion *r) : R(r), Offset(0) {} + RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {} + + const MemRegion *getRegion() const { return R; } + int64_t getOffset() const { return Offset; } +}; + //===----------------------------------------------------------------------===// // Base region classes. //===----------------------------------------------------------------------===// @@ -111,6 +128,9 @@ public: bool hasStackParametersStorage() const; + /// Compute the offset within the top level memory object. + RegionOffset getAsOffset() const; + virtual void dumpToStream(llvm::raw_ostream& os) const; void dump() const; @@ -261,6 +281,7 @@ public: } }; + /// SubRegion - A region that subsets another larger region. Most regions /// are subclasses of SubRegion. class SubRegion : public MemRegion { @@ -287,31 +308,6 @@ public: }; //===----------------------------------------------------------------------===// -// Auxillary data classes for use with MemRegions. -//===----------------------------------------------------------------------===// - -class ElementRegion; - -class RegionRawOffset { -private: - friend class ElementRegion; - - const MemRegion *Region; - int64_t Offset; - - RegionRawOffset(const MemRegion* reg, int64_t offset = 0) - : Region(reg), Offset(offset) {} - -public: - // FIXME: Eventually support symbolic offsets. - int64_t getByteOffset() const { return Offset; } - const MemRegion *getRegion() const { return Region; } - - void dumpToStream(llvm::raw_ostream& os) const; - void dump() const; -}; - -//===----------------------------------------------------------------------===// // MemRegion subclasses. //===----------------------------------------------------------------------===// @@ -353,25 +349,23 @@ protected: TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {} public: - virtual QualType getValueType(ASTContext &C) const = 0; + virtual QualType getValueType() const = 0; - virtual QualType getLocationType(ASTContext& C) const { + virtual QualType getLocationType() const { // FIXME: We can possibly optimize this later to cache this value. - return C.getPointerType(getValueType(C)); + return getContext().getPointerType(getValueType()); } - QualType getDesugaredValueType(ASTContext& C) const { - QualType T = getValueType(C); + QualType getDesugaredValueType() const { + QualType T = getValueType(); return T.getTypePtr() ? T.getDesugaredType() : T; } - QualType getDesugaredLocationType(ASTContext& C) const { - return getLocationType(C).getDesugaredType(); + QualType getDesugaredLocationType() const { + return getLocationType().getDesugaredType(); } - bool isBoundable() const { - return !getValueType(getContext()).isNull(); - } + bool isBoundable() const { return true; } static bool classof(const MemRegion* R) { unsigned k = R->getKind(); @@ -384,9 +378,8 @@ class CodeTextRegion : public TypedRegion { protected: CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} public: - QualType getValueType(ASTContext &C) const { - // Do not get the object type of a CodeTextRegion. - assert(0); + QualType getValueType() const { + assert(0 && "Do not get the object type of a CodeTextRegion."); return QualType(); } @@ -405,8 +398,8 @@ public: FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg) : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {} - QualType getLocationType(ASTContext &C) const { - return C.getPointerType(FD->getType()); + QualType getLocationType() const { + return getContext().getPointerType(FD->getType()); } const FunctionDecl *getDecl() const { @@ -444,7 +437,7 @@ class BlockTextRegion : public CodeTextRegion { : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} public: - QualType getLocationType(ASTContext &C) const { + QualType getLocationType() const { return locTy; } @@ -581,7 +574,7 @@ public: const StringLiteral* getStringLiteral() const { return Str; } - QualType getValueType(ASTContext& C) const { + QualType getValueType() const { return Str->getType(); } @@ -615,8 +608,8 @@ private: const CompoundLiteralExpr* CL, const MemRegion* superRegion); public: - QualType getValueType(ASTContext& C) const { - return C.getCanonicalType(CL->getType()); + QualType getValueType() const { + return CL->getType(); } bool isBoundable() const { return !CL->isFileScope(); } @@ -673,9 +666,9 @@ public: const StackFrameContext *getStackFrame() const; - QualType getValueType(ASTContext& C) const { + QualType getValueType() const { // FIXME: We can cache this if needed. - return C.getCanonicalType(getDecl()->getType()); + return getDecl()->getType(); } void dumpToStream(llvm::raw_ostream& os) const; @@ -701,10 +694,10 @@ class CXXThisRegion : public TypedRegion { void Profile(llvm::FoldingSetNodeID &ID) const; public: - QualType getValueType(ASTContext &C) const { + QualType getValueType() const { return QualType(ThisPointerTy, 0); } - + void dumpToStream(llvm::raw_ostream& os) const; static bool classof(const MemRegion* R) { @@ -727,9 +720,9 @@ public: const FieldDecl* getDecl() const { return cast<FieldDecl>(D); } - QualType getValueType(ASTContext& C) const { + QualType getValueType() const { // FIXME: We can cache this if needed. - return C.getCanonicalType(getDecl()->getType()); + return getDecl()->getType(); } DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; @@ -758,7 +751,7 @@ class ObjCIvarRegion : public DeclRegion { public: const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); } - QualType getValueType(ASTContext&) const { return getDecl()->getType(); } + QualType getValueType() const { return getDecl()->getType(); } void dumpToStream(llvm::raw_ostream& os) const; @@ -766,6 +759,30 @@ public: return R->getKind() == ObjCIvarRegionKind; } }; +//===----------------------------------------------------------------------===// +// Auxillary data classes for use with MemRegions. +//===----------------------------------------------------------------------===// + +class ElementRegion; + +class RegionRawOffset { +private: + friend class ElementRegion; + + const MemRegion *Region; + int64_t Offset; + + RegionRawOffset(const MemRegion* reg, int64_t offset = 0) + : Region(reg), Offset(offset) {} + +public: + // FIXME: Eventually support symbolic offsets. + int64_t getByteOffset() const { return Offset; } + const MemRegion *getRegion() const { return Region; } + + void dumpToStream(llvm::raw_ostream& os) const; + void dump() const; +}; class ElementRegion : public TypedRegion { friend class MemRegionManager; @@ -788,15 +805,15 @@ public: SVal getIndex() const { return Index; } - QualType getValueType(ASTContext&) const { + QualType getValueType() const { return ElementType; } QualType getElementType() const { return ElementType; } - - RegionRawOffset getAsRawOffset() const; + /// Compute the offset within the array. The array might also be a subobject. + RegionRawOffset getAsArrayOffset() const; void dumpToStream(llvm::raw_ostream& os) const; @@ -820,7 +837,7 @@ class CXXObjectRegion : public TypedRegion { Expr const *E, const MemRegion *sReg); public: - QualType getValueType(ASTContext& C) const { + QualType getValueType() const { return Ex->getType(); } diff --git a/include/clang/Checker/PathSensitive/SVals.h b/include/clang/Checker/PathSensitive/SVals.h index 55fd3ea5c929..cdb338a3f2cc 100644 --- a/include/clang/Checker/PathSensitive/SVals.h +++ b/include/clang/Checker/PathSensitive/SVals.h @@ -45,15 +45,14 @@ public: enum { BaseBits = 2, BaseMask = 0x3 }; protected: - void* Data; + const void* Data; unsigned Kind; protected: SVal(const void* d, bool isLoc, unsigned ValKind) - : Data(const_cast<void*>(d)), - Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {} + : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {} - explicit SVal(BaseKind k, void* D = NULL) + explicit SVal(BaseKind k, const void* D = NULL) : Data(D), Kind(k) {} public: @@ -69,7 +68,7 @@ public: inline void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger((unsigned) getRawKind()); - ID.AddPointer(reinterpret_cast<void*>(Data)); + ID.AddPointer(Data); } inline bool operator==(const SVal& R) const { @@ -163,13 +162,13 @@ public: class UndefinedVal : public SVal { public: UndefinedVal() : SVal(UndefinedKind) {} - UndefinedVal(void* D) : SVal(UndefinedKind, D) {} + UndefinedVal(const void* D) : SVal(UndefinedKind, D) {} static inline bool classof(const SVal* V) { return V->getBaseKind() == UndefinedKind; } - void* getData() const { return Data; } + const void* getData() const { return Data; } }; class DefinedOrUnknownSVal : public SVal { @@ -287,7 +286,7 @@ public: : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {} const SymExpr *getSymbolicExpression() const { - return reinterpret_cast<SymExpr*>(Data); + return reinterpret_cast<const SymExpr*>(Data); } static inline bool classof(const SVal* V) { @@ -305,7 +304,7 @@ public: ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {} const llvm::APSInt& getValue() const { - return *static_cast<llvm::APSInt*>(Data); + return *static_cast<const llvm::APSInt*>(Data); } // Transfer functions for binary/unary operations on ConcreteInts. @@ -368,7 +367,7 @@ class CompoundVal : public NonLoc { public: const CompoundValData* getValue() const { - return static_cast<CompoundValData*>(Data); + return static_cast<const CompoundValData*>(Data); } typedef llvm::ImmutableList<SVal>::iterator iterator; @@ -419,8 +418,8 @@ class GotoLabel : public Loc { public: GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {} - LabelStmt* getLabel() const { - return static_cast<LabelStmt*>(Data); + const LabelStmt* getLabel() const { + return static_cast<const LabelStmt*>(Data); } static inline bool classof(const SVal* V) { @@ -439,7 +438,7 @@ public: MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {} const MemRegion* getRegion() const { - return static_cast<MemRegion*>(Data); + return static_cast<const MemRegion*>(Data); } const MemRegion* StripCasts() const; @@ -473,7 +472,7 @@ public: ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {} const llvm::APSInt& getValue() const { - return *static_cast<llvm::APSInt*>(Data); + return *static_cast<const llvm::APSInt*>(Data); } // Transfer functions for binary/unary operations on ConcreteInts. diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h index 7a60ebb0838e..a1a41847a206 100644 --- a/include/clang/Checker/PathSensitive/Store.h +++ b/include/clang/Checker/PathSensitive/Store.h @@ -149,9 +149,8 @@ public: return UnknownVal(); } - virtual const GRState *RemoveDeadBindings(GRState &state, - const StackFrameContext *LCtx, - SymbolReaper& SymReaper, + virtual Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx, + SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0; virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0; @@ -159,25 +158,39 @@ public: virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0; typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; - - virtual Store InvalidateRegion(Store store, - const MemRegion *R, - const Expr *E, unsigned Count, - InvalidatedSymbols *IS) = 0; - + typedef llvm::SmallVector<const MemRegion *, 8> InvalidatedRegions; + + /// InvalidateRegions - Clears out the specified regions from the store, + /// marking their values as unknown. Depending on the store, this may also + /// invalidate additional regions that may have changed based on accessing + /// the given regions. Optionally, invalidates non-static globals as well. + /// \param[in] store The initial store + /// \param[in] Begin A pointer to the first region to invalidate. + /// \param[in] End A pointer just past the last region to invalidate. + /// \param[in] E The current statement being evaluated. Used to conjure + /// symbols to mark the values of invalidated regions. + /// \param[in] Count The current block count. Used to conjure + /// symbols to mark the values of invalidated regions. + /// \param[in,out] IS A set to fill with any symbols that are no longer + /// accessible. Pass \c NULL if this information will not be used. + /// \param[in] invalidateGlobals If \c true, any non-static global regions + /// are invalidated as well. + /// \param[in,out] Regions A vector to fill with any regions being + /// invalidated. This should include any regions explicitly invalidated + /// even if they do not currently have bindings. Pass \c NULL if this + /// information will not be used. virtual Store InvalidateRegions(Store store, const MemRegion * const *Begin, const MemRegion * const *End, const Expr *E, unsigned Count, InvalidatedSymbols *IS, - bool invalidateGlobals) = 0; + bool invalidateGlobals, + InvalidatedRegions *Regions) = 0; /// EnterStackFrame - Let the StoreManager to do something when execution /// engine is about to execute into a callee. - virtual const GRState *EnterStackFrame(const GRState *state, - const StackFrameContext *frame) { - return state; - } + virtual Store EnterStackFrame(const GRState *state, + const StackFrameContext *frame); virtual void print(Store store, llvm::raw_ostream& Out, const char* nl, const char *sep) = 0; diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h index ffbd2892499e..26ed0c1bc06f 100644 --- a/include/clang/Checker/PathSensitive/SymbolManager.h +++ b/include/clang/Checker/PathSensitive/SymbolManager.h @@ -40,6 +40,7 @@ class SymExpr : public llvm::FoldingSetNode { public: enum Kind { BEGIN_SYMBOLS, RegionValueKind, ConjuredKind, DerivedKind, ExtentKind, + MetadataKind, END_SYMBOLS, SymIntKind, SymSymKind }; private: @@ -190,6 +191,9 @@ public: } }; +/// SymbolExtent - Represents the extent (size in bytes) of a bounded region. +/// Clients should not ask the SymbolManager for a region's extent. Always use +/// SubRegion::getExtent instead -- the value returned may not be a symbol. class SymbolExtent : public SymbolData { const SubRegion *R; @@ -218,6 +222,51 @@ public: } }; +/// SymbolMetadata - Represents path-dependent metadata about a specific region. +/// Metadata symbols remain live as long as they are marked as in use before +/// dead-symbol sweeping AND their associated regions are still alive. +/// Intended for use by checkers. +class SymbolMetadata : public SymbolData { + const MemRegion* R; + const Stmt* S; + QualType T; + unsigned Count; + const void* Tag; +public: + SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt* s, QualType t, + unsigned count, const void* tag) + : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {} + + const MemRegion *getRegion() const { return R; } + const Stmt* getStmt() const { return S; } + unsigned getCount() const { return Count; } + const void* getTag() const { return Tag; } + + QualType getType(ASTContext&) const; + + void dumpToStream(llvm::raw_ostream &os) const; + + static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R, + const Stmt *S, QualType T, unsigned Count, + const void *Tag) { + profile.AddInteger((unsigned) MetadataKind); + profile.AddPointer(R); + profile.AddPointer(S); + profile.Add(T); + profile.AddInteger(Count); + profile.AddPointer(Tag); + } + + virtual void Profile(llvm::FoldingSetNodeID& profile) { + Profile(profile, R, S, T, Count, Tag); + } + + // Implement isa<T> support. + static inline bool classof(const SymExpr* SE) { + return SE->getKind() == MetadataKind; + } +}; + // SymIntExpr - Represents symbolic expression like 'x' + 3. class SymIntExpr : public SymExpr { const SymExpr *LHS; @@ -336,6 +385,10 @@ public: const SymbolExtent *getExtentSymbol(const SubRegion *R); + const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt* S, + QualType T, unsigned VisitCount, + const void* SymbolTag = 0); + const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType t); @@ -359,6 +412,7 @@ class SymbolReaper { typedef llvm::DenseSet<SymbolRef> SetTy; SetTy TheLiving; + SetTy MetadataInUse; SetTy TheDead; const LocationContext *LCtx; const Stmt *Loc; @@ -374,12 +428,24 @@ public: const Stmt *getCurrentStatement() const { return Loc; } bool isLive(SymbolRef sym); - bool isLive(const Stmt *ExprVal) const; - bool isLive(const VarRegion *VR) const; - + + // markLive - Unconditionally marks a symbol as live. This should never be + // used by checkers, only by the state infrastructure such as the store and + // environment. Checkers should instead use metadata symbols and markInUse. void markLive(SymbolRef sym); + + // markInUse - Marks a symbol as important to a checker. For metadata symbols, + // this will keep the symbol alive as long as its associated region is also + // live. For other symbols, this has no effect; checkers are not permitted + // to influence the life of other symbols. This should be used before any + // symbol marking has occurred, i.e. in the MarkLiveSymbols callback. + void markInUse(SymbolRef sym); + + // maybeDead - If a symbol is known to be live, marks the symbol as live. + // Otherwise, if the symbol cannot be proven live, it is marked as dead. + // Returns true if the symbol is dead, false if live. bool maybeDead(SymbolRef sym); typedef SetTy::const_iterator dead_iterator; @@ -389,6 +455,13 @@ public: bool hasDeadSymbols() const { return !TheDead.empty(); } + + /// isDead - Returns whether or not a symbol has been confirmed dead. This + /// should only be called once all marking of dead symbols has completed. + /// (For checkers, this means only in the EvalDeadSymbols callback.) + bool isDead(SymbolRef sym) const { + return TheDead.count(sym); + } }; class SymbolVisitor { diff --git a/include/clang/Checker/PathSensitive/ValueManager.h b/include/clang/Checker/PathSensitive/ValueManager.h index 5a9d54d337b0..b81e9c150234 100644 --- a/include/clang/Checker/PathSensitive/ValueManager.h +++ b/include/clang/Checker/PathSensitive/ValueManager.h @@ -106,6 +106,9 @@ public: DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, const TypedRegion *R); + DefinedSVal getMetadataSymbolVal(const void *SymbolTag, const MemRegion *MR, + const Expr *E, QualType T, unsigned Count); + DefinedSVal getFunctionPointer(const FunctionDecl *FD); DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy, diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 7076f30995d0..fd40aa0c5f4b 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -26,6 +26,8 @@ def target_cpu : Separate<"-target-cpu">, HelpText<"Target a specific cpu type">; def target_feature : Separate<"-target-feature">, HelpText<"Target specific attributes">; +def target_linker_version : Separate<"-target-linker-version">, + HelpText<"Target linker version">; def triple : Separate<"-triple">, HelpText<"Specify target triple (e.g. i686-apple-darwin9)">; def triple_EQ : Joined<"-triple=">, Alias<triple>; @@ -38,6 +40,8 @@ def analysis_CFGDump : Flag<"-cfg-dump">, HelpText<"Display Control-Flow Graphs">; def analysis_CFGView : Flag<"-cfg-view">, HelpText<"View Control-Flow Graphs using GraphViz">; +def analysis_UnoptimizedCFG : Flag<"-unoptimized-cfg">, + HelpText<"Generate unoptimized CFGs for all analyses">; def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">, HelpText<"Print results of live variable analysis">; def analysis_LLVMConventionChecker : Flag<"-analyzer-check-llvm-conventions">, @@ -58,6 +62,8 @@ def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">, HelpText<"Run the [Core] Foundation reference count checker">; def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">, HelpText<"Warn about unintended use of sizeof() on pointer expressions">; +def analysis_WarnIdempotentOps : Flag<"-analyzer-check-idempotent-operations">, + HelpText<"Warn about idempotent operations">; def analyzer_store : Separate<"-analyzer-store">, HelpText<"Source Code Analysis - Abstract Memory Store Models">; @@ -81,8 +87,6 @@ def analyzer_display_progress : Flag<"-analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">; def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">, HelpText<"Use experimental path-sensitive checks">; -def analyzer_idempotent_operation : Flag<"-analyzer-idempotent-operation">, - HelpText<"Use experimental path-sensitive idempotent operation checker">; def analyzer_experimental_internal_checks : Flag<"-analyzer-experimental-internal-checks">, HelpText<"Use new default path-sensitive checks currently in testing">; @@ -137,6 +141,8 @@ def ffunction_sections : Flag<"-ffunction-sections">, HelpText<"Place each function in its own section (ELF Only)">; def fdata_sections : Flag<"-fdata-sections">, HelpText<"Place each data in its own section (ELF Only)">; +def funroll_loops : Flag<"-funroll-loops">, + HelpText<"Turn on loop unroller">; def masm_verbose : Flag<"-masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<"-mcode-model">, @@ -209,6 +215,8 @@ def W : Joined<"-W">; def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, HelpText<"Print source range spans in numeric form">; +def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, + HelpText<"Print fix-its in machine parseable form">; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, HelpText<"Print diagnostic name with mappable diagnostics">; def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">, @@ -229,7 +237,7 @@ def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">, HelpText<"Silence ObjC rewriting warnings">; def Wwrite_strings : Flag<"-Wwrite-strings">, - HelpText<"Add const qualifier to string literals">; + HelpText<"Remove const qualifier from string literals">; def verify : Flag<"-verify">, HelpText<"Verify emitted diagnostics and warnings">; @@ -258,6 +266,8 @@ def code_completion_macros : Flag<"-code-completion-macros">, HelpText<"Include macros in code-completion results">; def code_completion_patterns : Flag<"-code-completion-patterns">, HelpText<"Include code patterns in code-completion results">; +def no_code_completion_globals : Flag<"-no-code-completion-globals">, + HelpText<"Do not include global declarations in code-completion results.">; def disable_free : Flag<"-disable-free">, HelpText<"Disable freeing of memory on exit">; def help : Flag<"-help">, @@ -296,16 +306,15 @@ def dump_tokens : Flag<"-dump-tokens">, HelpText<"Run preprocessor, dump internal rep of tokens">; def init_only : Flag<"-init-only">, HelpText<"Only execute frontend initialization">; -def parse_noop : Flag<"-parse-noop">, - HelpText<"Run parser with noop callbacks (for timings)">; def fsyntax_only : Flag<"-fsyntax-only">, HelpText<"Run parser and perform semantic analysis">; def fixit : Flag<"-fixit">, HelpText<"Apply fix-it advice to the input source">; def fixit_EQ : Joined<"-fixit=">, HelpText<"Apply fix-it advice creating a file with the given suffix">; -def parse_print_callbacks : Flag<"-parse-print-callbacks">, - HelpText<"Run parser and print each callback invoked">; +def print_preamble : Flag<"-print-preamble">, + HelpText<"Print the \"preamble\" of a file, which is a candidate for implicit" + " precompiled headers.">; def emit_html : Flag<"-emit-html">, HelpText<"Output input source as HTML">; def ast_print : Flag<"-ast-print">, @@ -343,8 +352,13 @@ def rewrite_objc : Flag<"-rewrite-objc">, def rewrite_macros : Flag<"-rewrite-macros">, HelpText<"Expand macros without full preprocessing">; +def create_module : Flag<"-create-module">, + HelpText<"Create a module definition file">; } +def import_module : Separate<"-import-module">, + HelpText<"Import a module definition file">; + def relocatable_pch : Flag<"-relocatable-pch">, HelpText<"Whether to build a relocatable precompiled header">; def chained_pch : Flag<"-chained-pch">, @@ -353,9 +367,10 @@ def print_stats : Flag<"-print-stats">, HelpText<"Print performance metrics and statistics">; def ftime_report : Flag<"-ftime-report">, HelpText<"Print the amount of time each phase of compilation takes">; - def fdump_record_layouts : Flag<"-fdump-record-layouts">, HelpText<"Dump record layout information">; +def fix_what_you_can : Flag<"-fix-what-you-can">, + HelpText<"Apply fix-it advice even in the presence of unfixable errors">; // Generic forwarding to LLVM options. This should only be used for debugging // and experimental features. @@ -395,12 +410,16 @@ def ffreestanding : Flag<"-ffreestanding">, HelpText<"Assert that the compilation takes place in a freestanding environment">; def fgnu_runtime : Flag<"-fgnu-runtime">, HelpText<"Generate output compatible with the standard GNU Objective-C runtime">; +def fhidden_weak_vtables : Flag<"-fhidden-weak-vtables">, + HelpText<"Generate weak vtables and RTTI with hidden visibility">; def std_EQ : Joined<"-std=">, HelpText<"Language standard to compile for">; def fmath_errno : Flag<"-fmath-errno">, HelpText<"Require math functions to indicate errors by setting errno">; def fms_extensions : Flag<"-fms-extensions">, HelpText<"Accept some non-standard constructs used in Microsoft header files ">; +def fborland_extensions : Flag<"-fborland-extensions">, + HelpText<"Accept non-standard constructs supported by the Borland compiler">; def main_file_name : Separate<"-main-file-name">, HelpText<"Main file name to use for debug info">; def fno_elide_constructors : Flag<"-fno-elide-constructors">, @@ -444,6 +463,8 @@ def fpascal_strings : Flag<"-fpascal-strings">, HelpText<"Recognize and construct Pascal-style string literals">; def fno_rtti : Flag<"-fno-rtti">, HelpText<"Disable generation of rtti information">; +def fno_validate_pch : Flag<"-fno-validate-pch">, + HelpText<"Disable validation of precompiled headers">; def fshort_wchar : Flag<"-fshort-wchar">, HelpText<"Force wchar_t to be a short unsigned int">; def static_define : Flag<"-static-define">, @@ -483,6 +504,9 @@ def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">, HelpText<"Add directory to QUOTE include search path">; def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to SYSTEM include search path">; +def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">, + HelpText<"Add directory to SYSTEM include search path, " + "absolute paths are relative to -isysroot">; def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">, HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">; def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">, @@ -508,6 +532,9 @@ def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">, HelpText<"Include precompiled header file">; def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">, HelpText<"Include file before parsing">; +def preamble_bytes_EQ : Joined<"-preamble-bytes=">, + HelpText<"Assume that the precompiled header is a precompiled preamble " + "covering the first N bytes of the main file">; def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">, HelpText<"Use specified token cache file">; def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">, @@ -531,3 +558,5 @@ def dM : Flag<"-dM">, HelpText<"Print macro definitions in -E mode instead of normal output">; def dD : Flag<"-dD">, HelpText<"Print macro definitions in -E mode in addition to normal output">; +def H : Flag<"-H">, + HelpText<"Show header includes and nesting depth">; diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 5f062a121c6d..22d6b4ec6c8f 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -80,6 +80,8 @@ public: JobList &getJobs() { return Jobs; } const JobList &getJobs() const { return Jobs; } + void addCommand(Command *C) { Jobs.addJob(C); } + const ArgStringList &getTempFiles() const { return TempFiles; } const ArgStringList &getResultFiles() const { return ResultFiles; } diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index bb578b516ce3..28eff4f1d71d 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -37,7 +37,6 @@ namespace driver { class InputInfo; class JobAction; class OptTable; - class PipedJob; class ToolChain; /// Driver - Encapsulate logic for constructing compilation processes @@ -65,6 +64,9 @@ public: /// The original path to the clang executable. std::string ClangExecutable; + /// The path to the installed clang directory, if any. + std::string InstalledDir; + /// The path to the compiler resource directory. std::string ResourceDir; @@ -145,7 +147,7 @@ private: DerivedArgList *TranslateInputArgs(const InputArgList &Args) const; public: - Driver(llvm::StringRef _Name, llvm::StringRef _Dir, + Driver(llvm::StringRef _ClangExecutable, llvm::StringRef _DefaultHostTriple, llvm::StringRef _DefaultImageName, bool IsProduction, bool CXXIsProduction, @@ -167,8 +169,18 @@ public: void setTitle(std::string Value) { DriverTitle = Value; } /// \brief Get the path to the main clang executable. - std::string getClangProgramPath() const { - return ClangExecutable; + const char *getClangProgramPath() const { + return ClangExecutable.c_str(); + } + + /// \brief Get the path to where the clang executable was installed. + const char *getInstalledDir() const { + if (!InstalledDir.empty()) + return InstalledDir.c_str(); + return Dir.c_str(); + } + void setInstalledDir(llvm::StringRef Value) { + InstalledDir = Value; } /// @} @@ -194,16 +206,20 @@ public: /// BuildActions - Construct the list of actions to perform for the /// given arguments, which are only done for a single architecture. /// + /// \param TC - The default host tool chain. /// \param Args - The input arguments. /// \param Actions - The list to store the resulting actions onto. - void BuildActions(const ArgList &Args, ActionList &Actions) const; + void BuildActions(const ToolChain &TC, const ArgList &Args, + ActionList &Actions) const; /// BuildUniversalActions - Construct the list of actions to perform /// for the given arguments, which may require a universal build. /// + /// \param TC - The default host tool chain. /// \param Args - The input arguments. /// \param Actions - The list to store the resulting actions onto. - void BuildUniversalActions(const ArgList &Args, ActionList &Actions) const; + void BuildUniversalActions(const ToolChain &TC, const ArgList &Args, + ActionList &Actions) const; /// BuildJobs - Bind actions to concrete tools and translate /// arguments to form the list of jobs to run. @@ -278,7 +294,6 @@ public: const Action *A, const ToolChain *TC, const char *BoundArch, - bool CanAcceptPipe, bool AtTopLevel, const char *LinkingOutput, InputInfo &Result) const; diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h index 1b99a4459d16..04e72992d684 100644 --- a/include/clang/Driver/HostInfo.h +++ b/include/clang/Driver/HostInfo.h @@ -10,7 +10,6 @@ #ifndef CLANG_DRIVER_HOSTINFO_H_ #define CLANG_DRIVER_HOSTINFO_H_ -#include "clang/Driver/Types.h" #include "llvm/ADT/Triple.h" #include <string> @@ -48,10 +47,6 @@ public: /// this host and support -arch, -Xarch, etc. virtual bool useDriverDriver() const = 0; - /// lookupTypeForExtension - Return the default language type to use for the - /// given extension. - virtual types::ID lookupTypeForExtension(const char *Ext) const = 0; - /// CreateToolChain - Construct the toolchain to use for this host (which the /// host retains ownership of). /// @@ -84,6 +79,10 @@ const HostInfo *createLinuxHostInfo(const Driver &D, const llvm::Triple& Triple); const HostInfo *createTCEHostInfo(const Driver &D, const llvm::Triple& Triple); +const HostInfo *createWindowsHostInfo(const Driver &D, + const llvm::Triple &Triple); +const HostInfo *createMinGWHostInfo(const Driver &D, + const llvm::Triple &Triple); const HostInfo *createUnknownHostInfo(const Driver &D, const llvm::Triple& Triple); diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index 5a789fbb8f41..d2767d1b877b 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -29,7 +29,6 @@ class Job { public: enum JobClass { CommandClass, - PipedJobClass, JobListClass }; @@ -86,39 +85,6 @@ public: static bool classof(const Command *) { return true; } }; - /// PipedJob - A list of Commands which should be executed together - /// with their standard inputs and outputs connected. -class PipedJob : public Job { -public: - typedef llvm::SmallVector<Command*, 4> list_type; - typedef list_type::size_type size_type; - typedef list_type::iterator iterator; - typedef list_type::const_iterator const_iterator; - -private: - list_type Commands; - -public: - PipedJob(); - virtual ~PipedJob(); - - /// Add a command to the piped job (taking ownership). - void addCommand(Command *C) { Commands.push_back(C); } - - const list_type &getCommands() const { return Commands; } - - size_type size() const { return Commands.size(); } - iterator begin() { return Commands.begin(); } - const_iterator begin() const { return Commands.begin(); } - iterator end() { return Commands.end(); } - const_iterator end() const { return Commands.end(); } - - static bool classof(const Job *J) { - return J->getKind() == PipedJobClass; - } - static bool classof(const PipedJob *) { return true; } -}; - /// JobList - A sequence of jobs to perform. class JobList : public Job { public: diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td index a9f4289fc86e..04efd00fb1d8 100644 --- a/include/clang/Driver/OptParser.td +++ b/include/clang/Driver/OptParser.td @@ -82,6 +82,9 @@ def Unsupported : OptionFlag; // arguments to implement hidden help groups. def HelpHidden : OptionFlag; +// NoForward - The option should not be implicitly forwarded to other tools. +def NoForward : OptionFlag; + // Define the option group class. class OptionGroup<string name> { diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h index e4a2eba578b8..08b483c90017 100644 --- a/include/clang/Driver/OptTable.h +++ b/include/clang/Driver/OptTable.h @@ -25,10 +25,11 @@ namespace options { HelpHidden = (1 << 1), LinkerInput = (1 << 2), NoArgumentUnused = (1 << 3), - RenderAsInput = (1 << 4), - RenderJoined = (1 << 5), - RenderSeparate = (1 << 6), - Unsupported = (1 << 7) + NoForward = (1 << 4), + RenderAsInput = (1 << 5), + RenderJoined = (1 << 6), + RenderSeparate = (1 << 7), + Unsupported = (1 << 8) }; } @@ -52,7 +53,7 @@ namespace options { const char *HelpText; const char *MetaVar; unsigned char Kind; - unsigned char Flags; + unsigned short Flags; unsigned char Param; unsigned short GroupID; unsigned short AliasID; diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h index 0864382cb3a6..9625465f48f4 100644 --- a/include/clang/Driver/Option.h +++ b/include/clang/Driver/Option.h @@ -92,6 +92,9 @@ namespace driver { /// This option should not report argument unused errors. bool NoArgumentUnused : 1; + /// This option should not be implicitly forwarded. + bool NoForward : 1; + protected: Option(OptionClass Kind, OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); @@ -124,7 +127,12 @@ namespace driver { bool hasNoArgumentUnused() const { return NoArgumentUnused; } void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; } - bool hasForwardToGCC() const { return !DriverOption && !LinkerInput; } + bool hasNoForward() const { return NoForward; } + void setNoForward(bool Value) { NoForward = Value; } + + bool hasForwardToGCC() const { + return !NoForward && !DriverOption && !LinkerInput; + } /// getUnaliasedOption - Return the final option this option /// aliases (itself, if the option has no alias). diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 73c8e6bda2e4..c51d12a48769 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -180,7 +180,8 @@ def Xarch__ : JoinedAndSeparate<"-Xarch_">, Flags<[DriverOption]>; def Xassembler : Separate<"-Xassembler">, HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">; def Xclang : Separate<"-Xclang">, - HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">; + HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">, + Flags<[NoForward]>; def Xlinker : Separate<"-Xlinker">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">; def Xpreprocessor : Separate<"-Xpreprocessor">, @@ -242,6 +243,7 @@ def fast : Flag<"-fast">, Group<f_Group>; def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>; def fblocks : Flag<"-fblocks">, Group<f_Group>; def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>; +def fborland_extensions : Flag<"-fborland-extensions">, Group<f_Group>; def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>; def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>; def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>; @@ -260,6 +262,7 @@ def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>; def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group<f_Group>, Flags<[HelpHidden]>; def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>; def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>; +def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_Group>; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>; def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_Group>; def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>; @@ -300,6 +303,7 @@ def fno_asm : Flag<"-fno-asm">, Group<f_Group>; def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>; def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>; def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>; +def fno_borland_extensions : Flag<"-fno-borland-extensions">, Group<f_Group>; def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>; def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>; def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>; @@ -361,6 +365,7 @@ def fno_pie : Flag<"-fno-pie">, Group<f_Group>; def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>; def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>; def framework : Separate<"-framework">, Flags<[LinkerInput]>; +def frandom_seed_EQ : Joined<"-frandom-seed=">, Group<clang_ignored_f_Group>; def frtti : Flag<"-frtti">, Group<f_Group>; def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>; def fshort_enums : Flag<"-fshort-enums">, Group<clang_ignored_f_Group>; @@ -385,6 +390,7 @@ def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>; def ftime_report : Flag<"-ftime-report">, Group<f_Group>; def ftrapv : Flag<"-ftrapv">, Group<f_Group>; def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>; +def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>; def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>; def funsigned_char : Flag<"-funsigned-char">, Group<f_Group>; def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>; @@ -420,7 +426,7 @@ def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>; def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>; def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>; def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>; -def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<i_Group>; +def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<clang_i_Group>; def i : Joined<"-i">, Group<i_Group>; def keep__private__externs : Flag<"-keep_private_externs">; def l : JoinedOrSeparate<"-l">, Flags<[LinkerInput, RenderJoined]>; @@ -441,6 +447,7 @@ def mhard_float : Flag<"-mhard-float">, Group<m_Group>; def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>; def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias<miphoneos_version_min_EQ>; def mkernel : Flag<"-mkernel">, Group<m_Group>; +def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>; def mllvm : Separate<"-mllvm">; def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>; def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>; @@ -461,6 +468,7 @@ def mno_sse4_2 : Flag<"-mno-sse4.2">, Group<m_x86_Features_Group>; def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>; def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>; def mno_aes : Flag<"-mno-aes">, Group<m_x86_Features_Group>; +def mno_avx : Flag<"-mno-avx">, Group<m_x86_Features_Group>; def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>; def marm : Flag<"-marm">, Alias<mno_thumb>; @@ -481,6 +489,7 @@ def msse4_2 : Flag<"-msse4.2">, Group<m_x86_Features_Group>; def msse : Flag<"-msse">, Group<m_x86_Features_Group>; def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>; def maes : Flag<"-maes">, Group<m_x86_Features_Group>; +def mavx : Flag<"-mavx">, Group<m_x86_Features_Group>; def mthumb : Flag<"-mthumb">, Group<m_Group>; def mtune_EQ : Joined<"-mtune=">, Group<m_Group>; def multi__module : Flag<"-multi_module">; diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h index 4368a81e3a41..c30fa4c6e731 100644 --- a/include/clang/Driver/Tool.h +++ b/include/clang/Driver/Tool.h @@ -49,8 +49,6 @@ public: const ToolChain &getToolChain() const { return TheToolChain; } - virtual bool acceptsPipedInput() const = 0; - virtual bool canPipeOutput() const = 0; virtual bool hasIntegratedAssembler() const { return false; } virtual bool hasIntegratedCPP() const = 0; @@ -61,13 +59,11 @@ public: /// ConstructJob - Construct jobs to perform the action \arg JA, /// writing to \arg Output and with \arg Inputs. /// - /// \param Dest - Where to put the resulting commands. /// \param TCArgs - The argument list for this toolchain, with any /// tool chain specific translations applied. /// \param LinkingOutput - If this output will eventually feed the /// linker, then this is the final output name of the linked image. virtual void ConstructJob(Compilation &C, const JobAction &JA, - Job &Dest, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &TCArgs, diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 11a153c48ca3..55be4eee3d19 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -10,6 +10,7 @@ #ifndef CLANG_DRIVER_TOOLCHAIN_H_ #define CLANG_DRIVER_TOOLCHAIN_H_ +#include "clang/Driver/Types.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/System/Path.h" @@ -17,6 +18,7 @@ namespace clang { namespace driver { + class ArgList; class Compilation; class DerivedArgList; class Driver; @@ -53,6 +55,7 @@ public: const Driver &getDriver() const; const llvm::Triple &getTriple() const { return Triple; } + llvm::Triple::ArchType getArch() const { return Triple.getArch(); } llvm::StringRef getArchName() const { return Triple.getArchName(); } llvm::StringRef getPlatform() const { return Triple.getVendorName(); } llvm::StringRef getOS() const { return Triple.getOSName(); } @@ -89,6 +92,10 @@ public: // Platform defaults information + /// LookupTypeForExtension - Return the default language type to use for the + /// given extension. + virtual types::ID LookupTypeForExtension(const char *Ext) const; + /// IsBlocksDefault - Does this tool chain enable -fblocks by default. virtual bool IsBlocksDefault() const { return false; } @@ -135,6 +142,17 @@ public: /// UseSjLjExceptions - Does this tool chain use SjLj exceptions. virtual bool UseSjLjExceptions() const { return false; } + + /// ComputeLLVMTriple - Return the LLVM target triple to use, after taking + /// command line arguments into account. + virtual std::string ComputeLLVMTriple(const ArgList &Args) const; + + /// ComputeEffectiveClangTriple - Return the Clang triple to use for this + /// target, which may take into account the command line arguments. For + /// example, on Darwin the -mmacosx-version-min= command line argument (which + /// sets the deployment target) determines the version in the triple passed to + /// Clang. + virtual std::string ComputeEffectiveClangTriple(const ArgList &Args) const; }; } // end namespace driver diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 2d1df44cc968..cca243d6cd71 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -29,7 +29,6 @@ class CodeGenOptions; class Diagnostic; class FileManager; class LangOptions; -class PCHReader; class Preprocessor; class TargetOptions; @@ -58,14 +57,6 @@ ASTConsumer *CreateASTViewer(); // to stderr; this is intended for debugging. ASTConsumer *CreateDeclContextPrinter(); -// PCH generator: generates a precompiled header file; this file can be used -// later with the PCHReader (clang -cc1 option -include-pch) to speed up compile -// times. -ASTConsumer *CreatePCHGenerator(const Preprocessor &PP, - llvm::raw_ostream *OS, - PCHReader *Chain, - const char *isysroot = 0); - // Inheritance viewer: for C++ code, creates a graph of the inheritance // tree for the given class and displays it with "dotty". ASTConsumer *CreateInheritanceViewer(const std::string& clsname); diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 9252358f42a6..e3fd4b37edac 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -14,19 +14,26 @@ #ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H #define LLVM_CLANG_FRONTEND_ASTUNIT_H +#include "clang/Index/ASTLocation.h" +#include "clang/Serialization/ASTBitCodes.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/FileManager.h" +#include "clang-c/Index.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" -#include "clang/Basic/FileManager.h" -#include "clang/Index/ASTLocation.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/System/Path.h" +#include "llvm/Support/Timer.h" #include <map> #include <string> #include <vector> #include <cassert> #include <utility> +#include <sys/types.h> namespace llvm { class MemoryBuffer; @@ -34,6 +41,7 @@ namespace llvm { namespace clang { class ASTContext; +class CodeCompleteConsumer; class CompilerInvocation; class Decl; class Diagnostic; @@ -45,13 +53,14 @@ class SourceManager; class TargetInfo; using namespace idx; - -/// \brief Utility class for loading a ASTContext from a PCH file. + +/// \brief Utility class for loading a ASTContext from an AST file. /// class ASTUnit { public: typedef std::map<FileID, std::vector<PreprocessedEntity *> > PreprocessedEntitiesByFileMap; + private: llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; llvm::OwningPtr<FileManager> FileMgr; @@ -61,18 +70,32 @@ private: llvm::OwningPtr<Preprocessor> PP; llvm::OwningPtr<ASTContext> Ctx; + /// \brief The AST consumer that received information about the translation + /// unit as it was parsed or loaded. + llvm::OwningPtr<ASTConsumer> Consumer; + + /// \brief The semantic analysis object used to type-check the translation + /// unit. + llvm::OwningPtr<Sema> TheSema; + /// Optional owned invocation, just used to make the invocation used in /// LoadFromCommandLine available. llvm::OwningPtr<CompilerInvocation> Invocation; - + // OnlyLocalDecls - when true, walking this AST should only visit declarations // that come from the AST itself, not from included precompiled headers. // FIXME: This is temporary; eventually, CIndex will always do this. bool OnlyLocalDecls; - /// Track whether the main file was loaded from an AST or not. + /// \brief Whether to capture any diagnostics produced. + bool CaptureDiagnostics; + + /// \brief Track whether the main file was loaded from an AST or not. bool MainFileIsAST; + /// \brief Whether this AST represents a complete translation unit. + bool CompleteTranslationUnit; + /// Track the top-level decls which appeared in an ASTUnit which was loaded /// from a source file. // @@ -114,12 +137,189 @@ private: unsigned int ConcurrencyCheckValue; static const unsigned int CheckLocked = 28573289; static const unsigned int CheckUnlocked = 9803453; + + /// \brief Counter that determines when we want to try building a + /// precompiled preamble. + /// + /// If zero, we will never build a precompiled preamble. Otherwise, + /// it's treated as a counter that decrements each time we reparse + /// without the benefit of a precompiled preamble. When it hits 1, + /// we'll attempt to rebuild the precompiled header. This way, if + /// building the precompiled preamble fails, we won't try again for + /// some number of calls. + unsigned PreambleRebuildCounter; + + /// \brief The file in which the precompiled preamble is stored. + std::string PreambleFile; + + /// \brief The contents of the preamble that has been precompiled to + /// \c PreambleFile. + std::vector<char> Preamble; + + /// \brief Whether the preamble ends at the start of a new line. + /// + /// Used to inform the lexer as to whether it's starting at the beginning of + /// a line after skipping the preamble. + bool PreambleEndsAtStartOfLine; + + /// \brief The size of the source buffer that we've reserved for the main + /// file within the precompiled preamble. + unsigned PreambleReservedSize; + + /// \brief Keeps track of the files that were used when computing the + /// preamble, with both their buffer size and their modification time. + /// + /// If any of the files have changed from one compile to the next, + /// the preamble must be thrown away. + llvm::StringMap<std::pair<off_t, time_t> > FilesInPreamble; + + /// \brief When non-NULL, this is the buffer used to store the contents of + /// the main file when it has been padded for use with the precompiled + /// preamble. + llvm::MemoryBuffer *SavedMainFileBuffer; + + /// \brief When non-NULL, this is the buffer used to store the + /// contents of the preamble when it has been padded to build the + /// precompiled preamble. + llvm::MemoryBuffer *PreambleBuffer; + + /// \brief The number of warnings that occurred while parsing the preamble. + /// + /// This value will be used to restore the state of the \c Diagnostic object + /// when re-using the precompiled preamble. Note that only the + /// number of warnings matters, since we will not save the preamble + /// when any errors are present. + unsigned NumWarningsInPreamble; + + /// \brief The number of diagnostics that were stored when parsing + /// the precompiled preamble. + /// + /// This value is used to determine how many of the stored + /// diagnostics should be retained when reparsing in the presence of + /// a precompiled preamble. + unsigned NumStoredDiagnosticsInPreamble; + + /// \brief The group of timers associated with this translation unit. + llvm::OwningPtr<llvm::TimerGroup> TimerGroup; + + /// \brief A list of the serialization ID numbers for each of the top-level + /// declarations parsed within the precompiled preamble. + std::vector<serialization::DeclID> TopLevelDeclsInPreamble; + + /// + /// \defgroup CodeCompleteCaching Code-completion caching + /// + /// \{ + /// + + /// \brief Whether we should be caching code-completion results. + bool ShouldCacheCodeCompletionResults; + +public: + /// \brief A cached code-completion result, which may be introduced in one of + /// many different contexts. + struct CachedCodeCompletionResult { + /// \brief The code-completion string corresponding to this completion + /// result. + CodeCompletionString *Completion; + + /// \brief A bitmask that indicates which code-completion contexts should + /// contain this completion result. + /// + /// The bits in the bitmask correspond to the values of + /// CodeCompleteContext::Kind. To map from a completion context kind to a + /// bit, subtract one from the completion context kind and shift 1 by that + /// number of bits. Many completions can occur in several different + /// contexts. + unsigned ShowInContexts; + + /// \brief The priority given to this code-completion result. + unsigned Priority; + + /// \brief The libclang cursor kind corresponding to this code-completion + /// result. + CXCursorKind Kind; + + /// \brief The availability of this code-completion result. + CXAvailabilityKind Availability; + + /// \brief The simplified type class for a non-macro completion result. + SimplifiedTypeClass TypeClass; + + /// \brief The type of a non-macro completion result, stored as a unique + /// integer used by the string map of cached completion types. + /// + /// This value will be zero if the type is not known, or a unique value + /// determined by the formatted type string. Se \c CachedCompletionTypes + /// for more information. + unsigned Type; + }; + + /// \brief Retrieve the mapping from formatted type names to unique type + /// identifiers. + llvm::StringMap<unsigned> &getCachedCompletionTypes() { + return CachedCompletionTypes; + } + +private: + /// \brief The set of cached code-completion results. + std::vector<CachedCodeCompletionResult> CachedCompletionResults; + + /// \brief A mapping from the formatted type name to a unique number for that + /// type, which is used for type equality comparisons. + llvm::StringMap<unsigned> CachedCompletionTypes; + + /// \brief The number of top-level declarations present the last time we + /// cached code-completion results. + /// + /// The value is used to help detect when we should repopulate the global + /// completion cache. + unsigned NumTopLevelDeclsAtLastCompletionCache; + + /// \brief The number of reparses left until we'll consider updating the + /// code-completion cache. + /// + /// This is meant to avoid thrashing during reparsing, by not allowing the + /// code-completion cache to be updated on every reparse. + unsigned CacheCodeCompletionCoolDown; + + /// \brief Bit used by CIndex to mark when a translation unit may be in an + /// inconsistent state, and is not safe to free. + unsigned UnsafeToFree : 1; + + /// \brief Cache any "global" code-completion results, so that we can avoid + /// recomputing them with each completion. + void CacheCodeCompletionResults(); + + /// \brief Clear out and deallocate + void ClearCachedCompletionResults(); + + /// + /// \} + /// + + /// \brief The timers we've created from the various parses, reparses, etc. + /// involved in this translation unit. + std::vector<llvm::Timer *> Timers; ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT explicit ASTUnit(bool MainFileIsAST); + void CleanTemporaryFiles(); + bool Parse(llvm::MemoryBuffer *OverrideMainBuffer); + + std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > + ComputePreamble(CompilerInvocation &Invocation, + unsigned MaxLines, bool &CreatedBuffer); + + llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble( + CompilerInvocation PreambleInvocation, + bool AllowRebuild = true, + unsigned MaxLines = 0); + void RealizeTopLevelDeclsFromPreamble(); + public: class ConcurrencyCheck { volatile ASTUnit &Self; @@ -143,6 +343,9 @@ public: bool isMainFileAST() const { return MainFileIsAST; } + bool isUnsafeToFree() const { return UnsafeToFree; } + void setUnsafeToFree(bool Value) { UnsafeToFree = Value; } + const Diagnostic &getDiagnostics() const { return *Diagnostics; } Diagnostic &getDiagnostics() { return *Diagnostics; } @@ -155,11 +358,17 @@ public: const ASTContext &getASTContext() const { return *Ctx.get(); } ASTContext &getASTContext() { return *Ctx.get(); } + bool hasSema() const { return TheSema; } + Sema &getSema() const { + assert(TheSema && "ASTUnit does not have a Sema object!"); + return *TheSema; + } + const FileManager &getFileManager() const { return *FileMgr; } FileManager &getFileManager() { return *FileMgr; } const std::string &getOriginalSourceFileName(); - const std::string &getPCHFileName(); + const std::string &getASTFileName(); /// \brief Add a temporary file that the ASTUnit depends on. /// @@ -170,16 +379,48 @@ public: bool getOnlyLocalDecls() const { return OnlyLocalDecls; } + /// \brief Retrieve the maximum PCH level of declarations that a + /// traversal of the translation unit should consider. + unsigned getMaxPCHLevel() const; + void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; } ASTLocation getLastASTLocation() const { return LastLoc; } - std::vector<Decl*> &getTopLevelDecls() { + typedef std::vector<Decl *>::iterator top_level_iterator; + + top_level_iterator top_level_begin() { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + if (!TopLevelDeclsInPreamble.empty()) + RealizeTopLevelDeclsFromPreamble(); + return TopLevelDecls.begin(); + } + + top_level_iterator top_level_end() { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + if (!TopLevelDeclsInPreamble.empty()) + RealizeTopLevelDeclsFromPreamble(); + return TopLevelDecls.end(); + } + + std::size_t top_level_size() const { assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); - return TopLevelDecls; + return TopLevelDeclsInPreamble.size() + TopLevelDecls.size(); } - const std::vector<Decl*> &getTopLevelDecls() const { + + bool top_level_empty() const { assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); - return TopLevelDecls; + return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty(); + } + + /// \brief Add a new top-level declaration. + void addTopLevelDecl(Decl *D) { + TopLevelDecls.push_back(D); + } + + /// \brief Add a new top-level declaration, identified by its ID in + /// the precompiled preamble. + void addTopLevelDeclFromPreamble(serialization::DeclID D) { + TopLevelDeclsInPreamble.push_back(D); } /// \brief Retrieve the mapping from File IDs to the preprocessed entities @@ -202,19 +443,40 @@ public: return StoredDiagnostics; } + typedef std::vector<CachedCodeCompletionResult>::iterator + cached_completion_iterator; + + cached_completion_iterator cached_completion_begin() { + return CachedCompletionResults.begin(); + } + + cached_completion_iterator cached_completion_end() { + return CachedCompletionResults.end(); + } + + unsigned cached_completion_size() const { + return CachedCompletionResults.size(); + } + + /// \brief Whether this AST represents a complete translation unit. + /// + /// If false, this AST is only a partial translation unit, e.g., one + /// that might still be used as a precompiled header or preamble. + bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; } + /// \brief A mapping from a file name to the memory buffer that stores the /// remapped contents of that file. typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile; - /// \brief Create a ASTUnit from a PCH file. + /// \brief Create a ASTUnit from an AST file. /// - /// \param Filename - The PCH file to load. + /// \param Filename - The AST file to load. /// /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. /// - /// \returns - The initialized ASTUnit or null if the PCH failed to load. - static ASTUnit *LoadFromPCHFile(const std::string &Filename, + /// \returns - The initialized ASTUnit or null if the AST failed to load. + static ASTUnit *LoadFromASTFile(const std::string &Filename, llvm::IntrusiveRefCntPtr<Diagnostic> Diags, bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, @@ -235,7 +497,10 @@ public: static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, llvm::IntrusiveRefCntPtr<Diagnostic> Diags, bool OnlyLocalDecls = false, - bool CaptureDiagnostics = false); + bool CaptureDiagnostics = false, + bool PrecompilePreamble = false, + bool CompleteTranslationUnit = true, + bool CacheCodeCompletionResults = false); /// LoadFromCommandLine - Create an ASTUnit from a vector of command line /// arguments, which must specify exactly one source file. @@ -258,7 +523,49 @@ public: bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0, - bool CaptureDiagnostics = false); + bool CaptureDiagnostics = false, + bool PrecompilePreamble = false, + bool CompleteTranslationUnit = true, + bool CacheCodeCompletionResults = false); + + /// \brief Reparse the source files using the same command-line options that + /// were originally used to produce this translation unit. + /// + /// \returns True if a failure occurred that causes the ASTUnit not to + /// contain any translation-unit information, false otherwise. + bool Reparse(RemappedFile *RemappedFiles = 0, + unsigned NumRemappedFiles = 0); + + /// \brief Perform code completion at the given file, line, and + /// column within this translation unit. + /// + /// \param File The file in which code completion will occur. + /// + /// \param Line The line at which code completion will occur. + /// + /// \param Column The column at which code completion will occur. + /// + /// \param IncludeMacros Whether to include macros in the code-completion + /// results. + /// + /// \param IncludeCodePatterns Whether to include code patterns (such as a + /// for loop) in the code-completion results. + /// + /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and + /// OwnedBuffers parameters are all disgusting hacks. They will go away. + void CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, + RemappedFile *RemappedFiles, unsigned NumRemappedFiles, + bool IncludeMacros, bool IncludeCodePatterns, + CodeCompleteConsumer &Consumer, + Diagnostic &Diag, LangOptions &LangOpts, + SourceManager &SourceMgr, FileManager &FileMgr, + llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, + llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers); + + /// \brief Save this translation unit to a file with the given name. + /// + /// \returns True if an error occurred, false otherwise. + bool Save(llvm::StringRef File); }; } // namespace clang diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h index ab4aed96d864..9ed15ba2f996 100644 --- a/include/clang/Frontend/AnalyzerOptions.h +++ b/include/clang/Frontend/AnalyzerOptions.h @@ -66,6 +66,7 @@ public: unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; unsigned EagerlyAssume : 1; + unsigned IdempotentOps : 1; unsigned PurgeDead : 1; unsigned TrimGraph : 1; unsigned VisualizeEGDot : 1; @@ -74,6 +75,7 @@ public: unsigned EnableExperimentalInternalChecks : 1; unsigned EnableIdempotentOperationChecker : 1; unsigned InlineCall : 1; + unsigned UnoptimizedCFG : 1; public: AnalyzerOptions() { @@ -90,6 +92,7 @@ public: VisualizeEGUbi = 0; EnableExperimentalChecks = 0; EnableExperimentalInternalChecks = 0; + UnoptimizedCFG = 0; } }; diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 2918f4e9d3cb..b3f57094b4af 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -46,7 +46,14 @@ public: /// internal state before optimizations are /// done. unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled. + unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what Decl* + /// various IR entities came from. Only useful + /// when running CodeGen as a subroutine. unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled + unsigned HiddenWeakTemplateVTables : 1; /// Emit weak vtables and RTTI for + /// template classes with hidden visibility + unsigned HiddenWeakVTables : 1; /// Emit weak vtables, RTTI, and thunks with + /// hidden visibility unsigned InstrumentFunctions : 1; /// Set when -finstrument-functions is enabled unsigned MergeAllConstants : 1; /// Merge identical constants. unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. @@ -67,9 +74,6 @@ public: unsigned UnwindTables : 1; /// Emit unwind tables. unsigned VerifyModule : 1; /// Control whether the module should be run /// through the LLVM Verifier. - unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what Decl* - /// various IR entities came from. Only useful - /// when running CodeGen as a subroutine. /// The code model to use (-mcmodel). std::string CodeModel; @@ -108,7 +112,11 @@ public: DisableFPElim = 0; DisableLLVMOpts = 0; DisableRedZone = 0; + EmitDeclMetadata = 0; FunctionSections = 0; + HiddenWeakTemplateVTables = 0; + HiddenWeakVTables = 0; + InstrumentFunctions = 0; MergeAllConstants = 1; NoCommon = 0; NoImplicitFloat = 0; @@ -125,7 +133,6 @@ public: UnrollLoops = 0; UnwindTables = 0; VerifyModule = 1; - EmitDeclMetadata = 0; Inlining = NoInlining; RelocationModel = "pic"; diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 54ce8bfe3ba0..1b3c336fc0eb 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -34,8 +34,9 @@ class DiagnosticClient; class ExternalASTSource; class FileManager; class FrontendAction; -class PCHReader; +class ASTReader; class Preprocessor; +class Sema; class SourceManager; class TargetInfo; @@ -67,9 +68,6 @@ class CompilerInstance { /// The diagnostics engine instance. llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; - /// The diagnostics client instance. - llvm::OwningPtr<DiagnosticClient> DiagClient; - /// The target being compiled for. llvm::OwningPtr<TargetInfo> Target; @@ -91,15 +89,15 @@ class CompilerInstance { /// The code completion consumer. llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer; + /// \brief The semantic analysis object. + llvm::OwningPtr<Sema> TheSema; + /// The frontend timer llvm::OwningPtr<llvm::Timer> FrontendTimer; /// The list of active output files. std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles; - /// The PCH reader. Not owned; the ASTContext owns this. - PCHReader *Reader; - void operator=(const CompilerInstance &); // DO NOT IMPLEMENT CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT public: @@ -265,18 +263,11 @@ public: void setDiagnostics(Diagnostic *Value); DiagnosticClient &getDiagnosticClient() const { - assert(DiagClient && "Compiler instance has no diagnostic client!"); - return *DiagClient; + assert(Diagnostics && Diagnostics->getClient() && + "Compiler instance has no diagnostic client!"); + return *Diagnostics->getClient(); } - /// takeDiagnosticClient - Remove the current diagnostics client and give - /// ownership to the caller. - DiagnosticClient *takeDiagnosticClient() { return DiagClient.take(); } - - /// setDiagnosticClient - Replace the current diagnostics client; the compiler - /// instance takes ownership of \arg Value. - void setDiagnosticClient(DiagnosticClient *Value); - /// } /// @name Target Info /// { @@ -372,6 +363,10 @@ public: /// takes ownership of \arg Value. void setASTContext(ASTContext *Value); + /// \brief Replace the current Sema; the compiler instance takes ownership + /// of S. + void setSema(Sema *S); + /// } /// @name ASTConsumer /// { @@ -392,6 +387,18 @@ public: void setASTConsumer(ASTConsumer *Value); /// } + /// @name Semantic analysis + /// { + bool hasSema() const { return TheSema != 0; } + + Sema &getSema() const { + assert(TheSema && "Compiler instance has no Sema object!"); + return *TheSema; + } + + Sema *takeSema() { return TheSema.take(); } + + /// } /// @name Code Completion /// { @@ -502,17 +509,18 @@ public: /// Create an external AST source to read a PCH file and attach it to the AST /// context. - void createPCHExternalASTSource(llvm::StringRef Path); + void createPCHExternalASTSource(llvm::StringRef Path, + bool DisablePCHValidation, + void *DeserializationListener); /// Create an external AST source to read a PCH file. /// /// \return - The new object on success, or null on failure. static ExternalASTSource * createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot, - Preprocessor &PP, ASTContext &Context); - - /// Get the PCH reader, if any. - PCHReader *getPCHReader() { return Reader; } + bool DisablePCHValidation, + Preprocessor &PP, ASTContext &Context, + void *DeserializationListener); /// Create a code completion consumer using the invocation; note that this /// will cause the source manager to truncate the input source file at the @@ -526,8 +534,13 @@ public: createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename, unsigned Line, unsigned Column, bool UseDebugPrinter, bool ShowMacros, - bool ShowCodePatterns, llvm::raw_ostream &OS); + bool ShowCodePatterns, bool ShowGlobals, + llvm::raw_ostream &OS); + /// \brief Create the Sema object to be used for parsing. + void createSema(bool CompleteTranslationUnit, + CodeCompleteConsumer *CompletionConsumer); + /// Create the frontend timer and replace any existing one with it. void createFrontendTimer(); diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def index 16551ee03e1f..18451189bc06 100644 --- a/include/clang/Frontend/DeclXML.def +++ b/include/clang/Frontend/DeclXML.def @@ -95,10 +95,10 @@ NODE_XML(FunctionDecl, "Function") TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") - ENUM_XML(FunctionDecl::None, "") - ENUM_XML(FunctionDecl::Extern, "extern") - ENUM_XML(FunctionDecl::Static, "static") - ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__") + ENUM_XML(SC_None, "") + ENUM_XML(SC_Extern, "extern") + ENUM_XML(SC_Static, "static") + ENUM_XML(SC_PrivateExtern, "__private_extern__") END_ENUM_XML ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") //ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference @@ -289,12 +289,12 @@ NODE_XML(VarDecl, "Var") ATTRIBUTE_XML(getNameAsString(), "name") TYPE_ATTRIBUTE_XML(getType()) ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") - ENUM_XML(VarDecl::None, "") - ENUM_XML(VarDecl::Auto, "auto") - ENUM_XML(VarDecl::Register, "register") - ENUM_XML(VarDecl::Extern, "extern") - ENUM_XML(VarDecl::Static, "static") - ENUM_XML(VarDecl::PrivateExtern, "__private_extern__") + ENUM_XML(SC_None, "") + ENUM_XML(SC_Auto, "auto") + ENUM_XML(SC_Register, "register") + ENUM_XML(SC_Extern, "extern") + ENUM_XML(SC_Static, "static") + ENUM_XML(SC_PrivateExtern, "__private_extern__") END_ENUM_XML SUB_NODE_OPT_XML(Expr) // init expr END_NODE_XML diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index 516dc67b425d..c80bc037212b 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -30,6 +30,7 @@ public: unsigned ShowCarets : 1; /// Show carets in diagnostics. unsigned ShowFixits : 1; /// Show fixit information. unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form. + unsigned ShowParseableFixits : 1; /// Show machine parseable fix-its. unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable /// diagnostics. unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number, @@ -83,6 +84,7 @@ public: ShowOptionNames = 0; ShowCategories = 0; ShowSourceRanges = 0; + ShowParseableFixits = 0; VerifyDiagnostics = 0; BinaryOutput = 0; ErrorLimit = 0; diff --git a/include/clang/Frontend/DocumentXML.h b/include/clang/Frontend/DocumentXML.h index 73d892105f21..602d84655828 100644 --- a/include/clang/Frontend/DocumentXML.h +++ b/include/clang/Frontend/DocumentXML.h @@ -150,7 +150,6 @@ inline void DocumentXML::addAttribute(const char* pName, const T& value) { { llvm::raw_string_ostream buf(repr); buf << value; - buf.flush(); } Out << ' ' << pName << "=\"" diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index f6a68bf69e89..773543ac06a5 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -145,8 +145,8 @@ public: /// @{ /// usesPreprocessorOnly - Does this action only use the preprocessor? If so - /// no AST context will be created and this action will be invalid with PCH - /// inputs. + /// no AST context will be created and this action will be invalid with AST + /// file inputs. virtual bool usesPreprocessorOnly() const = 0; /// usesCompleteTranslationUnit - For AST based actions, should the @@ -225,8 +225,14 @@ protected: llvm::StringRef InFile) = 0; public: - virtual bool ParseArgs(const std::vector<std::string>& arg) = 0; - virtual void PrintHelp(llvm::raw_ostream&) = 0; + /// ParseArgs - Parse the given plugin command line arguments. + /// + /// \param CI - The compiler instance, for use in reporting diagnostics. + /// \return True if the parsing succeeded; otherwise the plugin will be + /// destroyed and no action run. The plugin is responsible for using the + /// CompilerInstance's Diagnostic object to report errors. + virtual bool ParseArgs(const CompilerInstance &CI, + const std::vector<std::string> &arg) = 0; }; /// PreprocessorFrontendAction - Abstract base class to use for preprocessor diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 26262cfa9522..7b8063ce549c 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -74,6 +74,17 @@ protected: virtual bool usesCompleteTranslationUnit() { return false; } virtual bool hasASTFileSupport() const { return false; } + +public: + /// \brief Compute the AST consumer arguments that will be used to + /// create the PCHGenerator instance returned by CreateASTConsumer. + /// + /// \returns true if an error occurred, false otherwise. + static bool ComputeASTConsumerArguments(CompilerInstance &CI, + llvm::StringRef InFile, + std::string &Sysroot, + llvm::raw_ostream *&OS, + bool &Chaining); }; class InheritanceViewAction : public ASTFrontendAction { @@ -134,6 +145,16 @@ public: virtual bool hasCodeCompletionSupport() const; }; +class PrintPreambleAction : public FrontendAction { +protected: + void ExecuteAction(); + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &, llvm::StringRef) { + return 0; + } + + virtual bool usesPreprocessorOnly() const { return true; } +}; + //===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// @@ -153,28 +174,18 @@ protected: void ExecuteAction(); }; -class ParseOnlyAction : public PreprocessorFrontendAction { -protected: - void ExecuteAction(); -}; - class PreprocessOnlyAction : public PreprocessorFrontendAction { protected: void ExecuteAction(); }; -class PrintParseAction : public PreprocessorFrontendAction { -protected: - void ExecuteAction(); -}; - class PrintPreprocessedAction : public PreprocessorFrontendAction { protected: void ExecuteAction(); virtual bool hasPCHSupport() const { return true; } }; - + } // end namespace clang #endif diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 4010ea6dd7dc..4c16d084fc0d 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -25,6 +25,7 @@ namespace frontend { ASTPrintXML, ///< Parse ASTs and print them in XML. ASTView, ///< Parse ASTs and view them in Graphviz. BoostCon, ///< BoostCon mode. + CreateModule, ///< Create module definition DumpRawTokens, ///< Dump out raw tokens. DumpTokens, ///< Dump out preprocessed tokens. EmitAssembly, ///< Emit a .s file. @@ -39,11 +40,10 @@ namespace frontend { GeneratePTH, ///< Generate pre-tokenized header. InheritanceView, ///< View C++ inheritance for a specified class. InitOnly, ///< Only execute frontend initialization. - ParseNoop, ///< Parse with noop callbacks. - ParsePrintCallbacks, ///< Parse and print each callback. ParseSyntaxOnly, ///< Parse and perform semantic analysis. PluginAction, ///< Run a plugin action, \see ActionName. PrintDeclContext, ///< Print DeclContext and their Decls. + PrintPreamble, ///< Print the "preamble" of the input file PrintPreprocessedInput, ///< -E mode. RewriteMacros, ///< Expand macros but not #includes. RewriteObjC, ///< ObjC->C Rewriter. @@ -60,21 +60,25 @@ public: /// completion results. unsigned DisableFree : 1; ///< Disable memory freeing on exit. unsigned RelocatablePCH : 1; ///< When generating PCH files, - /// instruct the PCH writer to create + /// instruct the AST writer to create /// relocatable PCH files. unsigned ChainedPCH : 1; ///< When generating PCH files, - /// instruct the PCH writer to create + /// instruct the AST writer to create /// chained PCH files. unsigned ShowHelp : 1; ///< Show the -help text. unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion /// results. unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code /// completion results. + unsigned ShowGlobalSymbolsInCodeCompletion : 1; ///< Show top-level decls in + /// code completion results. unsigned ShowStats : 1; ///< Show frontend performance /// metrics and statistics. unsigned ShowTimers : 1; ///< Show timers for individual /// actions. unsigned ShowVersion : 1; ///< Show the -version text. + unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are + /// unfixable errors. /// The input files and their types. std::vector<std::pair<InputKind, std::string> > Inputs; @@ -106,6 +110,9 @@ public: /// \brief The list of AST files to merge. std::vector<std::string> ASTMergeFiles; + /// \brief The list of modules to import. + std::vector<std::string> Modules; + /// \brief A list of arguments to forward to LLVM's option processing; this /// should only be used for debugging and experimental features. std::vector<std::string> LLVMArgs; @@ -121,6 +128,7 @@ public: ShowHelp = 0; ShowMacrosInCodeCompletion = 0; ShowCodePatternsInCodeCompletion = 0; + ShowGlobalSymbolsInCodeCompletion = 1; ShowStats = 0; ShowTimers = 0; ShowVersion = 0; diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index c6682451835a..588d32bf736e 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -35,11 +35,16 @@ public: frontend::IncludeDirGroup Group; unsigned IsUserSupplied : 1; unsigned IsFramework : 1; - - Entry(llvm::StringRef _Path, frontend::IncludeDirGroup _Group, - bool _IsUserSupplied, bool _IsFramework) - : Path(_Path), Group(_Group), IsUserSupplied(_IsUserSupplied), - IsFramework(_IsFramework) {} + + /// IsSysRootRelative - This is true if an absolute path should be treated + /// relative to the sysroot, or false if it should always be the absolute + /// path. + unsigned IsSysRootRelative : 1; + + Entry(llvm::StringRef path, frontend::IncludeDirGroup group, + bool isUserSupplied, bool isFramework, bool isSysRootRelative) + : Path(path), Group(group), IsUserSupplied(isUserSupplied), + IsFramework(isFramework), IsSysRootRelative(isSysRootRelative) {} }; /// If non-empty, the directory to use as a "virtual system root" for include @@ -85,8 +90,9 @@ public: /// AddPath - Add the \arg Path path to the specified \arg Group list. void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group, - bool IsUserSupplied, bool IsFramework) { - UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework)); + bool IsUserSupplied, bool IsFramework, bool IsSysRootRelative) { + UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework, + IsSysRootRelative)); } }; diff --git a/include/clang/Frontend/PCHDeserializationListener.h b/include/clang/Frontend/PCHDeserializationListener.h deleted file mode 100644 index c9b90e22c8cd..000000000000 --- a/include/clang/Frontend/PCHDeserializationListener.h +++ /dev/null @@ -1,36 +0,0 @@ -//===- PCHDeserializationListener.h - Decl/Type PCH Read Events -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PCHDeserializationListener class, which is notified -// by the PCHReader whenever a type or declaration is deserialized. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_FRONTEND_PCH_DESERIALIZATION_LISTENER_H -#define LLVM_CLANG_FRONTEND_PCH_DESERIALIZATION_LISTENER_H - -#include "clang/Frontend/PCHBitCodes.h" - -namespace clang { - -class Decl; -class QualType; - -class PCHDeserializationListener { -protected: - ~PCHDeserializationListener() {} - -public: - virtual void TypeRead(pch::TypeID ID, QualType T) = 0; - virtual void DeclRead(pch::DeclID ID, const Decl *D) = 0; -}; - -} - -#endif diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h index 891359b74784..851c1f0108af 100644 --- a/include/clang/Frontend/PreprocessorOptions.h +++ b/include/clang/Frontend/PreprocessorOptions.h @@ -43,6 +43,17 @@ public: /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; + /// \brief When true, disables most of the normal validation performed on + /// precompiled headers. + bool DisablePCHValidation; + + /// \brief If non-zero, the implicit PCH include is actually a precompiled + /// preamble that covers this number of bytes in the main source file. + /// + /// The boolean indicates whether the preamble ends at the start of a new + /// line. + std::pair<unsigned, bool> PrecompiledPreambleBytes; + /// The implicit PTH input included at the start of the translation unit, or /// empty. std::string ImplicitPTHInclude; @@ -62,26 +73,53 @@ public: std::vector<std::pair<std::string, const llvm::MemoryBuffer *> > RemappedFileBuffers; - typedef std::vector<std::pair<std::string, std::string> >::const_iterator + /// \brief Whether the compiler instance should retain (i.e., not free) + /// the buffers associated with remapped files. + /// + /// This flag defaults to false; it can be set true only through direct + /// manipulation of the compiler invocation object, in cases where the + /// compiler invocation and its buffers will be reused. + bool RetainRemappedFileBuffers; + + typedef std::vector<std::pair<std::string, std::string> >::iterator remapped_file_iterator; - remapped_file_iterator remapped_file_begin() const { + typedef std::vector<std::pair<std::string, std::string> >::const_iterator + const_remapped_file_iterator; + remapped_file_iterator remapped_file_begin() { return RemappedFiles.begin(); } - remapped_file_iterator remapped_file_end() const { + const_remapped_file_iterator remapped_file_begin() const { + return RemappedFiles.begin(); + } + remapped_file_iterator remapped_file_end() { + return RemappedFiles.end(); + } + const_remapped_file_iterator remapped_file_end() const { return RemappedFiles.end(); } typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >:: - const_iterator remapped_file_buffer_iterator; - remapped_file_buffer_iterator remapped_file_buffer_begin() const { + iterator remapped_file_buffer_iterator; + typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >:: + const_iterator const_remapped_file_buffer_iterator; + remapped_file_buffer_iterator remapped_file_buffer_begin() { return RemappedFileBuffers.begin(); } - remapped_file_buffer_iterator remapped_file_buffer_end() const { + const_remapped_file_buffer_iterator remapped_file_buffer_begin() const { + return RemappedFileBuffers.begin(); + } + remapped_file_buffer_iterator remapped_file_buffer_end() { + return RemappedFileBuffers.end(); + } + const_remapped_file_buffer_iterator remapped_file_buffer_end() const { return RemappedFileBuffers.end(); } public: - PreprocessorOptions() : UsePredefines(true), DetailedRecord(false) {} + PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), + DisablePCHValidation(false), + PrecompiledPreambleBytes(0, true), + RetainRemappedFileBuffers(false) { } void addMacroDef(llvm::StringRef Name) { Macros.push_back(std::make_pair(Name, false)); @@ -92,9 +130,24 @@ public: void addRemappedFile(llvm::StringRef From, llvm::StringRef To) { RemappedFiles.push_back(std::make_pair(From, To)); } + + remapped_file_iterator eraseRemappedFile(remapped_file_iterator Remapped) { + return RemappedFiles.erase(Remapped); + } + void addRemappedFile(llvm::StringRef From, const llvm::MemoryBuffer * To) { RemappedFileBuffers.push_back(std::make_pair(From, To)); } + + remapped_file_buffer_iterator + eraseRemappedFile(remapped_file_buffer_iterator Remapped) { + return RemappedFileBuffers.erase(Remapped); + } + + void clearRemappedFiles() { + RemappedFiles.clear(); + RemappedFileBuffers.clear(); + } }; } // end namespace clang diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h index a712a3d1bb05..82517c51d1c1 100644 --- a/include/clang/Frontend/PreprocessorOutputOptions.h +++ b/include/clang/Frontend/PreprocessorOutputOptions.h @@ -16,19 +16,21 @@ namespace clang { /// output (e.g., -E). class PreprocessorOutputOptions { public: - unsigned ShowCPP : 1; ///< Print normal preprocessed output. - unsigned ShowMacros : 1; ///< Print macro definitions. - unsigned ShowLineMarkers : 1; ///< Show #line markers. - unsigned ShowComments : 1; ///< Show comments. - unsigned ShowMacroComments : 1; ///< Show comments, even in macros. + unsigned ShowCPP : 1; ///< Print normal preprocessed output. + unsigned ShowComments : 1; ///< Show comments. + unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H). + unsigned ShowLineMarkers : 1; ///< Show #line markers. + unsigned ShowMacroComments : 1; ///< Show comments, even in macros. + unsigned ShowMacros : 1; ///< Print macro definitions. public: PreprocessorOutputOptions() { ShowCPP = 1; - ShowMacros = 0; - ShowLineMarkers = 1; ShowComments = 0; + ShowHeaderIncludes = 0; + ShowLineMarkers = 1; ShowMacroComments = 0; + ShowMacros = 0; } }; diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def index f63761a908af..c03a5a883569 100644 --- a/include/clang/Frontend/StmtXML.def +++ b/include/clang/Frontend/StmtXML.def @@ -241,20 +241,19 @@ NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op ATTRIBUTE_FILE_LOCATION_XML TYPE_ATTRIBUTE_XML(getType()) ATTRIBUTE_ENUM_XML(getOpcode(), "kind") - ENUM_XML(UnaryOperator::PostInc, "postinc") - ENUM_XML(UnaryOperator::PostDec, "postdec") - ENUM_XML(UnaryOperator::PreInc, "preinc") - ENUM_XML(UnaryOperator::PreDec, "predec") - ENUM_XML(UnaryOperator::AddrOf, "addrof") - ENUM_XML(UnaryOperator::Deref, "deref") - ENUM_XML(UnaryOperator::Plus, "plus") - ENUM_XML(UnaryOperator::Minus, "minus") - ENUM_XML(UnaryOperator::Not, "not") // bitwise not - ENUM_XML(UnaryOperator::LNot, "lnot") // boolean not - ENUM_XML(UnaryOperator::Real, "__real") - ENUM_XML(UnaryOperator::Imag, "__imag") - ENUM_XML(UnaryOperator::Extension, "__extension__") - ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof") + ENUM_XML(UO_PostInc, "postinc") + ENUM_XML(UO_PostDec, "postdec") + ENUM_XML(UO_PreInc, "preinc") + ENUM_XML(UO_PreDec, "predec") + ENUM_XML(UO_AddrOf, "addrof") + ENUM_XML(UO_Deref, "deref") + ENUM_XML(UO_Plus, "plus") + ENUM_XML(UO_Minus, "minus") + ENUM_XML(UO_Not, "not") // bitwise not + ENUM_XML(UO_LNot, "lnot") // boolean not + ENUM_XML(UO_Real, "__real") + ENUM_XML(UO_Imag, "__imag") + ENUM_XML(UO_Extension, "__extension__") END_ENUM_XML SUB_NODE_XML(Expr) // expr END_NODE_XML @@ -263,38 +262,38 @@ NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2) ATTRIBUTE_FILE_LOCATION_XML TYPE_ATTRIBUTE_XML(getType()) ATTRIBUTE_ENUM_XML(getOpcode(), "kind") - ENUM_XML(BinaryOperator::PtrMemD , "ptrmemd") - ENUM_XML(BinaryOperator::PtrMemI , "ptrmemi") - ENUM_XML(BinaryOperator::Mul , "mul") - ENUM_XML(BinaryOperator::Div , "div") - ENUM_XML(BinaryOperator::Rem , "rem") - ENUM_XML(BinaryOperator::Add , "add") - ENUM_XML(BinaryOperator::Sub , "sub") - ENUM_XML(BinaryOperator::Shl , "shl") - ENUM_XML(BinaryOperator::Shr , "shr") - ENUM_XML(BinaryOperator::LT , "lt") - ENUM_XML(BinaryOperator::GT , "gt") - ENUM_XML(BinaryOperator::LE , "le") - ENUM_XML(BinaryOperator::GE , "ge") - ENUM_XML(BinaryOperator::EQ , "eq") - ENUM_XML(BinaryOperator::NE , "ne") - ENUM_XML(BinaryOperator::And , "and") // bitwise and - ENUM_XML(BinaryOperator::Xor , "xor") - ENUM_XML(BinaryOperator::Or , "or") // bitwise or - ENUM_XML(BinaryOperator::LAnd , "land") // boolean and - ENUM_XML(BinaryOperator::LOr , "lor") // boolean or - ENUM_XML(BinaryOperator::Assign , "assign") - ENUM_XML(BinaryOperator::MulAssign, "mulassign") - ENUM_XML(BinaryOperator::DivAssign, "divassign") - ENUM_XML(BinaryOperator::RemAssign, "remassign") - ENUM_XML(BinaryOperator::AddAssign, "addassign") - ENUM_XML(BinaryOperator::SubAssign, "subassign") - ENUM_XML(BinaryOperator::ShlAssign, "shlassign") - ENUM_XML(BinaryOperator::ShrAssign, "shrassign") - ENUM_XML(BinaryOperator::AndAssign, "andassign") - ENUM_XML(BinaryOperator::XorAssign, "xorassign") - ENUM_XML(BinaryOperator::OrAssign , "orassign") - ENUM_XML(BinaryOperator::Comma , "comma") + ENUM_XML(BO_PtrMemD , "ptrmemd") + ENUM_XML(BO_PtrMemI , "ptrmemi") + ENUM_XML(BO_Mul , "mul") + ENUM_XML(BO_Div , "div") + ENUM_XML(BO_Rem , "rem") + ENUM_XML(BO_Add , "add") + ENUM_XML(BO_Sub , "sub") + ENUM_XML(BO_Shl , "shl") + ENUM_XML(BO_Shr , "shr") + ENUM_XML(BO_LT , "lt") + ENUM_XML(BO_GT , "gt") + ENUM_XML(BO_LE , "le") + ENUM_XML(BO_GE , "ge") + ENUM_XML(BO_EQ , "eq") + ENUM_XML(BO_NE , "ne") + ENUM_XML(BO_And , "and") // bitwise and + ENUM_XML(BO_Xor , "xor") + ENUM_XML(BO_Or , "or") // bitwise or + ENUM_XML(BO_LAnd , "land") // boolean and + ENUM_XML(BO_LOr , "lor") // boolean or + ENUM_XML(BO_Assign , "assign") + ENUM_XML(BO_MulAssign, "mulassign") + ENUM_XML(BO_DivAssign, "divassign") + ENUM_XML(BO_RemAssign, "remassign") + ENUM_XML(BO_AddAssign, "addassign") + ENUM_XML(BO_SubAssign, "subassign") + ENUM_XML(BO_ShlAssign, "shlassign") + ENUM_XML(BO_ShrAssign, "shrassign") + ENUM_XML(BO_AndAssign, "andassign") + ENUM_XML(BO_XorAssign, "xorassign") + ENUM_XML(BO_OrAssign , "orassign") + ENUM_XML(BO_Comma , "comma") END_ENUM_XML SUB_NODE_XML(Expr) // expr1 SUB_NODE_XML(Expr) // expr2 @@ -445,6 +444,14 @@ NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, .. SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN END_NODE_XML +NODE_XML(CXXConstructExpr, "CXXConstructExpr") // ctor(arg1, arg2, ...) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned + SUB_NODE_XML(Expr) // fnexpr + SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN +END_NODE_XML + NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast<type>(expr) ATTRIBUTE_FILE_LOCATION_XML TYPE_ATTRIBUTE_XML(getType()) diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def index e8cb4a6de055..1536c924a82f 100644 --- a/include/clang/Frontend/TypeXML.def +++ b/include/clang/Frontend/TypeXML.def @@ -278,18 +278,10 @@ NODE_XML(UnresolvedUsingType, "UnresolvedUsing") ID_ATTRIBUTE_XML END_NODE_XML -NODE_XML(DependentTypeOfExprType, "DependentTypeOfExpr") - ID_ATTRIBUTE_XML -END_NODE_XML - NODE_XML(DecltypeType, "Decltype") ID_ATTRIBUTE_XML END_NODE_XML -NODE_XML(DependentDecltypeType, "DependentDecltype") - ID_ATTRIBUTE_XML -END_NODE_XML - //===----------------------------------------------------------------------===// #undef NODE_XML #undef ID_ATTRIBUTE_XML diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index f37cc01a2753..fe722db381d0 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -23,6 +23,7 @@ class Triple; namespace clang { class ASTConsumer; +class CompilerInstance; class Decl; class DependencyOutputOptions; class Diagnostic; @@ -31,7 +32,6 @@ class HeaderSearch; class HeaderSearchOptions; class IdentifierTable; class LangOptions; -class MinimalAction; class Preprocessor; class PreprocessorOptions; class PreprocessorOutputOptions; @@ -65,11 +65,6 @@ void ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts); void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS, const PreprocessorOutputOptions &Opts); -/// CreatePrintParserActionsAction - Return the actions implementation that -/// implements the -parse-print-callbacks option. -MinimalAction *CreatePrintParserActionsAction(Preprocessor &PP, - llvm::raw_ostream* OS); - /// CheckDiagnostics - Gather the expected diagnostics and check them. bool CheckDiagnostics(Preprocessor &PP); diff --git a/include/clang/FrontendTool/Utils.h b/include/clang/FrontendTool/Utils.h new file mode 100644 index 000000000000..031ee7df70ae --- /dev/null +++ b/include/clang/FrontendTool/Utils.h @@ -0,0 +1,30 @@ +//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains miscellaneous utilities for various front-end actions +// which were split from Frontend to minimise Frontend's dependencies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTENDTOOL_UTILS_H +#define LLVM_CLANG_FRONTENDTOOL_UTILS_H + +namespace clang { + +class CompilerInstance; + +/// ExecuteCompilerInvocation - Execute the given actions described by the +/// compiler invocation object in the given compiler instance. +/// +/// \return - True on success. +bool ExecuteCompilerInvocation(CompilerInstance *Clang); + +} // end namespace clang + +#endif diff --git a/include/clang/Index/TranslationUnit.h b/include/clang/Index/TranslationUnit.h index b86ba3ee8a58..0099d630f164 100644 --- a/include/clang/Index/TranslationUnit.h +++ b/include/clang/Index/TranslationUnit.h @@ -16,6 +16,7 @@ namespace clang { class ASTContext; + class Diagnostic; class Preprocessor; namespace idx { @@ -28,6 +29,7 @@ public: virtual ~TranslationUnit(); virtual ASTContext &getASTContext() = 0; virtual Preprocessor &getPreprocessor() = 0; + virtual Diagnostic &getDiagnostic() = 0; virtual DeclReferenceMap &getDeclReferenceMap() = 0; virtual SelectorMap &getSelectorMap() = 0; }; diff --git a/include/clang/Index/Utils.h b/include/clang/Index/Utils.h deleted file mode 100644 index f8e01f728648..000000000000 --- a/include/clang/Index/Utils.h +++ /dev/null @@ -1,36 +0,0 @@ -//===--- Utils.h - Misc utilities for indexing-----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header contains miscellaneous utilities for indexing related -// functionality. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_INDEX_UTILS_H -#define LLVM_CLANG_INDEX_UTILS_H - -namespace clang { - class ASTContext; - class SourceLocation; - -namespace idx { - class ASTLocation; - -/// \brief Returns the ASTLocation that a source location points to. -/// -/// \returns the resolved ASTLocation or an invalid ASTLocation if the source -/// location could not be resolved. -ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc, - ASTLocation *LastLoc = 0); - -} // end namespace idx - -} // end namespace clang - -#endif diff --git a/include/clang/Lex/CodeCompletionHandler.h b/include/clang/Lex/CodeCompletionHandler.h new file mode 100644 index 000000000000..d28a3aa7d630 --- /dev/null +++ b/include/clang/Lex/CodeCompletionHandler.h @@ -0,0 +1,67 @@ +//===--- CodeCompletionHandler.h - Preprocessor code completion -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the CodeCompletionHandler interface, which provides +// code-completion callbacks for the preprocessor. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H +#define LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H + +namespace clang { + +class IdentifierInfo; +class MacroInfo; + +/// \brief Callback handler that receives notifications when performing code +/// completion within the preprocessor. +class CodeCompletionHandler { +public: + virtual ~CodeCompletionHandler(); + + /// \brief Callback invoked when performing code completion for a preprocessor + /// directive. + /// + /// This callback will be invoked when the preprocessor processes a '#' at the + /// start of a line, followed by the code-completion token. + /// + /// \param InConditional Whether we're inside a preprocessor conditional + /// already. + virtual void CodeCompleteDirective(bool InConditional) { } + + /// \brief Callback invoked when performing code completion within a block of + /// code that was excluded due to preprocessor conditionals. + virtual void CodeCompleteInConditionalExclusion() { } + + /// \brief Callback invoked when performing code completion in a context + /// where the name of a macro is expected. + /// + /// \param IsDefinition Whether this is the definition of a macro, e.g., + /// in a #define. + virtual void CodeCompleteMacroName(bool IsDefinition) { } + + /// \brief Callback invoked when performing code completion in a preprocessor + /// expression, such as the condition of an #if or #elif directive. + virtual void CodeCompletePreprocessorExpression() { } + + /// \brief Callback invoked when performing code completion inside a + /// function-like macro argument. + virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro, + MacroInfo *MacroInfo, + unsigned ArgumentIndex) { } + + /// \brief Callback invoked when performing code completion in a part of the + /// file where we expect natural language, e.g., a comment, string, or + /// #error directive. + virtual void CodeCompleteNaturalLanguage() { } +}; + +} + +#endif // LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index af5c3898161e..791d3fe304ec 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -19,7 +19,7 @@ namespace clang { /// \brief Abstract interface for external sources of preprocessor /// information. /// -/// This abstract class allows an external sources (such as the \c PCHReader) +/// This abstract class allows an external sources (such as the \c ASTReader) /// to provide additional macro definitions. class ExternalPreprocessorSource { public: diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 978585caf0e4..80b38dee06af 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -219,7 +219,7 @@ public: header_file_iterator header_file_end() const { return FileInfo.end(); } unsigned header_file_size() const { return FileInfo.size(); } - // Used by PCHReader. + // Used by ASTReader. void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID); void PrintStats(); diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 6a6e319463f0..9e0fb7ee70ea 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -219,6 +219,33 @@ public: const SourceManager &SM, const LangOptions &LangOpts); + /// \brief Given a location any where in a source buffer, find the location + /// that corresponds to the beginning of the token in which the original + /// source location lands. + /// + /// \param Loc + static SourceLocation GetBeginningOfToken(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts); + + /// \brief Compute the preamble of the given file. + /// + /// The preamble of a file contains the initial comments, include directives, + /// and other preprocessor directives that occur before the code in this + /// particular file actually begins. The preamble of the main source file is + /// a potential prefix header. + /// + /// \param Buffer The memory buffer containing the file's contents. + /// + /// \param MaxLines If non-zero, restrict the length of the preamble + /// to fewer than this number of lines. + /// + /// \returns The offset into the file where the preamble ends and the rest + /// of the file begins along with a boolean value indicating whether + /// the preamble ends at the beginning of a new line. + static std::pair<unsigned, bool> + ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines = 0); + //===--------------------------------------------------------------------===// // Internal implementation interfaces. private: @@ -361,6 +388,8 @@ private: //===--------------------------------------------------------------------===// // Other lexer functions. + void SkipBytes(unsigned Bytes, bool StartOfLine); + // Helper functions to lex the remainder of a token of the specific type. void LexIdentifier (Token &Result, const char *CurPtr); void LexNumericConstant (Token &Result, const char *CurPtr); diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index 5887041c46b9..90f95b7acee3 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -62,6 +62,9 @@ class MacroInfo { /// it has not yet been redefined or undefined. bool IsBuiltinMacro : 1; + /// IsFromAST - True if this macro was loaded from an AST file. + bool IsFromAST : 1; + private: //===--------------------------------------------------------------------===// // State that changes as the macro is used. @@ -76,24 +79,28 @@ private: /// emit -Wunused-macros diagnostics. bool IsUsed : 1; - ~MacroInfo() { + /// AllowRedefinitionsWithoutWarning - True if this macro can be redefined + /// without emitting a warning. + bool IsAllowRedefinitionsWithoutWarning : 1; + + ~MacroInfo() { assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); } public: MacroInfo(SourceLocation DefLoc); - + MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator); + /// FreeArgumentList - Free the argument list of the macro, restoring it to a /// state where it can be reused for other devious purposes. - void FreeArgumentList(llvm::BumpPtrAllocator &PPAllocator) { - PPAllocator.Deallocate(ArgumentList); + void FreeArgumentList() { ArgumentList = 0; NumArguments = 0; } /// Destroy - destroy this MacroInfo object. - void Destroy(llvm::BumpPtrAllocator &PPAllocator) { - FreeArgumentList(PPAllocator); + void Destroy() { + FreeArgumentList(); this->~MacroInfo(); } @@ -125,6 +132,12 @@ public: IsUsed = Val; } + /// setIsAllowRedefinitionsWithoutWarning - Set the value of the + /// IsAllowRedefinitionsWithoutWarning flag. + void setIsAllowRedefinitionsWithoutWarning(bool Val) { + IsAllowRedefinitionsWithoutWarning = Val; + } + /// setArgumentList - Set the specified list of identifiers as the argument /// list for this macro. void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs, @@ -172,10 +185,22 @@ public: /// __LINE__, which requires processing before expansion. bool isBuiltinMacro() const { return IsBuiltinMacro; } + /// isFromAST - Return true if this macro was loaded from an AST file. + bool isFromAST() const { return IsFromAST; } + + /// setIsFromAST - Set whether this macro was loaded from an AST file. + void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; } + /// isUsed - Return false if this macro is defined in the main file and has /// not yet been used. bool isUsed() const { return IsUsed; } + /// isAllowRedefinitionsWithoutWarning - Return true if this macro can be + /// redefined without warning. + bool isAllowRedefinitionsWithoutWarning() const { + return IsAllowRedefinitionsWithoutWarning; + } + /// getNumTokens - Return the number of tokens that this macro expands to. /// unsigned getNumTokens() const { diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 99fe29b22dc2..782f2d57a5c6 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -89,7 +89,8 @@ public: /// MacroUndefined - This hook is called whenever a macro #undef is seen. /// MI is released immediately following this callback. - virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) { + virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II, + const MacroInfo *MI) { } }; @@ -149,9 +150,10 @@ public: Second->MacroDefined(II, MI); } - virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) { - First->MacroUndefined(II, MI); - Second->MacroUndefined(II, MI); + virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II, + const MacroInfo *MI) { + First->MacroUndefined(Loc, II, MI); + Second->MacroUndefined(Loc, II, MI); } }; diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h index e96a8c514e6e..0b5a76ccfd6e 100644 --- a/include/clang/Lex/PTHLexer.h +++ b/include/clang/Lex/PTHLexer.h @@ -50,6 +50,8 @@ class PTHLexer : public PreprocessorLexer { /// ReadToken - Used by PTHLexer to read tokens TokBuf. void ReadToken(Token& T); + + bool LexEndOfFile(Token &Result); /// PTHMgr - The PTHManager object that created this PTHLexer. PTHManager& PTHMgr; diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index ef28af9b7fe0..730f04f2fa09 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -257,7 +257,8 @@ namespace clang { virtual void MacroExpands(const Token &Id, const MacroInfo* MI); virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI); - virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI); + virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II, + const MacroInfo *MI); }; } // end namespace clang diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 1ee4bb635179..6b9b89ea5eb9 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -42,6 +42,7 @@ class CommentHandler; class ScratchBuffer; class TargetInfo; class PPCallbacks; +class CodeCompletionHandler; class DirectoryLookup; class PreprocessingRecord; @@ -77,7 +78,8 @@ class Preprocessor { IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__ IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__ IdentifierInfo *Ident__COUNTER__; // __COUNTER__ - IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__ + IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma + IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_builtin; // __has_builtin IdentifierInfo *Ident__has_include; // __has_include @@ -117,7 +119,7 @@ class Preprocessor { /// conceptually similar the IdentifierTable. In addition, the current control /// flow (in clang::ParseAST()), make it convenient to put here. /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to - /// the lifetime fo the preprocessor. + /// the lifetime of the preprocessor. SelectorTable Selectors; /// BuiltinInfo - Information about builtins. @@ -131,9 +133,18 @@ class Preprocessor { /// with this preprocessor. std::vector<CommentHandler *> CommentHandlers; + /// \brief The code-completion handler. + CodeCompletionHandler *CodeComplete; + /// \brief The file that we're performing code-completion for, if any. const FileEntry *CodeCompletionFile; + /// \brief The number of bytes that we will initially skip when entering the + /// main file, which is used when loading a precompiled preamble, along + /// with a flag that indicates whether skipping this number of bytes will + /// place the lexer at the start of a line. + std::pair<unsigned, bool> SkipMainFilePreamble; + /// CurLexer - This is the current top of the stack that we're lexing from if /// not expanding a macro and we are lexing directly from source code. /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. @@ -192,6 +203,11 @@ class Preprocessor { /// reused for quick allocation. MacroArgs *MacroArgCache; friend class MacroArgs; + + /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma + /// push_macro directive, we keep a MacroInfo stack used to restore + /// previous macro value. + llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo; // Various statistics we track for performance analysis. unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma; @@ -362,6 +378,25 @@ public: /// It is an error to remove a handler that has not been registered. void RemoveCommentHandler(CommentHandler *Handler); + /// \brief Set the code completion handler to the given object. + void setCodeCompletionHandler(CodeCompletionHandler &Handler) { + CodeComplete = &Handler; + } + + /// \brief Retrieve the current code-completion handler. + CodeCompletionHandler *getCodeCompletionHandler() const { + return CodeComplete; + } + + /// \brief Clear out the code completion handler. + void clearCodeCompletionHandler() { + CodeComplete = 0; + } + + /// \brief Hook used by the lexer to invoke the "natural language" code + /// completion point. + void CodeCompleteNaturalLanguage(); + /// \brief Retrieve the preprocessing record, or NULL if there is no /// preprocessing record. PreprocessingRecord *getPreprocessingRecord() const { return Record; } @@ -556,6 +591,18 @@ public: /// for which we are performing code completion. bool isCodeCompletionFile(SourceLocation FileLoc) const; + /// \brief Instruct the preprocessor to skip part of the main + /// the main source file. + /// + /// \brief Bytes The number of bytes in the preamble to skip. + /// + /// \brief StartOfLine Whether skipping these bytes puts the lexer at the + /// start of a line. + void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) { + SkipMainFilePreamble.first = Bytes; + SkipMainFilePreamble.second = StartOfLine; + } + /// Diag - Forwarding function for diagnostics. This emits a diagnostic at /// the specified Token's location, translating the token's start /// position in the current buffer into a SourcePosition object for rendering. @@ -726,7 +773,10 @@ public: /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide /// SourceLocation. - MacroInfo* AllocateMacroInfo(SourceLocation L); + MacroInfo *AllocateMacroInfo(SourceLocation L); + + /// CloneMacroInfo - Allocate a new MacroInfo object which is clone of MI. + MacroInfo *CloneMacroInfo(const MacroInfo &MI); /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully /// checked and spelled filename, e.g. as an operand of #include. This returns @@ -784,6 +834,9 @@ private: IncludeMacroStack.pop_back(); } + /// AllocateMacroInfo - Allocate a new MacroInfo object. + MacroInfo *AllocateMacroInfo(); + /// ReleaseMacroInfo - Release the specified MacroInfo. This memory will /// be reused for allocating new MacroInfo objects. void ReleaseMacroInfo(MacroInfo* MI); @@ -852,6 +905,13 @@ private: /// been read into 'Tok'. void Handle_Pragma(Token &Tok); + /// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text + /// is not enclosed within a string literal. + void HandleMicrosoft__pragma(Token &Tok); + + void Handle_Pragma(const std::string &StrVal, SourceLocation PragmaLoc, + SourceLocation RParenLoc); + /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and /// start lexing tokens from it instead of the current buffer. void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir); @@ -880,7 +940,8 @@ private: bool InCachingLexMode() const { // If the Lexer pointers are 0 and IncludeMacroStack is empty, it means // that we are past EOF, not that we are in CachingLex mode. - return CurPPLexer == 0 && CurTokenLexer == 0 && !IncludeMacroStack.empty(); + return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 && + !IncludeMacroStack.empty(); } void EnterCachingLexMode(); void ExitCachingLexMode() { @@ -929,6 +990,10 @@ public: void HandlePragmaDependency(Token &DependencyTok); void HandlePragmaComment(Token &CommentTok); void HandlePragmaMessage(Token &MessageTok); + void HandlePragmaPushMacro(Token &Tok); + void HandlePragmaPopMacro(Token &Tok); + IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok); + // Return true and store the first token only if any CommentHandler // has inserted some tokens and getCommentRetentionState() is false. bool HandleComment(Token &Token, SourceRange Comment); diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index bd9b46869a35..954b36ec6d11 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -231,6 +231,7 @@ public: /// newlines in it. /// bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; } + }; /// PPConditionalInfo - Information about the conditional stack (#if directives) diff --git a/include/clang/Makefile b/include/clang/Makefile index e366e4ec4458..030b0720fd81 100644 --- a/include/clang/Makefile +++ b/include/clang/Makefile @@ -1,5 +1,5 @@ CLANG_LEVEL := ../.. -DIRS := AST Basic Driver +DIRS := AST Basic Driver Serialization include $(CLANG_LEVEL)/Makefile diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h deleted file mode 100644 index 9cb47aa8da25..000000000000 --- a/include/clang/Parse/Action.h +++ /dev/null @@ -1,3309 +0,0 @@ -//===--- Action.h - Parser Action Interface ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the Action and EmptyAction interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_PARSE_ACTION_H -#define LLVM_CLANG_PARSE_ACTION_H - -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/Specifiers.h" -#include "clang/Basic/TemplateKinds.h" -#include "clang/Basic/TypeTraits.h" -#include "clang/Parse/DeclSpec.h" -#include "clang/Parse/Ownership.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/ADT/PointerUnion.h" - -namespace clang { - // Semantic. - class DeclSpec; - class ObjCDeclSpec; - class CXXScopeSpec; - class Declarator; - class AttributeList; - struct FieldDeclarator; - // Parse. - class Scope; - class Action; - class Selector; - class Designation; - class InitListDesignations; - // Lex. - class Preprocessor; - class Token; - - // We can re-use the low bit of expression, statement, base, and - // member-initializer pointers for the "invalid" flag of - // ActionResult. - template<> struct IsResultPtrLowBitFree<0> { static const bool value = true;}; - template<> struct IsResultPtrLowBitFree<1> { static const bool value = true;}; - template<> struct IsResultPtrLowBitFree<3> { static const bool value = true;}; - template<> struct IsResultPtrLowBitFree<4> { static const bool value = true;}; - template<> struct IsResultPtrLowBitFree<5> { static const bool value = true;}; - -/// Action - As the parser reads the input file and recognizes the productions -/// of the grammar, it invokes methods on this class to turn the parsed input -/// into something useful: e.g. a parse tree. -/// -/// The callback methods that this class provides are phrased as actions that -/// the parser has just done or is about to do when the method is called. They -/// are not requests that the actions module do the specified action. -/// -/// All of the methods here are optional except getTypeName() and -/// isCurrentClassName(), which must be specified in order for the -/// parse to complete accurately. The MinimalAction class does this -/// bare-minimum of tracking to implement this functionality. -class Action : public ActionBase { - /// \brief The parser's current scope. - /// - /// The parser maintains this state here so that is accessible to \c Action - /// subclasses via \c getCurScope(). - Scope *CurScope; - -protected: - friend class Parser; - - /// \brief Retrieve the parser's current scope. - Scope *getCurScope() const { return CurScope; } - -public: - Action() : CurScope(0) { } - - /// Out-of-line virtual destructor to provide home for this class. - virtual ~Action(); - - // Types - Though these don't actually enforce strong typing, they document - // what types are required to be identical for the actions. - typedef ActionBase::ExprTy ExprTy; - typedef ActionBase::StmtTy StmtTy; - - /// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap - /// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and - /// allowing for failure. - typedef ActionResult<0> ExprResult; - typedef ActionResult<1> StmtResult; - typedef ActionResult<2> TypeResult; - typedef ActionResult<3> BaseResult; - typedef ActionResult<4> MemInitResult; - typedef ActionResult<5, DeclPtrTy> DeclResult; - - /// Same, but with ownership. - typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult; - typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult; - // Note that these will replace ExprResult and StmtResult when the transition - // is complete. - - /// Single expressions or statements as arguments. -#if !defined(DISABLE_SMART_POINTERS) - typedef ASTOwningResult<&ActionBase::DeleteExpr> ExprArg; - typedef ASTOwningResult<&ActionBase::DeleteStmt> StmtArg; -#else - typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg; - typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg; -#endif - - /// Multiple expressions or statements as arguments. - typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg; - typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg; - typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg; - - class FullExprArg { - public: - FullExprArg(ActionBase &actions) : Expr(actions) { } - - // FIXME: The const_cast here is ugly. RValue references would make this - // much nicer (or we could duplicate a bunch of the move semantics - // emulation code from Ownership.h). - FullExprArg(const FullExprArg& Other) - : Expr(move(const_cast<FullExprArg&>(Other).Expr)) {} - - FullExprArg &operator=(const FullExprArg& Other) { - Expr.operator=(move(const_cast<FullExprArg&>(Other).Expr)); - return *this; - } - - OwningExprResult release() { - return move(Expr); - } - - ExprArg* operator->() { - return &Expr; - } - - private: - // FIXME: No need to make the entire Action class a friend when it's just - // Action::FullExpr that needs access to the constructor below. - friend class Action; - - explicit FullExprArg(ExprArg expr) - : Expr(move(expr)) {} - - ExprArg Expr; - }; - - template<typename T> - FullExprArg MakeFullExpr(T &Arg) { - return FullExprArg(ActOnFinishFullExpr(move(Arg))); - } - - // Utilities for Action implementations to return smart results. - - OwningExprResult ExprError() { return OwningExprResult(*this, true); } - OwningStmtResult StmtError() { return OwningStmtResult(*this, true); } - - OwningExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); } - OwningStmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); } - - OwningExprResult ExprEmpty() { return OwningExprResult(*this, false); } - OwningStmtResult StmtEmpty() { return OwningStmtResult(*this, false); } - - /// Statistics. - virtual void PrintStats() const {} - - /// getDeclName - Return a pretty name for the specified decl if possible, or - /// an empty string if not. This is used for pretty crash reporting. - virtual std::string getDeclName(DeclPtrTy D) { return ""; } - - //===--------------------------------------------------------------------===// - // Declaration Tracking Callbacks. - //===--------------------------------------------------------------------===// - - typedef uintptr_t ParsingDeclStackState; - - /// PushParsingDeclaration - Notes that the parser has begun - /// processing a declaration of some sort. Guaranteed to be matched - /// by a call to PopParsingDeclaration with the value returned by - /// this method. - virtual ParsingDeclStackState PushParsingDeclaration() { - return ParsingDeclStackState(); - } - - /// PopParsingDeclaration - Notes that the parser has completed - /// processing a declaration of some sort. The decl will be empty - /// if the declaration didn't correspond to a full declaration (or - /// if the actions module returned an empty decl for it). - virtual void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D) { - } - - /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it - /// needs a decl group, it calls this to convert between the two - /// representations. - virtual DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr) { - return DeclGroupPtrTy(); - } - - /// getTypeName - Return non-null if the specified identifier is a type name - /// in the current scope. - /// - /// \param II the identifier for which we are performing name lookup - /// - /// \param NameLoc the location of the identifier - /// - /// \param S the scope in which this name lookup occurs - /// - /// \param SS if non-NULL, the C++ scope specifier that precedes the - /// identifier - /// - /// \param isClassName whether this is a C++ class-name production, in - /// which we can end up referring to a member of an unknown specialization - /// that we know (from the grammar) is supposed to be a type. For example, - /// this occurs when deriving from "std::vector<T>::allocator_type", where T - /// is a template parameter. - /// - /// \param ObjectType if we're checking whether an identifier is a type - /// within a C++ member access expression, this will be the type of the - /// - /// \returns the type referred to by this identifier, or NULL if the type - /// does not name an identifier. - virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec *SS = 0, - bool isClassName = false, - TypeTy *ObjectType = 0) = 0; - - /// isTagName() - This method is called *for error recovery purposes only* - /// to determine if the specified name is a valid tag name ("struct foo"). If - /// so, this returns the TST for the tag corresponding to it (TST_enum, - /// TST_union, TST_struct, TST_class). This is used to diagnose cases in C - /// where the user forgot to specify the tag. - virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S) { - return DeclSpec::TST_unspecified; - } - - /// \brief Action called as part of error recovery when the parser has - /// determined that the given name must refer to a type, but - /// \c getTypeName() did not return a result. - /// - /// This callback permits the action to give a detailed diagnostic when an - /// unknown type name is encountered and, potentially, to try to recover - /// by producing a new type in \p SuggestedType. - /// - /// \param II the name that should be a type. - /// - /// \param IILoc the location of the name in the source. - /// - /// \param S the scope in which name lookup was performed. - /// - /// \param SS if non-NULL, the C++ scope specifier that preceded the name. - /// - /// \param SuggestedType if the action sets this type to a non-NULL type, - /// the parser will recovery by consuming the type name token and then - /// pretending that the given type was the type it parsed. - /// - /// \returns true if a diagnostic was emitted, false otherwise. When false, - /// the parser itself will emit a generic "unknown type name" diagnostic. - virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II, - SourceLocation IILoc, - Scope *S, - CXXScopeSpec *SS, - TypeTy *&SuggestedType) { - return false; - } - - /// isCurrentClassName - Return true if the specified name is the - /// name of the innermost C++ class type currently being defined. - virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S, - const CXXScopeSpec *SS = 0) = 0; - - /// \brief Determine whether the given name refers to a template. - /// - /// This callback is used by the parser after it has seen a '<' to determine - /// whether the given name refers to a template and, if so, what kind of - /// template. - /// - /// \param S the scope in which the name occurs. - /// - /// \param SS the C++ nested-name-specifier that precedes the template name, - /// if any. - /// - /// \param Name the name that we are querying to determine whether it is - /// a template. - /// - /// \param ObjectType if we are determining whether the given name is a - /// template name in the context of a member access expression (e.g., - /// \c p->X<int>), this is the type of the object referred to by the - /// member access (e.g., \c p). - /// - /// \param EnteringContext whether we are potentially entering the context - /// referred to by the nested-name-specifier \p SS, which allows semantic - /// analysis to look into uninstantiated templates. - /// - /// \param Template if the name does refer to a template, the declaration - /// of the template that the name refers to. - /// - /// \param MemberOfUnknownSpecialization Will be set true if the resulting - /// member would be a member of an unknown specialization, in which case this - /// lookup cannot possibly pass at this time. - /// - /// \returns the kind of template that this name refers to. - virtual TemplateNameKind isTemplateName(Scope *S, - CXXScopeSpec &SS, - UnqualifiedId &Name, - TypeTy *ObjectType, - bool EnteringContext, - TemplateTy &Template, - bool &MemberOfUnknownSpecialization) = 0; - - /// \brief Action called as part of error recovery when the parser has - /// determined that the given name must refer to a template, but - /// \c isTemplateName() did not return a result. - /// - /// This callback permits the action to give a detailed diagnostic when an - /// unknown template name is encountered and, potentially, to try to recover - /// by producing a new template in \p SuggestedTemplate. - /// - /// \param II the name that should be a template. - /// - /// \param IILoc the location of the name in the source. - /// - /// \param S the scope in which name lookup was performed. - /// - /// \param SS the C++ scope specifier that preceded the name. - /// - /// \param SuggestedTemplate if the action sets this template to a non-NULL, - /// template, the parser will recover by consuming the template name token - /// and the template argument list that follows. - /// - /// \param SuggestedTemplateKind as input, the kind of template that we - /// expect (e.g., \c TNK_Type_template or \c TNK_Function_template). If the - /// action provides a suggested template, this should be set to the kind of - /// template. - /// - /// \returns true if a diagnostic was emitted, false otherwise. When false, - /// the parser itself will emit a generic "unknown template name" diagnostic. - virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, - SourceLocation IILoc, - Scope *S, - const CXXScopeSpec *SS, - TemplateTy &SuggestedTemplate, - TemplateNameKind &SuggestedKind) { - return false; - } - - /// \brief Determine whether the given name refers to a non-type nested name - /// specifier, e.g., the name of a namespace or namespace alias. - /// - /// This actual is used in the parsing of pseudo-destructor names to - /// distinguish a nested-name-specifier and a "type-name ::" when we - /// see the token sequence "X :: ~". - virtual bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, - SourceLocation IdLoc, - IdentifierInfo &II, - TypeTy *ObjectType) { - return false; - } - - /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the - /// global scope ('::'). - virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S, - SourceLocation CCLoc) { - return 0; - } - - /// \brief Parsed an identifier followed by '::' in a C++ - /// nested-name-specifier. - /// - /// \param S the scope in which the nested-name-specifier was parsed. - /// - /// \param SS the nested-name-specifier that precedes the identifier. For - /// example, if we are parsing "foo::bar::", \p SS will describe the "foo::" - /// that has already been parsed. - /// - /// \param IdLoc the location of the identifier we have just parsed (e.g., - /// the "bar" in "foo::bar::". - /// - /// \param CCLoc the location of the '::' at the end of the - /// nested-name-specifier. - /// - /// \param II the identifier that represents the scope that this - /// nested-name-specifier refers to, e.g., the "bar" in "foo::bar::". - /// - /// \param ObjectType if this nested-name-specifier occurs as part of a - /// C++ member access expression such as "x->Base::f", the type of the base - /// object (e.g., *x in the example, if "x" were a pointer). - /// - /// \param EnteringContext if true, then we intend to immediately enter the - /// context of this nested-name-specifier, e.g., for an out-of-line - /// definition of a class member. - /// - /// \returns a CXXScopeTy* object representing the C++ scope. - virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - TypeTy *ObjectType, - bool EnteringContext) { - return 0; - } - - /// IsInvalidUnlessNestedName - This method is used for error recovery - /// purposes to determine whether the specified identifier is only valid as - /// a nested name specifier, for example a namespace name. It is - /// conservatively correct to always return false from this method. - /// - /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. - virtual bool IsInvalidUnlessNestedName(Scope *S, - CXXScopeSpec &SS, - IdentifierInfo &II, - TypeTy *ObjectType, - bool EnteringContext) { - return false; - } - - /// ActOnCXXNestedNameSpecifier - Called during parsing of a - /// nested-name-specifier that involves a template-id, e.g., - /// "foo::bar<int, float>::", and now we need to build a scope - /// specifier. \p SS is empty or the previously parsed nested-name - /// part ("foo::"), \p Type is the already-parsed class template - /// specialization (or other template-id that names a type), \p - /// TypeRange is the source range where the type is located, and \p - /// CCLoc is the location of the trailing '::'. - virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, - const CXXScopeSpec &SS, - TypeTy *Type, - SourceRange TypeRange, - SourceLocation CCLoc) { - return 0; - } - - /// ShouldEnterDeclaratorScope - Called when a C++ scope specifier - /// is parsed as part of a declarator-id to determine whether a scope - /// should be entered. - /// - /// \param S the current scope - /// \param SS the scope being entered - /// \param isFriendDeclaration whether this is a friend declaration - virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { - return false; - } - - /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global - /// scope or nested-name-specifier) is parsed as part of a declarator-id. - /// After this method is called, according to [C++ 3.4.3p3], names should be - /// looked up in the declarator-id's scope, until the declarator is parsed and - /// ActOnCXXExitDeclaratorScope is called. - /// The 'SS' should be a non-empty valid CXXScopeSpec. - /// \returns true if an error occurred, false otherwise. - virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { - return false; - } - - /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously - /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same - /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. - /// Used to indicate that names should revert to being looked up in the - /// defining scope. - virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { - } - - /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an - /// initializer for the declaration 'Dcl'. - /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a - /// static data member of class X, names should be looked up in the scope of - /// class X. - virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { - } - - /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an - /// initializer for the declaration 'Dcl'. - virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { - } - - /// ActOnDeclarator - This callback is invoked when a declarator is parsed and - /// 'Init' specifies the initializer if any. This is for things like: - /// "int X = 4" or "typedef int foo". - /// - virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) { - return DeclPtrTy(); - } - - /// ActOnParamDeclarator - This callback is invoked when a parameter - /// declarator is parsed. This callback only occurs for functions - /// with prototypes. S is the function prototype scope for the - /// parameters (C++ [basic.scope.proto]). - virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) { - return DeclPtrTy(); - } - - /// \brief Parsed an exception object declaration within an Objective-C - /// @catch statement. - virtual DeclPtrTy ActOnObjCExceptionDecl(Scope *S, Declarator &D) { - return DeclPtrTy(); - } - - /// AddInitializerToDecl - This action is called immediately after - /// ActOnDeclarator (when an initializer is present). The code is factored - /// this way to make sure we are able to handle the following: - /// void func() { int xx = xx; } - /// This allows ActOnDeclarator to register "xx" prior to parsing the - /// initializer. The declaration above should still result in a warning, - /// since the reference to "xx" is uninitialized. - virtual void AddInitializerToDecl(DeclPtrTy Dcl, ExprArg Init) { - return; - } - - /// SetDeclDeleted - This action is called immediately after ActOnDeclarator - /// if =delete is parsed. C++0x [dcl.fct.def]p10 - /// Note that this can be called even for variable declarations. It's the - /// action's job to reject it. - virtual void SetDeclDeleted(DeclPtrTy Dcl, SourceLocation DelLoc) { - return; - } - - /// ActOnUninitializedDecl - This action is called immediately after - /// ActOnDeclarator (when an initializer is *not* present). - /// If TypeContainsUndeducedAuto is true, then the type of the declarator - /// has an undeduced 'auto' type somewhere. - virtual void ActOnUninitializedDecl(DeclPtrTy Dcl, - bool TypeContainsUndeducedAuto) { - return; - } - - /// \brief Note that the given declaration had an initializer that could not - /// be parsed. - virtual void ActOnInitializerError(DeclPtrTy Dcl) { - return; - } - - /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this - /// gives the actions implementation a chance to process the group as a whole. - virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS, - DeclPtrTy *Group, - unsigned NumDecls) { - return DeclGroupPtrTy(); - } - - - /// @brief Indicates that all K&R-style parameter declarations have - /// been parsed prior to a function definition. - /// @param S The function prototype scope. - /// @param D The function declarator. - virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, - SourceLocation LocAfterDecls) { - } - - /// ActOnStartOfFunctionDef - This is called at the start of a function - /// definition, instead of calling ActOnDeclarator. The Declarator includes - /// information about formal arguments that are part of this function. - virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { - // Default to ActOnDeclarator. - return ActOnStartOfFunctionDef(FnBodyScope, - ActOnDeclarator(FnBodyScope, D)); - } - - /// ActOnStartOfFunctionDef - This is called at the start of a function - /// definition, after the FunctionDecl has already been created. - virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { - return D; - } - - virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { - return; - } - - /// ActOnFinishFunctionBody - This is called when a function body has - /// completed parsing. Decl is returned by ParseStartOfFunctionDef. - virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) { - return Decl; - } - - virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, - ExprArg AsmString) { - return DeclPtrTy(); - } - - /// ActOnPopScope - This callback is called immediately before the specified - /// scope is popped and deleted. - virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {} - - /// ActOnTranslationUnitScope - This callback is called once, immediately - /// after creating the translation unit scope (in Parser::Initialize). - virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {} - - /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with - /// no declarator (e.g. "struct foo;") is parsed. - virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, - AccessSpecifier Access, - DeclSpec &DS) { - return DeclPtrTy(); - } - - /// ActOnStartLinkageSpecification - Parsed the beginning of a C++ - /// linkage specification, including the language and (if present) - /// the '{'. ExternLoc is the location of the 'extern', LangLoc is - /// the location of the language string literal, which is provided - /// by Lang/StrSize. LBraceLoc, if valid, provides the location of - /// the '{' brace. Otherwise, this linkage specification does not - /// have any braces. - virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S, - SourceLocation ExternLoc, - SourceLocation LangLoc, - llvm::StringRef Lang, - SourceLocation LBraceLoc) { - return DeclPtrTy(); - } - - /// ActOnFinishLinkageSpecification - Completely the definition of - /// the C++ linkage specification LinkageSpec. If RBraceLoc is - /// valid, it's the position of the closing '}' brace in a linkage - /// specification that uses braces. - virtual DeclPtrTy ActOnFinishLinkageSpecification(Scope *S, - DeclPtrTy LinkageSpec, - SourceLocation RBraceLoc) { - return LinkageSpec; - } - - /// ActOnEndOfTranslationUnit - This is called at the very end of the - /// translation unit when EOF is reached and all but the top-level scope is - /// popped. - virtual void ActOnEndOfTranslationUnit() {} - - //===--------------------------------------------------------------------===// - // Type Parsing Callbacks. - //===--------------------------------------------------------------------===// - - /// ActOnTypeName - A type-name (type-id in C++) was parsed. - virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) { - return TypeResult(); - } - - enum TagUseKind { - TUK_Reference, // Reference to a tag: 'struct foo *X;' - TUK_Declaration, // Fwd decl of a tag: 'struct foo;' - TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;' - TUK_Friend // Friend declaration: 'friend struct foo;' - }; - - /// \brief The parser has encountered a tag (e.g., "class X") that should be - /// turned into a declaration by the action module. - /// - /// \param S the scope in which this tag occurs. - /// - /// \param TagSpec an instance of DeclSpec::TST, indicating what kind of tag - /// this is (struct/union/enum/class). - /// - /// \param TUK how the tag we have encountered is being used, which - /// can be a reference to a (possibly pre-existing) tag, a - /// declaration of that tag, or the beginning of a definition of - /// that tag. - /// - /// \param KWLoc the location of the "struct", "class", "union", or "enum" - /// keyword. - /// - /// \param SS C++ scope specifier that precedes the name of the tag, e.g., - /// the "std::" in "class std::type_info". - /// - /// \param Name the name of the tag, e.g., "X" in "struct X". This parameter - /// may be NULL, to indicate an anonymous class/struct/union/enum type. - /// - /// \param NameLoc the location of the name of the tag. - /// - /// \param Attr the set of attributes that appertain to the tag. - /// - /// \param AS when this tag occurs within a C++ class, provides the - /// current access specifier (AS_public, AS_private, AS_protected). - /// Otherwise, it will be AS_none. - /// - /// \param TemplateParameterLists the set of C++ template parameter lists - /// that apply to this tag, if the tag is a declaration or definition (see - /// the \p TK parameter). The action module is responsible for determining, - /// based on the template parameter lists and the scope specifier, whether - /// the declared tag is a class template or not. - /// - /// \param OwnedDecl the callee should set this flag true when the returned - /// declaration is "owned" by this reference. Ownership is handled entirely - /// by the action module. - /// - /// \returns the declaration to which this tag refers. - virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, AccessSpecifier AS, - MultiTemplateParamsArg TemplateParameterLists, - bool &OwnedDecl, bool &IsDependent) { - return DeclPtrTy(); - } - - /// Acts on a reference to a dependent tag name. This arises in - /// cases like: - /// - /// template <class T> class A; - /// template <class T> class B { - /// friend class A<T>::M; // here - /// }; - /// - /// \param TagSpec an instance of DeclSpec::TST corresponding to the - /// tag specifier. - /// - /// \param TUK the tag use kind (either TUK_Friend or TUK_Reference) - /// - /// \param SS the scope specifier (always defined) - virtual TypeResult ActOnDependentTag(Scope *S, - unsigned TagSpec, - TagUseKind TUK, - const CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation KWLoc, - SourceLocation NameLoc) { - return TypeResult(); - } - - /// Act on @defs() element found when parsing a structure. ClassName is the - /// name of the referenced class. - virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, - IdentifierInfo *ClassName, - llvm::SmallVectorImpl<DeclPtrTy> &Decls) {} - virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD, - SourceLocation DeclStart, - Declarator &D, ExprTy *BitfieldWidth) { - return DeclPtrTy(); - } - - virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart, - DeclPtrTy IntfDecl, - Declarator &D, ExprTy *BitfieldWidth, - tok::ObjCKeywordKind visibility) { - return DeclPtrTy(); - } - - virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl, - DeclPtrTy *Fields, unsigned NumFields, - SourceLocation LBrac, SourceLocation RBrac, - AttributeList *AttrList) {} - - /// ActOnTagStartDefinition - Invoked when we have entered the - /// scope of a tag's definition (e.g., for an enumeration, class, - /// struct, or union). - virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl) { } - - /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a - /// C++ record definition's base-specifiers clause and are starting its - /// member declarations. - virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl, - SourceLocation LBraceLoc) { } - - /// ActOnTagFinishDefinition - Invoked once we have finished parsing - /// the definition of a tag (enumeration, class, struct, or union). - /// - /// The scope is the scope of the tag definition. - virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl, - SourceLocation RBraceLoc) { } - - /// ActOnTagDefinitionError - Invoked if there's an unrecoverable - /// error parsing the definition of a tag. - /// - /// The scope is the scope of the tag definition. - virtual void ActOnTagDefinitionError(Scope *S, DeclPtrTy TagDecl) { } - - virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl, - DeclPtrTy LastEnumConstant, - SourceLocation IdLoc, IdentifierInfo *Id, - SourceLocation EqualLoc, ExprTy *Val) { - return DeclPtrTy(); - } - virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, - SourceLocation RBraceLoc, DeclPtrTy EnumDecl, - DeclPtrTy *Elements, unsigned NumElements, - Scope *S, AttributeList *AttrList) {} - - //===--------------------------------------------------------------------===// - // Statement Parsing Callbacks. - //===--------------------------------------------------------------------===// - - virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) { - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, - MultiStmtArg Elts, - bool isStmtExpr) { - return StmtEmpty(); - } - virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, - SourceLocation StartLoc, - SourceLocation EndLoc) { - return StmtEmpty(); - } - - virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl) { - } - - virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) { - return OwningStmtResult(*this, Expr->release()); - } - - /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension, - /// which can specify an RHS value. The sub-statement of the case is - /// specified in a separate action. - virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal, - SourceLocation DotDotDotLoc, - ExprArg RHSVal, - SourceLocation ColonLoc) { - return StmtEmpty(); - } - - /// ActOnCaseStmtBody - This installs a statement as the body of a case. - virtual void ActOnCaseStmtBody(StmtTy *CaseStmt, StmtArg SubStmt) {} - - virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, - SourceLocation ColonLoc, - StmtArg SubStmt, Scope *CurScope){ - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc, - IdentifierInfo *II, - SourceLocation ColonLoc, - StmtArg SubStmt) { - return StmtEmpty(); - } - - /// \brief Parsed an "if" statement. - /// - /// \param IfLoc the location of the "if" keyword. - /// - /// \param CondVal if the "if" condition was parsed as an expression, - /// the expression itself. - /// - /// \param CondVar if the "if" condition was parsed as a condition variable, - /// the condition variable itself. - /// - /// \param ThenVal the "then" statement. - /// - /// \param ElseLoc the location of the "else" keyword. - /// - /// \param ElseVal the "else" statement. - virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, - FullExprArg CondVal, - DeclPtrTy CondVar, - StmtArg ThenVal, - SourceLocation ElseLoc, - StmtArg ElseVal) { - return StmtEmpty(); - } - - /// \brief Parsed the start of a "switch" statement. - /// - /// \param SwitchLoc The location of the "switch" keyword. - /// - /// \param Cond if the "switch" condition was parsed as an expression, - /// the expression itself. - /// - /// \param CondVar if the "switch" condition was parsed as a condition - /// variable, the condition variable itself. - virtual OwningStmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, - ExprArg Cond, - DeclPtrTy CondVar) { - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, - StmtArg Switch, StmtArg Body) { - return StmtEmpty(); - } - - /// \brief Parsed a "while" statement. - /// - /// \param Cond if the "while" condition was parsed as an expression, - /// the expression itself. - /// - /// \param CondVar if the "while" condition was parsed as a condition - /// variable, the condition variable itself. - /// - /// \param Body the body of the "while" loop. - virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, - FullExprArg Cond, DeclPtrTy CondVar, - StmtArg Body) { - return StmtEmpty(); - } - virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, - SourceLocation WhileLoc, - SourceLocation CondLParen, - ExprArg Cond, - SourceLocation CondRParen) { - return StmtEmpty(); - } - - /// \brief Parsed a "for" statement. - /// - /// \param ForLoc the location of the "for" keyword. - /// - /// \param LParenLoc the location of the left parentheses. - /// - /// \param First the statement used to initialize the for loop. - /// - /// \param Second the condition to be checked during each iteration, if - /// that condition was parsed as an expression. - /// - /// \param SecondArg the condition variable to be checked during each - /// iterator, if that condition was parsed as a variable declaration. - /// - /// \param Third the expression that will be evaluated to "increment" any - /// values prior to the next iteration. - /// - /// \param RParenLoc the location of the right parentheses. - /// - /// \param Body the body of the "body" loop. - virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, - SourceLocation LParenLoc, - StmtArg First, FullExprArg Second, - DeclPtrTy SecondVar, FullExprArg Third, - SourceLocation RParenLoc, - StmtArg Body) { - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, - SourceLocation LParenLoc, - StmtArg First, ExprArg Second, - SourceLocation RParenLoc, StmtArg Body) { - return StmtEmpty(); - } - virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc, - SourceLocation LabelLoc, - IdentifierInfo *LabelII) { - return StmtEmpty(); - } - virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, - SourceLocation StarLoc, - ExprArg DestExp) { - return StmtEmpty(); - } - virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc, - Scope *CurScope) { - return StmtEmpty(); - } - virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc, - Scope *CurScope) { - return StmtEmpty(); - } - virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc, - ExprArg RetValExp) { - return StmtEmpty(); - } - virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc, - bool IsSimple, - bool IsVolatile, - unsigned NumOutputs, - unsigned NumInputs, - IdentifierInfo **Names, - MultiExprArg Constraints, - MultiExprArg Exprs, - ExprArg AsmString, - MultiExprArg Clobbers, - SourceLocation RParenLoc, - bool MSAsm = false) { - return StmtEmpty(); - } - - // Objective-c statements - - /// \brief Parsed an Objective-C @catch statement. - /// - /// \param AtLoc The location of the '@' starting the '@catch'. - /// - /// \param RParen The location of the right parentheses ')' after the - /// exception variable. - /// - /// \param Parm The variable that will catch the exception. Will be NULL if - /// this is a @catch(...) block. - /// - /// \param Body The body of the @catch block. - virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, - SourceLocation RParen, - DeclPtrTy Parm, StmtArg Body) { - return StmtEmpty(); - } - - /// \brief Parsed an Objective-C @finally statement. - /// - /// \param AtLoc The location of the '@' starting the '@finally'. - /// - /// \param Body The body of the @finally block. - virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, - StmtArg Body) { - return StmtEmpty(); - } - - /// \brief Parsed an Objective-C @try-@catch-@finally statement. - /// - /// \param AtLoc The location of the '@' starting '@try'. - /// - /// \param Try The body of the '@try' statement. - /// - /// \param CatchStmts The @catch statements. - /// - /// \param Finally The @finally statement. - virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, - StmtArg Try, - MultiStmtArg CatchStmts, - StmtArg Finally) { - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, - ExprArg Throw, - Scope *CurScope) { - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, - ExprArg SynchExpr, - StmtArg SynchBody) { - return StmtEmpty(); - } - - // C++ Statements - virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D) { - return DeclPtrTy(); - } - - virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, - DeclPtrTy ExceptionDecl, - StmtArg HandlerBlock) { - return StmtEmpty(); - } - - virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc, - StmtArg TryBlock, - MultiStmtArg Handlers) { - return StmtEmpty(); - } - - //===--------------------------------------------------------------------===// - // Expression Parsing Callbacks. - //===--------------------------------------------------------------------===// - - /// \brief Describes how the expressions currently being parsed are - /// evaluated at run-time, if at all. - enum ExpressionEvaluationContext { - /// \brief The current expression and its subexpressions occur within an - /// unevaluated operand (C++0x [expr]p8), such as a constant expression - /// or the subexpression of \c sizeof, where the type or the value of the - /// expression may be significant but no code will be generated to evaluate - /// the value of the expression at run time. - Unevaluated, - - /// \brief The current expression is potentially evaluated at run time, - /// which means that code may be generated to evaluate the value of the - /// expression at run time. - PotentiallyEvaluated, - - /// \brief The current expression may be potentially evaluated or it may - /// be unevaluated, but it is impossible to tell from the lexical context. - /// This evaluation context is used primary for the operand of the C++ - /// \c typeid expression, whose argument is potentially evaluated only when - /// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2). - PotentiallyPotentiallyEvaluated - }; - - /// \brief The parser is entering a new expression evaluation context. - /// - /// \param NewContext is the new expression evaluation context. - virtual void - PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { } - - /// \brief The parser is exiting an expression evaluation context. - virtual void - PopExpressionEvaluationContext() { } - - // Primary Expressions. - - /// \brief Retrieve the source range that corresponds to the given - /// expression. - virtual SourceRange getExprRange(ExprTy *E) const { - return SourceRange(); - } - - /// \brief Parsed an id-expression (C++) or identifier (C) in expression - /// context, e.g., the expression "x" that refers to a variable named "x". - /// - /// \param S the scope in which this id-expression or identifier occurs. - /// - /// \param SS the C++ nested-name-specifier that qualifies the name of the - /// value, e.g., "std::" in "std::sort". - /// - /// \param Name the name to which the id-expression refers. In C, this will - /// always be an identifier. In C++, it may also be an overloaded operator, - /// destructor name (if there is a nested-name-specifier), or template-id. - /// - /// \param HasTrailingLParen whether the next token following the - /// id-expression or identifier is a left parentheses ('('). - /// - /// \param IsAddressOfOperand whether the token that precedes this - /// id-expression or identifier was an ampersand ('&'), indicating that - /// we will be taking the address of this expression. - virtual OwningExprResult ActOnIdExpression(Scope *S, - CXXScopeSpec &SS, - UnqualifiedId &Name, - bool HasTrailingLParen, - bool IsAddressOfOperand) { - return ExprEmpty(); - } - - virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, - tok::TokenKind Kind) { - return ExprEmpty(); - } - virtual OwningExprResult ActOnCharacterConstant(const Token &) { - return ExprEmpty(); - } - virtual OwningExprResult ActOnNumericConstant(const Token &) { - return ExprEmpty(); - } - - /// ActOnStringLiteral - The specified tokens were lexed as pasted string - /// fragments (e.g. "foo" "bar" L"baz"). - virtual OwningExprResult ActOnStringLiteral(const Token *Toks, - unsigned NumToks) { - return ExprEmpty(); - } - - virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, - ExprArg Val) { - return move(Val); // Default impl returns operand. - } - - virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L, - SourceLocation R, - MultiExprArg Val, - TypeTy *TypeOfCast=0) { - return ExprEmpty(); - } - - // Postfix Expressions. - virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, - tok::TokenKind Kind, - ExprArg Input) { - return ExprEmpty(); - } - virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base, - SourceLocation LLoc, - ExprArg Idx, - SourceLocation RLoc) { - return ExprEmpty(); - } - - /// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref]) - /// of the form \c x.m or \c p->m. - /// - /// \param S the scope in which the member access expression occurs. - /// - /// \param Base the class or pointer to class into which this member - /// access expression refers, e.g., \c x in \c x.m. - /// - /// \param OpLoc the location of the "." or "->" operator. - /// - /// \param OpKind the kind of member access operator, which will be either - /// tok::arrow ("->") or tok::period ("."). - /// - /// \param SS in C++, the nested-name-specifier that precedes the member - /// name, if any. - /// - /// \param Member the name of the member that we are referring to. In C, - /// this will always store an identifier; in C++, we may also have operator - /// names, conversion function names, destructors, and template names. - /// - /// \param ObjCImpDecl the Objective-C implementation declaration. - /// FIXME: Do we really need this? - /// - /// \param HasTrailingLParen whether this member name is immediately followed - /// by a left parentheses ('('). - virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - CXXScopeSpec &SS, - UnqualifiedId &Member, - DeclPtrTy ObjCImpDecl, - bool HasTrailingLParen) { - return ExprEmpty(); - } - - /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. - /// This provides the location of the left/right parens and a list of comma - /// locations. There are guaranteed to be one fewer commas than arguments, - /// unless there are zero arguments. - virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn, - SourceLocation LParenLoc, - MultiExprArg Args, - SourceLocation *CommaLocs, - SourceLocation RParenLoc) { - return ExprEmpty(); - } - - // Unary Operators. 'Tok' is the token for the operator. - virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, - tok::TokenKind Op, ExprArg Input) { - return ExprEmpty(); - } - virtual OwningExprResult - ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, - void *TyOrEx, const SourceRange &ArgRange) { - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen, - TypeTy *Ty, - SourceLocation RParen, - ExprArg Op) { - return ExprEmpty(); - } - virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc, - MultiExprArg InitList, - SourceLocation RParenLoc) { - return ExprEmpty(); - } - /// @brief Parsed a C99 designated initializer. - /// - /// @param Desig Contains the designation with one or more designators. - /// - /// @param Loc The location of the '=' or ':' prior to the - /// initialization expression. - /// - /// @param GNUSyntax If true, then this designated initializer used - /// the deprecated GNU syntax @c fieldname:foo or @c [expr]foo rather - /// than the C99 syntax @c .fieldname=foo or @c [expr]=foo. - /// - /// @param Init The value that the entity (or entities) described by - /// the designation will be initialized with. - virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig, - SourceLocation Loc, - bool GNUSyntax, - OwningExprResult Init) { - return ExprEmpty(); - } - - virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, - TypeTy *Ty, SourceLocation RParenLoc, - ExprArg Op) { - return ExprEmpty(); - } - - virtual bool TypeIsVectorType(TypeTy *Ty) { - return false; - } - - virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, - tok::TokenKind Kind, - ExprArg LHS, ExprArg RHS) { - return ExprEmpty(); - } - - /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null - /// in the case of a the GNU conditional expr extension. - virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc, - SourceLocation ColonLoc, - ExprArg Cond, ExprArg LHS, - ExprArg RHS) { - return ExprEmpty(); - } - - //===---------------------- GNU Extension Expressions -------------------===// - - virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc, - SourceLocation LabLoc, - IdentifierInfo *LabelII) { // "&&foo" - return ExprEmpty(); - } - - virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtArg SubStmt, - SourceLocation RPLoc) { // "({..})" - return ExprEmpty(); - } - - // __builtin_offsetof(type, identifier(.identifier|[expr])*) - struct OffsetOfComponent { - SourceLocation LocStart, LocEnd; - bool isBrackets; // true if [expr], false if .ident - union { - IdentifierInfo *IdentInfo; - ExprTy *E; - } U; - }; - - virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S, - SourceLocation BuiltinLoc, - SourceLocation TypeLoc, - TypeTy *Arg1, - OffsetOfComponent *CompPtr, - unsigned NumComponents, - SourceLocation RParenLoc) { - return ExprEmpty(); - } - - // __builtin_types_compatible_p(type1, type2) - virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, - TypeTy *arg1, TypeTy *arg2, - SourceLocation RPLoc) { - return ExprEmpty(); - } - // __builtin_choose_expr(constExpr, expr1, expr2) - virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, - ExprArg cond, ExprArg expr1, - ExprArg expr2, SourceLocation RPLoc){ - return ExprEmpty(); - } - - // __builtin_va_arg(expr, type) - virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc, - ExprArg expr, TypeTy *type, - SourceLocation RPLoc) { - return ExprEmpty(); - } - - /// ActOnGNUNullExpr - Parsed the GNU __null expression, the token - /// for which is at position TokenLoc. - virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) { - return ExprEmpty(); - } - - //===------------------------- "Block" Extension ------------------------===// - - /// ActOnBlockStart - This callback is invoked when a block literal is - /// started. The result pointer is passed into the block finalizers. - virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {} - - /// ActOnBlockArguments - This callback allows processing of block arguments. - /// If there are no arguments, this is still invoked. - virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {} - - /// ActOnBlockError - If there is an error parsing a block, this callback - /// is invoked to pop the information about the block from the action impl. - virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {} - - /// ActOnBlockStmtExpr - This is called when the body of a block statement - /// literal was successfully completed. ^(int x){...} - virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, - StmtArg Body, - Scope *CurScope) { - return ExprEmpty(); - } - - //===------------------------- C++ Declarations -------------------------===// - - /// ActOnStartNamespaceDef - This is called at the start of a namespace - /// definition. - virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc, - IdentifierInfo *Ident, - SourceLocation LBrace, - AttributeList *AttrList) { - return DeclPtrTy(); - } - - /// ActOnFinishNamespaceDef - This callback is called after a namespace is - /// exited. Decl is returned by ActOnStartNamespaceDef. - virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace) { - return; - } - - /// ActOnUsingDirective - This is called when using-directive is parsed. - virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *NamespcName, - AttributeList *AttrList); - - /// ActOnNamespaceAliasDef - This is called when a namespace alias definition - /// is parsed. - virtual DeclPtrTy ActOnNamespaceAliasDef(Scope *CurScope, - SourceLocation NamespaceLoc, - SourceLocation AliasLoc, - IdentifierInfo *Alias, - CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *Ident) { - return DeclPtrTy(); - } - - /// \brief Parsed a C++ using-declaration. - /// - /// This callback will be invoked when the parser has parsed a C++ - /// using-declaration, e.g., - /// - /// \code - /// namespace std { - /// template<typename T, typename Alloc> class vector; - /// } - /// - /// using std::vector; // using-declaration here - /// \endcode - /// - /// \param CurScope the scope in which this using declaration was parsed. - /// - /// \param AS the currently-active access specifier. - /// - /// \param HasUsingKeyword true if this was declared with an - /// explicit 'using' keyword (i.e. if this is technically a using - /// declaration, not an access declaration) - /// - /// \param UsingLoc the location of the 'using' keyword. - /// - /// \param SS the nested-name-specifier that precedes the name. - /// - /// \param Name the name to which the using declaration refers. - /// - /// \param AttrList attributes applied to this using declaration, if any. - /// - /// \param IsTypeName whether this using declaration started with the - /// 'typename' keyword. FIXME: This will eventually be split into a - /// separate action. - /// - /// \param TypenameLoc the location of the 'typename' keyword, if present - /// - /// \returns a representation of the using declaration. - virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope, - AccessSpecifier AS, - bool HasUsingKeyword, - SourceLocation UsingLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - AttributeList *AttrList, - bool IsTypeName, - SourceLocation TypenameLoc); - - /// ActOnParamDefaultArgument - Parse default argument for function parameter - virtual void ActOnParamDefaultArgument(DeclPtrTy param, - SourceLocation EqualLoc, - ExprArg defarg) { - } - - /// ActOnParamUnparsedDefaultArgument - We've seen a default - /// argument for a function parameter, but we can't parse it yet - /// because we're inside a class definition. Note that this default - /// argument will be parsed later. - virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param, - SourceLocation EqualLoc, - SourceLocation ArgLoc) { } - - /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of - /// the default argument for the parameter param failed. - virtual void ActOnParamDefaultArgumentError(DeclPtrTy param) { } - - /// AddCXXDirectInitializerToDecl - This action is called immediately after - /// ActOnDeclarator, when a C++ direct initializer is present. - /// e.g: "int x(1);" - virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, - SourceLocation LParenLoc, - MultiExprArg Exprs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc) { - return; - } - - /// \brief Called when we re-enter a template parameter scope. - /// - /// This action occurs when we are going to parse an member - /// function's default arguments or inline definition after the - /// outermost class definition has been completed, and when one or - /// more of the class definitions enclosing the member function is a - /// template. The "entity" in the given scope will be set as it was - /// when we entered the scope of the template initially, and should - /// be used to, e.g., reintroduce the names of template parameters - /// into the current scope so that they can be found by name lookup. - /// - /// \param S The (new) template parameter scope. - /// - /// \param Template the class template declaration whose template - /// parameters should be reintroduced into the current scope. - virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) { - } - - /// ActOnStartDelayedMemberDeclarations - We have completed parsing - /// a C++ class, and we are about to start parsing any parts of - /// member declarations that could not be parsed earlier. Enter - /// the appropriate record scope. - virtual void ActOnStartDelayedMemberDeclarations(Scope *S, - DeclPtrTy Record) { - } - - /// ActOnStartDelayedCXXMethodDeclaration - We have completed - /// parsing a top-level (non-nested) C++ class, and we are now - /// parsing those parts of the given Method declaration that could - /// not be parsed earlier (C++ [class.mem]p2), such as default - /// arguments. This action should enter the scope of the given - /// Method declaration as if we had just parsed the qualified method - /// name. However, it should not bring the parameters into scope; - /// that will be performed by ActOnDelayedCXXMethodParameter. - virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S, - DeclPtrTy Method) { - } - - /// ActOnDelayedCXXMethodParameter - We've already started a delayed - /// C++ method declaration. We're (re-)introducing the given - /// function parameter into scope for use in parsing later parts of - /// the method declaration. For example, we could see an - /// ActOnParamDefaultArgument event for this parameter. - virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param) { - } - - /// ActOnFinishDelayedCXXMethodDeclaration - We have finished - /// processing the delayed method declaration for Method. The method - /// declaration is now considered finished. There may be a separate - /// ActOnStartOfFunctionDef action later (not necessarily - /// immediately!) for this method, if it was also defined inside the - /// class body. - virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, - DeclPtrTy Method) { - } - - /// ActOnFinishDelayedMemberDeclarations - We have finished parsing - /// a C++ class, and we are about to start parsing any parts of - /// member declarations that could not be parsed earlier. Enter the - /// appropriate record scope. - virtual void ActOnFinishDelayedMemberDeclarations(Scope *S, - DeclPtrTy Record) { - } - - /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration. - virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc, - ExprArg AssertExpr, - ExprArg AssertMessageExpr) { - return DeclPtrTy(); - } - - /// ActOnFriendFunctionDecl - Parsed a friend function declarator. - /// The name is actually a slight misnomer, because the declarator - /// is not necessarily a function declarator. - virtual DeclPtrTy ActOnFriendFunctionDecl(Scope *S, - Declarator &D, - bool IsDefinition, - MultiTemplateParamsArg TParams) { - return DeclPtrTy(); - } - - /// ActOnFriendTypeDecl - Parsed a friend type declaration. - virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, - MultiTemplateParamsArg TParams) { - return DeclPtrTy(); - } - - //===------------------------- C++ Expressions --------------------------===// - - /// \brief Parsed a destructor name or pseudo-destructor name. - /// - /// \returns the type being destructed. - virtual TypeTy *getDestructorName(SourceLocation TildeLoc, - IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec &SS, - TypeTy *ObjectType, - bool EnteringContext) { - return getTypeName(II, NameLoc, S, &SS, false, ObjectType); - } - - - /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. - virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc, - tok::TokenKind Kind, - SourceLocation LAngleBracketLoc, - TypeTy *Ty, - SourceLocation RAngleBracketLoc, - SourceLocation LParenLoc, - ExprArg Op, - SourceLocation RParenLoc) { - return ExprEmpty(); - } - - /// ActOnCXXTypeidOfType - Parse typeid( type-id ). - virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc, - SourceLocation LParenLoc, bool isType, - void *TyOrExpr, - SourceLocation RParenLoc) { - return ExprEmpty(); - } - - /// ActOnCXXThis - Parse the C++ 'this' pointer. - virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc) { - return ExprEmpty(); - } - - /// ActOnCXXBoolLiteral - Parse {true,false} literals. - virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, - tok::TokenKind Kind) { - return ExprEmpty(); - } - - /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. - virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc) { - return ExprEmpty(); - } - - /// ActOnCXXThrow - Parse throw expressions. - virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, ExprArg Op) { - return ExprEmpty(); - } - - /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. - /// Can be interpreted either as function-style casting ("int(x)") - /// or class type construction ("ClassType(x,y,z)") - /// or creation of a value-initialized type ("int()"). - virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange, - TypeTy *TypeRep, - SourceLocation LParenLoc, - MultiExprArg Exprs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc) { - return ExprEmpty(); - } - - /// \brief Parsed a condition declaration in a C++ if, switch, or while - /// statement. - /// - /// This callback will be invoked after parsing the declaration of "x" in - /// - /// \code - /// if (int x = f()) { - /// // ... - /// } - /// \endcode - /// - /// \param S the scope of the if, switch, or while statement. - /// - /// \param D the declarator that that describes the variable being declared. - virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { - return DeclResult(); - } - - /// \brief Parsed an expression that will be handled as the condition in - /// an if/while/for statement. - /// - /// This routine handles the conversion of the expression to 'bool'. - /// - /// \param S The scope in which the expression occurs. - /// - /// \param Loc The location of the construct that requires the conversion to - /// a boolean value. - /// - /// \param SubExpr The expression that is being converted to bool. - virtual OwningExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, - ExprArg SubExpr) { - return move(SubExpr); - } - - /// \brief Parsed a C++ 'new' expression. - /// - /// \param StartLoc The start of the new expression, which is either the - /// "new" keyword or the "::" preceding it, depending on \p UseGlobal. - /// - /// \param UseGlobal True if the "new" was qualified with "::". - /// - /// \param PlacementLParen The location of the opening parenthesis ('(') for - /// the placement arguments, if any. - /// - /// \param PlacementArgs The placement arguments, if any. - /// - /// \param PlacementRParen The location of the closing parenthesis (')') for - /// the placement arguments, if any. - /// - /// \param TypeIdParens If the type was expressed as a type-id in parentheses, - /// the source range covering the parenthesized type-id. - /// - /// \param D The parsed declarator, which may include an array size (for - /// array new) as the first declarator. - /// - /// \param ConstructorLParen The location of the opening parenthesis ('(') for - /// the constructor arguments, if any. - /// - /// \param ConstructorArgs The constructor arguments, if any. - /// - /// \param ConstructorRParen The location of the closing parenthesis (')') for - /// the constructor arguments, if any. - virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, - SourceLocation PlacementLParen, - MultiExprArg PlacementArgs, - SourceLocation PlacementRParen, - SourceRange TypeIdParens, Declarator &D, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen) { - return ExprEmpty(); - } - - /// ActOnCXXDelete - Parsed a C++ 'delete' expression. UseGlobal is true if - /// the delete was qualified (::delete). ArrayForm is true if the array form - /// was used (delete[]). - virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc, - bool UseGlobal, bool ArrayForm, - ExprArg Operand) { - return ExprEmpty(); - } - - virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT, - SourceLocation KWLoc, - SourceLocation LParen, - TypeTy *Ty, - SourceLocation RParen) { - return ExprEmpty(); - } - - /// \brief Invoked when the parser is starting to parse a C++ member access - /// expression such as x.f or x->f. - /// - /// \param S the scope in which the member access expression occurs. - /// - /// \param Base the expression in which a member is being accessed, e.g., the - /// "x" in "x.f". - /// - /// \param OpLoc the location of the member access operator ("." or "->") - /// - /// \param OpKind the kind of member access operator ("." or "->") - /// - /// \param ObjectType originally NULL. The action should fill in this type - /// with the type into which name lookup should look to find the member in - /// the member access expression. - /// - /// \param MayBePseudoDestructor Originally false. The action should - /// set this true if the expression may end up being a - /// pseudo-destructor expression, indicating to the parser that it - /// shoudl be parsed as a pseudo-destructor rather than as a member - /// access expression. Note that this should apply both when the - /// object type is a scalar and when the object type is dependent. - /// - /// \returns the (possibly modified) \p Base expression - virtual OwningExprResult ActOnStartCXXMemberReference(Scope *S, - ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - TypeTy *&ObjectType, - bool &MayBePseudoDestructor) { - return ExprEmpty(); - } - - /// \brief Parsed a C++ pseudo-destructor expression or a dependent - /// member access expression that has the same syntactic form as a - /// pseudo-destructor expression. - /// - /// \param S The scope in which the member access expression occurs. - /// - /// \param Base The expression in which a member is being accessed, e.g., the - /// "x" in "x.f". - /// - /// \param OpLoc The location of the member access operator ("." or "->") - /// - /// \param OpKind The kind of member access operator ("." or "->") - /// - /// \param SS The nested-name-specifier that precedes the type names - /// in the grammar. Note that this nested-name-specifier will not - /// cover the last "type-name ::" in the grammar, because it isn't - /// necessarily a nested-name-specifier. - /// - /// \param FirstTypeName The type name that follows the optional - /// nested-name-specifier but precedes the '::', e.g., the first - /// type-name in "type-name :: type-name". This type name may be - /// empty. This will be either an identifier or a template-id. - /// - /// \param CCLoc The location of the '::' in "type-name :: - /// typename". May be invalid, if there is no \p FirstTypeName. - /// - /// \param TildeLoc The location of the '~'. - /// - /// \param SecondTypeName The type-name following the '~', which is - /// the name of the type being destroyed. This will be either an - /// identifier or a template-id. - /// - /// \param HasTrailingLParen Whether the next token in the stream is - /// a left parentheses. - virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - CXXScopeSpec &SS, - UnqualifiedId &FirstTypeName, - SourceLocation CCLoc, - SourceLocation TildeLoc, - UnqualifiedId &SecondTypeName, - bool HasTrailingLParen) { - return ExprEmpty(); - } - - /// ActOnFinishFullExpr - Called whenever a full expression has been parsed. - /// (C++ [intro.execution]p12). - virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) { - return move(Expr); - } - - //===---------------------------- C++ Classes ---------------------------===// - /// ActOnBaseSpecifier - Parsed a base specifier - virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl, - SourceRange SpecifierRange, - bool Virtual, AccessSpecifier Access, - TypeTy *basetype, - SourceLocation BaseLoc) { - return BaseResult(); - } - - virtual void ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, - unsigned NumBases) { - } - - /// ActOnAccessSpecifier - This is invoked when an access specifier - /// (and the colon following it) is found during the parsing of a - /// C++ class member declarator. - virtual DeclPtrTy ActOnAccessSpecifier(AccessSpecifier AS, - SourceLocation ASLoc, - SourceLocation ColonLoc) { - return DeclPtrTy(); - } - - /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member - /// declarator is parsed. 'AS' is the access specifier, 'BitfieldWidth' - /// specifies the bitfield width if there is one and 'Init' specifies the - /// initializer if any. 'Deleted' is true if there's a =delete - /// specifier on the function. - virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, - Declarator &D, - MultiTemplateParamsArg TemplateParameterLists, - ExprTy *BitfieldWidth, - ExprTy *Init, - bool IsDefinition, - bool Deleted = false) { - return DeclPtrTy(); - } - - virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorDecl, - Scope *S, - CXXScopeSpec &SS, - IdentifierInfo *MemberOrBase, - TypeTy *TemplateTypeTy, - SourceLocation IdLoc, - SourceLocation LParenLoc, - ExprTy **Args, unsigned NumArgs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc) { - return true; - } - - /// ActOnMemInitializers - This is invoked when all of the member - /// initializers of a constructor have been parsed. ConstructorDecl - /// is the function declaration (which will be a C++ constructor in - /// a well-formed program), ColonLoc is the location of the ':' that - /// starts the constructor initializer, and MemInit/NumMemInits - /// contains the individual member (and base) initializers. - /// AnyErrors will be true if there were any invalid member initializers - /// that are not represented in the list. - virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, - SourceLocation ColonLoc, - MemInitTy **MemInits, unsigned NumMemInits, - bool AnyErrors){ - } - - virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {} - - /// ActOnFinishCXXMemberSpecification - Invoked after all member declarators - /// are parsed but *before* parsing of inline method definitions. - virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - DeclPtrTy TagDecl, - SourceLocation LBrac, - SourceLocation RBrac, - AttributeList *AttrList) { - } - - //===---------------------------C++ Templates----------------------------===// - - /// \brief Called when a C++ template type parameter(e.g., "typename T") has - /// been parsed. - /// - /// Given - /// - /// \code - /// template<typename T, typename U = T> struct pair; - /// \endcode - /// - /// this callback will be invoked twice: once for the type parameter \c T - /// with \p Depth=0 and \p Position=0, and once for the type parameter \c U - /// with \p Depth=0 and \p Position=1. - /// - /// \param Typename Specifies whether the keyword "typename" was used to - /// declare the type parameter (otherwise, "class" was used). - /// - /// \param Ellipsis Specifies whether this is a C++0x parameter pack. - /// - /// \param EllipsisLoc Specifies the start of the ellipsis. - /// - /// \param KeyLoc The location of the "class" or "typename" keyword. - /// - /// \param ParamName The name of the parameter, where NULL indicates an - /// unnamed template parameter. - /// - /// \param ParamNameLoc The location of the parameter name (if any). - /// - /// \param Depth The depth of this template parameter, e.g., the number of - /// template parameter lists that occurred outside the template parameter - /// list in which this template type parameter occurs. - /// - /// \param Position The zero-based position of this template parameter within - /// its template parameter list, which is also the number of template - /// parameters that precede this parameter in the template parameter list. - /// - /// \param EqualLoc The location of the '=' sign for the default template - /// argument, if any. - /// - /// \param DefaultArg The default argument, if provided. - virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, - SourceLocation EllipsisLoc, - SourceLocation KeyLoc, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, - unsigned Depth, unsigned Position, - SourceLocation EqualLoc, - TypeTy *DefaultArg) { - return DeclPtrTy(); - } - - /// \brief Called when a C++ non-type template parameter has been parsed. - /// - /// Given - /// - /// \code - /// template<int Size> class Array; - /// \endcode - /// - /// This callback will be invoked for the 'Size' non-type template parameter. - /// - /// \param S The current scope. - /// - /// \param D The parsed declarator. - /// - /// \param Depth The depth of this template parameter, e.g., the number of - /// template parameter lists that occurred outside the template parameter - /// list in which this template type parameter occurs. - /// - /// \param Position The zero-based position of this template parameter within - /// its template parameter list, which is also the number of template - /// parameters that precede this parameter in the template parameter list. - /// - /// \param EqualLoc The location of the '=' sign for the default template - /// argument, if any. - /// - /// \param DefaultArg The default argument, if provided. - virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, - unsigned Depth, - unsigned Position, - SourceLocation EqualLoc, - ExprArg DefaultArg) { - return DeclPtrTy(); - } - - /// \brief Adds a default argument to the given non-type template - /// parameter. - virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam, - SourceLocation EqualLoc, - ExprArg Default) { - } - - /// \brief Called when a C++ template template parameter has been parsed. - /// - /// Given - /// - /// \code - /// template<template <typename> class T> class X; - /// \endcode - /// - /// this callback will be invoked for the template template parameter \c T. - /// - /// \param S The scope in which this template template parameter occurs. - /// - /// \param TmpLoc The location of the "template" keyword. - /// - /// \param TemplateParams The template parameters required by the template. - /// - /// \param ParamName The name of the parameter, or NULL if unnamed. - /// - /// \param ParamNameLoc The source location of the parameter name (if given). - /// - /// \param Depth The depth of this template parameter, e.g., the number of - /// template parameter lists that occurred outside the template parameter - /// list in which this template parameter occurs. - /// - /// \param Position The zero-based position of this template parameter within - /// its template parameter list, which is also the number of template - /// parameters that precede this parameter in the template parameter list. - /// - /// \param EqualLoc The location of the '=' sign for the default template - /// argument, if any. - /// - /// \param DefaultArg The default argument, if provided. - virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S, - SourceLocation TmpLoc, - TemplateParamsTy *Params, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, - unsigned Depth, - unsigned Position, - SourceLocation EqualLoc, - const ParsedTemplateArgument &DefaultArg) { - return DeclPtrTy(); - } - - /// ActOnTemplateParameterList - Called when a complete template - /// parameter list has been parsed, e.g., - /// - /// @code - /// export template<typename T, T Size> - /// @endcode - /// - /// Depth is the number of enclosing template parameter lists. This - /// value does not include templates from outer scopes. For example: - /// - /// @code - /// template<typename T> // depth = 0 - /// class A { - /// template<typename U> // depth = 0 - /// class B; - /// }; - /// - /// template<typename T> // depth = 0 - /// template<typename U> // depth = 1 - /// class A<T>::B { ... }; - /// @endcode - /// - /// ExportLoc, if valid, is the position of the "export" - /// keyword. Otherwise, "export" was not specified. - /// TemplateLoc is the position of the template keyword, LAngleLoc - /// is the position of the left angle bracket, and RAngleLoc is the - /// position of the corresponding right angle bracket. - /// Params/NumParams provides the template parameters that were - /// parsed as part of the template-parameter-list. - virtual TemplateParamsTy * - ActOnTemplateParameterList(unsigned Depth, - SourceLocation ExportLoc, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - DeclPtrTy *Params, unsigned NumParams, - SourceLocation RAngleLoc) { - return 0; - } - - /// \brief Form a type from a template and a list of template - /// arguments. - /// - /// This action merely forms the type for the template-id, possibly - /// checking well-formedness of the template arguments. It does not - /// imply the declaration of any entity. - /// - /// \param Template A template whose specialization results in a - /// type, e.g., a class template or template template parameter. - virtual TypeResult ActOnTemplateIdType(TemplateTy Template, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc) { - return TypeResult(); - } - - /// \brief Note that a template ID was used with a tag. - /// - /// \param Type The result of ActOnTemplateIdType. - /// - /// \param TUK Either TUK_Reference or TUK_Friend. Declarations and - /// definitions are interpreted as explicit instantiations or - /// specializations. - /// - /// \param TagSpec The tag keyword that was provided as part of the - /// elaborated-type-specifier; either class, struct, union, or enum. - /// - /// \param TagLoc The location of the tag keyword. - virtual TypeResult ActOnTagTemplateIdType(TypeResult Type, - TagUseKind TUK, - DeclSpec::TST TagSpec, - SourceLocation TagLoc) { - return TypeResult(); - } - - /// \brief Form a dependent template name. - /// - /// This action forms a dependent template name given the template - /// name and its (presumably dependent) scope specifier. For - /// example, given "MetaFun::template apply", the scope specifier \p - /// SS will be "MetaFun::", \p TemplateKWLoc contains the location - /// of the "template" keyword, and "apply" is the \p Name. - /// - /// \param S The scope in which the dependent template name was parsed. - /// - /// \param TemplateKWLoc the location of the "template" keyword (if any). - /// - /// \param SS the nested-name-specifier that precedes the "template" keyword - /// or the template name. If the dependent template name occurs in - /// a member access expression, e.g., "x.template f<T>", this - /// nested-name-specifier will be empty. - /// - /// \param Name the name of the template. - /// - /// \param ObjectType if this dependent template name occurs in the - /// context of a member access expression, the type of the object being - /// accessed. - /// - /// \param EnteringContext whether we are entering the context of this - /// template. - /// - /// \param Template Will be set to the dependent template name, on success. - /// - /// \returns The kind of template name that was produced. Generally, this will - /// be \c TNK_Dependent_template_name. However, if the nested-name-specifier - /// is not dependent, or refers to the current instantiation, then we may - /// be able to resolve the template kind more specifically. - virtual TemplateNameKind ActOnDependentTemplateName(Scope *S, - SourceLocation TemplateKWLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - TypeTy *ObjectType, - bool EnteringContext, - TemplateTy &Template) { - return TNK_Non_template; - } - - /// \brief Process the declaration or definition of an explicit - /// class template specialization or a class template partial - /// specialization. - /// - /// This routine is invoked when an explicit class template - /// specialization or a class template partial specialization is - /// declared or defined, to introduce the (partial) specialization - /// and produce a declaration for it. In the following example, - /// ActOnClassTemplateSpecialization will be invoked for the - /// declarations at both A and B: - /// - /// \code - /// template<typename T> class X; - /// template<> class X<int> { }; // A: explicit specialization - /// template<typename T> class X<T*> { }; // B: partial specialization - /// \endcode - /// - /// Note that it is the job of semantic analysis to determine which - /// of the two cases actually occurred in the source code, since - /// they are parsed through the same path. The formulation of the - /// template parameter lists describes which case we are in. - /// - /// \param S the current scope - /// - /// \param TagSpec whether this declares a class, struct, or union - /// (template) - /// - /// \param TUK whether this is a declaration or a definition - /// - /// \param KWLoc the location of the 'class', 'struct', or 'union' - /// keyword. - /// - /// \param SS the scope specifier preceding the template-id - /// - /// \param Template the declaration of the class template that we - /// are specializing. - /// - /// \param Attr attributes on the specialization - /// - /// \param TemplateParameterLists the set of template parameter - /// lists that apply to this declaration. In a well-formed program, - /// the number of template parameter lists will be one more than the - /// number of template-ids in the scope specifier. However, it is - /// common for users to provide the wrong number of template - /// parameter lists (such as a missing \c template<> prior to a - /// specialization); the parser does not check this condition. - virtual DeclResult - ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, - CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc, - AttributeList *Attr, - MultiTemplateParamsArg TemplateParameterLists) { - return DeclResult(); - } - - /// \brief Invoked when a declarator that has one or more template parameter - /// lists has been parsed. - /// - /// This action is similar to ActOnDeclarator(), except that the declaration - /// being created somehow involves a template, e.g., it is a template - /// declaration or specialization. - virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S, - MultiTemplateParamsArg TemplateParameterLists, - Declarator &D) { - return DeclPtrTy(); - } - - /// \brief Invoked when the parser is beginning to parse a function template - /// or function template specialization definition. - virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, - MultiTemplateParamsArg TemplateParameterLists, - Declarator &D) { - return DeclPtrTy(); - } - - /// \brief Process the explicit instantiation of a class template - /// specialization. - /// - /// This routine is invoked when an explicit instantiation of a - /// class template specialization is encountered. In the following - /// example, ActOnExplicitInstantiation will be invoked to force the - /// instantiation of X<int>: - /// - /// \code - /// template<typename T> class X { /* ... */ }; - /// template class X<int>; // explicit instantiation - /// \endcode - /// - /// \param S the current scope - /// - /// \param ExternLoc the location of the 'extern' keyword that specifies that - /// this is an extern template (if any). - /// - /// \param TemplateLoc the location of the 'template' keyword that - /// specifies that this is an explicit instantiation. - /// - /// \param TagSpec whether this declares a class, struct, or union - /// (template). - /// - /// \param KWLoc the location of the 'class', 'struct', or 'union' - /// keyword. - /// - /// \param SS the scope specifier preceding the template-id. - /// - /// \param Template the declaration of the class template that we - /// are instantiation. - /// - /// \param LAngleLoc the location of the '<' token in the template-id. - /// - /// \param TemplateArgs the template arguments used to form the - /// template-id. - /// - /// \param TemplateArgLocs the locations of the template arguments. - /// - /// \param RAngleLoc the location of the '>' token in the template-id. - /// - /// \param Attr attributes that apply to this instantiation. - virtual DeclResult - ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - const CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc, - AttributeList *Attr) { - return DeclResult(); - } - - /// \brief Process the explicit instantiation of a member class of a - /// class template specialization. - /// - /// This routine is invoked when an explicit instantiation of a - /// member class of a class template specialization is - /// encountered. In the following example, - /// ActOnExplicitInstantiation will be invoked to force the - /// instantiation of X<int>::Inner: - /// - /// \code - /// template<typename T> class X { class Inner { /* ... */}; }; - /// template class X<int>::Inner; // explicit instantiation - /// \endcode - /// - /// \param S the current scope - /// - /// \param ExternLoc the location of the 'extern' keyword that specifies that - /// this is an extern template (if any). - /// - /// \param TemplateLoc the location of the 'template' keyword that - /// specifies that this is an explicit instantiation. - /// - /// \param TagSpec whether this declares a class, struct, or union - /// (template). - /// - /// \param KWLoc the location of the 'class', 'struct', or 'union' - /// keyword. - /// - /// \param SS the scope specifier preceding the template-id. - /// - /// \param Template the declaration of the class template that we - /// are instantiation. - /// - /// \param LAngleLoc the location of the '<' token in the template-id. - /// - /// \param TemplateArgs the template arguments used to form the - /// template-id. - /// - /// \param TemplateArgLocs the locations of the template arguments. - /// - /// \param RAngleLoc the location of the '>' token in the template-id. - /// - /// \param Attr attributes that apply to this instantiation. - virtual DeclResult - ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation NameLoc, - AttributeList *Attr) { - return DeclResult(); - } - - /// \brief Process the explicit instantiation of a function template or a - /// member of a class template. - /// - /// This routine is invoked when an explicit instantiation of a - /// function template or member function of a class template specialization - /// is encountered. In the following example, - /// ActOnExplicitInstantiation will be invoked to force the - /// instantiation of X<int>: - /// - /// \code - /// template<typename T> void f(T); - /// template void f(int); // explicit instantiation - /// \endcode - /// - /// \param S the current scope - /// - /// \param ExternLoc the location of the 'extern' keyword that specifies that - /// this is an extern template (if any). - /// - /// \param TemplateLoc the location of the 'template' keyword that - /// specifies that this is an explicit instantiation. - /// - /// \param D the declarator describing the declaration to be implicitly - /// instantiated. - virtual DeclResult ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - Declarator &D) { - return DeclResult(); - } - - - /// \brief Called when the parser has parsed a C++ typename - /// specifier that ends in an identifier, e.g., "typename T::type". - /// - /// \param TypenameLoc the location of the 'typename' keyword - /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). - /// \param II the identifier we're retrieving (e.g., 'type' in the example). - /// \param IdLoc the location of the identifier. - virtual TypeResult - ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, const IdentifierInfo &II, - SourceLocation IdLoc) { - return TypeResult(); - } - - /// \brief Called when the parser has parsed a C++ typename - /// specifier that ends in a template-id, e.g., - /// "typename MetaFun::template apply<T1, T2>". - /// - /// \param TypenameLoc the location of the 'typename' keyword - /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). - /// \param TemplateLoc the location of the 'template' keyword, if any. - /// \param Ty the type that the typename specifier refers to. - virtual TypeResult - ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, SourceLocation TemplateLoc, - TypeTy *Ty) { - return TypeResult(); - } - - /// \brief Called when the parser begins parsing a construct which should not - /// have access control applied to it. - virtual void ActOnStartSuppressingAccessChecks() { - } - - /// \brief Called when the parser finishes parsing a construct which should - /// not have access control applied to it. - virtual void ActOnStopSuppressingAccessChecks() { - } - - //===----------------------- Obj-C Declarations -------------------------===// - - // ActOnStartClassInterface - this action is called immediately after parsing - // the prologue for a class interface (before parsing the instance - // variables). Instance variables are processed by ActOnFields(). - virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *SuperName, - SourceLocation SuperLoc, - const DeclPtrTy *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { - return DeclPtrTy(); - } - - /// ActOnCompatiblityAlias - this action is called after complete parsing of - /// @compaatibility_alias declaration. It sets up the alias relationships. - virtual DeclPtrTy ActOnCompatiblityAlias( - SourceLocation AtCompatibilityAliasLoc, - IdentifierInfo *AliasName, SourceLocation AliasLocation, - IdentifierInfo *ClassName, SourceLocation ClassLocation) { - return DeclPtrTy(); - } - - // ActOnStartProtocolInterface - this action is called immdiately after - // parsing the prologue for a protocol interface. - virtual DeclPtrTy ActOnStartProtocolInterface(SourceLocation AtProtoLoc, - IdentifierInfo *ProtocolName, - SourceLocation ProtocolLoc, - const DeclPtrTy *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { - return DeclPtrTy(); - } - // ActOnStartCategoryInterface - this action is called immdiately after - // parsing the prologue for a category interface. - virtual DeclPtrTy ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *CategoryName, - SourceLocation CategoryLoc, - const DeclPtrTy *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc) { - return DeclPtrTy(); - } - // ActOnStartClassImplementation - this action is called immdiately after - // parsing the prologue for a class implementation. Instance variables are - // processed by ActOnFields(). - virtual DeclPtrTy ActOnStartClassImplementation( - SourceLocation AtClassImplLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *SuperClassname, - SourceLocation SuperClassLoc) { - return DeclPtrTy(); - } - // ActOnStartCategoryImplementation - this action is called immdiately after - // parsing the prologue for a category implementation. - virtual DeclPtrTy ActOnStartCategoryImplementation( - SourceLocation AtCatImplLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *CatName, - SourceLocation CatLoc) { - return DeclPtrTy(); - } - // ActOnPropertyImplDecl - called for every property implementation - virtual DeclPtrTy ActOnPropertyImplDecl( - Scope *S, - SourceLocation AtLoc, // location of the @synthesize/@dynamic - SourceLocation PropertyNameLoc, // location for the property name - bool ImplKind, // true for @synthesize, false for - // @dynamic - DeclPtrTy ClassImplDecl, // class or category implementation - IdentifierInfo *propertyId, // name of property - IdentifierInfo *propertyIvar) { // name of the ivar - return DeclPtrTy(); - } - - struct ObjCArgInfo { - IdentifierInfo *Name; - SourceLocation NameLoc; - // The Type is null if no type was specified, and the DeclSpec is invalid - // in this case. - TypeTy *Type; - ObjCDeclSpec DeclSpec; - - /// ArgAttrs - Attribute list for this argument. - AttributeList *ArgAttrs; - }; - - // ActOnMethodDeclaration - called for all method declarations. - virtual DeclPtrTy ActOnMethodDeclaration( - SourceLocation BeginLoc, // location of the + or -. - SourceLocation EndLoc, // location of the ; or {. - tok::TokenKind MethodType, // tok::minus for instance, tok::plus for class. - DeclPtrTy ClassDecl, // class this methods belongs to. - ObjCDeclSpec &ReturnQT, // for return type's in inout etc. - TypeTy *ReturnType, // the method return type. - Selector Sel, // a unique name for the method. - ObjCArgInfo *ArgInfo, // ArgInfo: Has 'Sel.getNumArgs()' entries. - DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args - AttributeList *MethodAttrList, // optional - // tok::objc_not_keyword, tok::objc_optional, tok::objc_required - tok::ObjCKeywordKind impKind, - bool isVariadic = false) { - return DeclPtrTy(); - } - // ActOnAtEnd - called to mark the @end. For declarations (interfaces, - // protocols, categories), the parser passes all methods/properties. - // For class implementations, these values default to 0. For implementations, - // methods are processed incrementally (by ActOnMethodDeclaration above). - virtual void ActOnAtEnd(Scope *S, SourceRange AtEnd, - DeclPtrTy classDecl, - DeclPtrTy *allMethods = 0, - unsigned allNum = 0, - DeclPtrTy *allProperties = 0, - unsigned pNum = 0, - DeclGroupPtrTy *allTUVars = 0, - unsigned tuvNum = 0) { - } - // ActOnProperty - called to build one property AST - virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc, - FieldDeclarator &FD, ObjCDeclSpec &ODS, - Selector GetterSel, Selector SetterSel, - DeclPtrTy ClassCategory, - bool *OverridingProperty, - tok::ObjCKeywordKind MethodImplKind) { - return DeclPtrTy(); - } - - virtual OwningExprResult - ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, - IdentifierInfo &propertyName, - SourceLocation receiverNameLoc, - SourceLocation propertyNameLoc) { - return ExprEmpty(); - } - - /// \brief Describes the kind of message expression indicated by a message - /// send that starts with an identifier. - enum ObjCMessageKind { - /// \brief The message is sent to 'super'. - ObjCSuperMessage, - /// \brief The message is an instance message. - ObjCInstanceMessage, - /// \brief The message is a class message, and the identifier is a type - /// name. - ObjCClassMessage - }; - - /// \brief Determine the kind of Objective-C message send that we will be - /// performing based on the identifier given. - /// - /// This action determines how a message send that starts with [ - /// identifier (followed by another identifier) will be parsed, - /// e.g., as a class message, instance message, super message. The - /// result depends on the meaning of the given identifier. If the - /// identifier is unknown, the action should indicate that the - /// message is an instance message. - /// - /// By default, this routine applies syntactic disambiguation and uses - /// \c getTypeName() to determine whether the identifier refers to a type. - /// However, \c Action subclasses may override this routine to improve - /// error recovery. - /// - /// \param S The scope in which the message send occurs. - /// - /// \param Name The identifier following the '['. - /// - /// \param NameLoc The location of the identifier. - /// - /// \param IsSuper Whether the name is the pseudo-keyword "super". - /// - /// \param HasTrailingDot Whether the name is followed by a period. - /// - /// \param ReceiverType If this routine returns \c ObjCClassMessage, - /// this argument will be set to the receiver type. - /// - /// \returns The kind of message send. - virtual ObjCMessageKind getObjCMessageKind(Scope *S, - IdentifierInfo *Name, - SourceLocation NameLoc, - bool IsSuper, - bool HasTrailingDot, - TypeTy *&ReceiverType); - - /// \brief Parsed a message send to 'super'. - /// - /// \param S The scope in which the message send occurs. - /// \param SuperLoc The location of the 'super' keyword. - /// \param Sel The selector to which the message is being sent. - /// \param LBracLoc The location of the opening square bracket ']'. - /// \param SelectorLoc The location of the first identifier in the selector. - /// \param RBrac The location of the closing square bracket ']'. - /// \param Args The message arguments. - virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, - Selector Sel, - SourceLocation LBracLoc, - SourceLocation SelectorLoc, - SourceLocation RBracLoc, - MultiExprArg Args) { - return OwningExprResult(*this); - } - - /// \brief Parsed a message send to a class. - /// - /// \param S The scope in which the message send occurs. - /// \param Receiver The type of the class receiving the message. - /// \param Sel The selector to which the message is being sent. - /// \param LBracLoc The location of the opening square bracket ']'. - /// \param SelectorLoc The location of the first identifier in the selector. - /// \param RBrac The location of the closing square bracket ']'. - /// \param Args The message arguments. - virtual OwningExprResult ActOnClassMessage(Scope *S, - TypeTy *Receiver, - Selector Sel, - SourceLocation LBracLoc, - SourceLocation SelectorLoc, - SourceLocation RBracLoc, - MultiExprArg Args) { - return OwningExprResult(*this); - } - - /// \brief Parsed a message send to an object instance. - /// - /// \param S The scope in which the message send occurs. - /// \param Receiver The expression that computes the receiver object. - /// \param Sel The selector to which the message is being sent. - /// \param LBracLoc The location of the opening square bracket ']'. - /// \param SelectorLoc The location of the first identifier in the selector. - /// \param RBrac The location of the closing square bracket ']'. - /// \param Args The message arguments. - virtual OwningExprResult ActOnInstanceMessage(Scope *S, - ExprArg Receiver, - Selector Sel, - SourceLocation LBracLoc, - SourceLocation SelectorLoc, - SourceLocation RBracLoc, - MultiExprArg Args) { - return OwningExprResult(*this); - } - - virtual DeclPtrTy ActOnForwardClassDeclaration( - SourceLocation AtClassLoc, - IdentifierInfo **IdentList, - SourceLocation *IdentLocs, - unsigned NumElts) { - return DeclPtrTy(); - } - virtual DeclPtrTy ActOnForwardProtocolDeclaration( - SourceLocation AtProtocolLoc, - const IdentifierLocPair*IdentList, - unsigned NumElts, - AttributeList *AttrList) { - return DeclPtrTy(); - } - - /// FindProtocolDeclaration - This routine looks up protocols and - /// issues error if they are not declared. It returns list of valid - /// protocols found. - virtual void FindProtocolDeclaration(bool WarnOnDeclarations, - const IdentifierLocPair *ProtocolId, - unsigned NumProtocols, - llvm::SmallVectorImpl<DeclPtrTy> &ResProtos) { - } - - //===----------------------- Obj-C Expressions --------------------------===// - - virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, - ExprTy **Strings, - unsigned NumStrings) { - return ExprResult(); - } - - virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, - SourceLocation EncLoc, - SourceLocation LParenLoc, - TypeTy *Ty, - SourceLocation RParenLoc) { - return ExprResult(); - } - - virtual ExprResult ParseObjCSelectorExpression(Selector Sel, - SourceLocation AtLoc, - SourceLocation SelLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc) { - return ExprResult(); - } - - virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, - SourceLocation AtLoc, - SourceLocation ProtoLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc) { - return ExprResult(); - } - - //===---------------------------- Pragmas -------------------------------===// - - enum PragmaOptionsAlignKind { - POAK_Native, // #pragma options align=native - POAK_Natural, // #pragma options align=natural - POAK_Packed, // #pragma options align=packed - POAK_Power, // #pragma options align=power - POAK_Mac68k, // #pragma options align=mac68k - POAK_Reset // #pragma options align=reset - }; - - /// ActOnPragmaOptionsAlign - Called on well formed #pragma options - /// align={...}. - virtual void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, - SourceLocation PragmaLoc, - SourceLocation KindLoc) { - return; - } - - enum PragmaPackKind { - PPK_Default, // #pragma pack([n]) - PPK_Show, // #pragma pack(show), only supported by MSVC. - PPK_Push, // #pragma pack(push, [identifier], [n]) - PPK_Pop // #pragma pack(pop, [identifier], [n]) - }; - - /// ActOnPragmaPack - Called on well formed #pragma pack(...). - virtual void ActOnPragmaPack(PragmaPackKind Kind, - IdentifierInfo *Name, - ExprTy *Alignment, - SourceLocation PragmaLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc) { - return; - } - - /// ActOnPragmaUnused - Called on well formed #pragma unused(...). - virtual void ActOnPragmaUnused(const Token *Identifiers, - unsigned NumIdentifiers, Scope *CurScope, - SourceLocation PragmaLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc) { - return; - } - - /// ActOnPragmaWeakID - Called on well formed #pragma weak ident. - virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName, - SourceLocation PragmaLoc, - SourceLocation WeakNameLoc) { - return; - } - - /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident. - virtual void ActOnPragmaWeakAlias(IdentifierInfo* WeakName, - IdentifierInfo* AliasName, - SourceLocation PragmaLoc, - SourceLocation WeakNameLoc, - SourceLocation AliasNameLoc) { - return; - } - - /// \name Code completion actions - /// - /// These actions are used to signal that a code-completion token has been - /// found at a point in the grammar where the Action implementation is - /// likely to be able to provide a list of possible completions, e.g., - /// after the "." or "->" of a member access expression. - /// - /// \todo Code completion for designated field initializers - /// \todo Code completion for call arguments after a function template-id - /// \todo Code completion within a call expression, object construction, etc. - /// \todo Code completion within a template argument list. - /// \todo Code completion for attributes. - //@{ - - /// \brief Describes the context in which code completion occurs. - enum CodeCompletionContext { - /// \brief Code completion occurs at top-level or namespace context. - CCC_Namespace, - /// \brief Code completion occurs within a class, struct, or union. - CCC_Class, - /// \brief Code completion occurs within an Objective-C interface, protocol, - /// or category. - CCC_ObjCInterface, - /// \brief Code completion occurs within an Objective-C implementation or - /// category implementation - CCC_ObjCImplementation, - /// \brief Code completion occurs within the list of instance variables - /// in an Objective-C interface, protocol, category, or implementation. - CCC_ObjCInstanceVariableList, - /// \brief Code completion occurs following one or more template - /// headers. - CCC_Template, - /// \brief Code completion occurs following one or more template - /// headers within a class. - CCC_MemberTemplate, - /// \brief Code completion occurs within an expression. - CCC_Expression, - /// \brief Code completion occurs within a statement, which may - /// also be an expression or a declaration. - CCC_Statement, - /// \brief Code completion occurs at the beginning of the - /// initialization statement (or expression) in a for loop. - CCC_ForInit, - /// \brief Code completion occurs within the condition of an if, - /// while, switch, or for statement. - CCC_Condition, - /// \brief Code completion occurs within the body of a function on a - /// recovery path, where we do not have a specific handle on our position - /// in the grammar. - CCC_RecoveryInFunction - }; - - /// \brief Code completion for an ordinary name that occurs within the given - /// scope. - /// - /// \param S the scope in which the name occurs. - /// - /// \param CompletionContext the context in which code completion - /// occurs. - virtual void CodeCompleteOrdinaryName(Scope *S, - CodeCompletionContext CompletionContext) { } - - /// \brief Code completion for a member access expression. - /// - /// This code completion action is invoked when the code-completion token - /// is found after the "." or "->" of a member access expression. - /// - /// \param S the scope in which the member access expression occurs. - /// - /// \param Base the base expression (e.g., the x in "x.foo") of the member - /// access. - /// - /// \param OpLoc the location of the "." or "->" operator. - /// - /// \param IsArrow true when the operator is "->", false when it is ".". - virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base, - SourceLocation OpLoc, - bool IsArrow) { } - - /// \brief Code completion for a reference to a tag. - /// - /// This code completion action is invoked when the code-completion - /// token is found after a tag keyword (struct, union, enum, or class). - /// - /// \param S the scope in which the tag reference occurs. - /// - /// \param TagSpec an instance of DeclSpec::TST, indicating what kind of tag - /// this is (struct/union/enum/class). - virtual void CodeCompleteTag(Scope *S, unsigned TagSpec) { } - - /// \brief Code completion for a case statement. - /// - /// \brief S the scope in which the case statement occurs. - virtual void CodeCompleteCase(Scope *S) { } - - /// \brief Code completion for a call. - /// - /// \brief S the scope in which the call occurs. - /// - /// \param Fn the expression describing the function being called. - /// - /// \param Args the arguments to the function call (so far). - /// - /// \param NumArgs the number of arguments in \p Args. - virtual void CodeCompleteCall(Scope *S, ExprTy *Fn, - ExprTy **Args, unsigned NumArgs) { } - - /// \brief Code completion for the initializer of a variable declaration. - /// - /// \param S The scope in which the initializer occurs. - /// - /// \param D The declaration being initialized. - virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D) { } - - /// \brief Code completion after the "return" keyword within a function. - /// - /// \param S The scope in which the return statement occurs. - virtual void CodeCompleteReturn(Scope *S) { } - - /// \brief Code completion for the right-hand side of an assignment or - /// compound assignment operator. - /// - /// \param S The scope in which the assignment occurs. - /// - /// \param LHS The left-hand side of the assignment expression. - virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { } - - /// \brief Code completion for a C++ nested-name-specifier that precedes a - /// qualified-id of some form. - /// - /// This code completion action is invoked when the code-completion token - /// is found after the "::" of a nested-name-specifier. - /// - /// \param S the scope in which the nested-name-specifier occurs. - /// - /// \param SS the scope specifier ending with "::". - /// - /// \parame EnteringContext whether we're entering the context of this - /// scope specifier. - virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, - bool EnteringContext) { } - - /// \brief Code completion for a C++ "using" declaration or directive. - /// - /// This code completion action is invoked when the code-completion token is - /// found after the "using" keyword. - /// - /// \param S the scope in which the "using" occurs. - virtual void CodeCompleteUsing(Scope *S) { } - - /// \brief Code completion for a C++ using directive. - /// - /// This code completion action is invoked when the code-completion token is - /// found after "using namespace". - /// - /// \param S the scope in which the "using namespace" occurs. - virtual void CodeCompleteUsingDirective(Scope *S) { } - - /// \brief Code completion for a C++ namespace declaration or namespace - /// alias declaration. - /// - /// This code completion action is invoked when the code-completion token is - /// found after "namespace". - /// - /// \param S the scope in which the "namespace" token occurs. - virtual void CodeCompleteNamespaceDecl(Scope *S) { } - - /// \brief Code completion for a C++ namespace alias declaration. - /// - /// This code completion action is invoked when the code-completion token is - /// found after "namespace identifier = ". - /// - /// \param S the scope in which the namespace alias declaration occurs. - virtual void CodeCompleteNamespaceAliasDecl(Scope *S) { } - - /// \brief Code completion for an operator name. - /// - /// This code completion action is invoked when the code-completion token is - /// found after the keyword "operator". - /// - /// \param S the scope in which the operator keyword occurs. - virtual void CodeCompleteOperatorName(Scope *S) { } - - /// \brief Code completion after the '@' at the top level. - /// - /// \param S the scope in which the '@' occurs. - /// - /// \param ObjCImpDecl the Objective-C implementation or category - /// implementation. - /// - /// \param InInterface whether we are in an Objective-C interface or - /// protocol. - virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl, - bool InInterface) { } - - /// \brief Code completion after the '@' in the list of instance variables. - virtual void CodeCompleteObjCAtVisibility(Scope *S) { } - - /// \brief Code completion after the '@' in a statement. - virtual void CodeCompleteObjCAtStatement(Scope *S) { } - - /// \brief Code completion after the '@' in an expression. - virtual void CodeCompleteObjCAtExpression(Scope *S) { } - - /// \brief Code completion for an ObjC property decl. - /// - /// This code completion action is invoked when the code-completion token is - /// found after the left paren. - /// - /// \param S the scope in which the operator keyword occurs. - virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { } - - /// \brief Code completion for the getter of an Objective-C property - /// declaration. - /// - /// This code completion action is invoked when the code-completion - /// token is found after the "getter = " in a property declaration. - /// - /// \param S the scope in which the property is being declared. - /// - /// \param ClassDecl the Objective-C class or category in which the property - /// is being defined. - /// - /// \param Methods the set of methods declared thus far within \p ClassDecl. - /// - /// \param NumMethods the number of methods in \p Methods - virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl, - DeclPtrTy *Methods, - unsigned NumMethods) { - } - - /// \brief Code completion for the setter of an Objective-C property - /// declaration. - /// - /// This code completion action is invoked when the code-completion - /// token is found after the "setter = " in a property declaration. - /// - /// \param S the scope in which the property is being declared. - /// - /// \param ClassDecl the Objective-C class or category in which the property - /// is being defined. - /// - /// \param Methods the set of methods declared thus far within \p ClassDecl. - /// - /// \param NumMethods the number of methods in \p Methods - virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl, - DeclPtrTy *Methods, - unsigned NumMethods) { - } - - /// \brief Code completion for the receiver in an Objective-C message send. - /// - /// This code completion action is invoked when we see a '[' that indicates - /// the start of an Objective-C message send. - /// - /// \param S The scope in which the Objective-C message send occurs. - virtual void CodeCompleteObjCMessageReceiver(Scope *S) { } - - /// \brief Code completion for an ObjC message expression that sends - /// a message to the superclass. - /// - /// This code completion action is invoked when the code-completion token is - /// found after the class name and after each argument. - /// - /// \param S The scope in which the message expression occurs. - /// \param SuperLoc The location of the 'super' keyword. - /// \param SelIdents The identifiers that describe the selector (thus far). - /// \param NumSelIdents The number of identifiers in \p SelIdents. - virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, - IdentifierInfo **SelIdents, - unsigned NumSelIdents) { } - - /// \brief Code completion for an ObjC message expression that refers to - /// a class method. - /// - /// This code completion action is invoked when the code-completion token is - /// found after the class name and after each argument. - /// - /// \param S The scope in which the message expression occurs. - /// \param Receiver The type of the class that is receiving a message. - /// \param SelIdents The identifiers that describe the selector (thus far). - /// \param NumSelIdents The number of identifiers in \p SelIdents. - virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, - IdentifierInfo **SelIdents, - unsigned NumSelIdents) { } - - /// \brief Code completion for an ObjC message expression that refers to - /// an instance method. - /// - /// This code completion action is invoked when the code-completion token is - /// found after the receiver expression and after each argument. - /// - /// \param S the scope in which the operator keyword occurs. - /// \param Receiver an expression for the receiver of the message. - /// \param SelIdents the identifiers that describe the selector (thus far). - /// \param NumSelIdents the number of identifiers in \p SelIdents. - virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, - IdentifierInfo **SelIdents, - unsigned NumSelIdents) { } - - /// \brief Code completion for a list of protocol references in Objective-C, - /// such as P1 and P2 in \c id<P1,P2>. - /// - /// This code completion action is invoked prior to each identifier - /// in the protocol list. - /// - /// \param Protocols the set of protocols that have already been parsed. - /// - /// \param NumProtocols the number of protocols that have already been - /// parsed. - virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, - unsigned NumProtocols) { } - - /// \brief Code completion for a protocol declaration or definition, after - /// the @protocol but before any identifier. - /// - /// \param S the scope in which the protocol declaration occurs. - virtual void CodeCompleteObjCProtocolDecl(Scope *S) { } - - /// \brief Code completion for an Objective-C interface, after the - /// @interface but before any identifier. - virtual void CodeCompleteObjCInterfaceDecl(Scope *S) { } - - /// \brief Code completion for the superclass of an Objective-C - /// interface, after the ':'. - /// - /// \param S the scope in which the interface declaration occurs. - /// - /// \param ClassName the name of the class being defined. - virtual void CodeCompleteObjCSuperclass(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc) { - } - - /// \brief Code completion for an Objective-C implementation, after the - /// @implementation but before any identifier. - virtual void CodeCompleteObjCImplementationDecl(Scope *S) { } - - /// \brief Code completion for the category name in an Objective-C interface - /// declaration. - /// - /// This code completion action is invoked after the '(' that indicates - /// a category name within an Objective-C interface declaration. - virtual void CodeCompleteObjCInterfaceCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc) { - } - - /// \brief Code completion for the category name in an Objective-C category - /// implementation. - /// - /// This code completion action is invoked after the '(' that indicates - /// the category name within an Objective-C category implementation. - virtual void CodeCompleteObjCImplementationCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc) { - } - - /// \brief Code completion for the property names when defining an - /// Objective-C property. - /// - /// This code completion action is invoked after @synthesize or @dynamic and - /// after each "," within one of those definitions. - virtual void CodeCompleteObjCPropertyDefinition(Scope *S, - DeclPtrTy ObjCImpDecl) { - } - - /// \brief Code completion for the instance variable name that should - /// follow an '=' when synthesizing an Objective-C property. - /// - /// This code completion action is invoked after each '=' that occurs within - /// an @synthesized definition. - virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, - IdentifierInfo *PropertyName, - DeclPtrTy ObjCImpDecl) { - } - - /// \brief Code completion for an Objective-C method declaration or - /// definition, which may occur within an interface, category, - /// extension, protocol, or implementation thereof (where applicable). - /// - /// This code completion action is invoked after the "-" or "+" that - /// starts a method declaration or definition, and after the return - /// type such a declaration (e.g., "- (id)"). - /// - /// \param S The scope in which the completion occurs. - /// - /// \param IsInstanceMethod Whether this is an instance method - /// (introduced with '-'); otherwise, it's a class method - /// (introduced with '+'). - /// - /// \param ReturnType If non-NULL, the specified return type of the method - /// being declared or defined. - /// - /// \param IDecl The interface, category, protocol, or - /// implementation, or category implementation in which this method - /// declaration or definition occurs. - virtual void CodeCompleteObjCMethodDecl(Scope *S, - bool IsInstanceMethod, - TypeTy *ReturnType, - DeclPtrTy IDecl) { - } - - /// \brief Code completion for a selector identifier or argument name within - /// an Objective-C method declaration. - /// - /// \param S The scope in which this code completion occurs. - /// - /// \param IsInstanceMethod Whether we are parsing an instance method (or, - /// if false, a class method). - /// - /// \param AtParameterName Whether the actual code completion point is at the - /// argument name. - /// - /// \param ReturnType If non-NULL, the specified return type of the method - /// being declared or defined. - /// - /// \param SelIdents The identifiers that occurred in the selector for the - /// method declaration prior to the code completion point. - /// - /// \param NumSelIdents The number of identifiers provided by SelIdents. - virtual void CodeCompleteObjCMethodDeclSelector(Scope *S, - bool IsInstanceMethod, - bool AtParameterName, - TypeTy *ReturnType, - IdentifierInfo **SelIdents, - unsigned NumSelIdents) { } - - //@} -}; - -/// MinimalAction - Minimal actions are used by light-weight clients of the -/// parser that do not need name resolution or significant semantic analysis to -/// be performed. The actions implemented here are in the form of unresolved -/// identifiers. By using a simpler interface than the SemanticAction class, -/// the parser doesn't have to build complex data structures and thus runs more -/// quickly. -class MinimalAction : public Action { - /// Translation Unit Scope - useful to Objective-C actions that need - /// to lookup file scope declarations in the "ordinary" C decl namespace. - /// For example, user-defined classes, built-in "id" type, etc. - Scope *TUScope; - IdentifierTable &Idents; - Preprocessor &PP; - void *TypeNameInfoTablePtr; -public: - MinimalAction(Preprocessor &pp); - ~MinimalAction(); - - /// getTypeName - This looks at the IdentifierInfo::FETokenInfo field to - /// determine whether the name is a typedef or not in this scope. - /// - /// \param II the identifier for which we are performing name lookup - /// - /// \param NameLoc the location of the identifier - /// - /// \param S the scope in which this name lookup occurs - /// - /// \param SS if non-NULL, the C++ scope specifier that precedes the - /// identifier - /// - /// \param isClassName whether this is a C++ class-name production, in - /// which we can end up referring to a member of an unknown specialization - /// that we know (from the grammar) is supposed to be a type. For example, - /// this occurs when deriving from "std::vector<T>::allocator_type", where T - /// is a template parameter. - /// - /// \returns the type referred to by this identifier, or NULL if the type - /// does not name an identifier. - virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec *SS, - bool isClassName = false, - TypeTy *ObjectType = 0); - - /// isCurrentClassName - Always returns false, because MinimalAction - /// does not support C++ classes with constructors. - virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S, - const CXXScopeSpec *SS); - - virtual TemplateNameKind isTemplateName(Scope *S, - CXXScopeSpec &SS, - UnqualifiedId &Name, - TypeTy *ObjectType, - bool EnteringContext, - TemplateTy &Template, - bool &MemberOfUnknownSpecialization); - - - /// ActOnDeclarator - If this is a typedef declarator, we modify the - /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is - /// popped. - virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D); - - /// ActOnPopScope - When a scope is popped, if any typedefs are now - /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field. - virtual void ActOnPopScope(SourceLocation Loc, Scope *S); - virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S); - - virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc, - IdentifierInfo **IdentList, - SourceLocation *SLocs, - unsigned NumElts); - - virtual DeclPtrTy ActOnStartClassInterface(SourceLocation interLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *SuperName, - SourceLocation SuperLoc, - const DeclPtrTy *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); -}; - -/// PrettyStackTraceActionsDecl - If a crash occurs in the parser while parsing -/// something related to a virtualized decl, include that virtualized decl in -/// the stack trace. -class PrettyStackTraceActionsDecl : public llvm::PrettyStackTraceEntry { - Action::DeclPtrTy TheDecl; - SourceLocation Loc; - Action &Actions; - SourceManager &SM; - const char *Message; -public: - PrettyStackTraceActionsDecl(Action::DeclPtrTy Decl, SourceLocation L, - Action &actions, SourceManager &sm, - const char *Msg) - : TheDecl(Decl), Loc(L), Actions(actions), SM(sm), Message(Msg) {} - - virtual void print(llvm::raw_ostream &OS) const; -}; - -/// \brief RAII object that enters a new expression evaluation context. -class EnterExpressionEvaluationContext { - /// \brief The action object. - Action &Actions; - -public: - EnterExpressionEvaluationContext(Action &Actions, - Action::ExpressionEvaluationContext NewContext) - : Actions(Actions) { - Actions.PushExpressionEvaluationContext(NewContext); - } - - ~EnterExpressionEvaluationContext() { - Actions.PopExpressionEvaluationContext(); - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h deleted file mode 100644 index e9a20b7872b5..000000000000 --- a/include/clang/Parse/Ownership.h +++ /dev/null @@ -1,845 +0,0 @@ -//===--- Ownership.h - Parser Ownership Helpers -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains classes for managing ownership of Stmt and Expr nodes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_PARSE_OWNERSHIP_H -#define LLVM_CLANG_PARSE_OWNERSHIP_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/PointerIntPair.h" - -//===----------------------------------------------------------------------===// -// OpaquePtr -//===----------------------------------------------------------------------===// - -namespace clang { - class ActionBase; - - /// OpaquePtr - This is a very simple POD type that wraps a pointer that the - /// Parser doesn't know about but that Sema or another client does. The UID - /// template argument is used to make sure that "Decl" pointers are not - /// compatible with "Type" pointers for example. - template<int UID> - class OpaquePtr { - void *Ptr; - public: - OpaquePtr() : Ptr(0) {} - - template <typename T> - T* getAs() const { - return llvm::PointerLikeTypeTraits<T*>::getFromVoidPointer(Ptr); - } - - template <typename T> - T getAsVal() const { - return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer(Ptr); - } - - void *get() const { return Ptr; } - - template<typename T> - static OpaquePtr make(T P) { - OpaquePtr R; R.set(P); return R; - } - - template<typename T> - void set(T P) { - Ptr = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(P); - } - - operator bool() const { return Ptr != 0; } - }; -} - -namespace llvm { - template <int UID> - class PointerLikeTypeTraits<clang::OpaquePtr<UID> > { - public: - static inline void *getAsVoidPointer(clang::OpaquePtr<UID> P) { - // FIXME: Doesn't work? return P.getAs< void >(); - return P.get(); - } - static inline clang::OpaquePtr<UID> getFromVoidPointer(void *P) { - return clang::OpaquePtr<UID>::make(P); - } - enum { NumLowBitsAvailable = 3 }; - }; -} - - - -// -------------------------- About Move Emulation -------------------------- // -// The smart pointer classes in this file attempt to emulate move semantics -// as they appear in C++0x with rvalue references. Since C++03 doesn't have -// rvalue references, some tricks are needed to get similar results. -// Move semantics in C++0x have the following properties: -// 1) "Moving" means transferring the value of an object to another object, -// similar to copying, but without caring what happens to the old object. -// In particular, this means that the new object can steal the old object's -// resources instead of creating a copy. -// 2) Since moving can modify the source object, it must either be explicitly -// requested by the user, or the modifications must be unnoticeable. -// 3) As such, C++0x moving is only allowed in three contexts: -// * By explicitly using std::move() to request it. -// * From a temporary object, since that object cannot be accessed -// afterwards anyway, thus making the state unobservable. -// * On function return, since the object is not observable afterwards. -// -// To sum up: moving from a named object should only be possible with an -// explicit std::move(), or on function return. Moving from a temporary should -// be implicitly done. Moving from a const object is forbidden. -// -// The emulation is not perfect, and has the following shortcomings: -// * move() is not in namespace std. -// * move() is required on function return. -// * There are difficulties with implicit conversions. -// * Microsoft's compiler must be given the /Za switch to successfully compile. -// -// -------------------------- Implementation -------------------------------- // -// The move emulation relies on the peculiar reference binding semantics of -// C++03: as a rule, a non-const reference may not bind to a temporary object, -// except for the implicit object parameter in a member function call, which -// can refer to a temporary even when not being const. -// The moveable object has five important functions to facilitate moving: -// * A private, unimplemented constructor taking a non-const reference to its -// own class. This constructor serves a two-fold purpose. -// - It prevents the creation of a copy constructor that takes a const -// reference. Temporaries would be able to bind to the argument of such a -// constructor, and that would be bad. -// - Named objects will bind to the non-const reference, but since it's -// private, this will fail to compile. This prevents implicit moving from -// named objects. -// There's also a copy assignment operator for the same purpose. -// * An implicit, non-const conversion operator to a special mover type. This -// type represents the rvalue reference of C++0x. Being a non-const member, -// its implicit this parameter can bind to temporaries. -// * A constructor that takes an object of this mover type. This constructor -// performs the actual move operation. There is an equivalent assignment -// operator. -// There is also a free move() function that takes a non-const reference to -// an object and returns a temporary. Internally, this function uses explicit -// constructor calls to move the value from the referenced object to the return -// value. -// -// There are now three possible scenarios of use. -// * Copying from a const object. Constructor overload resolution will find the -// non-const copy constructor, and the move constructor. The first is not -// viable because the const object cannot be bound to the non-const reference. -// The second fails because the conversion to the mover object is non-const. -// Moving from a const object fails as intended. -// * Copying from a named object. Constructor overload resolution will select -// the non-const copy constructor, but fail as intended, because this -// constructor is private. -// * Copying from a temporary. Constructor overload resolution cannot select -// the non-const copy constructor, because the temporary cannot be bound to -// the non-const reference. It thus selects the move constructor. The -// temporary can be bound to the implicit this parameter of the conversion -// operator, because of the special binding rule. Construction succeeds. -// Note that the Microsoft compiler, as an extension, allows binding -// temporaries against non-const references. The compiler thus selects the -// non-const copy constructor and fails, because the constructor is private. -// Passing /Za (disable extensions) disables this behaviour. -// The free move() function is used to move from a named object. -// -// Note that when passing an object of a different type (the classes below -// have OwningResult and OwningPtr, which should be mixable), you get a problem. -// Argument passing and function return use copy initialization rules. The -// effect of this is that, when the source object is not already of the target -// type, the compiler will first seek a way to convert the source object to the -// target type, and only then attempt to copy the resulting object. This means -// that when passing an OwningResult where an OwningPtr is expected, the -// compiler will first seek a conversion from OwningResult to OwningPtr, then -// copy the OwningPtr. The resulting conversion sequence is: -// OwningResult object -> ResultMover -> OwningResult argument to -// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr -// This conversion sequence is too complex to be allowed. Thus the special -// move_* functions, which help the compiler out with some explicit -// conversions. - -// Flip this switch to measure performance impact of the smart pointers. -// #define DISABLE_SMART_POINTERS - -namespace llvm { - template<> - class PointerLikeTypeTraits<clang::ActionBase*> { - typedef clang::ActionBase* PT; - public: - static inline void *getAsVoidPointer(PT P) { return P; } - static inline PT getFromVoidPointer(void *P) { - return static_cast<PT>(P); - } - enum { NumLowBitsAvailable = 2 }; - }; -} - -namespace clang { - // Basic - class DiagnosticBuilder; - - // Determines whether the low bit of the result pointer for the - // given UID is always zero. If so, ActionResult will use that bit - // for it's "invalid" flag. - template<unsigned UID> - struct IsResultPtrLowBitFree { - static const bool value = false; - }; - - /// ActionBase - A small part split from Action because of the horrible - /// definition order dependencies between Action and the smart pointers. - class ActionBase { - public: - /// Out-of-line virtual destructor to provide home for this class. - virtual ~ActionBase(); - - // Types - Though these don't actually enforce strong typing, they document - // what types are required to be identical for the actions. - typedef OpaquePtr<0> DeclPtrTy; - typedef OpaquePtr<1> DeclGroupPtrTy; - typedef OpaquePtr<2> TemplateTy; - typedef void AttrTy; - typedef void BaseTy; - typedef void MemInitTy; - typedef void ExprTy; - typedef void StmtTy; - typedef void TemplateParamsTy; - typedef void CXXScopeTy; - typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<N>. - - /// ActionResult - This structure is used while parsing/acting on - /// expressions, stmts, etc. It encapsulates both the object returned by - /// the action, plus a sense of whether or not it is valid. - /// When CompressInvalid is true, the "invalid" flag will be - /// stored in the low bit of the Val pointer. - template<unsigned UID, - typename PtrTy = void*, - bool CompressInvalid = IsResultPtrLowBitFree<UID>::value> - class ActionResult { - PtrTy Val; - bool Invalid; - - public: - ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {} - template<typename ActualExprTy> - ActionResult(ActualExprTy val) : Val(val), Invalid(false) {} - ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {} - - PtrTy get() const { return Val; } - void set(PtrTy V) { Val = V; } - bool isInvalid() const { return Invalid; } - - const ActionResult &operator=(PtrTy RHS) { - Val = RHS; - Invalid = false; - return *this; - } - }; - - // This ActionResult partial specialization places the "invalid" - // flag into the low bit of the pointer. - template<unsigned UID, typename PtrTy> - class ActionResult<UID, PtrTy, true> { - // A pointer whose low bit is 1 if this result is invalid, 0 - // otherwise. - uintptr_t PtrWithInvalid; - typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits; - public: - ActionResult(bool Invalid = false) - : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { } - - template<typename ActualExprTy> - ActionResult(ActualExprTy *val) { - PtrTy V(val); - void *VP = PtrTraits::getAsVoidPointer(V); - PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); - assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); - } - - ActionResult(PtrTy V) { - void *VP = PtrTraits::getAsVoidPointer(V); - PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); - assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); - } - - ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { } - - PtrTy get() const { - void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); - return PtrTraits::getFromVoidPointer(VP); - } - - void set(PtrTy V) { - void *VP = PtrTraits::getAsVoidPointer(V); - PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); - assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); - } - - bool isInvalid() const { return PtrWithInvalid & 0x01; } - - const ActionResult &operator=(PtrTy RHS) { - void *VP = PtrTraits::getAsVoidPointer(RHS); - PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); - assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); - return *this; - } - }; - - /// Deletion callbacks - Since the parser doesn't know the concrete types of - /// the AST nodes being generated, it must do callbacks to delete objects - /// when recovering from errors. These are in ActionBase because the smart - /// pointers need access to them. - virtual void DeleteExpr(ExprTy *E) {} - virtual void DeleteStmt(StmtTy *S) {} - virtual void DeleteTemplateParams(TemplateParamsTy *P) {} - }; - - /// ASTDestroyer - The type of an AST node destruction function pointer. - typedef void (ActionBase::*ASTDestroyer)(void *); - - /// For the transition phase: translate from an ASTDestroyer to its - /// ActionResult UID. - template <ASTDestroyer Destroyer> struct DestroyerToUID; - template <> struct DestroyerToUID<&ActionBase::DeleteExpr> { - static const unsigned UID = 0; - }; - template <> struct DestroyerToUID<&ActionBase::DeleteStmt> { - static const unsigned UID = 1; - }; - /// ASTOwningResult - A moveable smart pointer for AST nodes that also - /// has an extra flag to indicate an additional success status. - template <ASTDestroyer Destroyer> class ASTOwningResult; - - /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns - /// the individual pointers, not the array holding them. - template <ASTDestroyer Destroyer> class ASTMultiPtr; - -#if !defined(DISABLE_SMART_POINTERS) - namespace moving { - /// Move emulation helper for ASTOwningResult. NEVER EVER use this class - /// directly if you don't know what you're doing. - template <ASTDestroyer Destroyer> - class ASTResultMover { - ASTOwningResult<Destroyer> &Moved; - - public: - ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {} - - ASTOwningResult<Destroyer> * operator ->() { return &Moved; } - }; - - /// Move emulation helper for ASTMultiPtr. NEVER EVER use this class - /// directly if you don't know what you're doing. - template <ASTDestroyer Destroyer> - class ASTMultiMover { - ASTMultiPtr<Destroyer> &Moved; - - public: - ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {} - - ASTMultiPtr<Destroyer> * operator ->() { return &Moved; } - - /// Reset the moved object's internal structures. - void release(); - }; - } -#else - - /// Kept only as a type-safe wrapper for a void pointer, when smart pointers - /// are disabled. When they are enabled, ASTOwningResult takes over. - template <ASTDestroyer Destroyer> - class ASTOwningPtr { - void *Node; - - public: - explicit ASTOwningPtr(ActionBase &) : Node(0) {} - ASTOwningPtr(ActionBase &, void *node) : Node(node) {} - // Normal copying operators are defined implicitly. - ASTOwningPtr(const ASTOwningResult<Destroyer> &o); - - ASTOwningPtr & operator =(void *raw) { - Node = raw; - return *this; - } - - /// Access to the raw pointer. - void * get() const { return Node; } - - /// Release the raw pointer. - void * take() { - return Node; - } - - /// Take outside ownership of the raw pointer and cast it down. - template<typename T> - T *takeAs() { - return static_cast<T*>(Node); - } - - /// Alias for interface familiarity with unique_ptr. - void * release() { - return take(); - } - }; -#endif - - // Important: There are two different implementations of - // ASTOwningResult below, depending on whether - // DISABLE_SMART_POINTERS is defined. If you make changes that - // affect the interface, be sure to compile and test both ways! - -#if !defined(DISABLE_SMART_POINTERS) - template <ASTDestroyer Destroyer> - class ASTOwningResult { - llvm::PointerIntPair<ActionBase*, 1, bool> ActionInv; - void *Ptr; - - friend class moving::ASTResultMover<Destroyer>; - -#if !(defined(_MSC_VER) && _MSC_VER >= 1600) - ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT - ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT -#endif - - void destroy() { - if (Ptr) { - assert(ActionInv.getPointer() && - "Smart pointer has node but no action."); - (ActionInv.getPointer()->*Destroyer)(Ptr); - Ptr = 0; - } - } - - public: - typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult; - - explicit ASTOwningResult(ActionBase &actions, bool invalid = false) - : ActionInv(&actions, invalid), Ptr(0) {} - ASTOwningResult(ActionBase &actions, void *node) - : ActionInv(&actions, false), Ptr(node) {} - ASTOwningResult(ActionBase &actions, const DumbResult &res) - : ActionInv(&actions, res.isInvalid()), Ptr(res.get()) {} - /// Move from another owning result - ASTOwningResult(moving::ASTResultMover<Destroyer> mover) - : ActionInv(mover->ActionInv), - Ptr(mover->Ptr) { - mover->Ptr = 0; - } - - ~ASTOwningResult() { - destroy(); - } - - /// Move assignment from another owning result - ASTOwningResult &operator=(moving::ASTResultMover<Destroyer> mover) { - destroy(); - ActionInv = mover->ActionInv; - Ptr = mover->Ptr; - mover->Ptr = 0; - return *this; - } - -#if defined(_MSC_VER) && _MSC_VER >= 1600 - // Emulated move semantics don't work with msvc. - ASTOwningResult(ASTOwningResult &&mover) - : ActionInv(mover.ActionInv), - Ptr(mover.Ptr) { - mover.Ptr = 0; - } - ASTOwningResult &operator=(ASTOwningResult &&mover) { - *this = moving::ASTResultMover<Destroyer>(mover); - return *this; - } -#endif - - /// Assignment from a raw pointer. Takes ownership - beware! - ASTOwningResult &operator=(void *raw) { - destroy(); - Ptr = raw; - ActionInv.setInt(false); - return *this; - } - - /// Assignment from an ActionResult. Takes ownership - beware! - ASTOwningResult &operator=(const DumbResult &res) { - destroy(); - Ptr = res.get(); - ActionInv.setInt(res.isInvalid()); - return *this; - } - - /// Access to the raw pointer. - void *get() const { return Ptr; } - - bool isInvalid() const { return ActionInv.getInt(); } - - /// Does this point to a usable AST node? To be usable, the node must be - /// valid and non-null. - bool isUsable() const { return !isInvalid() && get(); } - - /// Take outside ownership of the raw pointer. - void *take() { - if (isInvalid()) - return 0; - void *tmp = Ptr; - Ptr = 0; - return tmp; - } - - /// Take outside ownership of the raw pointer and cast it down. - template<typename T> - T *takeAs() { - return static_cast<T*>(take()); - } - - /// Alias for interface familiarity with unique_ptr. - void *release() { return take(); } - - /// Pass ownership to a classical ActionResult. - DumbResult result() { - if (isInvalid()) - return true; - return take(); - } - - /// Move hook - operator moving::ASTResultMover<Destroyer>() { - return moving::ASTResultMover<Destroyer>(*this); - } - }; -#else - template <ASTDestroyer Destroyer> - class ASTOwningResult { - public: - typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult; - - private: - DumbResult Result; - - public: - explicit ASTOwningResult(ActionBase &actions, bool invalid = false) - : Result(invalid) { } - ASTOwningResult(ActionBase &actions, void *node) : Result(node) { } - ASTOwningResult(ActionBase &actions, const DumbResult &res) : Result(res) { } - // Normal copying semantics are defined implicitly. - ASTOwningResult(const ASTOwningPtr<Destroyer> &o) : Result(o.get()) { } - - /// Assignment from a raw pointer. Takes ownership - beware! - ASTOwningResult & operator =(void *raw) { - Result = raw; - return *this; - } - - /// Assignment from an ActionResult. Takes ownership - beware! - ASTOwningResult & operator =(const DumbResult &res) { - Result = res; - return *this; - } - - /// Access to the raw pointer. - void * get() const { return Result.get(); } - - bool isInvalid() const { return Result.isInvalid(); } - - /// Does this point to a usable AST node? To be usable, the node must be - /// valid and non-null. - bool isUsable() const { return !Result.isInvalid() && get(); } - - /// Take outside ownership of the raw pointer. - void * take() { - return Result.get(); - } - - /// Take outside ownership of the raw pointer and cast it down. - template<typename T> - T *takeAs() { - return static_cast<T*>(take()); - } - - /// Alias for interface familiarity with unique_ptr. - void * release() { return take(); } - - /// Pass ownership to a classical ActionResult. - DumbResult result() { return Result; } - }; -#endif - - template <ASTDestroyer Destroyer> - class ASTMultiPtr { -#if !defined(DISABLE_SMART_POINTERS) - ActionBase &Actions; -#endif - void **Nodes; - unsigned Count; - -#if !defined(DISABLE_SMART_POINTERS) - friend class moving::ASTMultiMover<Destroyer>; - -#if defined(_MSC_VER) - // Last tested with Visual Studio 2008. - // Visual C++ appears to have a bug where it does not recognise - // the return value from ASTMultiMover<Destroyer>::opeator-> as - // being a pointer to ASTMultiPtr. However, the diagnostics - // suggest it has the right name, simply that the pointer type - // is not convertible to itself. - // Either way, a classic C-style hard cast resolves any issue. - static ASTMultiPtr* hack(moving::ASTMultiMover<Destroyer> & source) { - return (ASTMultiPtr*)source.operator->(); - } -#endif - - ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT - // Reference member prevents copy assignment. - - void destroy() { - assert((Count == 0 || Nodes) && "No nodes when count is not zero."); - for (unsigned i = 0; i < Count; ++i) { - if (Nodes[i]) - (Actions.*Destroyer)(Nodes[i]); - } - } -#endif - - public: -#if !defined(DISABLE_SMART_POINTERS) - explicit ASTMultiPtr(ActionBase &actions) - : Actions(actions), Nodes(0), Count(0) {} - ASTMultiPtr(ActionBase &actions, void **nodes, unsigned count) - : Actions(actions), Nodes(nodes), Count(count) {} - /// Move constructor - ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover) -#if defined(_MSC_VER) - // Apply the visual C++ hack supplied above. - // Last tested with Visual Studio 2008. - : Actions(hack(mover)->Actions), Nodes(hack(mover)->Nodes), Count(hack(mover)->Count) { -#else - : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) { -#endif - mover.release(); - } -#else - // Normal copying implicitly defined - explicit ASTMultiPtr(ActionBase &) : Nodes(0), Count(0) {} - ASTMultiPtr(ActionBase &, void **nodes, unsigned count) - : Nodes(nodes), Count(count) {} - // Fake mover in Parse/AstGuard.h needs this: - ASTMultiPtr(void **nodes, unsigned count) : Nodes(nodes), Count(count) {} -#endif - -#if !defined(DISABLE_SMART_POINTERS) - /// Move assignment - ASTMultiPtr & operator =(moving::ASTMultiMover<Destroyer> mover) { - destroy(); - Nodes = mover->Nodes; - Count = mover->Count; - mover.release(); - return *this; - } -#endif - - /// Access to the raw pointers. - void ** get() const { return Nodes; } - - /// Access to the count. - unsigned size() const { return Count; } - - void ** release() { -#if !defined(DISABLE_SMART_POINTERS) - void **tmp = Nodes; - Nodes = 0; - Count = 0; - return tmp; -#else - return Nodes; -#endif - } - -#if !defined(DISABLE_SMART_POINTERS) - /// Move hook - operator moving::ASTMultiMover<Destroyer>() { - return moving::ASTMultiMover<Destroyer>(*this); - } -#endif - }; - - class ParsedTemplateArgument; - - class ASTTemplateArgsPtr { -#if !defined(DISABLE_SMART_POINTERS) - ActionBase &Actions; -#endif - ParsedTemplateArgument *Args; - mutable unsigned Count; - -#if !defined(DISABLE_SMART_POINTERS) - void destroy(); -#endif - - public: - ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args, - unsigned count) : -#if !defined(DISABLE_SMART_POINTERS) - Actions(actions), -#endif - Args(args), Count(count) { } - - // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. - ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : -#if !defined(DISABLE_SMART_POINTERS) - Actions(Other.Actions), -#endif - Args(Other.Args), Count(Other.Count) { -#if !defined(DISABLE_SMART_POINTERS) - Other.Count = 0; -#endif - } - - // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. - ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) { -#if !defined(DISABLE_SMART_POINTERS) - Actions = Other.Actions; -#endif - Args = Other.Args; - Count = Other.Count; -#if !defined(DISABLE_SMART_POINTERS) - Other.Count = 0; -#endif - return *this; - } - -#if !defined(DISABLE_SMART_POINTERS) - ~ASTTemplateArgsPtr() { destroy(); } -#endif - - ParsedTemplateArgument *getArgs() const { return Args; } - unsigned size() const { return Count; } - - void reset(ParsedTemplateArgument *args, unsigned count) { -#if !defined(DISABLE_SMART_POINTERS) - destroy(); -#endif - Args = args; - Count = count; - } - - const ParsedTemplateArgument &operator[](unsigned Arg) const; - - ParsedTemplateArgument *release() const { -#if !defined(DISABLE_SMART_POINTERS) - Count = 0; -#endif - return Args; - } - }; - - /// \brief A small vector that owns a set of AST nodes. - template <ASTDestroyer Destroyer, unsigned N = 8> - class ASTOwningVector : public llvm::SmallVector<void *, N> { -#if !defined(DISABLE_SMART_POINTERS) - ActionBase &Actions; - bool Owned; -#endif - - ASTOwningVector(ASTOwningVector &); // do not implement - ASTOwningVector &operator=(ASTOwningVector &); // do not implement - - public: - explicit ASTOwningVector(ActionBase &Actions) -#if !defined(DISABLE_SMART_POINTERS) - : Actions(Actions), Owned(true) -#endif - { } - -#if !defined(DISABLE_SMART_POINTERS) - ~ASTOwningVector() { - if (!Owned) - return; - - for (unsigned I = 0, Last = this->size(); I != Last; ++I) - (Actions.*Destroyer)((*this)[I]); - } -#endif - - void **take() { -#if !defined(DISABLE_SMART_POINTERS) - Owned = false; -#endif - return &this->front(); - } - - template<typename T> T **takeAs() { return (T**)take(); } - -#if !defined(DISABLE_SMART_POINTERS) - ActionBase &getActions() const { return Actions; } -#endif - }; - - /// A SmallVector of statements, with stack size 32 (as that is the only one - /// used.) - typedef ASTOwningVector<&ActionBase::DeleteStmt, 32> StmtVector; - /// A SmallVector of expressions, with stack size 12 (the maximum used.) - typedef ASTOwningVector<&ActionBase::DeleteExpr, 12> ExprVector; - - template <ASTDestroyer Destroyer, unsigned N> inline - ASTMultiPtr<Destroyer> move_arg(ASTOwningVector<Destroyer, N> &vec) { -#if !defined(DISABLE_SMART_POINTERS) - return ASTMultiPtr<Destroyer>(vec.getActions(), vec.take(), vec.size()); -#else - return ASTMultiPtr<Destroyer>(vec.take(), vec.size()); -#endif - } - -#if !defined(DISABLE_SMART_POINTERS) - - // Out-of-line implementations due to definition dependencies - - template <ASTDestroyer Destroyer> inline - void moving::ASTMultiMover<Destroyer>::release() { - Moved.Nodes = 0; - Moved.Count = 0; - } - - // Move overloads. - - template <ASTDestroyer Destroyer> inline - ASTOwningResult<Destroyer> move(ASTOwningResult<Destroyer> &ptr) { - return ASTOwningResult<Destroyer>(moving::ASTResultMover<Destroyer>(ptr)); - } - - template <ASTDestroyer Destroyer> inline - ASTMultiPtr<Destroyer> move(ASTMultiPtr<Destroyer> &ptr) { - return ASTMultiPtr<Destroyer>(moving::ASTMultiMover<Destroyer>(ptr)); - } - -#else - - template <ASTDestroyer Destroyer> inline - ASTOwningPtr<Destroyer>::ASTOwningPtr(const ASTOwningResult<Destroyer> &o) - : Node(o.get()) { } - - // These versions are hopefully no-ops. - template <ASTDestroyer Destroyer> inline - ASTOwningResult<Destroyer>& move(ASTOwningResult<Destroyer> &ptr) { - return ptr; - } - - template <ASTDestroyer Destroyer> inline - ASTOwningPtr<Destroyer>& move(ASTOwningPtr<Destroyer> &ptr) { - return ptr; - } - - template <ASTDestroyer Destroyer> inline - ASTMultiPtr<Destroyer>& move(ASTMultiPtr<Destroyer> &ptr) { - return ptr; - } -#endif -} - -#endif diff --git a/include/clang/Sema/ParseAST.h b/include/clang/Parse/ParseAST.h index f6cff2a023e6..0d37e21becd3 100644 --- a/include/clang/Sema/ParseAST.h +++ b/include/clang/Parse/ParseAST.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_PARSEAST_H -#define LLVM_CLANG_SEMA_PARSEAST_H +#ifndef LLVM_CLANG_PARSE_PARSEAST_H +#define LLVM_CLANG_PARSE_PARSEAST_H namespace clang { class Preprocessor; @@ -38,6 +38,10 @@ namespace clang { bool CompleteTranslationUnit = true, CodeCompleteConsumer *CompletionConsumer = 0); + /// \brief Parse the main file known to the preprocessor, producing an + /// abstract syntax tree. + void ParseAST(Sema &S, bool PrintStats = false); + } // end namespace clang #endif diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index b8c294ada691..41a2fb615791 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -16,8 +16,10 @@ #include "clang/Basic/Specifiers.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Parse/Action.h" -#include "clang/Parse/DeclSpec.h" +#include "clang/Lex/CodeCompletionHandler.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/DeclSpec.h" +#include "llvm/Support/PrettyStackTrace.h" #include "llvm/ADT/OwningPtr.h" #include <stack> #include <list> @@ -27,6 +29,7 @@ namespace clang { struct CXX0XAttributeList; class PragmaHandler; class Scope; + class DeclGroupRef; class DiagnosticBuilder; class Parser; class PragmaUnusedHandler; @@ -69,7 +72,7 @@ namespace prec { /// parsing units of the grammar, productions are invoked to handle whatever has /// been read. /// -class Parser { +class Parser : public CodeCompletionHandler { friend class PragmaUnusedHandler; friend class ColonProtectionRAIIObject; friend class ParenBraceBracketBalancer; @@ -90,9 +93,8 @@ class Parser { unsigned short ParenCount, BracketCount, BraceCount; /// Actions - These are the callbacks we invoke as we parse various constructs - /// in the file. This refers to the common base class between MinimalActions - /// and SemaActions for those uses that don't matter. - Action &Actions; + /// in the file. + Sema &Actions; Diagnostic &Diags; @@ -110,6 +112,8 @@ class Parser { IdentifierInfo *Ident_vector; IdentifierInfo *Ident_pixel; + llvm::OwningPtr<PragmaHandler> AlignHandler; + llvm::OwningPtr<PragmaHandler> GCCVisibilityHandler; llvm::OwningPtr<PragmaHandler> OptionsHandler; llvm::OwningPtr<PragmaHandler> PackHandler; llvm::OwningPtr<PragmaHandler> UnusedHandler; @@ -131,61 +135,56 @@ class Parser { unsigned TemplateParameterDepth; public: - Parser(Preprocessor &PP, Action &Actions); + Parser(Preprocessor &PP, Sema &Actions); ~Parser(); const LangOptions &getLang() const { return PP.getLangOptions(); } const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); } Preprocessor &getPreprocessor() const { return PP; } - Action &getActions() const { return Actions; } + Sema &getActions() const { return Actions; } const Token &getCurToken() const { return Tok; } Scope *getCurScope() const { return Actions.getCurScope(); } // Type forwarding. All of these are statically 'void*', but they may all be // different actual classes based on the actions in place. - typedef Action::ExprTy ExprTy; - typedef Action::StmtTy StmtTy; - typedef Action::DeclPtrTy DeclPtrTy; - typedef Action::DeclGroupPtrTy DeclGroupPtrTy; - typedef Action::TypeTy TypeTy; - typedef Action::BaseTy BaseTy; - typedef Action::MemInitTy MemInitTy; - typedef Action::CXXScopeTy CXXScopeTy; - typedef Action::TemplateParamsTy TemplateParamsTy; - typedef Action::TemplateTy TemplateTy; - - typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists; - - typedef Action::ExprResult ExprResult; - typedef Action::StmtResult StmtResult; - typedef Action::BaseResult BaseResult; - typedef Action::MemInitResult MemInitResult; - typedef Action::TypeResult TypeResult; - - typedef Action::OwningExprResult OwningExprResult; - typedef Action::OwningStmtResult OwningStmtResult; - - typedef Action::ExprArg ExprArg; - typedef Action::MultiStmtArg MultiStmtArg; - typedef Action::FullExprArg FullExprArg; - - /// Adorns a ExprResult with Actions to make it an OwningExprResult - OwningExprResult Owned(ExprResult res) { - return OwningExprResult(Actions, res); + typedef Expr ExprTy; + typedef Stmt StmtTy; + typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy; + typedef CXXBaseSpecifier BaseTy; + typedef CXXBaseOrMemberInitializer MemInitTy; + typedef NestedNameSpecifier CXXScopeTy; + typedef TemplateParameterList TemplateParamsTy; + typedef OpaquePtr<TemplateName> TemplateTy; + + typedef llvm::SmallVector<TemplateParameterList *, 4> TemplateParameterLists; + + typedef clang::ExprResult ExprResult; + typedef clang::StmtResult StmtResult; + typedef clang::BaseResult BaseResult; + typedef clang::MemInitResult MemInitResult; + typedef clang::TypeResult TypeResult; + + typedef Expr *ExprArg; + typedef ASTMultiPtr<Stmt*> MultiStmtArg; + typedef Sema::FullExprArg FullExprArg; + + /// Adorns a ExprResult with Actions to make it an ExprResult + ExprResult Owned(ExprResult res) { + return ExprResult(res); } - /// Adorns a StmtResult with Actions to make it an OwningStmtResult - OwningStmtResult Owned(StmtResult res) { - return OwningStmtResult(Actions, res); + /// Adorns a StmtResult with Actions to make it an StmtResult + StmtResult Owned(StmtResult res) { + return StmtResult(res); } - OwningExprResult ExprError() { return OwningExprResult(Actions, true); } - OwningStmtResult StmtError() { return OwningStmtResult(Actions, true); } + ExprResult ExprError() { return ExprResult(true); } + StmtResult StmtError() { return StmtResult(true); } - OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); } - OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); } + ExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); } + StmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); } - OwningExprResult ExprEmpty() { return OwningExprResult(Actions, false); } + ExprResult ExprEmpty() { return ExprResult(false); } // Parsing methods. @@ -201,7 +200,7 @@ public: /// the EOF was encountered. bool ParseTopLevelDecl(DeclGroupPtrTy &Result); - DeclGroupPtrTy RetrievePendingObjCImpDecl(); + DeclGroupPtrTy FinishPendingObjCActions(); private: //===--------------------------------------------------------------------===// @@ -349,6 +348,15 @@ private: return PP.LookAhead(0); } + /// getTypeAnnotation - Read a parsed type out of an annotation token. + static ParsedType getTypeAnnotation(Token &Tok) { + return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue()); + } + + static void setTypeAnnotation(Token &Tok, ParsedType T) { + Tok.setAnnotationValue(T.getAsOpaquePtr()); + } + /// TryAnnotateTypeOrScopeToken - If the current token position is on a /// typename (possibly qualified in C++) or a C++ scope specifier not followed /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens @@ -538,7 +546,7 @@ private: // Lexing and parsing of C++ inline methods. struct LexedMethod { - Action::DeclPtrTy D; + Decl *D; CachedTokens Toks; /// \brief Whether this member function had an associated template @@ -546,7 +554,7 @@ private: /// othewise, it is a member function declaration. bool TemplateScope; - explicit LexedMethod(Action::DeclPtrTy MD) : D(MD), TemplateScope(false) {} + explicit LexedMethod(Decl *MD) : D(MD), TemplateScope(false) {} }; /// LateParsedDefaultArgument - Keeps track of a parameter that may @@ -554,12 +562,12 @@ private: /// occurs within a member function declaration inside the class /// (C++ [class.mem]p2). struct LateParsedDefaultArgument { - explicit LateParsedDefaultArgument(Action::DeclPtrTy P, + explicit LateParsedDefaultArgument(Decl *P, CachedTokens *Toks = 0) : Param(P), Toks(Toks) { } /// Param - The parameter declaration for this parameter. - Action::DeclPtrTy Param; + Decl *Param; /// Toks - The sequence of tokens that comprises the default /// argument expression, not including the '=' or the terminating @@ -573,11 +581,11 @@ private: /// until the class itself is completely-defined, such as a default /// argument (C++ [class.mem]p2). struct LateParsedMethodDeclaration { - explicit LateParsedMethodDeclaration(Action::DeclPtrTy M) + explicit LateParsedMethodDeclaration(Decl *M) : Method(M), TemplateScope(false) { } /// Method - The method declaration. - Action::DeclPtrTy Method; + Decl *Method; /// \brief Whether this member function had an associated template /// scope. When true, D is a template declaration. @@ -608,7 +616,7 @@ private: /// any member function declarations or definitions that need to be /// parsed after the corresponding top-level class is complete. struct ParsingClass { - ParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass) + ParsingClass(Decl *TagOrTemplate, bool TopLevelClass) : TopLevelClass(TopLevelClass), TemplateScope(false), TagOrTemplate(TagOrTemplate) { } @@ -622,7 +630,7 @@ private: bool TemplateScope : 1; /// \brief The class or class template whose definition we are parsing. - DeclPtrTy TagOrTemplate; + Decl *TagOrTemplate; /// MethodDecls - Method declarations that contain pieces whose /// parsing will be delayed until the class is fully defined. @@ -651,15 +659,28 @@ private: /// variable's initializer, but not when parsing the body of a /// class or function definition. class ParsingDeclRAIIObject { - Action &Actions; - Action::ParsingDeclStackState State; + Sema &Actions; + Sema::ParsingDeclStackState State; bool Popped; - + public: ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) { push(); } + ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *Other) + : Actions(P.Actions) { + if (Other) steal(*Other); + else push(); + } + + /// Creates a RAII object which steals the state from a different + /// object instead of pushing. + ParsingDeclRAIIObject(ParsingDeclRAIIObject &Other) + : Actions(Other.Actions) { + steal(Other); + } + ~ParsingDeclRAIIObject() { abort(); } @@ -673,21 +694,27 @@ private: /// Signals that the context was completed without an appropriate /// declaration being parsed. void abort() { - pop(DeclPtrTy()); + pop(0); } - void complete(DeclPtrTy D) { + void complete(Decl *D) { assert(!Popped && "ParsingDeclaration has already been popped!"); pop(D); } private: + void steal(ParsingDeclRAIIObject &Other) { + State = Other.State; + Popped = Other.Popped; + Other.Popped = true; + } + void push() { State = Actions.PushParsingDeclaration(); Popped = false; } - void pop(DeclPtrTy D) { + void pop(Decl *D) { if (!Popped) { Actions.PopParsingDeclaration(State, D); Popped = true; @@ -700,10 +727,12 @@ private: ParsingDeclRAIIObject ParsingRAII; public: - ParsingDeclSpec(Parser &P) : ParsingRAII(P) { - } + ParsingDeclSpec(Parser &P) : ParsingRAII(P) {} + ParsingDeclSpec(ParsingDeclRAIIObject &RAII) : ParsingRAII(RAII) {} + ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII) + : ParsingRAII(P, RAII) {} - void complete(DeclPtrTy D) { + void complete(Decl *D) { ParsingRAII.complete(D); } @@ -734,7 +763,7 @@ private: ParsingRAII.reset(); } - void complete(DeclPtrTy D) { + void complete(Decl *D) { ParsingRAII.complete(D); } }; @@ -745,7 +774,7 @@ private: bool Popped; public: - ParsingClassDefinition(Parser &P, DeclPtrTy TagOrTemplate, bool TopLevelClass) + ParsingClassDefinition(Parser &P, Decl *TagOrTemplate, bool TopLevelClass) : P(P), Popped(false) { P.PushParsingClass(TagOrTemplate, TopLevelClass); } @@ -811,12 +840,12 @@ private: bool LastParameterListWasEmpty; }; - void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass); + void PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass); void DeallocateParsedClasses(ParsingClass *Class); void PopParsingClass(); - DeclPtrTy ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, - const ParsedTemplateInfo &TemplateInfo); + Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, + const ParsedTemplateInfo &TemplateInfo); void ParseLexedMethodDeclarations(ParsingClass &Class); void ParseLexedMethodDefs(ParsingClass &Class); bool ConsumeAndStoreUntil(tok::TokenKind T1, @@ -832,7 +861,8 @@ private: //===--------------------------------------------------------------------===// // C99 6.9: External Definitions. - DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr); + DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr, + ParsingDeclSpec *DS = 0); bool isDeclarationAfterDeclarator() const; bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator); DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr, @@ -841,40 +871,40 @@ private: AttributeList *Attr, AccessSpecifier AS = AS_none); - DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D, + Decl *ParseFunctionDefinition(ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); void ParseKNRParamDeclarations(Declarator &D); // EndLoc, if non-NULL, is filled with the location of the last token of // the simple-asm. - OwningExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0); - OwningExprResult ParseAsmStringLiteral(); + ExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0); + ExprResult ParseAsmStringLiteral(); // Objective-C External Declarations - DeclPtrTy ParseObjCAtDirectives(); - DeclPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); - DeclPtrTy ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, + Decl *ParseObjCAtDirectives(); + Decl *ParseObjCAtClassDeclaration(SourceLocation atLoc); + Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, AttributeList *prefixAttrs = 0); - void ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, + void ParseObjCClassInstanceVariables(Decl *interfaceDecl, tok::ObjCKeywordKind visibility, SourceLocation atLoc); - bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &P, + bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Decl *> &P, llvm::SmallVectorImpl<SourceLocation> &PLocs, bool WarnOnDeclarations, SourceLocation &LAngleLoc, SourceLocation &EndProtoLoc); - void ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, + void ParseObjCInterfaceDeclList(Decl *interfaceDecl, tok::ObjCKeywordKind contextKey); - DeclPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc, + Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc, AttributeList *prefixAttrs = 0); - DeclPtrTy ObjCImpDecl; - llvm::SmallVector<DeclPtrTy, 4> PendingObjCImpDecl; + Decl *ObjCImpDecl; + llvm::SmallVector<Decl *, 4> PendingObjCImpDecl; - DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc); - DeclPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd); - DeclPtrTy ParseObjCAtAliasDeclaration(SourceLocation atLoc); - DeclPtrTy ParseObjCPropertySynthesize(SourceLocation atLoc); - DeclPtrTy ParseObjCPropertyDynamic(SourceLocation atLoc); + Decl *ParseObjCAtImplementationDeclaration(SourceLocation atLoc); + Decl *ParseObjCAtEndDeclaration(SourceRange atEnd); + Decl *ParseObjCAtAliasDeclaration(SourceLocation atLoc); + Decl *ParseObjCPropertySynthesize(SourceLocation atLoc); + Decl *ParseObjCPropertyDynamic(SourceLocation atLoc); IdentifierInfo *ParseObjCSelectorPiece(SourceLocation &MethodLocation); // Definitions for Objective-c context sensitive keywords recognition. @@ -886,58 +916,69 @@ private: bool isTokIdentifier_in() const; - TypeTy *ParseObjCTypeName(ObjCDeclSpec &DS); + ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter); void ParseObjCMethodRequirement(); - DeclPtrTy ParseObjCMethodPrototype(DeclPtrTy classOrCat, + Decl *ParseObjCMethodPrototype(Decl *classOrCat, tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); - DeclPtrTy ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, - DeclPtrTy classDecl, + Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, + Decl *classDecl, tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); - void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl, - DeclPtrTy *Methods, unsigned NumMethods); + void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl, + Decl **Methods, unsigned NumMethods); - DeclPtrTy ParseObjCMethodDefinition(); + Decl *ParseObjCMethodDefinition(); //===--------------------------------------------------------------------===// // C99 6.5: Expressions. - OwningExprResult ParseExpression(); - OwningExprResult ParseConstantExpression(); + ExprResult ParseExpression(); + ExprResult ParseConstantExpression(); // Expr that doesn't include commas. - OwningExprResult ParseAssignmentExpression(); + ExprResult ParseAssignmentExpression(); - OwningExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc); + ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc); - OwningExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); + ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); - OwningExprResult ParseRHSOfBinaryExpression(OwningExprResult LHS, + ExprResult ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec); - OwningExprResult ParseCastExpression(bool isUnaryExpression, + ExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, bool &NotCastExpr, - TypeTy *TypeOfCast); - OwningExprResult ParseCastExpression(bool isUnaryExpression, + ParsedType TypeOfCast); + ExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand = false, - TypeTy *TypeOfCast = 0); - OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS); - OwningExprResult ParseSizeofAlignofExpression(); - OwningExprResult ParseBuiltinPrimaryExpression(); + ParsedType TypeOfCast = ParsedType()); + + /// Returns true if the next token would start a postfix-expression + /// suffix. + bool isPostfixExpressionSuffixStart() { + tok::TokenKind K = Tok.getKind(); + return (K == tok::l_square || K == tok::l_paren || + K == tok::period || K == tok::arrow || + K == tok::plusplus || K == tok::minusminus); + } - OwningExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, + ExprResult ParsePostfixExpressionSuffix(ExprResult LHS); + ExprResult ParseSizeofAlignofExpression(); + ExprResult ParseBuiltinPrimaryExpression(); + + ExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, bool &isCastExpr, - TypeTy *&CastTy, + ParsedType &CastTy, SourceRange &CastRange); - static const unsigned ExprListSize = 12; - typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy; - typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy; + typedef llvm::SmallVector<Expr*, 20> ExprListTy; + typedef llvm::SmallVector<SourceLocation, 20> CommaLocsTy; /// ParseExpressionList - Used for C/C++ (argument-)expression-list. - bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs, - void (Action::*Completer)(Scope *S, void *Data, - ExprTy **Args, - unsigned NumArgs) = 0, - void *Data = 0); + bool ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs, + llvm::SmallVectorImpl<SourceLocation> &CommaLocs, + void (Sema::*Completer)(Scope *S, + Expr *Data, + Expr **Args, + unsigned NumArgs) = 0, + Expr *Data = 0); /// ParenParseOption - Control what ParseParenExpression will parse. enum ParenParseOption { @@ -946,67 +987,67 @@ private: CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}' CastExpr // Also allow '(' type-name ')' <anything> }; - OwningExprResult ParseParenExpression(ParenParseOption &ExprType, + ExprResult ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, - TypeTy *TypeOfCast, - TypeTy *&CastTy, + ParsedType TypeOfCast, + ParsedType &CastTy, SourceLocation &RParenLoc); - OwningExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, - TypeTy *&CastTy, + ExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, + ParsedType &CastTy, SourceLocation LParenLoc, SourceLocation &RParenLoc); - OwningExprResult ParseCompoundLiteralExpression(TypeTy *Ty, + ExprResult ParseCompoundLiteralExpression(ParsedType Ty, SourceLocation LParenLoc, SourceLocation RParenLoc); - OwningExprResult ParseStringLiteralExpression(); + ExprResult ParseStringLiteralExpression(); //===--------------------------------------------------------------------===// // C++ Expressions - OwningExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); + ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, - TypeTy *ObjectType, + ParsedType ObjectType, bool EnteringContext, bool *MayBePseudoDestructor = 0); //===--------------------------------------------------------------------===// // C++ 5.2p1: C++ Casts - OwningExprResult ParseCXXCasts(); + ExprResult ParseCXXCasts(); //===--------------------------------------------------------------------===// // C++ 5.2p1: C++ Type Identification - OwningExprResult ParseCXXTypeid(); + ExprResult ParseCXXTypeid(); //===--------------------------------------------------------------------===// // C++ 5.2.4: C++ Pseudo-Destructor Expressions - OwningExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, + ExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, - Action::TypeTy *ObjectType); + ParsedType ObjectType); //===--------------------------------------------------------------------===// // C++ 9.3.2: C++ 'this' pointer - OwningExprResult ParseCXXThis(); + ExprResult ParseCXXThis(); //===--------------------------------------------------------------------===// // C++ 15: C++ Throw Expression - OwningExprResult ParseThrowExpression(); + ExprResult ParseThrowExpression(); // EndLoc is filled with the location of the last token of the specification. bool ParseExceptionSpecification(SourceLocation &EndLoc, - llvm::SmallVector<TypeTy*, 2> &Exceptions, - llvm::SmallVector<SourceRange, 2> &Ranges, + llvm::SmallVectorImpl<ParsedType> &Exns, + llvm::SmallVectorImpl<SourceRange> &Ranges, bool &hasAnyExceptionSpec); //===--------------------------------------------------------------------===// // C++ 2.13.5: C++ Boolean Literals - OwningExprResult ParseCXXBoolLiteral(); + ExprResult ParseCXXBoolLiteral(); //===--------------------------------------------------------------------===// // C++ 5.2.3: Explicit type conversion (functional notation) - OwningExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS); + ExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS); bool isCXXSimpleTypeSpecifier() const; @@ -1019,15 +1060,16 @@ private: //===--------------------------------------------------------------------===// // C++ 5.3.4 and 5.3.5: C++ new and delete - bool ParseExpressionListOrTypeId(ExprListTy &Exprs, Declarator &D); + bool ParseExpressionListOrTypeId(llvm::SmallVectorImpl<Expr*> &Exprs, + Declarator &D); void ParseDirectNewDeclarator(Declarator &D); - OwningExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start); - OwningExprResult ParseCXXDeleteExpression(bool UseGlobal, + ExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start); + ExprResult ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start); //===--------------------------------------------------------------------===// // C++ if/switch/while condition expression. - bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult, + bool ParseCXXCondition(ExprResult &ExprResult, Decl *&DeclResult, SourceLocation Loc, bool ConvertToBoolean); //===--------------------------------------------------------------------===// @@ -1040,65 +1082,65 @@ private: /// initializer: [C99 6.7.8] /// assignment-expression /// '{' ... - OwningExprResult ParseInitializer() { + ExprResult ParseInitializer() { if (Tok.isNot(tok::l_brace)) return ParseAssignmentExpression(); return ParseBraceInitializer(); } - OwningExprResult ParseBraceInitializer(); - OwningExprResult ParseInitializerWithPotentialDesignator(); + ExprResult ParseBraceInitializer(); + ExprResult ParseInitializerWithPotentialDesignator(); //===--------------------------------------------------------------------===// // clang Expressions - OwningExprResult ParseBlockLiteralExpression(); // ^{...} + ExprResult ParseBlockLiteralExpression(); // ^{...} //===--------------------------------------------------------------------===// // Objective-C Expressions - OwningExprResult ParseObjCAtExpression(SourceLocation AtLocation); - OwningExprResult ParseObjCStringLiteral(SourceLocation AtLoc); - OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc); - OwningExprResult ParseObjCSelectorExpression(SourceLocation AtLoc); - OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc); + ExprResult ParseObjCAtExpression(SourceLocation AtLocation); + ExprResult ParseObjCStringLiteral(SourceLocation AtLoc); + ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc); + ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc); + ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc); bool isSimpleObjCMessageExpression(); - OwningExprResult ParseObjCMessageExpression(); - OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc, + ExprResult ParseObjCMessageExpression(); + ExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc, SourceLocation SuperLoc, - TypeTy *ReceiverType, + ParsedType ReceiverType, ExprArg ReceiverExpr); - OwningExprResult ParseAssignmentExprWithObjCMessageExprStart( + ExprResult ParseAssignmentExprWithObjCMessageExprStart( SourceLocation LBracloc, SourceLocation SuperLoc, - TypeTy *ReceiverType, ExprArg ReceiverExpr); + ParsedType ReceiverType, ExprArg ReceiverExpr); bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr); //===--------------------------------------------------------------------===// // C99 6.8: Statements and Blocks. - OwningStmtResult ParseStatement() { + StmtResult ParseStatement() { return ParseStatementOrDeclaration(true); } - OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false); - OwningStmtResult ParseLabeledStatement(AttributeList *Attr); - OwningStmtResult ParseCaseStatement(AttributeList *Attr); - OwningStmtResult ParseDefaultStatement(AttributeList *Attr); - OwningStmtResult ParseCompoundStatement(AttributeList *Attr, + StmtResult ParseStatementOrDeclaration(bool OnlyStatement = false); + StmtResult ParseLabeledStatement(AttributeList *Attr); + StmtResult ParseCaseStatement(AttributeList *Attr); + StmtResult ParseDefaultStatement(AttributeList *Attr); + StmtResult ParseCompoundStatement(AttributeList *Attr, bool isStmtExpr = false); - OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false); - bool ParseParenExprOrCondition(OwningExprResult &ExprResult, - DeclPtrTy &DeclResult, + StmtResult ParseCompoundStatementBody(bool isStmtExpr = false); + bool ParseParenExprOrCondition(ExprResult &ExprResult, + Decl *&DeclResult, SourceLocation Loc, bool ConvertToBoolean); - OwningStmtResult ParseIfStatement(AttributeList *Attr); - OwningStmtResult ParseSwitchStatement(AttributeList *Attr); - OwningStmtResult ParseWhileStatement(AttributeList *Attr); - OwningStmtResult ParseDoStatement(AttributeList *Attr); - OwningStmtResult ParseForStatement(AttributeList *Attr); - OwningStmtResult ParseGotoStatement(AttributeList *Attr); - OwningStmtResult ParseContinueStatement(AttributeList *Attr); - OwningStmtResult ParseBreakStatement(AttributeList *Attr); - OwningStmtResult ParseReturnStatement(AttributeList *Attr); - OwningStmtResult ParseAsmStatement(bool &msAsm); - OwningStmtResult FuzzyParseMicrosoftAsmStatement(); + StmtResult ParseIfStatement(AttributeList *Attr); + StmtResult ParseSwitchStatement(AttributeList *Attr); + StmtResult ParseWhileStatement(AttributeList *Attr); + StmtResult ParseDoStatement(AttributeList *Attr); + StmtResult ParseForStatement(AttributeList *Attr); + StmtResult ParseGotoStatement(AttributeList *Attr); + StmtResult ParseContinueStatement(AttributeList *Attr); + StmtResult ParseBreakStatement(AttributeList *Attr); + StmtResult ParseReturnStatement(AttributeList *Attr); + StmtResult ParseAsmStatement(bool &msAsm); + StmtResult FuzzyParseMicrosoftAsmStatement(); bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, llvm::SmallVectorImpl<ExprTy *> &Constraints, llvm::SmallVectorImpl<ExprTy *> &Exprs); @@ -1106,17 +1148,17 @@ private: //===--------------------------------------------------------------------===// // C++ 6: Statements and Blocks - OwningStmtResult ParseCXXTryBlock(AttributeList *Attr); - OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc); - OwningStmtResult ParseCXXCatchBlock(); + StmtResult ParseCXXTryBlock(AttributeList *Attr); + StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc); + StmtResult ParseCXXCatchBlock(); //===--------------------------------------------------------------------===// // Objective-C Statements - OwningStmtResult ParseObjCAtStatement(SourceLocation atLoc); - OwningStmtResult ParseObjCTryStmt(SourceLocation atLoc); - OwningStmtResult ParseObjCThrowStmt(SourceLocation atLoc); - OwningStmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc); + StmtResult ParseObjCAtStatement(SourceLocation atLoc); + StmtResult ParseObjCTryStmt(SourceLocation atLoc); + StmtResult ParseObjCThrowStmt(SourceLocation atLoc); + StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc); //===--------------------------------------------------------------------===// @@ -1140,10 +1182,10 @@ private: DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, SourceLocation *DeclEnd = 0); - DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D, + Decl *ParseDeclarationAfterDeclarator(Declarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); - DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl); - DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl); + Decl *ParseFunctionStatementBody(Decl *Decl); + Decl *ParseFunctionTryBlock(Decl *Decl); bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, const ParsedTemplateInfo &TemplateInfo, @@ -1161,16 +1203,16 @@ private: void ParseSpecifierQualifierList(DeclSpec &DS); - void ParseObjCTypeQualifierList(ObjCDeclSpec &DS); + void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter); void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none); - void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl); + void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl); void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, - DeclPtrTy TagDecl); + Decl *TagDecl); struct FieldCallback { - virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0; + virtual Decl *invoke(FieldDeclarator &Field) = 0; virtual ~FieldCallback() {} private: @@ -1323,10 +1365,11 @@ private: AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0); AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0); AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0); + AttributeList *ParseBorlandTypeAttributes(AttributeList* CurrAttr = 0); void ParseTypeofSpecifier(DeclSpec &DS); void ParseDecltypeSpecifier(DeclSpec &DS); - OwningExprResult ParseCXX0XAlignArgument(SourceLocation Start); + ExprResult ParseCXX0XAlignArgument(SourceLocation Start); /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to /// enter a new C++ declarator scope and exit it when the function is @@ -1386,21 +1429,21 @@ private: bool isCXX0XAttributeSpecifier(bool FullLookahead = false, tok::TokenKind *After = 0); - DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd); - DeclPtrTy ParseLinkage(ParsingDeclSpec &DS, unsigned Context); - DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context, - SourceLocation &DeclEnd, - CXX0XAttributeList Attrs); - DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, - SourceLocation &DeclEnd, - AttributeList *Attr); - DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc, - SourceLocation &DeclEnd, - AccessSpecifier AS = AS_none); - DeclPtrTy ParseStaticAssertDeclaration(SourceLocation &DeclEnd); - DeclPtrTy ParseNamespaceAlias(SourceLocation NamespaceLoc, - SourceLocation AliasLoc, IdentifierInfo *Alias, - SourceLocation &DeclEnd); + Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd, + SourceLocation InlineLoc = SourceLocation()); + Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context); + Decl *ParseUsingDirectiveOrDeclaration(unsigned Context, + SourceLocation &DeclEnd, + CXX0XAttributeList Attrs); + Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, + SourceLocation &DeclEnd, AttributeList *Attr); + Decl *ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc, + SourceLocation &DeclEnd, + AccessSpecifier AS = AS_none); + Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd); + Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc, + SourceLocation AliasLoc, IdentifierInfo *Alias, + SourceLocation &DeclEnd); //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. @@ -1412,64 +1455,65 @@ private: AccessSpecifier AS = AS_none, bool SuppressDeclarations = false); void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType, - DeclPtrTy TagDecl); + Decl *TagDecl); void ParseCXXClassMemberDeclaration(AccessSpecifier AS, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); - void ParseConstructorInitializer(DeclPtrTy ConstructorDecl); - MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl); + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + ParsingDeclRAIIObject *DiagsFromTParams = 0); + void ParseConstructorInitializer(Decl *ConstructorDecl); + MemInitResult ParseMemInitializer(Decl *ConstructorDecl); void HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, - DeclPtrTy ThisDecl); + Decl *ThisDecl); //===--------------------------------------------------------------------===// // C++ 10: Derived classes [class.derived] - void ParseBaseClause(DeclPtrTy ClassDecl); - BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl); + void ParseBaseClause(Decl *ClassDecl); + BaseResult ParseBaseSpecifier(Decl *ClassDecl); AccessSpecifier getAccessSpecifierIfPresent() const; bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, bool EnteringContext, - TypeTy *ObjectType, + ParsedType ObjectType, UnqualifiedId &Id, bool AssumeTemplateId, SourceLocation TemplateKWLoc); bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, - TypeTy *ObjectType, + ParsedType ObjectType, UnqualifiedId &Result); bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, - TypeTy *ObjectType, + ParsedType ObjectType, UnqualifiedId &Result); //===--------------------------------------------------------------------===// // C++ 14: Templates [temp] - typedef llvm::SmallVector<DeclPtrTy, 4> TemplateParameterList; // C++ 14.1: Template Parameters [temp.param] - DeclPtrTy ParseDeclarationStartingWithTemplate(unsigned Context, + Decl *ParseDeclarationStartingWithTemplate(unsigned Context, SourceLocation &DeclEnd, AccessSpecifier AS = AS_none); - DeclPtrTy ParseTemplateDeclarationOrSpecialization(unsigned Context, + Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context, SourceLocation &DeclEnd, AccessSpecifier AS); - DeclPtrTy ParseSingleDeclarationAfterTemplate( + Decl *ParseSingleDeclarationAfterTemplate( unsigned Context, const ParsedTemplateInfo &TemplateInfo, + ParsingDeclRAIIObject &DiagsFromParams, SourceLocation &DeclEnd, AccessSpecifier AS=AS_none); bool ParseTemplateParameters(unsigned Depth, - TemplateParameterList &TemplateParams, + llvm::SmallVectorImpl<Decl*> &TemplateParams, SourceLocation &LAngleLoc, SourceLocation &RAngleLoc); bool ParseTemplateParameterList(unsigned Depth, - TemplateParameterList &TemplateParams); + llvm::SmallVectorImpl<Decl*> &TemplateParams); bool isStartOfTemplateTypeParameter(); - DeclPtrTy ParseTemplateParameter(unsigned Depth, unsigned Position); - DeclPtrTy ParseTypeParameter(unsigned Depth, unsigned Position); - DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position); - DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position); + Decl *ParseTemplateParameter(unsigned Depth, unsigned Position); + Decl *ParseTypeParameter(unsigned Depth, unsigned Position); + Decl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position); + Decl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position); // C++ 14.3: Template arguments [temp.arg] typedef llvm::SmallVector<ParsedTemplateArgument, 16> TemplateArgList; @@ -1491,13 +1535,24 @@ private: bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); ParsedTemplateArgument ParseTemplateTemplateArgument(); ParsedTemplateArgument ParseTemplateArgument(); - DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc, - SourceLocation TemplateLoc, - SourceLocation &DeclEnd); + Decl *ParseExplicitInstantiation(SourceLocation ExternLoc, + SourceLocation TemplateLoc, + SourceLocation &DeclEnd); //===--------------------------------------------------------------------===// // GNU G++: Type Traits [Type-Traits.html in the GCC manual] - OwningExprResult ParseUnaryTypeTrait(); + ExprResult ParseUnaryTypeTrait(); + + //===--------------------------------------------------------------------===// + // Preprocessor code-completion pass-through + virtual void CodeCompleteDirective(bool InConditional); + virtual void CodeCompleteInConditionalExclusion(); + virtual void CodeCompleteMacroName(bool IsDefinition); + virtual void CodeCompletePreprocessorExpression(); + virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro, + MacroInfo *MacroInfo, + unsigned ArgumentIndex); + virtual void CodeCompleteNaturalLanguage(); }; } // end namespace clang diff --git a/include/clang/Rewrite/FixItRewriter.h b/include/clang/Rewrite/FixItRewriter.h index 4ebcef0fff61..9b2e0160c5d6 100644 --- a/include/clang/Rewrite/FixItRewriter.h +++ b/include/clang/Rewrite/FixItRewriter.h @@ -27,13 +27,16 @@ namespace clang { class SourceManager; class FileEntry; -class FixItPathRewriter { +class FixItOptions { public: - virtual ~FixItPathRewriter(); + virtual ~FixItOptions(); /// \brief This file is about to be rewritten. Return the name of the file /// that is okay to write to. virtual std::string RewriteFilename(const std::string &Filename) = 0; + + /// \brief Whether to abort fixing a file when not all errors could be fixed. + bool FixWhatYouCan; }; class FixItRewriter : public DiagnosticClient { @@ -50,7 +53,7 @@ class FixItRewriter : public DiagnosticClient { /// \brief Turn an input path into an output path. NULL implies overwriting /// the original. - FixItPathRewriter *PathRewriter; + FixItOptions *FixItOpts; /// \brief The number of rewriter failures. unsigned NumFailures; @@ -60,7 +63,7 @@ public: /// \brief Initialize a new fix-it rewriter. FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr, - const LangOptions &LangOpts, FixItPathRewriter *PathRewriter); + const LangOptions &LangOpts, FixItOptions *FixItOpts); /// \brief Destroy the fix-it rewriter. ~FixItRewriter(); diff --git a/include/clang/Rewrite/FrontendActions.h b/include/clang/Rewrite/FrontendActions.h index 2ff8d0a5b60a..2b5f88ccee9d 100644 --- a/include/clang/Rewrite/FrontendActions.h +++ b/include/clang/Rewrite/FrontendActions.h @@ -16,7 +16,7 @@ namespace clang { class FixItRewriter; -class FixItPathRewriter; +class FixItOptions; //===----------------------------------------------------------------------===// // AST Consumer Actions @@ -31,7 +31,7 @@ protected: class FixItAction : public ASTFrontendAction { protected: llvm::OwningPtr<FixItRewriter> Rewriter; - llvm::OwningPtr<FixItPathRewriter> PathRewriter; + llvm::OwningPtr<FixItOptions> FixItOpts; virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile); diff --git a/include/clang/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h new file mode 100644 index 000000000000..0a6656e97e1b --- /dev/null +++ b/include/clang/Sema/AnalysisBasedWarnings.h @@ -0,0 +1,64 @@ +//=- AnalysisBasedWarnings.h - Sema warnings based on libAnalysis -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines AnalysisBasedWarnings, a worker object used by Sema +// that issues warnings based on dataflow-analysis. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_ANALYSIS_WARNINGS_H +#define LLVM_CLANG_SEMA_ANALYSIS_WARNINGS_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" + +namespace clang { + +class BlockExpr; +class Decl; +class FunctionDecl; +class ObjCMethodDecl; +class QualType; +class Sema; + +namespace sema { + +class AnalysisBasedWarnings { +public: + class Policy { + friend class AnalysisBasedWarnings; + // The warnings to run. + unsigned enableCheckFallThrough : 1; + unsigned enableCheckUnreachable : 1; + public: + Policy(); + void disableCheckFallThrough() { enableCheckFallThrough = 0; } + }; + +private: + Sema &S; + Policy DefaultPolicy; + + enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 }; + llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD; + + void IssueWarnings(Policy P, const Decl *D, QualType BlockTy); + +public: + AnalysisBasedWarnings(Sema &s); + + Policy getDefaultPolicy() { return DefaultPolicy; } + + void IssueWarnings(Policy P, const BlockExpr *E); + void IssueWarnings(Policy P, const FunctionDecl *D); + void IssueWarnings(Policy P, const ObjCMethodDecl *D); +}; + +}} // end namespace clang::sema + +#endif diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Sema/AttributeList.h index b60a94025e09..53316477e1c5 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -1,4 +1,4 @@ -//===--- AttributeList.h ----------------------------------------*- C++ -*-===// +//===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,20 +7,21 @@ // //===----------------------------------------------------------------------===// // -// This file defines the AttributeList class interface. +// This file defines the AttributeList class, which is used to collect +// parsed attributes. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ATTRLIST_H -#define LLVM_CLANG_ATTRLIST_H +#ifndef LLVM_CLANG_SEMA_ATTRLIST_H +#define LLVM_CLANG_SEMA_ATTRLIST_H -#include "clang/Parse/Ownership.h" +#include "clang/Sema/Ownership.h" #include "clang/Basic/SourceLocation.h" #include <cassert> namespace clang { class IdentifierInfo; - class Action; + class Expr; /// AttributeList - Represents GCC's __attribute__ declaration. There are /// 4 forms of this construct...they are: @@ -37,7 +38,7 @@ class AttributeList { SourceLocation ScopeLoc; IdentifierInfo *ParmName; SourceLocation ParmLoc; - ActionBase::ExprTy **Args; + Expr **Args; unsigned NumArgs; AttributeList *Next; bool DeclspecAttribute, CXX0XAttribute; @@ -48,7 +49,7 @@ public: AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, IdentifierInfo *ParmName, SourceLocation ParmLoc, - ActionBase::ExprTy **args, unsigned numargs, + Expr **args, unsigned numargs, AttributeList *Next, bool declspec = false, bool cxx0x = false); ~AttributeList(); @@ -97,7 +98,11 @@ public: AT_ns_returns_retained, // Clang-specific. AT_objc_gc, AT_overloadable, // Clang-specific. + AT_ownership_holds, // Clang-specific. + AT_ownership_returns, // Clang-specific. + AT_ownership_takes, // Clang-specific. AT_packed, + AT_pascal, AT_pure, AT_regparm, AT_section, @@ -108,6 +113,7 @@ public: AT_unavailable, AT_unused, AT_used, + AT_vecreturn, // PS3 PPU-specific. AT_vector_size, AT_visibility, AT_warn_unused_result, @@ -145,16 +151,16 @@ public: unsigned getNumArgs() const { return NumArgs; } /// getArg - Return the specified argument. - ActionBase::ExprTy *getArg(unsigned Arg) const { + Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); return Args[Arg]; } class arg_iterator { - ActionBase::ExprTy** X; + Expr** X; unsigned Idx; public: - arg_iterator(ActionBase::ExprTy** x, unsigned idx) : X(x), Idx(idx) {} + arg_iterator(Expr** x, unsigned idx) : X(x), Idx(idx) {} arg_iterator& operator++() { ++Idx; @@ -171,7 +177,7 @@ public: return !operator==(I); } - ActionBase::ExprTy* operator*() const { + Expr* operator*() const { return X[Idx]; } diff --git a/include/clang/Sema/CXXFieldCollector.h b/include/clang/Sema/CXXFieldCollector.h new file mode 100644 index 000000000000..63c6ee3f74ba --- /dev/null +++ b/include/clang/Sema/CXXFieldCollector.h @@ -0,0 +1,79 @@ +//===- CXXFieldCollector.h - Utility class for C++ class semantic analysis ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides CXXFieldCollector that is used during parsing & semantic +// analysis of C++ classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H +#define LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H + +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class FieldDecl; + +/// CXXFieldCollector - Used to keep track of CXXFieldDecls during parsing of +/// C++ classes. +class CXXFieldCollector { + /// Fields - Contains all FieldDecls collected during parsing of a C++ + /// class. When a nested class is entered, its fields are appended to the + /// fields of its parent class, when it is exited its fields are removed. + llvm::SmallVector<FieldDecl*, 32> Fields; + + /// FieldCount - Each entry represents the number of fields collected during + /// the parsing of a C++ class. When a nested class is entered, a new field + /// count is pushed, when it is exited, the field count is popped. + llvm::SmallVector<size_t, 4> FieldCount; + + // Example: + // + // class C { + // int x,y; + // class NC { + // int q; + // // At this point, Fields contains [x,y,q] decls and FieldCount contains + // // [2,1]. + // }; + // int z; + // // At this point, Fields contains [x,y,z] decls and FieldCount contains + // // [3]. + // }; + +public: + /// StartClass - Called by Sema::ActOnStartCXXClassDef. + void StartClass() { FieldCount.push_back(0); } + + /// Add - Called by Sema::ActOnCXXMemberDeclarator. + void Add(FieldDecl *D) { + Fields.push_back(D); + ++FieldCount.back(); + } + + /// getCurNumField - The number of fields added to the currently parsed class. + size_t getCurNumFields() const { + assert(!FieldCount.empty() && "no currently-parsed class"); + return FieldCount.back(); + } + + /// getCurFields - Pointer to array of fields added to the currently parsed + /// class. + FieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); } + + /// FinishClass - Called by Sema::ActOnFinishCXXClassDef. + void FinishClass() { + Fields.resize(Fields.size() - getCurNumFields()); + FieldCount.pop_back(); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 1d9d25073177..6c1ecbf2cc29 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -13,20 +13,30 @@ #ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H #define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H +#include "clang/AST/Type.h" +#include "clang/AST/CanonicalType.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "clang-c/Index.h" #include <memory> #include <string> namespace llvm { -class raw_ostream; + class raw_ostream; } namespace clang { +class Decl; + /// \brief Default priority values for code-completion results based /// on their kind. enum { + /// \brief Priority for the next initialization in a constructor initializer + /// list. + CCP_NextInitializer = 7, + /// \brief Priority for a send-to-super completion. + CCP_SuperCompletion = 8, /// \brief Priority for a declaration that is in the local scope. CCP_LocalDeclaration = 8, /// \brief Priority for a member declaration found from the current @@ -37,12 +47,12 @@ enum { CCP_Keyword = 30, /// \brief Priority for a code pattern. CCP_CodePattern = 30, - /// \brief Priority for a type. - CCP_Type = 40, /// \brief Priority for a non-type declaration. CCP_Declaration = 50, /// \brief Priority for a constant value (e.g., enumerator). CCP_Constant = 60, + /// \brief Priority for a type. + CCP_Type = 65, /// \brief Priority for a preprocessor macro. CCP_Macro = 70, /// \brief Priority for a nested-name-specifier. @@ -52,11 +62,23 @@ enum { CCP_Unlikely = 80 }; -/// \brief Priority value deltas that are applied to code-completion results +/// \brief Priority value deltas that are added to code-completion results /// based on the context of the result. enum { /// \brief The result is in a base class. - CCD_InBaseClass = 2 + CCD_InBaseClass = 2, + /// \brief The result is a type match against void. + /// + /// Since everything converts to "void", we don't give as drastic an + /// adjustment for matching void. + CCD_VoidMatch = -5, + /// \brief The result is a C++ non-static member function whose qualifiers + /// exactly match the object type on which the member function can be called. + CCD_ObjectQualifierMatch = -1, + /// \brief The selector of the given message exactly matches the selector + /// of the current method, which might imply that some kind of delegation + /// is occurring. + CCD_SelectorMatch = -3 }; /// \brief Priority value factors by which we will divide or multiply the @@ -70,6 +92,41 @@ enum { /// Objective-C object pointer types). CCF_SimilarTypeMatch = 2 }; + +/// \brief A simplified classification of types used when determining +/// "similar" types for code completion. +enum SimplifiedTypeClass { + STC_Arithmetic, + STC_Array, + STC_Block, + STC_Function, + STC_ObjectiveC, + STC_Other, + STC_Pointer, + STC_Record, + STC_Void +}; + +/// \brief Determine the simplified type class of the given canonical type. +SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T); + +/// \brief Determine the type that this declaration will have if it is used +/// as a type or in an expression. +QualType getDeclUsageType(ASTContext &C, NamedDecl *ND); + +/// \brief Determine the priority to be given to a macro code completion result +/// with the given name. +/// +/// \param MacroName The name of the macro. +/// +/// \param PreferredTypeIsPointer Whether the preferred type for the context +/// of this macro is a pointer type. +unsigned getMacroUsagePriority(llvm::StringRef MacroName, + bool PreferredTypeIsPointer = false); + +/// \brief Determine the libclang cursor kind associated with the given +/// declaration. +CXCursorKind getCursorKindForDecl(Decl *D); class FunctionDecl; class FunctionType; @@ -79,6 +136,121 @@ class NamedDecl; class NestedNameSpecifier; class Sema; +/// \brief The context in which code completion occurred, so that the +/// code-completion consumer can process the results accordingly. +class CodeCompletionContext { +public: + enum Kind { + /// \brief An unspecified code-completion context. + CCC_Other, + /// \brief Code completion occurred within a "top-level" completion context, + /// e.g., at namespace or global scope. + CCC_TopLevel, + /// \brief Code completion occurred within an Objective-C interface, + /// protocol, or category interface. + CCC_ObjCInterface, + /// \brief Code completion occurred within an Objective-C implementation + /// or category implementation. + CCC_ObjCImplementation, + /// \brief Code completion occurred within the instance variable list of + /// an Objective-C interface, implementation, or category implementation. + CCC_ObjCIvarList, + /// \brief Code completion occurred within a class, struct, or union. + CCC_ClassStructUnion, + /// \brief Code completion occurred where a statement (or declaration) is + /// expected in a function, method, or block. + CCC_Statement, + /// \brief Code completion occurred where an expression is expected. + CCC_Expression, + /// \brief Code completion occurred where an Objective-C message receiver + /// is expected. + CCC_ObjCMessageReceiver, + /// \brief Code completion occurred on the right-hand side of a member + /// access expression. + /// + /// The results of this completion are the members of the type being + /// accessed. The type itself is available via + /// \c CodeCompletionContext::getType(). + CCC_MemberAccess, + /// \brief Code completion occurred after the "enum" keyword, to indicate + /// an enumeration name. + CCC_EnumTag, + /// \brief Code completion occurred after the "union" keyword, to indicate + /// a union name. + CCC_UnionTag, + /// \brief Code completion occurred after the "struct" or "class" keyword, + /// to indicate a struct or class name. + CCC_ClassOrStructTag, + /// \brief Code completion occurred where a protocol name is expected. + CCC_ObjCProtocolName, + /// \brief Code completion occurred where a namespace or namespace alias + /// is expected. + CCC_Namespace, + /// \brief Code completion occurred where a type name is expected. + CCC_Type, + /// \brief Code completion occurred where a new name is expected. + CCC_Name, + /// \brief Code completion occurred where a new name is expected and a + /// qualified name is permissible. + CCC_PotentiallyQualifiedName, + /// \brief Code completion occurred where an macro is being defined. + CCC_MacroName, + /// \brief Code completion occurred where a macro name is expected + /// (without any arguments, in the case of a function-like macro). + CCC_MacroNameUse, + /// \brief Code completion occurred within a preprocessor expression. + CCC_PreprocessorExpression, + /// \brief Code completion occurred where a preprocessor directive is + /// expected. + CCC_PreprocessorDirective, + /// \brief Code completion occurred in a context where natural language is + /// expected, e.g., a comment or string literal. + /// + /// This context usually implies that no completions should be added, + /// unless they come from an appropriate natural-language dictionary. + CCC_NaturalLanguage, + /// \brief Code completion for a selector, as in an @selector expression. + CCC_SelectorName, + /// \brief Code completion within a type-qualifier list. + CCC_TypeQualifiers + }; + +private: + enum Kind Kind; + + /// \brief The type that would prefer to see at this point (e.g., the type + /// of an initializer or function parameter). + QualType PreferredType; + + /// \brief The type of the base object in a member access expression. + QualType BaseType; + +public: + /// \brief Construct a new code-completion context of the given kind. + CodeCompletionContext(enum Kind Kind) : Kind(Kind) { } + + /// \brief Construct a new code-completion context of the given kind. + CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind) { + if (Kind == CCC_MemberAccess) + BaseType = T; + else + PreferredType = T; + } + + /// \brief Retrieve the kind of code-completion context. + enum Kind getKind() const { return Kind; } + + /// \brief Retrieve the type that this expression would prefer to have, e.g., + /// if the expression is a variable initializer or a function argument, the + /// type of the corresponding variable or function parameter. + QualType getPreferredType() const { return PreferredType; } + + /// \brief Retrieve the type of the base object in a member-access + /// expression. + QualType getBaseType() const { return BaseType; } +}; + + /// \brief A "string" used to describe how code completion can /// be performed for an entity. /// @@ -274,7 +446,10 @@ public: std::string getAsString() const; /// \brief Clone this code-completion string. - CodeCompletionString *Clone() const; + /// + /// \param Result If non-NULL, points to an empty code-completion + /// result that will be given a cloned copy of + CodeCompletionString *Clone(CodeCompletionString *Result = 0) const; /// \brief Serialize this code-completion string to the given stream. void Serialize(llvm::raw_ostream &OS) const; @@ -284,140 +459,193 @@ public: /// \returns true if successful, false otherwise. bool Deserialize(const char *&Str, const char *StrEnd); }; - -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const CodeCompletionString &CCS); -/// \brief Abstract interface for a consumer of code-completion -/// information. -class CodeCompleteConsumer { -protected: - /// \brief Whether to include macros in the code-completion results. - bool IncludeMacros; - - /// \brief Whether to include code patterns (such as for loops) within - /// the completion results. - bool IncludeCodePatterns; - - /// \brief Whether the output format for the code-completion consumer is - /// binary. - bool OutputIsBinary; - +/// \brief Captures a result of code completion. +class CodeCompletionResult { public: - /// \brief Captures a result of code completion. - struct Result { - /// \brief Describes the kind of result generated. - enum ResultKind { - RK_Declaration = 0, //< Refers to a declaration - RK_Keyword, //< Refers to a keyword or symbol. - RK_Macro, //< Refers to a macro - RK_Pattern //< Refers to a precomputed pattern. - }; + /// \brief Describes the kind of result generated. + enum ResultKind { + RK_Declaration = 0, //< Refers to a declaration + RK_Keyword, //< Refers to a keyword or symbol. + RK_Macro, //< Refers to a macro + RK_Pattern //< Refers to a precomputed pattern. + }; - /// \brief The kind of result stored here. - ResultKind Kind; + /// \brief The kind of result stored here. + ResultKind Kind; - union { - /// \brief When Kind == RK_Declaration, the declaration we are referring - /// to. - NamedDecl *Declaration; + union { + /// \brief When Kind == RK_Declaration, the declaration we are referring + /// to. + NamedDecl *Declaration; - /// \brief When Kind == RK_Keyword, the string representing the keyword - /// or symbol's spelling. - const char *Keyword; + /// \brief When Kind == RK_Keyword, the string representing the keyword + /// or symbol's spelling. + const char *Keyword; - /// \brief When Kind == RK_Pattern, the code-completion string that - /// describes the completion text to insert. - CodeCompletionString *Pattern; + /// \brief When Kind == RK_Pattern, the code-completion string that + /// describes the completion text to insert. + CodeCompletionString *Pattern; - /// \brief When Kind == RK_Macro, the identifier that refers to a macro. - IdentifierInfo *Macro; - }; + /// \brief When Kind == RK_Macro, the identifier that refers to a macro. + IdentifierInfo *Macro; + }; - /// \brief The priority of this particular code-completion result. - unsigned Priority; + /// \brief The priority of this particular code-completion result. + unsigned Priority; - /// \brief Specifies which parameter (of a function, Objective-C method, - /// macro, etc.) we should start with when formatting the result. - unsigned StartParameter; + /// \brief The cursor kind that describes this result. + CXCursorKind CursorKind; + + /// \brief The availability of this result. + CXAvailabilityKind Availability; - /// \brief Whether this result is hidden by another name. - bool Hidden : 1; + /// \brief Specifies which parameter (of a function, Objective-C method, + /// macro, etc.) we should start with when formatting the result. + unsigned StartParameter; - /// \brief Whether this result was found via lookup into a base class. - bool QualifierIsInformative : 1; + /// \brief Whether this result is hidden by another name. + bool Hidden : 1; - /// \brief Whether this declaration is the beginning of a - /// nested-name-specifier and, therefore, should be followed by '::'. - bool StartsNestedNameSpecifier : 1; + /// \brief Whether this result was found via lookup into a base class. + bool QualifierIsInformative : 1; + + /// \brief Whether this declaration is the beginning of a + /// nested-name-specifier and, therefore, should be followed by '::'. + bool StartsNestedNameSpecifier : 1; - /// \brief Whether all parameters (of a function, Objective-C - /// method, etc.) should be considered "informative". - bool AllParametersAreInformative : 1; + /// \brief Whether all parameters (of a function, Objective-C + /// method, etc.) should be considered "informative". + bool AllParametersAreInformative : 1; - /// \brief Whether we're completing a declaration of the given entity, - /// rather than a use of that entity. - bool DeclaringEntity : 1; + /// \brief Whether we're completing a declaration of the given entity, + /// rather than a use of that entity. + bool DeclaringEntity : 1; - /// \brief If the result should have a nested-name-specifier, this is it. - /// When \c QualifierIsInformative, the nested-name-specifier is - /// informative rather than required. - NestedNameSpecifier *Qualifier; + /// \brief If the result should have a nested-name-specifier, this is it. + /// When \c QualifierIsInformative, the nested-name-specifier is + /// informative rather than required. + NestedNameSpecifier *Qualifier; - /// \brief Build a result that refers to a declaration. - Result(NamedDecl *Declaration, - NestedNameSpecifier *Qualifier = 0, - bool QualifierIsInformative = false) - : Kind(RK_Declaration), Declaration(Declaration), - Priority(getPriorityFromDecl(Declaration)), StartParameter(0), - Hidden(false), QualifierIsInformative(QualifierIsInformative), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(Qualifier) { - } + /// \brief Build a result that refers to a declaration. + CodeCompletionResult(NamedDecl *Declaration, + NestedNameSpecifier *Qualifier = 0, + bool QualifierIsInformative = false) + : Kind(RK_Declaration), Declaration(Declaration), + Priority(getPriorityFromDecl(Declaration)), + Availability(CXAvailability_Available), StartParameter(0), + Hidden(false), QualifierIsInformative(QualifierIsInformative), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + DeclaringEntity(false), Qualifier(Qualifier) { + computeCursorKindAndAvailability(); + } - /// \brief Build a result that refers to a keyword or symbol. - Result(const char *Keyword, unsigned Priority = CCP_Keyword) - : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority), - StartParameter(0), Hidden(false), QualifierIsInformative(0), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(0) { } + /// \brief Build a result that refers to a keyword or symbol. + CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword) + : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority), + Availability(CXAvailability_Available), + StartParameter(0), Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + DeclaringEntity(false), Qualifier(0) { + computeCursorKindAndAvailability(); + } - /// \brief Build a result that refers to a macro. - Result(IdentifierInfo *Macro, unsigned Priority = CCP_Macro) - : Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0), - Hidden(false), QualifierIsInformative(0), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(0) { } - - /// \brief Build a result that refers to a pattern. - Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern) - : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority), - StartParameter(0), Hidden(false), QualifierIsInformative(0), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(0) { } + /// \brief Build a result that refers to a macro. + CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro) + : Kind(RK_Macro), Macro(Macro), Priority(Priority), + Availability(CXAvailability_Available), StartParameter(0), + Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + DeclaringEntity(false), Qualifier(0) { + computeCursorKindAndAvailability(); + } + + /// \brief Build a result that refers to a pattern. + CodeCompletionResult(CodeCompletionString *Pattern, + unsigned Priority = CCP_CodePattern, + CXCursorKind CursorKind = CXCursor_NotImplemented, + CXAvailabilityKind Availability = CXAvailability_Available) + : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority), + CursorKind(CursorKind), Availability(Availability), StartParameter(0), + Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + DeclaringEntity(false), Qualifier(0) + { + } - /// \brief Retrieve the declaration stored in this result. - NamedDecl *getDeclaration() const { - assert(Kind == RK_Declaration && "Not a declaration result"); - return Declaration; - } + /// \brief Retrieve the declaration stored in this result. + NamedDecl *getDeclaration() const { + assert(Kind == RK_Declaration && "Not a declaration result"); + return Declaration; + } - /// \brief Retrieve the keyword stored in this result. - const char *getKeyword() const { - assert(Kind == RK_Keyword && "Not a keyword result"); - return Keyword; - } + /// \brief Retrieve the keyword stored in this result. + const char *getKeyword() const { + assert(Kind == RK_Keyword && "Not a keyword result"); + return Keyword; + } - /// \brief Create a new code-completion string that describes how to insert - /// this result into a program. - CodeCompletionString *CreateCodeCompletionString(Sema &S); + /// \brief Create a new code-completion string that describes how to insert + /// this result into a program. + /// + /// \param S The semantic analysis that created the result. + /// + /// \param Result If non-NULL, the already-allocated, empty + /// code-completion string that will be populated with the + /// appropriate code completion string for this result. + CodeCompletionString *CreateCodeCompletionString(Sema &S, + CodeCompletionString *Result = 0); - void Destroy(); + void Destroy(); - /// brief Determine a base priority for the given declaration. - static unsigned getPriorityFromDecl(NamedDecl *ND); - }; + /// brief Determine a base priority for the given declaration. + static unsigned getPriorityFromDecl(NamedDecl *ND); +private: + void computeCursorKindAndAvailability(); +}; + +bool operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y); + +inline bool operator>(const CodeCompletionResult &X, + const CodeCompletionResult &Y) { + return Y < X; +} + +inline bool operator<=(const CodeCompletionResult &X, + const CodeCompletionResult &Y) { + return !(Y < X); +} + +inline bool operator>=(const CodeCompletionResult &X, + const CodeCompletionResult &Y) { + return !(X < Y); +} + + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const CodeCompletionString &CCS); + +/// \brief Abstract interface for a consumer of code-completion +/// information. +class CodeCompleteConsumer { +protected: + /// \brief Whether to include macros in the code-completion results. + bool IncludeMacros; + + /// \brief Whether to include code patterns (such as for loops) within + /// the completion results. + bool IncludeCodePatterns; + + /// \brief Whether to include global (top-level) declarations and names in + /// the completion results. + bool IncludeGlobals; + + /// \brief Whether the output format for the code-completion consumer is + /// binary. + bool OutputIsBinary; + +public: class OverloadCandidate { public: /// \brief Describes the type of overload candidate. @@ -482,12 +710,13 @@ public: Sema &S) const; }; - CodeCompleteConsumer() : IncludeMacros(false), OutputIsBinary(false) { } + CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false), + IncludeGlobals(true), OutputIsBinary(false) { } CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, - bool OutputIsBinary) + bool IncludeGlobals, bool OutputIsBinary) : IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns), - OutputIsBinary(OutputIsBinary) { } + IncludeGlobals(IncludeGlobals), OutputIsBinary(OutputIsBinary) { } /// \brief Whether the code-completion consumer wants to see macros. bool includeMacros() const { return IncludeMacros; } @@ -495,6 +724,9 @@ public: /// \brief Whether the code-completion consumer wants to see code patterns. bool includeCodePatterns() const { return IncludeCodePatterns; } + /// \brief Whether to include global (top-level) declaration results. + bool includeGlobals() const { return IncludeGlobals; } + /// \brief Determine whether the output of this consumer is binary. bool isOutputBinary() const { return OutputIsBinary; } @@ -504,7 +736,9 @@ public: /// \name Code-completion callbacks //@{ /// \brief Process the finalized code-completion results. - virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, + virtual void ProcessCodeCompleteResults(Sema &S, + CodeCompletionContext Context, + CodeCompletionResult *Results, unsigned NumResults) { } /// \param S the semantic-analyzer object for which code-completion is being @@ -520,7 +754,7 @@ public: unsigned NumCandidates) { } //@} }; - + /// \brief A simple code-completion consumer that prints the results it /// receives in a simple format. class PrintingCodeCompleteConsumer : public CodeCompleteConsumer { @@ -531,11 +765,15 @@ public: /// \brief Create a new printing code-completion consumer that prints its /// results to the given raw output stream. PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, + bool IncludeGlobals, llvm::raw_ostream &OS) - : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, false), OS(OS) {} + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals, + false), OS(OS) {} /// \brief Prints the finalized code-completion results. - virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, + virtual void ProcessCodeCompleteResults(Sema &S, + CodeCompletionContext Context, + CodeCompletionResult *Results, unsigned NumResults); virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, @@ -554,18 +792,21 @@ public: /// results to the given raw output stream in a format readable to the CIndex /// library. CIndexCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, - llvm::raw_ostream &OS) - : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, true), OS(OS) {} + bool IncludeGlobals, llvm::raw_ostream &OS) + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals, + true), OS(OS) {} /// \brief Prints the finalized code-completion results. - virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, + virtual void ProcessCodeCompleteResults(Sema &S, + CodeCompletionContext Context, + CodeCompletionResult *Results, unsigned NumResults); virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, OverloadCandidate *Candidates, unsigned NumCandidates); }; - + } // end namespace clang #endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 0e6dbecb36d6..0893ae7e4958 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1,4 +1,4 @@ -//===--- SemaDeclSpec.h - Declaration Specifier Semantic Analys -*- C++ -*-===// +//===--- DeclSpec.h - Parsed declaration specifiers -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,21 @@ // //===----------------------------------------------------------------------===// // -// This file defines interfaces used for Declaration Specifiers and Declarators. +// This file defines the classes used to store parsed information about +// declaration-specifiers and declarators. +// +// static const int volatile x, *y, *(*(*z)[10])(const void *x); +// ------------------------- - -- --------------------------- +// declaration-specifiers \ | / +// declarators // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PARSE_DECLSPEC_H -#define LLVM_CLANG_PARSE_DECLSPEC_H +#ifndef LLVM_CLANG_SEMA_DECLSPEC_H +#define LLVM_CLANG_SEMA_DECLSPEC_H -#include "clang/Parse/AttributeList.h" +#include "clang/Sema/AttributeList.h" +#include "clang/Sema/Ownership.h" #include "clang/Lex/Token.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" @@ -24,6 +31,7 @@ namespace clang { class LangOptions; class Diagnostic; class IdentifierInfo; + class NestedNameSpecifier; class Preprocessor; class Declarator; struct TemplateIdAnnotation; @@ -41,7 +49,7 @@ namespace clang { /// The actual scope is described by getScopeRep(). class CXXScopeSpec { SourceRange Range; - void *ScopeRep; + NestedNameSpecifier *ScopeRep; public: CXXScopeSpec() : Range(), ScopeRep() { } @@ -53,8 +61,8 @@ public: SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } - ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; } - void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; } + NestedNameSpecifier *getScopeRep() const { return ScopeRep; } + void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; } /// No scope specifier. bool isEmpty() const { return !Range.isValid(); } @@ -162,6 +170,7 @@ private: // storage-class-specifier /*SCS*/unsigned StorageClassSpec : 3; bool SCS_thread_specified : 1; + bool SCS_extern_in_linkage_spec : 1; // type-specifier /*TSW*/unsigned TypeSpecWidth : 2; @@ -189,10 +198,11 @@ private: /*SCS*/unsigned StorageClassSpecAsWritten : 3; - /// TypeRep - This contains action-specific information about a specific TST. - /// For example, for a typedef or struct, it might contain the declaration for - /// these. - void *TypeRep; + union { + UnionParsedType TypeRep; + Decl *DeclRep; + Expr *ExprRep; + }; // attributes. AttributeList *AttrList; @@ -203,7 +213,7 @@ private: // List of protocol qualifiers for objective-c classes. Used for // protocol-qualified interfaces "NString<foo>" and protocol-qualified id // "id<foo>". - const ActionBase::DeclPtrTy *ProtocolQualifiers; + Decl * const *ProtocolQualifiers; unsigned NumProtocolQualifiers; SourceLocation ProtocolLAngleLoc; SourceLocation *ProtocolLocs; @@ -221,8 +231,17 @@ private: WrittenBuiltinSpecs writtenBS; void SaveWrittenBuiltinSpecs(); - void SaveStorageSpecifierAsWritten() { - StorageClassSpecAsWritten = StorageClassSpec; + void SaveStorageSpecifierAsWritten(); + + static bool isTypeRep(TST T) { + return (T == TST_typename || T == TST_typeofType); + } + static bool isExprRep(TST T) { + return (T == TST_typeofExpr || T == TST_decltype); + } + static bool isDeclRep(TST T) { + return (T == TST_enum || T == TST_struct || + T == TST_union || T == TST_class); } DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT @@ -232,6 +251,7 @@ public: DeclSpec() : StorageClassSpec(SCS_unspecified), SCS_thread_specified(false), + SCS_extern_in_linkage_spec(false), TypeSpecWidth(TSW_unspecified), TypeSpecComplex(TSC_unspecified), TypeSpecSign(TSS_unspecified), @@ -247,7 +267,6 @@ public: Friend_specified(false), Constexpr_specified(false), StorageClassSpecAsWritten(SCS_unspecified), - TypeRep(0), AttrList(0), ProtocolQualifiers(0), NumProtocolQualifiers(0), @@ -262,6 +281,10 @@ public: // storage-class-specifier SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; } bool isThreadSpecified() const { return SCS_thread_specified; } + bool isExternInLinkageSpec() const { return SCS_extern_in_linkage_spec; } + void setExternInLinkageSpec(bool Value) { + SCS_extern_in_linkage_spec = Value; + } SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; } SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; } @@ -269,6 +292,7 @@ public: void ClearStorageClassSpecs() { StorageClassSpec = DeclSpec::SCS_unspecified; SCS_thread_specified = false; + SCS_extern_in_linkage_spec = false; StorageClassSpecLoc = SourceLocation(); SCS_threadLoc = SourceLocation(); } @@ -282,7 +306,18 @@ public: bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; } bool isTypeAltiVecBool() const { return TypeAltiVecBool; } bool isTypeSpecOwned() const { return TypeSpecOwned; } - void *getTypeRep() const { return TypeRep; } + ParsedType getRepAsType() const { + assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type"); + return TypeRep; + } + Decl *getRepAsDecl() const { + assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl"); + return DeclRep; + } + Expr *getRepAsExpr() const { + assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr"); + return ExprRep; + } CXXScopeSpec &getTypeSpecScope() { return TypeScope; } const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; } @@ -379,13 +414,30 @@ public: bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID, void *Rep = 0, bool Owned = false); + unsigned &DiagID); + bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID, ParsedType Rep); + bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID, Decl *Rep, bool Owned); + bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID, Expr *Rep); bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); bool SetTypeSpecError(); - void UpdateTypeRep(void *Rep) { TypeRep = Rep; } + void UpdateDeclRep(Decl *Rep) { + assert(isDeclRep((TST) TypeSpecType)); + DeclRep = Rep; + } + void UpdateTypeRep(ParsedType Rep) { + assert(isTypeRep((TST) TypeSpecType)); + TypeRep = Rep; + } + void UpdateExprRep(Expr *Rep) { + assert(isExprRep((TST) TypeSpecType)); + ExprRep = Rep; + } bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const LangOptions &Lang); @@ -436,7 +488,7 @@ public: return AL; } - typedef const ActionBase::DeclPtrTy *ProtocolQualifierListTy; + typedef Decl * const *ProtocolQualifierListTy; ProtocolQualifierListTy getProtocolQualifiers() const { return ProtocolQualifiers; } @@ -445,7 +497,7 @@ public: return NumProtocolQualifiers; } SourceLocation getProtocolLAngleLoc() const { return ProtocolLAngleLoc; } - void setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos, unsigned NP, + void setProtocolQualifiers(Decl * const *Protos, unsigned NP, SourceLocation *ProtoLocs, SourceLocation LAngleLoc); @@ -577,15 +629,15 @@ public: /// \brief When Kind == IK_ConversionFunctionId, the type that the /// conversion function names. - ActionBase::TypeTy *ConversionFunctionId; + UnionParsedType ConversionFunctionId; /// \brief When Kind == IK_ConstructorName, the class-name of the type /// whose constructor is being referenced. - ActionBase::TypeTy *ConstructorName; + UnionParsedType ConstructorName; /// \brief When Kind == IK_DestructorName, the type referred to by the /// class-name. - ActionBase::TypeTy *DestructorName; + UnionParsedType DestructorName; /// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId, /// the template-id annotation that contains the template name and @@ -662,7 +714,7 @@ public: /// /// \param EndLoc the location of the last token that makes up the type name. void setConversionFunctionId(SourceLocation OperatorLoc, - ActionBase::TypeTy *Ty, + ParsedType Ty, SourceLocation EndLoc) { Kind = IK_ConversionFunctionId; StartLocation = OperatorLoc; @@ -693,7 +745,7 @@ public: /// \param ClassNameLoc the location of the class name. /// /// \param EndLoc the location of the last token that makes up the type name. - void setConstructorName(ActionBase::TypeTy *ClassType, + void setConstructorName(ParsedType ClassType, SourceLocation ClassNameLoc, SourceLocation EndLoc) { Kind = IK_ConstructorName; @@ -716,7 +768,8 @@ public: /// name. /// /// \param ClassType the name of the class referred to by the destructor name. - void setDestructorName(SourceLocation TildeLoc, ActionBase::TypeTy *ClassType, + void setDestructorName(SourceLocation TildeLoc, + ParsedType ClassType, SourceLocation EndLoc) { Kind = IK_DestructorName; StartLocation = TildeLoc; @@ -788,7 +841,7 @@ struct DeclaratorChunk { /// This is the size of the array, or null if [] or [*] was specified. /// Since the parser is multi-purpose, and we don't want to impose a root /// expression class on all clients, NumElts is untyped. - ActionBase::ExprTy *NumElts; + Expr *NumElts; void destroy() {} }; @@ -801,7 +854,7 @@ struct DeclaratorChunk { struct ParamInfo { IdentifierInfo *Ident; SourceLocation IdentLoc; - ActionBase::DeclPtrTy Param; + Decl *Param; /// DefaultArgTokens - When the parameter's default argument /// cannot be parsed immediately (because it occurs within the @@ -812,14 +865,14 @@ struct DeclaratorChunk { ParamInfo() {} ParamInfo(IdentifierInfo *ident, SourceLocation iloc, - ActionBase::DeclPtrTy param, + Decl *param, CachedTokens *DefArgTokens = 0) : Ident(ident), IdentLoc(iloc), Param(param), DefaultArgTokens(DefArgTokens) {} }; struct TypeAndRange { - ActionBase::TypeTy *Ty; + ParsedType Ty; SourceRange Range; }; @@ -999,7 +1052,7 @@ struct DeclaratorChunk { /// getArray - Return a DeclaratorChunk for an array. /// static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic, - bool isStar, void *NumElts, + bool isStar, Expr *NumElts, SourceLocation LBLoc, SourceLocation RBLoc) { DeclaratorChunk I; I.Kind = Array; @@ -1020,7 +1073,7 @@ struct DeclaratorChunk { unsigned TypeQuals, bool hasExceptionSpec, SourceLocation ThrowLoc, bool hasAnyExceptionSpec, - ActionBase::TypeTy **Exceptions, + ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, SourceLocation LPLoc, SourceLocation RPLoc, @@ -1104,7 +1157,7 @@ private: AttributeList *AttrList; /// AsmLabel - The asm label, if specified. - ActionBase::ExprTy *AsmLabel; + Expr *AsmLabel; /// InlineParams - This is a local array used for the first function decl /// chunk to avoid going to the heap for the common case when we have one @@ -1303,8 +1356,8 @@ public: return false; } - void setAsmLabel(ActionBase::ExprTy *E) { AsmLabel = E; } - ActionBase::ExprTy *getAsmLabel() const { return AsmLabel; } + void setAsmLabel(Expr *E) { AsmLabel = E; } + Expr *getAsmLabel() const { return AsmLabel; } void setExtension(bool Val = true) { Extension = Val; } bool getExtension() const { return Extension; } @@ -1322,7 +1375,7 @@ public: /// structure field declarators, which is basically just a bitfield size. struct FieldDeclarator { Declarator D; - ActionBase::ExprTy *BitfieldSize; + Expr *BitfieldSize; explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) { BitfieldSize = 0; } diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h new file mode 100644 index 000000000000..6a9a1bf5b608 --- /dev/null +++ b/include/clang/Sema/DelayedDiagnostic.h @@ -0,0 +1,168 @@ +//===--- DelayedDiagnostic.h - Delayed declarator diagnostics ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DelayedDiagnostic class, which is used to +// record diagnostics that are being conditionally produced during +// declarator parsing. Certain kinds of diagnostics --- notably +// deprecation and access control --- are suppressed based on +// semantic properties of the parsed declaration that aren't known +// until it is fully parsed. +// +// This file also defines AccessedEntity. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H +#define LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H + +#include "clang/AST/DeclCXX.h" + +namespace clang { +namespace sema { + +/// A declaration being accessed, together with information about how +/// it was accessed. +class AccessedEntity { +public: + /// A member declaration found through lookup. The target is the + /// member. + enum MemberNonce { Member }; + + /// A hierarchy (base-to-derived or derived-to-base) conversion. + /// The target is the base class. + enum BaseNonce { Base }; + + bool isMemberAccess() const { return IsMember; } + + AccessedEntity(ASTContext &Context, + MemberNonce _, + CXXRecordDecl *NamingClass, + DeclAccessPair FoundDecl, + QualType BaseObjectType) + : Access(FoundDecl.getAccess()), IsMember(true), + Target(FoundDecl.getDecl()), NamingClass(NamingClass), + BaseObjectType(BaseObjectType), Diag(0, Context.getDiagAllocator()) { + } + + AccessedEntity(ASTContext &Context, + BaseNonce _, + CXXRecordDecl *BaseClass, + CXXRecordDecl *DerivedClass, + AccessSpecifier Access) + : Access(Access), IsMember(false), + Target(BaseClass), + NamingClass(DerivedClass), + Diag(0, Context.getDiagAllocator()) { + } + + bool isQuiet() const { return Diag.getDiagID() == 0; } + + AccessSpecifier getAccess() const { return AccessSpecifier(Access); } + + // These apply to member decls... + NamedDecl *getTargetDecl() const { return Target; } + CXXRecordDecl *getNamingClass() const { return NamingClass; } + + // ...and these apply to hierarchy conversions. + CXXRecordDecl *getBaseClass() const { + assert(!IsMember); return cast<CXXRecordDecl>(Target); + } + CXXRecordDecl *getDerivedClass() const { return NamingClass; } + + /// Retrieves the base object type, important when accessing + /// an instance member. + QualType getBaseObjectType() const { return BaseObjectType; } + + /// Sets a diagnostic to be performed. The diagnostic is given + /// four (additional) arguments: + /// %0 - 0 if the entity was private, 1 if protected + /// %1 - the DeclarationName of the entity + /// %2 - the TypeDecl type of the naming class + /// %3 - the TypeDecl type of the declaring class + void setDiag(const PartialDiagnostic &PDiag) { + assert(isQuiet() && "partial diagnostic already defined"); + Diag = PDiag; + } + PartialDiagnostic &setDiag(unsigned DiagID) { + assert(isQuiet() && "partial diagnostic already defined"); + assert(DiagID && "creating null diagnostic"); + Diag.Reset(DiagID); + return Diag; + } + const PartialDiagnostic &getDiag() const { + return Diag; + } + +private: + unsigned Access : 2; + bool IsMember; + NamedDecl *Target; + CXXRecordDecl *NamingClass; + QualType BaseObjectType; + PartialDiagnostic Diag; +}; + +/// A diagnostic message which has been conditionally emitted pending +/// the complete parsing of the current declaration. +class DelayedDiagnostic { +public: + enum DDKind { Deprecation, Access }; + + unsigned char Kind; // actually a DDKind + bool Triggered; + + SourceLocation Loc; + + union { + /// Deprecation. + struct { NamedDecl *Decl; } DeprecationData; + + /// Access control. + char AccessData[sizeof(AccessedEntity)]; + }; + + void destroy() { + switch (Kind) { + case Access: getAccessData().~AccessedEntity(); break; + case Deprecation: break; + } + } + + static DelayedDiagnostic makeDeprecation(SourceLocation Loc, + NamedDecl *D) { + DelayedDiagnostic DD; + DD.Kind = Deprecation; + DD.Triggered = false; + DD.Loc = Loc; + DD.DeprecationData.Decl = D; + return DD; + } + + static DelayedDiagnostic makeAccess(SourceLocation Loc, + const AccessedEntity &Entity) { + DelayedDiagnostic DD; + DD.Kind = Access; + DD.Triggered = false; + DD.Loc = Loc; + new (&DD.getAccessData()) AccessedEntity(Entity); + return DD; + } + + AccessedEntity &getAccessData() { + return *reinterpret_cast<AccessedEntity*>(AccessData); + } + const AccessedEntity &getAccessData() const { + return *reinterpret_cast<const AccessedEntity*>(AccessData); + } +}; + +} +} + +#endif diff --git a/include/clang/Parse/Designator.h b/include/clang/Sema/Designator.h index 255af5901819..6fe7ab24f0a2 100644 --- a/include/clang/Parse/Designator.h +++ b/include/clang/Sema/Designator.h @@ -7,19 +7,26 @@ // //===----------------------------------------------------------------------===// // -// This file defines interfaces used to represent Designators in the parser and -// is the input to Actions module. +// This file defines interfaces used to represent designators (a la +// C99 designated initializers) during parsing. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PARSE_DESIGNATOR_H -#define LLVM_CLANG_PARSE_DESIGNATOR_H +#ifndef LLVM_CLANG_SEMA_DESIGNATOR_H +#define LLVM_CLANG_SEMA_DESIGNATOR_H -#include "clang/Parse/Action.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/SmallVector.h" namespace clang { -/// Designator - This class is a discriminated union which holds the various +class Expr; +class IdentifierInfo; +class Sema; + +/// Designator - A designator in a C99 designated initializer. +/// +/// This class is a discriminated union which holds the various /// different sorts of designators possible. A Designation is an array of /// these. An example of a designator are things like this: /// [8] .field [47] // C99 designation: 3 designators @@ -41,12 +48,12 @@ private: unsigned NameLoc; }; struct ArrayDesignatorInfo { - ActionBase::ExprTy *Index; + Expr *Index; unsigned LBracketLoc; mutable unsigned RBracketLoc; }; struct ArrayRangeDesignatorInfo { - ActionBase::ExprTy *Start, *End; + Expr *Start, *End; unsigned LBracketLoc, EllipsisLoc; mutable unsigned RBracketLoc; }; @@ -79,16 +86,16 @@ public: return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc); } - ActionBase::ExprTy *getArrayIndex() const { + Expr *getArrayIndex() const { assert(isArrayDesignator() && "Invalid accessor"); return ArrayInfo.Index; } - ActionBase::ExprTy *getArrayRangeStart() const { + Expr *getArrayRangeStart() const { assert(isArrayRangeDesignator() && "Invalid accessor"); return ArrayRangeInfo.Start; } - ActionBase::ExprTy *getArrayRangeEnd() const { + Expr *getArrayRangeEnd() const { assert(isArrayRangeDesignator() && "Invalid accessor"); return ArrayRangeInfo.End; } @@ -126,7 +133,7 @@ public: return D; } - static Designator getArray(ActionBase::ExprTy *Index, + static Designator getArray(Expr *Index, SourceLocation LBracketLoc) { Designator D; D.Kind = ArrayDesignator; @@ -136,8 +143,8 @@ public: return D; } - static Designator getArrayRange(ActionBase::ExprTy *Start, - ActionBase::ExprTy *End, + static Designator getArrayRange(Expr *Start, + Expr *End, SourceLocation LBracketLoc, SourceLocation EllipsisLoc) { Designator D; @@ -159,35 +166,13 @@ public: ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding(); } - /// ClearExprs - Null out any expression references, which prevents them from - /// being 'delete'd later. - void ClearExprs(Action &Actions) { - switch (Kind) { - case FieldDesignator: return; - case ArrayDesignator: - ArrayInfo.Index = 0; - return; - case ArrayRangeDesignator: - ArrayRangeInfo.Start = 0; - ArrayRangeInfo.End = 0; - return; - } - } + /// ClearExprs - Null out any expression references, which prevents + /// them from being 'delete'd later. + void ClearExprs(Sema &Actions) {} - /// FreeExprs - Release any unclaimed memory for the expressions in this - /// designator. - void FreeExprs(Action &Actions) { - switch (Kind) { - case FieldDesignator: return; // nothing to free. - case ArrayDesignator: - Actions.DeleteExpr(getArrayIndex()); - return; - case ArrayRangeDesignator: - Actions.DeleteExpr(getArrayRangeStart()); - Actions.DeleteExpr(getArrayRangeEnd()); - return; - } - } + /// FreeExprs - Release any unclaimed memory for the expressions in + /// this designator. + void FreeExprs(Sema &Actions) {} }; @@ -221,17 +206,11 @@ public: /// ClearExprs - Null out any expression references, which prevents them from /// being 'delete'd later. - void ClearExprs(Action &Actions) { - for (unsigned i = 0, e = Designators.size(); i != e; ++i) - Designators[i].ClearExprs(Actions); - } + void ClearExprs(Sema &Actions) {} /// FreeExprs - Release any unclaimed memory for the expressions in this /// designation. - void FreeExprs(Action &Actions) { - for (unsigned i = 0, e = Designators.size(); i != e; ++i) - Designators[i].FreeExprs(Actions); - } + void FreeExprs(Sema &Actions) {} }; } // end namespace clang diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index ad42a847fa48..7be003390b10 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -13,8 +13,8 @@ #ifndef LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H #define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H -#include "clang/AST/DeclObjC.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/Sema/ObjCMethodList.h" namespace clang { diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h new file mode 100644 index 000000000000..7e9d338293ee --- /dev/null +++ b/include/clang/Sema/IdentifierResolver.h @@ -0,0 +1,198 @@ +//===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the IdentifierResolver class, which is used for lexical +// scoped lookup, based on declaration names. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H +#define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H + +#include "clang/Basic/IdentifierTable.h" + +namespace clang { + +class ASTContext; +class Decl; +class DeclContext; +class DeclarationName; +class NamedDecl; +class Scope; + +/// IdentifierResolver - Keeps track of shadowed decls on enclosing +/// scopes. It manages the shadowing chains of declaration names and +/// implements efficent decl lookup based on a declaration name. +class IdentifierResolver { + + /// IdDeclInfo - Keeps track of information about decls associated + /// to a particular declaration name. IdDeclInfos are lazily + /// constructed and assigned to a declaration name the first time a + /// decl with that declaration name is shadowed in some scope. + class IdDeclInfo { + public: + typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy; + + inline DeclsTy::iterator decls_begin() { return Decls.begin(); } + inline DeclsTy::iterator decls_end() { return Decls.end(); } + + void AddDecl(NamedDecl *D) { Decls.push_back(D); } + + /// RemoveDecl - Remove the decl from the scope chain. + /// The decl must already be part of the decl chain. + void RemoveDecl(NamedDecl *D); + + /// Replaces the Old declaration with the New declaration. If the + /// replacement is successful, returns true. If the old + /// declaration was not found, returns false. + bool ReplaceDecl(NamedDecl *Old, NamedDecl *New); + + private: + DeclsTy Decls; + }; + +public: + + /// iterator - Iterate over the decls of a specified declaration name. + /// It will walk or not the parent declaration contexts depending on how + /// it was instantiated. + class iterator { + public: + typedef NamedDecl * value_type; + typedef NamedDecl * reference; + typedef NamedDecl * pointer; + typedef std::input_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + /// Ptr - There are 3 forms that 'Ptr' represents: + /// 1) A single NamedDecl. (Ptr & 0x1 == 0) + /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the + /// same declaration context. (Ptr & 0x3 == 0x1) + /// 3) A IdDeclInfo::DeclsTy::iterator that traverses the decls of parent + /// declaration contexts too. (Ptr & 0x3 == 0x3) + uintptr_t Ptr; + typedef IdDeclInfo::DeclsTy::iterator BaseIter; + + /// A single NamedDecl. (Ptr & 0x1 == 0) + iterator(NamedDecl *D) { + Ptr = reinterpret_cast<uintptr_t>(D); + assert((Ptr & 0x1) == 0 && "Invalid Ptr!"); + } + /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration + /// contexts depending on 'LookInParentCtx'. + iterator(BaseIter I) { + Ptr = reinterpret_cast<uintptr_t>(I) | 0x1; + } + + bool isIterator() const { return (Ptr & 0x1); } + + BaseIter getIterator() const { + assert(isIterator() && "Ptr not an iterator!"); + return reinterpret_cast<BaseIter>(Ptr & ~0x3); + } + + friend class IdentifierResolver; + + void incrementSlowCase(); + public: + iterator() : Ptr(0) {} + + NamedDecl *operator*() const { + if (isIterator()) + return *getIterator(); + else + return reinterpret_cast<NamedDecl*>(Ptr); + } + + bool operator==(const iterator &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const iterator &RHS) const { + return Ptr != RHS.Ptr; + } + + // Preincrement. + iterator& operator++() { + if (!isIterator()) // common case. + Ptr = 0; + else + incrementSlowCase(); + return *this; + } + + uintptr_t getAsOpaqueValue() const { return Ptr; } + + static iterator getFromOpaqueValue(uintptr_t P) { + iterator Result; + Result.Ptr = P; + return Result; + } + }; + + /// begin - Returns an iterator for decls with the name 'Name'. + static iterator begin(DeclarationName Name); + + /// end - Returns an iterator that has 'finished'. + static iterator end() { + return iterator(); + } + + /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true + /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns + /// true if 'D' belongs to the given declaration context. + bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context, + Scope *S = 0) const; + + /// AddDecl - Link the decl to its shadowed decl chain. + void AddDecl(NamedDecl *D); + + /// RemoveDecl - Unlink the decl from its shadowed decl chain. + /// The decl must already be part of the decl chain. + void RemoveDecl(NamedDecl *D); + + /// Replace the decl Old with the new declaration New on its + /// identifier chain. Returns true if the old declaration was found + /// (and, therefore, replaced). + bool ReplaceDecl(NamedDecl *Old, NamedDecl *New); + + /// \brief Link the declaration into the chain of declarations for + /// the given identifier. + /// + /// This is a lower-level routine used by the AST reader to link a + /// declaration into a specific IdentifierInfo before the + /// declaration actually has a name. + void AddDeclToIdentifierChain(IdentifierInfo *II, NamedDecl *D); + + explicit IdentifierResolver(const LangOptions &LangOpt); + ~IdentifierResolver(); + +private: + const LangOptions &LangOpt; + + class IdDeclInfoMap; + IdDeclInfoMap *IdDeclInfos; + + /// FETokenInfo contains a Decl pointer if lower bit == 0. + static inline bool isDeclPtr(void *Ptr) { + return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0; + } + + /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1. + static inline IdDeclInfo *toIdDeclInfo(void *Ptr) { + assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1 + && "Ptr not a IdDeclInfo* !"); + return reinterpret_cast<IdDeclInfo*>( + reinterpret_cast<uintptr_t>(Ptr) & ~0x1 + ); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h new file mode 100644 index 000000000000..0062b3a29adc --- /dev/null +++ b/include/clang/Sema/Initialization.h @@ -0,0 +1,780 @@ +//===--- SemaInit.h - Semantic Analysis for Initializers --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides supporting data types for initialization of objects. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SEMA_INITIALIZATION_H +#define LLVM_CLANG_SEMA_INITIALIZATION_H + +#include "clang/Sema/Ownership.h" +#include "clang/Sema/Overload.h" +#include "clang/AST/Type.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include <cassert> + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +class CXXBaseSpecifier; +class DeclaratorDecl; +class DeclaratorInfo; +class FieldDecl; +class FunctionDecl; +class ParmVarDecl; +class Sema; +class TypeLoc; +class VarDecl; + +/// \brief Describes an entity that is being initialized. +class InitializedEntity { +public: + /// \brief Specifies the kind of entity being initialized. + enum EntityKind { + /// \brief The entity being initialized is a variable. + EK_Variable, + /// \brief The entity being initialized is a function parameter. + EK_Parameter, + /// \brief The entity being initialized is the result of a function call. + EK_Result, + /// \brief The entity being initialized is an exception object that + /// is being thrown. + EK_Exception, + /// \brief The entity being initialized is a non-static data member + /// subobject. + EK_Member, + /// \brief The entity being initialized is an element of an array. + EK_ArrayElement, + /// \brief The entity being initialized is an object (or array of + /// objects) allocated via new. + EK_New, + /// \brief The entity being initialized is a temporary object. + EK_Temporary, + /// \brief The entity being initialized is a base member subobject. + EK_Base, + /// \brief The entity being initialized is an element of a vector. + /// or vector. + EK_VectorElement, + /// \brief The entity being initialized is a field of block descriptor for + /// the copied-in c++ object. + EK_BlockElement + }; + +private: + /// \brief The kind of entity being initialized. + EntityKind Kind; + + /// \brief If non-NULL, the parent entity in which this + /// initialization occurs. + const InitializedEntity *Parent; + + /// \brief The type of the object or reference being initialized. + QualType Type; + + union { + /// \brief When Kind == EK_Variable, EK_Parameter, or EK_Member, + /// the VarDecl, ParmVarDecl, or FieldDecl, respectively. + DeclaratorDecl *VariableOrMember; + + struct { + /// \brief When Kind == EK_Result, EK_Exception, or EK_New, the + /// location of the 'return', 'throw', or 'new' keyword, + /// respectively. When Kind == EK_Temporary, the location where + /// the temporary is being created. + unsigned Location; + + /// \brief Whether the + bool NRVO; + } LocAndNRVO; + + /// \brief When Kind == EK_Base, the base specifier that provides the + /// base class. The lower bit specifies whether the base is an inherited + /// virtual base. + uintptr_t Base; + + /// \brief When Kind == EK_ArrayElement or EK_VectorElement, the + /// index of the array or vector element being initialized. + unsigned Index; + }; + + InitializedEntity() { } + + /// \brief Create the initialization entity for a variable. + InitializedEntity(VarDecl *Var) + : Kind(EK_Variable), Parent(0), Type(Var->getType()), + VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Var)) { } + + /// \brief Create the initialization entity for a parameter. + InitializedEntity(ParmVarDecl *Parm) + : Kind(EK_Parameter), Parent(0), Type(Parm->getType().getUnqualifiedType()), + VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Parm)) { } + + /// \brief Create the initialization entity for the result of a + /// function, throwing an object, performing an explicit cast, or + /// initializing a parameter for which there is no declaration. + InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type, + bool NRVO = false) + : Kind(Kind), Parent(0), Type(Type) + { + LocAndNRVO.Location = Loc.getRawEncoding(); + LocAndNRVO.NRVO = NRVO; + } + + /// \brief Create the initialization entity for a member subobject. + InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent) + : Kind(EK_Member), Parent(Parent), Type(Member->getType()), + VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Member)) { } + + /// \brief Create the initialization entity for an array element. + InitializedEntity(ASTContext &Context, unsigned Index, + const InitializedEntity &Parent); + +public: + /// \brief Create the initialization entity for a variable. + static InitializedEntity InitializeVariable(VarDecl *Var) { + return InitializedEntity(Var); + } + + /// \brief Create the initialization entity for a parameter. + static InitializedEntity InitializeParameter(ParmVarDecl *Parm) { + return InitializedEntity(Parm); + } + + /// \brief Create the initialization entity for a parameter that is + /// only known by its type. + static InitializedEntity InitializeParameter(QualType Type) { + InitializedEntity Entity; + Entity.Kind = EK_Parameter; + Entity.Type = Type; + Entity.Parent = 0; + Entity.VariableOrMember = 0; + return Entity; + } + + /// \brief Create the initialization entity for the result of a function. + static InitializedEntity InitializeResult(SourceLocation ReturnLoc, + QualType Type, bool NRVO) { + return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO); + } + + static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc, + QualType Type, bool NRVO) { + return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO); + } + + /// \brief Create the initialization entity for an exception object. + static InitializedEntity InitializeException(SourceLocation ThrowLoc, + QualType Type, bool NRVO) { + return InitializedEntity(EK_Exception, ThrowLoc, Type, NRVO); + } + + /// \brief Create the initialization entity for an object allocated via new. + static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) { + return InitializedEntity(EK_New, NewLoc, Type); + } + + /// \brief Create the initialization entity for a temporary. + static InitializedEntity InitializeTemporary(QualType Type) { + return InitializedEntity(EK_Temporary, SourceLocation(), Type); + } + + /// \brief Create the initialization entity for a base class subobject. + static InitializedEntity InitializeBase(ASTContext &Context, + CXXBaseSpecifier *Base, + bool IsInheritedVirtualBase); + + /// \brief Create the initialization entity for a member subobject. + static InitializedEntity InitializeMember(FieldDecl *Member, + const InitializedEntity *Parent = 0) { + return InitializedEntity(Member, Parent); + } + + /// \brief Create the initialization entity for an array element. + static InitializedEntity InitializeElement(ASTContext &Context, + unsigned Index, + const InitializedEntity &Parent) { + return InitializedEntity(Context, Index, Parent); + } + + /// \brief Determine the kind of initialization. + EntityKind getKind() const { return Kind; } + + /// \brief Retrieve the parent of the entity being initialized, when + /// the initialization itself is occuring within the context of a + /// larger initialization. + const InitializedEntity *getParent() const { return Parent; } + + /// \brief Retrieve type being initialized. + QualType getType() const { return Type; } + + /// \brief Retrieve the name of the entity being initialized. + DeclarationName getName() const; + + /// \brief Retrieve the variable, parameter, or field being + /// initialized. + DeclaratorDecl *getDecl() const; + + /// \brief Determine whether this initialization allows the named return + /// value optimization, which also applies to thrown objects. + bool allowsNRVO() const; + + /// \brief Retrieve the base specifier. + CXXBaseSpecifier *getBaseSpecifier() const { + assert(getKind() == EK_Base && "Not a base specifier"); + return reinterpret_cast<CXXBaseSpecifier *>(Base & ~0x1); + } + + /// \brief Return whether the base is an inherited virtual base. + bool isInheritedVirtualBase() const { + assert(getKind() == EK_Base && "Not a base specifier"); + return Base & 0x1; + } + + /// \brief Determine the location of the 'return' keyword when initializing + /// the result of a function call. + SourceLocation getReturnLoc() const { + assert(getKind() == EK_Result && "No 'return' location!"); + return SourceLocation::getFromRawEncoding(LocAndNRVO.Location); + } + + /// \brief Determine the location of the 'throw' keyword when initializing + /// an exception object. + SourceLocation getThrowLoc() const { + assert(getKind() == EK_Exception && "No 'throw' location!"); + return SourceLocation::getFromRawEncoding(LocAndNRVO.Location); + } + + /// \brief If this is already the initializer for an array or vector + /// element, sets the element index. + void setElementIndex(unsigned Index) { + assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement); + this->Index = Index; + } +}; + +/// \brief Describes the kind of initialization being performed, along with +/// location information for tokens related to the initialization (equal sign, +/// parentheses). +class InitializationKind { +public: + /// \brief The kind of initialization being performed. + enum InitKind { + IK_Direct, ///< Direct initialization + IK_Copy, ///< Copy initialization + IK_Default, ///< Default initialization + IK_Value ///< Value initialization + }; + +private: + /// \brief The kind of initialization that we're storing. + enum StoredInitKind { + SIK_Direct = IK_Direct, ///< Direct initialization + SIK_Copy = IK_Copy, ///< Copy initialization + SIK_Default = IK_Default, ///< Default initialization + SIK_Value = IK_Value, ///< Value initialization + SIK_ImplicitValue, ///< Implicit value initialization + SIK_DirectCast, ///< Direct initialization due to a cast + /// \brief Direct initialization due to a C-style or functional cast. + SIK_DirectCStyleOrFunctionalCast + }; + + /// \brief The kind of initialization being performed. + StoredInitKind Kind; + + /// \brief The source locations involved in the initialization. + SourceLocation Locations[3]; + + InitializationKind(StoredInitKind Kind, SourceLocation Loc1, + SourceLocation Loc2, SourceLocation Loc3) + : Kind(Kind) + { + Locations[0] = Loc1; + Locations[1] = Loc2; + Locations[2] = Loc3; + } + +public: + /// \brief Create a direct initialization. + static InitializationKind CreateDirect(SourceLocation InitLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc); + } + + /// \brief Create a direct initialization due to a cast. + static InitializationKind CreateCast(SourceRange TypeRange, + bool IsCStyleCast) { + return InitializationKind(IsCStyleCast? SIK_DirectCStyleOrFunctionalCast + : SIK_DirectCast, + TypeRange.getBegin(), TypeRange.getBegin(), + TypeRange.getEnd()); + } + + /// \brief Create a copy initialization. + static InitializationKind CreateCopy(SourceLocation InitLoc, + SourceLocation EqualLoc) { + return InitializationKind(SIK_Copy, InitLoc, EqualLoc, EqualLoc); + } + + /// \brief Create a default initialization. + static InitializationKind CreateDefault(SourceLocation InitLoc) { + return InitializationKind(SIK_Default, InitLoc, InitLoc, InitLoc); + } + + /// \brief Create a value initialization. + static InitializationKind CreateValue(SourceLocation InitLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc, + bool isImplicit = false) { + return InitializationKind(isImplicit? SIK_ImplicitValue : SIK_Value, + InitLoc, LParenLoc, RParenLoc); + } + + /// \brief Determine the initialization kind. + InitKind getKind() const { + if (Kind > SIK_ImplicitValue) + return IK_Direct; + if (Kind == SIK_ImplicitValue) + return IK_Value; + + return (InitKind)Kind; + } + + /// \brief Determine whether this initialization is an explicit cast. + bool isExplicitCast() const { + return Kind == SIK_DirectCast || Kind == SIK_DirectCStyleOrFunctionalCast; + } + + /// \brief Determine whether this initialization is a C-style cast. + bool isCStyleOrFunctionalCast() const { + return Kind == SIK_DirectCStyleOrFunctionalCast; + } + + /// \brief Determine whether this initialization is an implicit + /// value-initialization, e.g., as occurs during aggregate + /// initialization. + bool isImplicitValueInit() const { return Kind == SIK_ImplicitValue; } + + /// \brief Retrieve the location at which initialization is occurring. + SourceLocation getLocation() const { return Locations[0]; } + + /// \brief Retrieve the source range that covers the initialization. + SourceRange getRange() const { + return SourceRange(Locations[0], Locations[2]); + } + + /// \brief Retrieve the location of the equal sign for copy initialization + /// (if present). + SourceLocation getEqualLoc() const { + assert(Kind == SIK_Copy && "Only copy initialization has an '='"); + return Locations[1]; + } + + bool isCopyInit() const { return Kind == SIK_Copy; } + + /// \brief Retrieve the source range containing the locations of the open + /// and closing parentheses for value and direct initializations. + SourceRange getParenRange() const { + assert((getKind() == IK_Direct || Kind == SIK_Value) && + "Only direct- and value-initialization have parentheses"); + return SourceRange(Locations[1], Locations[2]); + } +}; + +/// \brief Describes the sequence of initializations required to initialize +/// a given object or reference with a set of arguments. +class InitializationSequence { +public: + /// \brief Describes the kind of initialization sequence computed. + /// + /// FIXME: Much of this information is in the initialization steps... why is + /// it duplicated here? + enum SequenceKind { + /// \brief A failed initialization sequence. The failure kind tells what + /// happened. + FailedSequence = 0, + + /// \brief A dependent initialization, which could not be + /// type-checked due to the presence of dependent types or + /// dependently-type expressions. + DependentSequence, + + /// \brief A user-defined conversion sequence. + UserDefinedConversion, + + /// \brief A constructor call. + ConstructorInitialization, + + /// \brief A reference binding. + ReferenceBinding, + + /// \brief List initialization + ListInitialization, + + /// \brief Zero-initialization. + ZeroInitialization, + + /// \brief No initialization required. + NoInitialization, + + /// \brief Standard conversion sequence. + StandardConversion, + + /// \brief C conversion sequence. + CAssignment, + + /// \brief String initialization + StringInit + }; + + /// \brief Describes the kind of a particular step in an initialization + /// sequence. + enum StepKind { + /// \brief Resolve the address of an overloaded function to a specific + /// function declaration. + SK_ResolveAddressOfOverloadedFunction, + /// \brief Perform a derived-to-base cast, producing an rvalue. + SK_CastDerivedToBaseRValue, + /// \brief Perform a derived-to-base cast, producing an xvalue. + SK_CastDerivedToBaseXValue, + /// \brief Perform a derived-to-base cast, producing an lvalue. + SK_CastDerivedToBaseLValue, + /// \brief Reference binding to an lvalue. + SK_BindReference, + /// \brief Reference binding to a temporary. + SK_BindReferenceToTemporary, + /// \brief An optional copy of a temporary object to another + /// temporary object, which is permitted (but not required) by + /// C++98/03 but not C++0x. + SK_ExtraneousCopyToTemporary, + /// \brief Perform a user-defined conversion, either via a conversion + /// function or via a constructor. + SK_UserConversion, + /// \brief Perform a qualification conversion, producing an rvalue. + SK_QualificationConversionRValue, + /// \brief Perform a qualification conversion, producing an xvalue. + SK_QualificationConversionXValue, + /// \brief Perform a qualification conversion, producing an lvalue. + SK_QualificationConversionLValue, + /// \brief Perform an implicit conversion sequence. + SK_ConversionSequence, + /// \brief Perform list-initialization + SK_ListInitialization, + /// \brief Perform initialization via a constructor. + SK_ConstructorInitialization, + /// \brief Zero-initialize the object + SK_ZeroInitialization, + /// \brief C assignment + SK_CAssignment, + /// \brief Initialization by string + SK_StringInit, + /// \brief An initialization that "converts" an Objective-C object + /// (not a point to an object) to another Objective-C object type. + SK_ObjCObjectConversion + }; + + /// \brief A single step in the initialization sequence. + class Step { + public: + /// \brief The kind of conversion or initialization step we are taking. + StepKind Kind; + + // \brief The type that results from this initialization. + QualType Type; + + union { + /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind == + /// SK_UserConversion, the function that the expression should be + /// resolved to or the conversion function to call, respectively. + /// + /// Always a FunctionDecl. + /// For conversion decls, the naming class is the source type. + /// For construct decls, the naming class is the target type. + struct { + FunctionDecl *Function; + DeclAccessPair FoundDecl; + } Function; + + /// \brief When Kind = SK_ConversionSequence, the implicit conversion + /// sequence + ImplicitConversionSequence *ICS; + }; + + void Destroy(); + }; + +private: + /// \brief The kind of initialization sequence computed. + enum SequenceKind SequenceKind; + + /// \brief Steps taken by this initialization. + llvm::SmallVector<Step, 4> Steps; + +public: + /// \brief Describes why initialization failed. + enum FailureKind { + /// \brief Too many initializers provided for a reference. + FK_TooManyInitsForReference, + /// \brief Array must be initialized with an initializer list. + FK_ArrayNeedsInitList, + /// \brief Array must be initialized with an initializer list or a + /// string literal. + FK_ArrayNeedsInitListOrStringLiteral, + /// \brief Cannot resolve the address of an overloaded function. + FK_AddressOfOverloadFailed, + /// \brief Overloading due to reference initialization failed. + FK_ReferenceInitOverloadFailed, + /// \brief Non-const lvalue reference binding to a temporary. + FK_NonConstLValueReferenceBindingToTemporary, + /// \brief Non-const lvalue reference binding to an lvalue of unrelated + /// type. + FK_NonConstLValueReferenceBindingToUnrelated, + /// \brief Rvalue reference binding to an lvalue. + FK_RValueReferenceBindingToLValue, + /// \brief Reference binding drops qualifiers. + FK_ReferenceInitDropsQualifiers, + /// \brief Reference binding failed. + FK_ReferenceInitFailed, + /// \brief Implicit conversion failed. + FK_ConversionFailed, + /// \brief Too many initializers for scalar + FK_TooManyInitsForScalar, + /// \brief Reference initialization from an initializer list + FK_ReferenceBindingToInitList, + /// \brief Initialization of some unused destination type with an + /// initializer list. + FK_InitListBadDestinationType, + /// \brief Overloading for a user-defined conversion failed. + FK_UserConversionOverloadFailed, + /// \brief Overloaded for initialization by constructor failed. + FK_ConstructorOverloadFailed, + /// \brief Default-initialization of a 'const' object. + FK_DefaultInitOfConst, + /// \brief Initialization of an incomplete type. + FK_Incomplete + }; + +private: + /// \brief The reason why initialization failued. + FailureKind Failure; + + /// \brief The failed result of overload resolution. + OverloadingResult FailedOverloadResult; + + /// \brief The candidate set created when initialization failed. + OverloadCandidateSet FailedCandidateSet; + + /// \brief Prints a follow-up note that highlights the location of + /// the initialized entity, if it's remote. + void PrintInitLocationNote(Sema &S, const InitializedEntity &Entity); + +public: + /// \brief Try to perform initialization of the given entity, creating a + /// record of the steps required to perform the initialization. + /// + /// The generated initialization sequence will either contain enough + /// information to diagnose + /// + /// \param S the semantic analysis object. + /// + /// \param Entity the entity being initialized. + /// + /// \param Kind the kind of initialization being performed. + /// + /// \param Args the argument(s) provided for initialization. + /// + /// \param NumArgs the number of arguments provided for initialization. + InitializationSequence(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr **Args, + unsigned NumArgs); + + ~InitializationSequence(); + + /// \brief Perform the actual initialization of the given entity based on + /// the computed initialization sequence. + /// + /// \param S the semantic analysis object. + /// + /// \param Entity the entity being initialized. + /// + /// \param Kind the kind of initialization being performed. + /// + /// \param Args the argument(s) provided for initialization, ownership of + /// which is transfered into the routine. + /// + /// \param ResultType if non-NULL, will be set to the type of the + /// initialized object, which is the type of the declaration in most + /// cases. However, when the initialized object is a variable of + /// incomplete array type and the initializer is an initializer + /// list, this type will be set to the completed array type. + /// + /// \returns an expression that performs the actual object initialization, if + /// the initialization is well-formed. Otherwise, emits diagnostics + /// and returns an invalid expression. + ExprResult Perform(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + MultiExprArg Args, + QualType *ResultType = 0); + + /// \brief Diagnose an potentially-invalid initialization sequence. + /// + /// \returns true if the initialization sequence was ill-formed, + /// false otherwise. + bool Diagnose(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr **Args, unsigned NumArgs); + + /// \brief Determine the kind of initialization sequence computed. + enum SequenceKind getKind() const { return SequenceKind; } + + /// \brief Set the kind of sequence computed. + void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; } + + /// \brief Determine whether the initialization sequence is valid. + operator bool() const { return SequenceKind != FailedSequence; } + + typedef llvm::SmallVector<Step, 4>::const_iterator step_iterator; + step_iterator step_begin() const { return Steps.begin(); } + step_iterator step_end() const { return Steps.end(); } + + /// \brief Determine whether this initialization is a direct reference + /// binding (C++ [dcl.init.ref]). + bool isDirectReferenceBinding() const; + + /// \brief Determine whether this initialization failed due to an ambiguity. + bool isAmbiguous() const; + + /// \brief Determine whether this initialization is direct call to a + /// constructor. + bool isConstructorInitialization() const; + + /// \brief Add a new step in the initialization that resolves the address + /// of an overloaded function to a specific function declaration. + /// + /// \param Function the function to which the overloaded function reference + /// resolves. + void AddAddressOverloadResolutionStep(FunctionDecl *Function, + DeclAccessPair Found); + + /// \brief Add a new step in the initialization that performs a derived-to- + /// base cast. + /// + /// \param BaseType the base type to which we will be casting. + /// + /// \param IsLValue true if the result of this cast will be treated as + /// an lvalue. + void AddDerivedToBaseCastStep(QualType BaseType, + ExprValueKind Category); + + /// \brief Add a new step binding a reference to an object. + /// + /// \param BindingTemporary True if we are binding a reference to a temporary + /// object (thereby extending its lifetime); false if we are binding to an + /// lvalue or an lvalue treated as an rvalue. + /// + /// \param UnnecessaryCopy True if we should check for a copy + /// constructor for a completely unnecessary but + void AddReferenceBindingStep(QualType T, bool BindingTemporary); + + /// \brief Add a new step that makes an extraneous copy of the input + /// to a temporary of the same class type. + /// + /// This extraneous copy only occurs during reference binding in + /// C++98/03, where we are permitted (but not required) to introduce + /// an extra copy. At a bare minimum, we must check that we could + /// call the copy constructor, and produce a diagnostic if the copy + /// constructor is inaccessible or no copy constructor matches. + // + /// \param T The type of the temporary being created. + void AddExtraneousCopyToTemporary(QualType T); + + /// \brief Add a new step invoking a conversion function, which is either + /// a constructor or a conversion function. + void AddUserConversionStep(FunctionDecl *Function, + DeclAccessPair FoundDecl, + QualType T); + + /// \brief Add a new step that performs a qualification conversion to the + /// given type. + void AddQualificationConversionStep(QualType Ty, + ExprValueKind Category); + + /// \brief Add a new step that applies an implicit conversion sequence. + void AddConversionSequenceStep(const ImplicitConversionSequence &ICS, + QualType T); + + /// \brief Add a list-initialiation step + void AddListInitializationStep(QualType T); + + /// \brief Add a constructor-initialization step. + void AddConstructorInitializationStep(CXXConstructorDecl *Constructor, + AccessSpecifier Access, + QualType T); + + /// \brief Add a zero-initialization step. + void AddZeroInitializationStep(QualType T); + + /// \brief Add a C assignment step. + // + // FIXME: It isn't clear whether this should ever be needed; + // ideally, we would handle everything needed in C in the common + // path. However, that isn't the case yet. + void AddCAssignmentStep(QualType T); + + /// \brief Add a string init step. + void AddStringInitStep(QualType T); + + /// \brief Add an Objective-C object conversion step, which is + /// always a no-op. + void AddObjCObjectConversionStep(QualType T); + + /// \brief Note that this initialization sequence failed. + void SetFailed(FailureKind Failure) { + SequenceKind = FailedSequence; + this->Failure = Failure; + } + + /// \brief Note that this initialization sequence failed due to failed + /// overload resolution. + void SetOverloadFailure(FailureKind Failure, OverloadingResult Result); + + /// \brief Retrieve a reference to the candidate set when overload + /// resolution fails. + OverloadCandidateSet &getFailedCandidateSet() { + return FailedCandidateSet; + } + + /// \brief Determine why initialization failed. + FailureKind getFailureKind() const { + assert(getKind() == FailedSequence && "Not an initialization failure!"); + return Failure; + } + + /// \brief Dump a representation of this initialization sequence to + /// the given stream, for debugging purposes. + void dump(llvm::raw_ostream &OS) const; + + /// \brief Dump a representation of this initialization sequence to + /// standard error, for debugging purposes. + void dump() const; +}; + +} // end namespace clang + +#endif // LLVM_CLANG_SEMA_INITIALIZATION_H diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h new file mode 100644 index 000000000000..1c7720abb1e1 --- /dev/null +++ b/include/clang/Sema/Lookup.h @@ -0,0 +1,679 @@ +//===--- Lookup.h - Classes for name lookup ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LookupResult class, which is integral to +// Sema's name-lookup subsystem. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_LOOKUP_H +#define LLVM_CLANG_SEMA_LOOKUP_H + +#include "clang/Sema/Sema.h" +#include "clang/AST/DeclCXX.h" + +namespace clang { + +/// @brief Represents the results of name lookup. +/// +/// An instance of the LookupResult class captures the results of a +/// single name lookup, which can return no result (nothing found), +/// a single declaration, a set of overloaded functions, or an +/// ambiguity. Use the getKind() method to determine which of these +/// results occurred for a given lookup. +class LookupResult { +public: + enum LookupResultKind { + /// @brief No entity found met the criteria. + NotFound = 0, + + /// @brief No entity found met the criteria within the current + /// instantiation,, but there were dependent base classes of the + /// current instantiation that could not be searched. + NotFoundInCurrentInstantiation, + + /// @brief Name lookup found a single declaration that met the + /// criteria. getFoundDecl() will return this declaration. + Found, + + /// @brief Name lookup found a set of overloaded functions that + /// met the criteria. + FoundOverloaded, + + /// @brief Name lookup found an unresolvable value declaration + /// and cannot yet complete. This only happens in C++ dependent + /// contexts with dependent using declarations. + FoundUnresolvedValue, + + /// @brief Name lookup results in an ambiguity; use + /// getAmbiguityKind to figure out what kind of ambiguity + /// we have. + Ambiguous + }; + + enum AmbiguityKind { + /// Name lookup results in an ambiguity because multiple + /// entities that meet the lookup criteria were found in + /// subobjects of different types. For example: + /// @code + /// struct A { void f(int); } + /// struct B { void f(double); } + /// struct C : A, B { }; + /// void test(C c) { + /// c.f(0); // error: A::f and B::f come from subobjects of different + /// // types. overload resolution is not performed. + /// } + /// @endcode + AmbiguousBaseSubobjectTypes, + + /// Name lookup results in an ambiguity because multiple + /// nonstatic entities that meet the lookup criteria were found + /// in different subobjects of the same type. For example: + /// @code + /// struct A { int x; }; + /// struct B : A { }; + /// struct C : A { }; + /// struct D : B, C { }; + /// int test(D d) { + /// return d.x; // error: 'x' is found in two A subobjects (of B and C) + /// } + /// @endcode + AmbiguousBaseSubobjects, + + /// Name lookup results in an ambiguity because multiple definitions + /// of entity that meet the lookup criteria were found in different + /// declaration contexts. + /// @code + /// namespace A { + /// int i; + /// namespace B { int i; } + /// int test() { + /// using namespace B; + /// return i; // error 'i' is found in namespace A and A::B + /// } + /// } + /// @endcode + AmbiguousReference, + + /// Name lookup results in an ambiguity because an entity with a + /// tag name was hidden by an entity with an ordinary name from + /// a different context. + /// @code + /// namespace A { struct Foo {}; } + /// namespace B { void Foo(); } + /// namespace C { + /// using namespace A; + /// using namespace B; + /// } + /// void test() { + /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a + /// // different namespace + /// } + /// @endcode + AmbiguousTagHiding + }; + + /// A little identifier for flagging temporary lookup results. + enum TemporaryToken { + Temporary + }; + + typedef UnresolvedSetImpl::iterator iterator; + + LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo, + Sema::LookupNameKind LookupKind, + Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) + : ResultKind(NotFound), + Paths(0), + NamingClass(0), + SemaRef(SemaRef), + NameInfo(NameInfo), + LookupKind(LookupKind), + IDNS(0), + Redecl(Redecl != Sema::NotForRedeclaration), + HideTags(true), + Diagnose(Redecl == Sema::NotForRedeclaration) + { + configure(); + } + + // TODO: consider whether this constructor should be restricted to take + // as input a const IndentifierInfo* (instead of Name), + // forcing other cases towards the constructor taking a DNInfo. + LookupResult(Sema &SemaRef, DeclarationName Name, + SourceLocation NameLoc, Sema::LookupNameKind LookupKind, + Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) + : ResultKind(NotFound), + Paths(0), + NamingClass(0), + SemaRef(SemaRef), + NameInfo(Name, NameLoc), + LookupKind(LookupKind), + IDNS(0), + Redecl(Redecl != Sema::NotForRedeclaration), + HideTags(true), + Diagnose(Redecl == Sema::NotForRedeclaration) + { + configure(); + } + + /// Creates a temporary lookup result, initializing its core data + /// using the information from another result. Diagnostics are always + /// disabled. + LookupResult(TemporaryToken _, const LookupResult &Other) + : ResultKind(NotFound), + Paths(0), + NamingClass(0), + SemaRef(Other.SemaRef), + NameInfo(Other.NameInfo), + LookupKind(Other.LookupKind), + IDNS(Other.IDNS), + Redecl(Other.Redecl), + HideTags(Other.HideTags), + Diagnose(false) + {} + + ~LookupResult() { + if (Diagnose) diagnose(); + if (Paths) deletePaths(Paths); + } + + /// Gets the name info to look up. + const DeclarationNameInfo &getLookupNameInfo() const { + return NameInfo; + } + + /// \brief Sets the name info to look up. + void setLookupNameInfo(const DeclarationNameInfo &NameInfo) { + this->NameInfo = NameInfo; + } + + /// Gets the name to look up. + DeclarationName getLookupName() const { + return NameInfo.getName(); + } + + /// \brief Sets the name to look up. + void setLookupName(DeclarationName Name) { + NameInfo.setName(Name); + } + + /// Gets the kind of lookup to perform. + Sema::LookupNameKind getLookupKind() const { + return LookupKind; + } + + /// True if this lookup is just looking for an existing declaration. + bool isForRedeclaration() const { + return Redecl; + } + + /// Sets whether tag declarations should be hidden by non-tag + /// declarations during resolution. The default is true. + void setHideTags(bool Hide) { + HideTags = Hide; + } + + bool isAmbiguous() const { + return getResultKind() == Ambiguous; + } + + /// Determines if this names a single result which is not an + /// unresolved value using decl. If so, it is safe to call + /// getFoundDecl(). + bool isSingleResult() const { + return getResultKind() == Found; + } + + /// Determines if the results are overloaded. + bool isOverloadedResult() const { + return getResultKind() == FoundOverloaded; + } + + bool isUnresolvableResult() const { + return getResultKind() == FoundUnresolvedValue; + } + + LookupResultKind getResultKind() const { + sanity(); + return ResultKind; + } + + AmbiguityKind getAmbiguityKind() const { + assert(isAmbiguous()); + return Ambiguity; + } + + const UnresolvedSetImpl &asUnresolvedSet() const { + return Decls; + } + + iterator begin() const { return iterator(Decls.begin()); } + iterator end() const { return iterator(Decls.end()); } + + /// \brief Return true if no decls were found + bool empty() const { return Decls.empty(); } + + /// \brief Return the base paths structure that's associated with + /// these results, or null if none is. + CXXBasePaths *getBasePaths() const { + return Paths; + } + + /// \brief Tests whether the given declaration is acceptable. + bool isAcceptableDecl(NamedDecl *D) const { + return D->isInIdentifierNamespace(IDNS); + } + + /// \brief Returns the identifier namespace mask for this lookup. + unsigned getIdentifierNamespace() const { + return IDNS; + } + + /// \brief Returns whether these results arose from performing a + /// lookup into a class. + bool isClassLookup() const { + return NamingClass != 0; + } + + /// \brief Returns the 'naming class' for this lookup, i.e. the + /// class which was looked into to find these results. + /// + /// C++0x [class.access.base]p5: + /// The access to a member is affected by the class in which the + /// member is named. This naming class is the class in which the + /// member name was looked up and found. [Note: this class can be + /// explicit, e.g., when a qualified-id is used, or implicit, + /// e.g., when a class member access operator (5.2.5) is used + /// (including cases where an implicit "this->" is added). If both + /// a class member access operator and a qualified-id are used to + /// name the member (as in p->T::m), the class naming the member + /// is the class named by the nested-name-specifier of the + /// qualified-id (that is, T). -- end note ] + /// + /// This is set by the lookup routines when they find results in a class. + CXXRecordDecl *getNamingClass() const { + return NamingClass; + } + + /// \brief Sets the 'naming class' for this lookup. + void setNamingClass(CXXRecordDecl *Record) { + NamingClass = Record; + } + + /// \brief Returns the base object type associated with this lookup; + /// important for [class.protected]. Most lookups do not have an + /// associated base object. + QualType getBaseObjectType() const { + return BaseObjectType; + } + + /// \brief Sets the base object type for this lookup. + void setBaseObjectType(QualType T) { + BaseObjectType = T; + } + + /// \brief Add a declaration to these results with its natural access. + /// Does not test the acceptance criteria. + void addDecl(NamedDecl *D) { + addDecl(D, D->getAccess()); + } + + /// \brief Add a declaration to these results with the given access. + /// Does not test the acceptance criteria. + void addDecl(NamedDecl *D, AccessSpecifier AS) { + Decls.addDecl(D, AS); + ResultKind = Found; + } + + /// \brief Add all the declarations from another set of lookup + /// results. + void addAllDecls(const LookupResult &Other) { + Decls.append(Other.Decls.begin(), Other.Decls.end()); + ResultKind = Found; + } + + /// \brief Determine whether no result was found because we could not + /// search into dependent base classes of the current instantiation. + bool wasNotFoundInCurrentInstantiation() const { + return ResultKind == NotFoundInCurrentInstantiation; + } + + /// \brief Note that while no result was found in the current instantiation, + /// there were dependent base classes that could not be searched. + void setNotFoundInCurrentInstantiation() { + assert(ResultKind == NotFound && Decls.empty()); + ResultKind = NotFoundInCurrentInstantiation; + } + + /// \brief Resolves the result kind of the lookup, possibly hiding + /// decls. + /// + /// This should be called in any environment where lookup might + /// generate multiple lookup results. + void resolveKind(); + + /// \brief Re-resolves the result kind of the lookup after a set of + /// removals has been performed. + void resolveKindAfterFilter() { + if (Decls.empty()) { + if (ResultKind != NotFoundInCurrentInstantiation) + ResultKind = NotFound; + } else { + AmbiguityKind SavedAK = Ambiguity; + ResultKind = Found; + resolveKind(); + + // If we didn't make the lookup unambiguous, restore the old + // ambiguity kind. + if (ResultKind == Ambiguous) { + Ambiguity = SavedAK; + } else if (Paths) { + deletePaths(Paths); + Paths = 0; + } + } + } + + template <class DeclClass> + DeclClass *getAsSingle() const { + if (getResultKind() != Found) return 0; + return dyn_cast<DeclClass>(getFoundDecl()); + } + + /// \brief Fetch the unique decl found by this lookup. Asserts + /// that one was found. + /// + /// This is intended for users who have examined the result kind + /// and are certain that there is only one result. + NamedDecl *getFoundDecl() const { + assert(getResultKind() == Found + && "getFoundDecl called on non-unique result"); + return (*begin())->getUnderlyingDecl(); + } + + /// Fetches a representative decl. Useful for lazy diagnostics. + NamedDecl *getRepresentativeDecl() const { + assert(!Decls.empty() && "cannot get representative of empty set"); + return *begin(); + } + + /// \brief Asks if the result is a single tag decl. + bool isSingleTagDecl() const { + return getResultKind() == Found && isa<TagDecl>(getFoundDecl()); + } + + /// \brief Make these results show that the name was found in + /// base classes of different types. + /// + /// The given paths object is copied and invalidated. + void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P); + + /// \brief Make these results show that the name was found in + /// distinct base classes of the same type. + /// + /// The given paths object is copied and invalidated. + void setAmbiguousBaseSubobjects(CXXBasePaths &P); + + /// \brief Make these results show that the name was found in + /// different contexts and a tag decl was hidden by an ordinary + /// decl in a different context. + void setAmbiguousQualifiedTagHiding() { + setAmbiguous(AmbiguousTagHiding); + } + + /// \brief Clears out any current state. + void clear() { + ResultKind = NotFound; + Decls.clear(); + if (Paths) deletePaths(Paths); + Paths = NULL; + } + + /// \brief Clears out any current state and re-initializes for a + /// different kind of lookup. + void clear(Sema::LookupNameKind Kind) { + clear(); + LookupKind = Kind; + configure(); + } + + /// \brief Change this lookup's redeclaration kind. + void setRedeclarationKind(Sema::RedeclarationKind RK) { + Redecl = RK; + configure(); + } + + void print(llvm::raw_ostream &); + + /// Suppress the diagnostics that would normally fire because of this + /// lookup. This happens during (e.g.) redeclaration lookups. + void suppressDiagnostics() { + Diagnose = false; + } + + /// Determines whether this lookup is suppressing diagnostics. + bool isSuppressingDiagnostics() const { + return !Diagnose; + } + + /// Sets a 'context' source range. + void setContextRange(SourceRange SR) { + NameContextRange = SR; + } + + /// Gets the source range of the context of this name; for C++ + /// qualified lookups, this is the source range of the scope + /// specifier. + SourceRange getContextRange() const { + return NameContextRange; + } + + /// Gets the location of the identifier. This isn't always defined: + /// sometimes we're doing lookups on synthesized names. + SourceLocation getNameLoc() const { + return NameInfo.getLoc(); + } + + /// \brief Get the Sema object that this lookup result is searching + /// with. + Sema &getSema() const { return SemaRef; } + + /// A class for iterating through a result set and possibly + /// filtering out results. The results returned are possibly + /// sugared. + class Filter { + LookupResult &Results; + LookupResult::iterator I; + bool Changed; +#ifndef NDEBUG + bool CalledDone; +#endif + + friend class LookupResult; + Filter(LookupResult &Results) + : Results(Results), I(Results.begin()), Changed(false) +#ifndef NDEBUG + , CalledDone(false) +#endif + {} + + public: +#ifndef NDEBUG + ~Filter() { + assert(CalledDone && + "LookupResult::Filter destroyed without done() call"); + } +#endif + + bool hasNext() const { + return I != Results.end(); + } + + NamedDecl *next() { + assert(I != Results.end() && "next() called on empty filter"); + return *I++; + } + + /// Erase the last element returned from this iterator. + void erase() { + Results.Decls.erase(--I); + Changed = true; + } + + /// Replaces the current entry with the given one, preserving the + /// access bits. + void replace(NamedDecl *D) { + Results.Decls.replace(I-1, D); + Changed = true; + } + + /// Replaces the current entry with the given one. + void replace(NamedDecl *D, AccessSpecifier AS) { + Results.Decls.replace(I-1, D, AS); + Changed = true; + } + + void done() { +#ifndef NDEBUG + assert(!CalledDone && "done() called twice"); + CalledDone = true; +#endif + + if (Changed) + Results.resolveKindAfterFilter(); + } + }; + + /// Create a filter for this result set. + Filter makeFilter() { + return Filter(*this); + } + +private: + void diagnose() { + if (isAmbiguous()) + SemaRef.DiagnoseAmbiguousLookup(*this); + else if (isClassLookup() && SemaRef.getLangOptions().AccessControl) + SemaRef.CheckLookupAccess(*this); + } + + void setAmbiguous(AmbiguityKind AK) { + ResultKind = Ambiguous; + Ambiguity = AK; + } + + void addDeclsFromBasePaths(const CXXBasePaths &P); + void configure(); + + // Sanity checks. +#ifndef NDEBUG + void sanity() const; +#else + void sanity() const {} +#endif + + bool sanityCheckUnresolved() const { + for (iterator I = begin(), E = end(); I != E; ++I) + if (isa<UnresolvedUsingValueDecl>(*I)) + return true; + return false; + } + + static void deletePaths(CXXBasePaths *); + + // Results. + LookupResultKind ResultKind; + AmbiguityKind Ambiguity; // ill-defined unless ambiguous + UnresolvedSet<8> Decls; + CXXBasePaths *Paths; + CXXRecordDecl *NamingClass; + QualType BaseObjectType; + + // Parameters. + Sema &SemaRef; + DeclarationNameInfo NameInfo; + SourceRange NameContextRange; + Sema::LookupNameKind LookupKind; + unsigned IDNS; // set by configure() + + bool Redecl; + + /// \brief True if tag declarations should be hidden if non-tags + /// are present + bool HideTags; + + bool Diagnose; +}; + + /// \brief Consumes visible declarations found when searching for + /// all visible names within a given scope or context. + /// + /// This abstract class is meant to be subclassed by clients of \c + /// Sema::LookupVisibleDecls(), each of which should override the \c + /// FoundDecl() function to process declarations as they are found. + class VisibleDeclConsumer { + public: + /// \brief Destroys the visible declaration consumer. + virtual ~VisibleDeclConsumer(); + + /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a + /// declaration visible from the current scope or context. + /// + /// \param ND the declaration found. + /// + /// \param Hiding a declaration that hides the declaration \p ND, + /// or NULL if no such declaration exists. + /// + /// \param InBaseClass whether this declaration was found in base + /// class of the context we searched. + virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, + bool InBaseClass) = 0; + }; + +/// \brief A class for storing results from argument-dependent lookup. +class ADLResult { +private: + /// A map from canonical decls to the 'most recent' decl. + llvm::DenseMap<NamedDecl*, NamedDecl*> Decls; + +public: + /// Adds a new ADL candidate to this map. + void insert(NamedDecl *D); + + /// Removes any data associated with a given decl. + void erase(NamedDecl *D) { + Decls.erase(cast<NamedDecl>(D->getCanonicalDecl())); + } + + class iterator { + typedef llvm::DenseMap<NamedDecl*,NamedDecl*>::iterator inner_iterator; + inner_iterator iter; + + friend class ADLResult; + iterator(const inner_iterator &iter) : iter(iter) {} + public: + iterator() {} + + iterator &operator++() { ++iter; return *this; } + iterator operator++(int) { return iterator(iter++); } + + NamedDecl *operator*() const { return iter->second; } + + bool operator==(const iterator &other) const { return iter == other.iter; } + bool operator!=(const iterator &other) const { return iter != other.iter; } + }; + + iterator begin() { return iterator(Decls.begin()); } + iterator end() { return iterator(Decls.end()); } +}; + +} + +#endif diff --git a/include/clang/Sema/ObjCMethodList.h b/include/clang/Sema/ObjCMethodList.h new file mode 100644 index 000000000000..225c13776c59 --- /dev/null +++ b/include/clang/Sema/ObjCMethodList.h @@ -0,0 +1,38 @@ +//===--- ObjCMethodList.h - A singly linked list of methods -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines ObjCMethodList, a singly-linked list of methods. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H +#define LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H + +namespace clang { + +class ObjCMethodDecl; + +/// ObjCMethodList - a linked list of methods with different signatures. +struct ObjCMethodList { + ObjCMethodDecl *Method; + ObjCMethodList *Next; + + ObjCMethodList() { + Method = 0; + Next = 0; + } + ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) { + Method = M; + Next = C; + } +}; + +} + +#endif diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h new file mode 100644 index 000000000000..851d68ac4d79 --- /dev/null +++ b/include/clang/Sema/Overload.h @@ -0,0 +1,648 @@ +//===--- Overload.h - C++ Overloading ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the data structures and types used in C++ +// overload resolution. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_OVERLOAD_H +#define LLVM_CLANG_SEMA_OVERLOAD_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/AST/UnresolvedSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class ASTContext; + class CXXConstructorDecl; + class CXXConversionDecl; + class FunctionDecl; + class Sema; + + /// OverloadingResult - Capture the result of performing overload + /// resolution. + enum OverloadingResult { + OR_Success, ///< Overload resolution succeeded. + OR_No_Viable_Function, ///< No viable function found. + OR_Ambiguous, ///< Ambiguous candidates found. + OR_Deleted ///< Succeeded, but refers to a deleted function. + }; + + enum OverloadCandidateDisplayKind { + /// Requests that all candidates be shown. Viable candidates will + /// be printed first. + OCD_AllCandidates, + + /// Requests that only viable candidates be shown. + OCD_ViableCandidates + }; + + /// ImplicitConversionKind - The kind of implicit conversion used to + /// convert an argument to a parameter's type. The enumerator values + /// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that + /// better conversion kinds have smaller values. + enum ImplicitConversionKind { + ICK_Identity = 0, ///< Identity conversion (no conversion) + ICK_Lvalue_To_Rvalue, ///< Lvalue-to-rvalue conversion (C++ 4.1) + ICK_Array_To_Pointer, ///< Array-to-pointer conversion (C++ 4.2) + ICK_Function_To_Pointer, ///< Function-to-pointer (C++ 4.3) + ICK_NoReturn_Adjustment, ///< Removal of noreturn from a type (Clang) + ICK_Qualification, ///< Qualification conversions (C++ 4.4) + ICK_Integral_Promotion, ///< Integral promotions (C++ 4.5) + ICK_Floating_Promotion, ///< Floating point promotions (C++ 4.6) + ICK_Complex_Promotion, ///< Complex promotions (Clang extension) + ICK_Integral_Conversion, ///< Integral conversions (C++ 4.7) + ICK_Floating_Conversion, ///< Floating point conversions (C++ 4.8) + ICK_Complex_Conversion, ///< Complex conversions (C99 6.3.1.6) + ICK_Floating_Integral, ///< Floating-integral conversions (C++ 4.9) + ICK_Pointer_Conversion, ///< Pointer conversions (C++ 4.10) + ICK_Pointer_Member, ///< Pointer-to-member conversions (C++ 4.11) + ICK_Boolean_Conversion, ///< Boolean conversions (C++ 4.12) + ICK_Compatible_Conversion, ///< Conversions between compatible types in C99 + ICK_Derived_To_Base, ///< Derived-to-base (C++ [over.best.ics]) + ICK_Vector_Conversion, ///< Vector conversions + ICK_Vector_Splat, ///< A vector splat from an arithmetic type + ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7) + ICK_Num_Conversion_Kinds ///< The number of conversion kinds + }; + + /// ImplicitConversionCategory - The category of an implicit + /// conversion kind. The enumerator values match with Table 9 of + /// (C++ 13.3.3.1.1) and are listed such that better conversion + /// categories have smaller values. + enum ImplicitConversionCategory { + ICC_Identity = 0, ///< Identity + ICC_Lvalue_Transformation, ///< Lvalue transformation + ICC_Qualification_Adjustment, ///< Qualification adjustment + ICC_Promotion, ///< Promotion + ICC_Conversion ///< Conversion + }; + + ImplicitConversionCategory + GetConversionCategory(ImplicitConversionKind Kind); + + /// ImplicitConversionRank - The rank of an implicit conversion + /// kind. The enumerator values match with Table 9 of (C++ + /// 13.3.3.1.1) and are listed such that better conversion ranks + /// have smaller values. + enum ImplicitConversionRank { + ICR_Exact_Match = 0, ///< Exact Match + ICR_Promotion, ///< Promotion + ICR_Conversion, ///< Conversion + ICR_Complex_Real_Conversion ///< Complex <-> Real conversion + }; + + ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind); + + /// StandardConversionSequence - represents a standard conversion + /// sequence (C++ 13.3.3.1.1). A standard conversion sequence + /// contains between zero and three conversions. If a particular + /// conversion is not needed, it will be set to the identity conversion + /// (ICK_Identity). Note that the three conversions are + /// specified as separate members (rather than in an array) so that + /// we can keep the size of a standard conversion sequence to a + /// single word. + class StandardConversionSequence { + public: + /// First -- The first conversion can be an lvalue-to-rvalue + /// conversion, array-to-pointer conversion, or + /// function-to-pointer conversion. + ImplicitConversionKind First : 8; + + /// Second - The second conversion can be an integral promotion, + /// floating point promotion, integral conversion, floating point + /// conversion, floating-integral conversion, pointer conversion, + /// pointer-to-member conversion, or boolean conversion. + ImplicitConversionKind Second : 8; + + /// Third - The third conversion can be a qualification conversion. + ImplicitConversionKind Third : 8; + + /// Deprecated - Whether this the deprecated conversion of a + /// string literal to a pointer to non-const character data + /// (C++ 4.2p2). + bool DeprecatedStringLiteralToCharPtr : 1; + + /// IncompatibleObjC - Whether this is an Objective-C conversion + /// that we should warn about (if we actually use it). + bool IncompatibleObjC : 1; + + /// ReferenceBinding - True when this is a reference binding + /// (C++ [over.ics.ref]). + bool ReferenceBinding : 1; + + /// DirectBinding - True when this is a reference binding that is a + /// direct binding (C++ [dcl.init.ref]). + bool DirectBinding : 1; + + /// RRefBinding - True when this is a reference binding of an rvalue + /// reference to an rvalue (C++0x [over.ics.rank]p3b4). + bool RRefBinding : 1; + + /// FromType - The type that this conversion is converting + /// from. This is an opaque pointer that can be translated into a + /// QualType. + void *FromTypePtr; + + /// ToType - The types that this conversion is converting to in + /// each step. This is an opaque pointer that can be translated + /// into a QualType. + void *ToTypePtrs[3]; + + /// CopyConstructor - The copy constructor that is used to perform + /// this conversion, when the conversion is actually just the + /// initialization of an object via copy constructor. Such + /// conversions are either identity conversions or derived-to-base + /// conversions. + CXXConstructorDecl *CopyConstructor; + + void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); } + void setToType(unsigned Idx, QualType T) { + assert(Idx < 3 && "To type index is out of range"); + ToTypePtrs[Idx] = T.getAsOpaquePtr(); + } + void setAllToTypes(QualType T) { + ToTypePtrs[0] = T.getAsOpaquePtr(); + ToTypePtrs[1] = ToTypePtrs[0]; + ToTypePtrs[2] = ToTypePtrs[0]; + } + + QualType getFromType() const { + return QualType::getFromOpaquePtr(FromTypePtr); + } + QualType getToType(unsigned Idx) const { + assert(Idx < 3 && "To type index is out of range"); + return QualType::getFromOpaquePtr(ToTypePtrs[Idx]); + } + + void setAsIdentityConversion(); + + bool isIdentityConversion() const { + return First == ICK_Identity && Second == ICK_Identity && + Third == ICK_Identity; + } + + ImplicitConversionRank getRank() const; + bool isPointerConversionToBool() const; + bool isPointerConversionToVoidPointer(ASTContext& Context) const; + void DebugPrint() const; + }; + + /// UserDefinedConversionSequence - Represents a user-defined + /// conversion sequence (C++ 13.3.3.1.2). + struct UserDefinedConversionSequence { + /// Before - Represents the standard conversion that occurs before + /// the actual user-defined conversion. (C++ 13.3.3.1.2p1): + /// + /// If the user-defined conversion is specified by a constructor + /// (12.3.1), the initial standard conversion sequence converts + /// the source type to the type required by the argument of the + /// constructor. If the user-defined conversion is specified by + /// a conversion function (12.3.2), the initial standard + /// conversion sequence converts the source type to the implicit + /// object parameter of the conversion function. + StandardConversionSequence Before; + + /// EllipsisConversion - When this is true, it means user-defined + /// conversion sequence starts with a ... (elipsis) conversion, instead of + /// a standard conversion. In this case, 'Before' field must be ignored. + // FIXME. I much rather put this as the first field. But there seems to be + // a gcc code gen. bug which causes a crash in a test. Putting it here seems + // to work around the crash. + bool EllipsisConversion : 1; + + /// After - Represents the standard conversion that occurs after + /// the actual user-defined conversion. + StandardConversionSequence After; + + /// ConversionFunction - The function that will perform the + /// user-defined conversion. + FunctionDecl* ConversionFunction; + + void DebugPrint() const; + }; + + /// Represents an ambiguous user-defined conversion sequence. + struct AmbiguousConversionSequence { + typedef llvm::SmallVector<FunctionDecl*, 4> ConversionSet; + + void *FromTypePtr; + void *ToTypePtr; + char Buffer[sizeof(ConversionSet)]; + + QualType getFromType() const { + return QualType::getFromOpaquePtr(FromTypePtr); + } + QualType getToType() const { + return QualType::getFromOpaquePtr(ToTypePtr); + } + void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); } + void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); } + + ConversionSet &conversions() { + return *reinterpret_cast<ConversionSet*>(Buffer); + } + + const ConversionSet &conversions() const { + return *reinterpret_cast<const ConversionSet*>(Buffer); + } + + void addConversion(FunctionDecl *D) { + conversions().push_back(D); + } + + typedef ConversionSet::iterator iterator; + iterator begin() { return conversions().begin(); } + iterator end() { return conversions().end(); } + + typedef ConversionSet::const_iterator const_iterator; + const_iterator begin() const { return conversions().begin(); } + const_iterator end() const { return conversions().end(); } + + void construct(); + void destruct(); + void copyFrom(const AmbiguousConversionSequence &); + }; + + /// BadConversionSequence - Records information about an invalid + /// conversion sequence. + struct BadConversionSequence { + enum FailureKind { + no_conversion, + unrelated_class, + suppressed_user, + bad_qualifiers + }; + + // This can be null, e.g. for implicit object arguments. + Expr *FromExpr; + + FailureKind Kind; + + private: + // The type we're converting from (an opaque QualType). + void *FromTy; + + // The type we're converting to (an opaque QualType). + void *ToTy; + + public: + void init(FailureKind K, Expr *From, QualType To) { + init(K, From->getType(), To); + FromExpr = From; + } + void init(FailureKind K, QualType From, QualType To) { + Kind = K; + FromExpr = 0; + setFromType(From); + setToType(To); + } + + QualType getFromType() const { return QualType::getFromOpaquePtr(FromTy); } + QualType getToType() const { return QualType::getFromOpaquePtr(ToTy); } + + void setFromExpr(Expr *E) { + FromExpr = E; + setFromType(E->getType()); + } + void setFromType(QualType T) { FromTy = T.getAsOpaquePtr(); } + void setToType(QualType T) { ToTy = T.getAsOpaquePtr(); } + }; + + /// ImplicitConversionSequence - Represents an implicit conversion + /// sequence, which may be a standard conversion sequence + /// (C++ 13.3.3.1.1), user-defined conversion sequence (C++ 13.3.3.1.2), + /// or an ellipsis conversion sequence (C++ 13.3.3.1.3). + class ImplicitConversionSequence { + public: + /// Kind - The kind of implicit conversion sequence. BadConversion + /// specifies that there is no conversion from the source type to + /// the target type. AmbiguousConversion represents the unique + /// ambiguous conversion (C++0x [over.best.ics]p10). + enum Kind { + StandardConversion = 0, + UserDefinedConversion, + AmbiguousConversion, + EllipsisConversion, + BadConversion + }; + + private: + enum { + Uninitialized = BadConversion + 1 + }; + + /// ConversionKind - The kind of implicit conversion sequence. + unsigned ConversionKind; + + void setKind(Kind K) { + destruct(); + ConversionKind = K; + } + + void destruct() { + if (ConversionKind == AmbiguousConversion) Ambiguous.destruct(); + } + + public: + union { + /// When ConversionKind == StandardConversion, provides the + /// details of the standard conversion sequence. + StandardConversionSequence Standard; + + /// When ConversionKind == UserDefinedConversion, provides the + /// details of the user-defined conversion sequence. + UserDefinedConversionSequence UserDefined; + + /// When ConversionKind == AmbiguousConversion, provides the + /// details of the ambiguous conversion. + AmbiguousConversionSequence Ambiguous; + + /// When ConversionKind == BadConversion, provides the details + /// of the bad conversion. + BadConversionSequence Bad; + }; + + ImplicitConversionSequence() : ConversionKind(Uninitialized) {} + ~ImplicitConversionSequence() { + destruct(); + } + ImplicitConversionSequence(const ImplicitConversionSequence &Other) + : ConversionKind(Other.ConversionKind) + { + switch (ConversionKind) { + case Uninitialized: break; + case StandardConversion: Standard = Other.Standard; break; + case UserDefinedConversion: UserDefined = Other.UserDefined; break; + case AmbiguousConversion: Ambiguous.copyFrom(Other.Ambiguous); break; + case EllipsisConversion: break; + case BadConversion: Bad = Other.Bad; break; + } + } + + ImplicitConversionSequence & + operator=(const ImplicitConversionSequence &Other) { + destruct(); + new (this) ImplicitConversionSequence(Other); + return *this; + } + + Kind getKind() const { + assert(isInitialized() && "querying uninitialized conversion"); + return Kind(ConversionKind); + } + + /// \brief Return a ranking of the implicit conversion sequence + /// kind, where smaller ranks represent better conversion + /// sequences. + /// + /// In particular, this routine gives user-defined conversion + /// sequences and ambiguous conversion sequences the same rank, + /// per C++ [over.best.ics]p10. + unsigned getKindRank() const { + switch (getKind()) { + case StandardConversion: + return 0; + + case UserDefinedConversion: + case AmbiguousConversion: + return 1; + + case EllipsisConversion: + return 2; + + case BadConversion: + return 3; + } + + return 3; + } + + bool isBad() const { return getKind() == BadConversion; } + bool isStandard() const { return getKind() == StandardConversion; } + bool isEllipsis() const { return getKind() == EllipsisConversion; } + bool isAmbiguous() const { return getKind() == AmbiguousConversion; } + bool isUserDefined() const { return getKind() == UserDefinedConversion; } + + /// Determines whether this conversion sequence has been + /// initialized. Most operations should never need to query + /// uninitialized conversions and should assert as above. + bool isInitialized() const { return ConversionKind != Uninitialized; } + + /// Sets this sequence as a bad conversion for an explicit argument. + void setBad(BadConversionSequence::FailureKind Failure, + Expr *FromExpr, QualType ToType) { + setKind(BadConversion); + Bad.init(Failure, FromExpr, ToType); + } + + /// Sets this sequence as a bad conversion for an implicit argument. + void setBad(BadConversionSequence::FailureKind Failure, + QualType FromType, QualType ToType) { + setKind(BadConversion); + Bad.init(Failure, FromType, ToType); + } + + void setStandard() { setKind(StandardConversion); } + void setEllipsis() { setKind(EllipsisConversion); } + void setUserDefined() { setKind(UserDefinedConversion); } + void setAmbiguous() { + if (ConversionKind == AmbiguousConversion) return; + ConversionKind = AmbiguousConversion; + Ambiguous.construct(); + } + + // The result of a comparison between implicit conversion + // sequences. Use Sema::CompareImplicitConversionSequences to + // actually perform the comparison. + enum CompareKind { + Better = -1, + Indistinguishable = 0, + Worse = 1 + }; + + void DiagnoseAmbiguousConversion(Sema &S, + SourceLocation CaretLoc, + const PartialDiagnostic &PDiag) const; + + void DebugPrint() const; + }; + + enum OverloadFailureKind { + ovl_fail_too_many_arguments, + ovl_fail_too_few_arguments, + ovl_fail_bad_conversion, + ovl_fail_bad_deduction, + + /// This conversion candidate was not considered because it + /// duplicates the work of a trivial or derived-to-base + /// conversion. + ovl_fail_trivial_conversion, + + /// This conversion candidate is not viable because its result + /// type is not implicitly convertible to the desired type. + ovl_fail_bad_final_conversion, + + /// This conversion function template specialization candidate is not + /// viable because the final conversion was not an exact match. + ovl_fail_final_conversion_not_exact + }; + + /// OverloadCandidate - A single candidate in an overload set (C++ 13.3). + struct OverloadCandidate { + /// Function - The actual function that this candidate + /// represents. When NULL, this is a built-in candidate + /// (C++ [over.oper]) or a surrogate for a conversion to a + /// function pointer or reference (C++ [over.call.object]). + FunctionDecl *Function; + + /// FoundDecl - The original declaration that was looked up / + /// invented / otherwise found, together with its access. + /// Might be a UsingShadowDecl or a FunctionTemplateDecl. + DeclAccessPair FoundDecl; + + // BuiltinTypes - Provides the return and parameter types of a + // built-in overload candidate. Only valid when Function is NULL. + struct { + QualType ResultTy; + QualType ParamTypes[3]; + } BuiltinTypes; + + /// Surrogate - The conversion function for which this candidate + /// is a surrogate, but only if IsSurrogate is true. + CXXConversionDecl *Surrogate; + + /// Conversions - The conversion sequences used to convert the + /// function arguments to the function parameters. + llvm::SmallVector<ImplicitConversionSequence, 4> Conversions; + + /// Viable - True to indicate that this overload candidate is viable. + bool Viable; + + /// IsSurrogate - True to indicate that this candidate is a + /// surrogate for a conversion to a function pointer or reference + /// (C++ [over.call.object]). + bool IsSurrogate; + + /// IgnoreObjectArgument - True to indicate that the first + /// argument's conversion, which for this function represents the + /// implicit object argument, should be ignored. This will be true + /// when the candidate is a static member function (where the + /// implicit object argument is just a placeholder) or a + /// non-static member function when the call doesn't have an + /// object argument. + bool IgnoreObjectArgument; + + /// FailureKind - The reason why this candidate is not viable. + /// Actually an OverloadFailureKind. + unsigned char FailureKind; + + /// A structure used to record information about a failed + /// template argument deduction. + struct DeductionFailureInfo { + // A Sema::TemplateDeductionResult. + unsigned Result; + + /// \brief Opaque pointer containing additional data about + /// this deduction failure. + void *Data; + + /// \brief Retrieve the template parameter this deduction failure + /// refers to, if any. + TemplateParameter getTemplateParameter(); + + /// \brief Retrieve the template argument list associated with this + /// deduction failure, if any. + TemplateArgumentList *getTemplateArgumentList(); + + /// \brief Return the first template argument this deduction failure + /// refers to, if any. + const TemplateArgument *getFirstArg(); + + /// \brief Return the second template argument this deduction failure + /// refers to, if any. + const TemplateArgument *getSecondArg(); + + /// \brief Free any memory associated with this deduction failure. + void Destroy(); + }; + + union { + DeductionFailureInfo DeductionFailure; + + /// FinalConversion - For a conversion function (where Function is + /// a CXXConversionDecl), the standard conversion that occurs + /// after the call to the overload candidate to convert the result + /// of calling the conversion function to the required type. + StandardConversionSequence FinalConversion; + }; + + /// hasAmbiguousConversion - Returns whether this overload + /// candidate requires an ambiguous conversion or not. + bool hasAmbiguousConversion() const { + for (llvm::SmallVectorImpl<ImplicitConversionSequence>::const_iterator + I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { + if (!I->isInitialized()) return false; + if (I->isAmbiguous()) return true; + } + return false; + } + }; + + /// OverloadCandidateSet - A set of overload candidates, used in C++ + /// overload resolution (C++ 13.3). + class OverloadCandidateSet : public llvm::SmallVector<OverloadCandidate, 16> { + typedef llvm::SmallVector<OverloadCandidate, 16> inherited; + llvm::SmallPtrSet<Decl *, 16> Functions; + + SourceLocation Loc; + + OverloadCandidateSet(const OverloadCandidateSet &); + OverloadCandidateSet &operator=(const OverloadCandidateSet &); + + public: + OverloadCandidateSet(SourceLocation Loc) : Loc(Loc) {} + + SourceLocation getLocation() const { return Loc; } + + /// \brief Determine when this overload candidate will be new to the + /// overload set. + bool isNewCandidate(Decl *F) { + return Functions.insert(F->getCanonicalDecl()); + } + + /// \brief Clear out all of the candidates. + void clear(); + + ~OverloadCandidateSet() { clear(); } + + /// Find the best viable function on this overload set, if it exists. + OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, + OverloadCandidateSet::iterator& Best); + + void NoteCandidates(Sema &S, + OverloadCandidateDisplayKind OCD, + Expr **Args, unsigned NumArgs, + const char *Opc = 0, + SourceLocation Loc = SourceLocation()); + }; + + bool isBetterOverloadCandidate(Sema &S, + const OverloadCandidate& Cand1, + const OverloadCandidate& Cand2, + SourceLocation Loc); +} // end namespace clang + +#endif // LLVM_CLANG_SEMA_OVERLOAD_H diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h new file mode 100644 index 000000000000..7739f3a5d229 --- /dev/null +++ b/include/clang/Sema/Ownership.h @@ -0,0 +1,462 @@ +//===--- Ownership.h - Parser ownership helpers -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains classes for managing ownership of Stmt and Expr nodes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_OWNERSHIP_H +#define LLVM_CLANG_SEMA_OWNERSHIP_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerIntPair.h" + +//===----------------------------------------------------------------------===// +// OpaquePtr +//===----------------------------------------------------------------------===// + +namespace clang { + class Attr; + class CXXBaseOrMemberInitializer; + class CXXBaseSpecifier; + class Decl; + class DeclGroupRef; + class Expr; + class NestedNameSpecifier; + class QualType; + class Sema; + class Stmt; + class TemplateName; + class TemplateParameterList; + + /// OpaquePtr - This is a very simple POD type that wraps a pointer that the + /// Parser doesn't know about but that Sema or another client does. The UID + /// template argument is used to make sure that "Decl" pointers are not + /// compatible with "Type" pointers for example. + template <class PtrTy> + class OpaquePtr { + void *Ptr; + explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {} + + typedef llvm::PointerLikeTypeTraits<PtrTy> Traits; + + public: + OpaquePtr() : Ptr(0) {} + + static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; } + + template <typename T> T* getAs() const { + return get(); + } + + template <typename T> T getAsVal() const { + return get(); + } + + PtrTy get() const { + return Traits::getFromVoidPointer(Ptr); + } + + void set(PtrTy P) { + Ptr = Traits::getAsVoidPointer(P); + } + + operator bool() const { return Ptr != 0; } + + void *getAsOpaquePtr() const { return Ptr; } + static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); } + }; + + /// UnionOpaquePtr - A version of OpaquePtr suitable for membership + /// in a union. + template <class T> struct UnionOpaquePtr { + void *Ptr; + + static UnionOpaquePtr make(OpaquePtr<T> P) { + UnionOpaquePtr OP = { P.getAsOpaquePtr() }; + return OP; + } + + OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); } + operator OpaquePtr<T>() const { return get(); } + + UnionOpaquePtr &operator=(OpaquePtr<T> P) { + Ptr = P.getAsOpaquePtr(); + return *this; + } + }; +} + +namespace llvm { + template <class T> + class PointerLikeTypeTraits<clang::OpaquePtr<T> > { + public: + static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) { + // FIXME: Doesn't work? return P.getAs< void >(); + return P.getAsOpaquePtr(); + } + static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) { + return clang::OpaquePtr<T>::getFromOpaquePtr(P); + } + enum { NumLowBitsAvailable = 0 }; + }; +} + + + +// -------------------------- About Move Emulation -------------------------- // +// The smart pointer classes in this file attempt to emulate move semantics +// as they appear in C++0x with rvalue references. Since C++03 doesn't have +// rvalue references, some tricks are needed to get similar results. +// Move semantics in C++0x have the following properties: +// 1) "Moving" means transferring the value of an object to another object, +// similar to copying, but without caring what happens to the old object. +// In particular, this means that the new object can steal the old object's +// resources instead of creating a copy. +// 2) Since moving can modify the source object, it must either be explicitly +// requested by the user, or the modifications must be unnoticeable. +// 3) As such, C++0x moving is only allowed in three contexts: +// * By explicitly using std::move() to request it. +// * From a temporary object, since that object cannot be accessed +// afterwards anyway, thus making the state unobservable. +// * On function return, since the object is not observable afterwards. +// +// To sum up: moving from a named object should only be possible with an +// explicit std::move(), or on function return. Moving from a temporary should +// be implicitly done. Moving from a const object is forbidden. +// +// The emulation is not perfect, and has the following shortcomings: +// * move() is not in namespace std. +// * move() is required on function return. +// * There are difficulties with implicit conversions. +// * Microsoft's compiler must be given the /Za switch to successfully compile. +// +// -------------------------- Implementation -------------------------------- // +// The move emulation relies on the peculiar reference binding semantics of +// C++03: as a rule, a non-const reference may not bind to a temporary object, +// except for the implicit object parameter in a member function call, which +// can refer to a temporary even when not being const. +// The moveable object has five important functions to facilitate moving: +// * A private, unimplemented constructor taking a non-const reference to its +// own class. This constructor serves a two-fold purpose. +// - It prevents the creation of a copy constructor that takes a const +// reference. Temporaries would be able to bind to the argument of such a +// constructor, and that would be bad. +// - Named objects will bind to the non-const reference, but since it's +// private, this will fail to compile. This prevents implicit moving from +// named objects. +// There's also a copy assignment operator for the same purpose. +// * An implicit, non-const conversion operator to a special mover type. This +// type represents the rvalue reference of C++0x. Being a non-const member, +// its implicit this parameter can bind to temporaries. +// * A constructor that takes an object of this mover type. This constructor +// performs the actual move operation. There is an equivalent assignment +// operator. +// There is also a free move() function that takes a non-const reference to +// an object and returns a temporary. Internally, this function uses explicit +// constructor calls to move the value from the referenced object to the return +// value. +// +// There are now three possible scenarios of use. +// * Copying from a const object. Constructor overload resolution will find the +// non-const copy constructor, and the move constructor. The first is not +// viable because the const object cannot be bound to the non-const reference. +// The second fails because the conversion to the mover object is non-const. +// Moving from a const object fails as intended. +// * Copying from a named object. Constructor overload resolution will select +// the non-const copy constructor, but fail as intended, because this +// constructor is private. +// * Copying from a temporary. Constructor overload resolution cannot select +// the non-const copy constructor, because the temporary cannot be bound to +// the non-const reference. It thus selects the move constructor. The +// temporary can be bound to the implicit this parameter of the conversion +// operator, because of the special binding rule. Construction succeeds. +// Note that the Microsoft compiler, as an extension, allows binding +// temporaries against non-const references. The compiler thus selects the +// non-const copy constructor and fails, because the constructor is private. +// Passing /Za (disable extensions) disables this behaviour. +// The free move() function is used to move from a named object. +// +// Note that when passing an object of a different type (the classes below +// have OwningResult and OwningPtr, which should be mixable), you get a problem. +// Argument passing and function return use copy initialization rules. The +// effect of this is that, when the source object is not already of the target +// type, the compiler will first seek a way to convert the source object to the +// target type, and only then attempt to copy the resulting object. This means +// that when passing an OwningResult where an OwningPtr is expected, the +// compiler will first seek a conversion from OwningResult to OwningPtr, then +// copy the OwningPtr. The resulting conversion sequence is: +// OwningResult object -> ResultMover -> OwningResult argument to +// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr +// This conversion sequence is too complex to be allowed. Thus the special +// move_* functions, which help the compiler out with some explicit +// conversions. + +namespace clang { + // Basic + class DiagnosticBuilder; + + // Determines whether the low bit of the result pointer for the + // given UID is always zero. If so, ActionResult will use that bit + // for it's "invalid" flag. + template<class Ptr> + struct IsResultPtrLowBitFree { + static const bool value = false; + }; + + /// ActionResult - This structure is used while parsing/acting on + /// expressions, stmts, etc. It encapsulates both the object returned by + /// the action, plus a sense of whether or not it is valid. + /// When CompressInvalid is true, the "invalid" flag will be + /// stored in the low bit of the Val pointer. + template<class PtrTy, + bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value> + class ActionResult { + PtrTy Val; + bool Invalid; + + public: + ActionResult(bool Invalid = false) + : Val(PtrTy()), Invalid(Invalid) {} + ActionResult(PtrTy val) : Val(val), Invalid(false) {} + ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {} + + // These two overloads prevent void* -> bool conversions. + ActionResult(const void *); + ActionResult(volatile void *); + + bool isInvalid() const { return Invalid; } + bool isUsable() const { return !Invalid && Val; } + + PtrTy get() const { return Val; } + PtrTy release() const { return Val; } + PtrTy take() const { return Val; } + template <typename T> T *takeAs() { return static_cast<T*>(get()); } + + void set(PtrTy V) { Val = V; } + + const ActionResult &operator=(PtrTy RHS) { + Val = RHS; + Invalid = false; + return *this; + } + }; + + // This ActionResult partial specialization places the "invalid" + // flag into the low bit of the pointer. + template<typename PtrTy> + class ActionResult<PtrTy, true> { + // A pointer whose low bit is 1 if this result is invalid, 0 + // otherwise. + uintptr_t PtrWithInvalid; + typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits; + public: + ActionResult(bool Invalid = false) + : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { } + + ActionResult(PtrTy V) { + void *VP = PtrTraits::getAsVoidPointer(V); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + } + ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { } + + // These two overloads prevent void* -> bool conversions. + ActionResult(const void *); + ActionResult(volatile void *); + + bool isInvalid() const { return PtrWithInvalid & 0x01; } + bool isUsable() const { return PtrWithInvalid > 0x01; } + + PtrTy get() const { + void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); + return PtrTraits::getFromVoidPointer(VP); + } + PtrTy take() const { return get(); } + PtrTy release() const { return get(); } + template <typename T> T *takeAs() { return static_cast<T*>(get()); } + + void set(PtrTy V) { + void *VP = PtrTraits::getAsVoidPointer(V); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + } + + const ActionResult &operator=(PtrTy RHS) { + void *VP = PtrTraits::getAsVoidPointer(RHS); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + return *this; + } + }; + + /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns + /// the individual pointers, not the array holding them. + template <typename PtrTy> class ASTMultiPtr; + + template <class PtrTy> + class ASTMultiPtr { + PtrTy *Nodes; + unsigned Count; + + public: + // Normal copying implicitly defined + ASTMultiPtr() : Nodes(0), Count(0) {} + explicit ASTMultiPtr(Sema &) : Nodes(0), Count(0) {} + ASTMultiPtr(Sema &, PtrTy *nodes, unsigned count) + : Nodes(nodes), Count(count) {} + // Fake mover in Parse/AstGuard.h needs this: + ASTMultiPtr(PtrTy *nodes, unsigned count) : Nodes(nodes), Count(count) {} + + /// Access to the raw pointers. + PtrTy *get() const { return Nodes; } + + /// Access to the count. + unsigned size() const { return Count; } + + PtrTy *release() { + return Nodes; + } + }; + + class ParsedTemplateArgument; + + class ASTTemplateArgsPtr { + ParsedTemplateArgument *Args; + mutable unsigned Count; + + public: + ASTTemplateArgsPtr(Sema &actions, ParsedTemplateArgument *args, + unsigned count) : + Args(args), Count(count) { } + + // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. + ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : + Args(Other.Args), Count(Other.Count) { + } + + // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. + ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) { + Args = Other.Args; + Count = Other.Count; + return *this; + } + + ParsedTemplateArgument *getArgs() const { return Args; } + unsigned size() const { return Count; } + + void reset(ParsedTemplateArgument *args, unsigned count) { + Args = args; + Count = count; + } + + const ParsedTemplateArgument &operator[](unsigned Arg) const; + + ParsedTemplateArgument *release() const { + return Args; + } + }; + + /// \brief A small vector that owns a set of AST nodes. + template <class PtrTy, unsigned N = 8> + class ASTOwningVector : public llvm::SmallVector<PtrTy, N> { + ASTOwningVector(ASTOwningVector &); // do not implement + ASTOwningVector &operator=(ASTOwningVector &); // do not implement + + public: + explicit ASTOwningVector(Sema &Actions) + { } + + PtrTy *take() { + return &this->front(); + } + + template<typename T> T **takeAs() { return reinterpret_cast<T**>(take()); } + }; + + /// A SmallVector of statements, with stack size 32 (as that is the only one + /// used.) + typedef ASTOwningVector<Stmt*, 32> StmtVector; + /// A SmallVector of expressions, with stack size 12 (the maximum used.) + typedef ASTOwningVector<Expr*, 12> ExprVector; + + template <class T, unsigned N> inline + ASTMultiPtr<T> move_arg(ASTOwningVector<T, N> &vec) { + return ASTMultiPtr<T>(vec.take(), vec.size()); + } + + // These versions are hopefully no-ops. + template <class T, bool C> + inline ActionResult<T,C> move(ActionResult<T,C> &ptr) { + return ptr; + } + + template <class T> inline + ASTMultiPtr<T>& move(ASTMultiPtr<T> &ptr) { + return ptr; + } + + // We can re-use the low bit of expression, statement, base, and + // member-initializer pointers for the "invalid" flag of + // ActionResult. + template<> struct IsResultPtrLowBitFree<Expr*> { + static const bool value = true; + }; + template<> struct IsResultPtrLowBitFree<Stmt*> { + static const bool value = true; + }; + template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> { + static const bool value = true; + }; + template<> struct IsResultPtrLowBitFree<CXXBaseOrMemberInitializer*> { + static const bool value = true; + }; + + /// An opaque type for threading parsed type information through the + /// parser. + typedef OpaquePtr<QualType> ParsedType; + typedef UnionOpaquePtr<QualType> UnionParsedType; + + typedef ActionResult<Expr*> ExprResult; + typedef ActionResult<Stmt*> StmtResult; + typedef ActionResult<ParsedType> TypeResult; + typedef ActionResult<CXXBaseSpecifier*> BaseResult; + typedef ActionResult<CXXBaseOrMemberInitializer*> MemInitResult; + + typedef ActionResult<Decl*> DeclResult; + typedef OpaquePtr<TemplateName> ParsedTemplateTy; + + inline Expr *move(Expr *E) { return E; } + inline Stmt *move(Stmt *S) { return S; } + + typedef ASTMultiPtr<Expr*> MultiExprArg; + typedef ASTMultiPtr<Stmt*> MultiStmtArg; + typedef ASTMultiPtr<TemplateParameterList*> MultiTemplateParamsArg; + + inline ExprResult ExprError() { return ExprResult(true); } + inline StmtResult StmtError() { return StmtResult(true); } + + inline ExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); } + inline StmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); } + + inline ExprResult ExprEmpty() { return ExprResult(false); } + inline StmtResult StmtEmpty() { return StmtResult(false); } + + inline Expr *AssertSuccess(ExprResult R) { + assert(!R.isInvalid() && "operation was asserted to never fail!"); + return R.get(); + } + + inline Stmt *AssertSuccess(StmtResult R) { + assert(!R.isInvalid() && "operation was asserted to never fail!"); + return R.get(); + } +} + +#endif diff --git a/include/clang/Parse/Template.h b/include/clang/Sema/ParsedTemplate.h index 84f4ed96b4c3..da68a494bf7b 100644 --- a/include/clang/Parse/Template.h +++ b/include/clang/Sema/ParsedTemplate.h @@ -1,4 +1,4 @@ -//===--- Template.h - Template Parsing Data Types -------------------------===// +//===--- ParsedTemplate.h - Template Parsing Data Types -------------------===// // // The LLVM Compiler Infrastructure // @@ -11,11 +11,11 @@ // templates. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PARSE_TEMPLATE_H -#define LLVM_CLANG_PARSE_TEMPLATE_H +#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H +#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H -#include "clang/Parse/DeclSpec.h" -#include "clang/Parse/Ownership.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Ownership.h" #include <cassert> namespace clang { @@ -52,9 +52,10 @@ namespace clang { /// /// \param TemplateLoc the location of the template name. ParsedTemplateArgument(const CXXScopeSpec &SS, - ActionBase::TemplateTy Template, + ParsedTemplateTy Template, SourceLocation TemplateLoc) - : Kind(ParsedTemplateArgument::Template), Arg(Template.get()), + : Kind(ParsedTemplateArgument::Template), + Arg(Template.getAsOpaquePtr()), Loc(TemplateLoc), SS(SS) { } /// \brief Determine whether the given template argument is invalid. @@ -64,21 +65,21 @@ namespace clang { KindType getKind() const { return Kind; } /// \brief Retrieve the template type argument's type. - ActionBase::TypeTy *getAsType() const { + ParsedType getAsType() const { assert(Kind == Type && "Not a template type argument"); - return Arg; + return ParsedType::getFromOpaquePtr(Arg); } /// \brief Retrieve the non-type template argument's expression. - ActionBase::ExprTy *getAsExpr() const { + Expr *getAsExpr() const { assert(Kind == NonType && "Not a non-type template argument"); - return Arg; + return static_cast<Expr*>(Arg); } /// \brief Retrieve the template template argument's template name. - ActionBase::TemplateTy getAsTemplate() const { + ParsedTemplateTy getAsTemplate() const { assert(Kind == Template && "Not a template template argument"); - return ActionBase::TemplateTy::make(Arg); + return ParsedTemplateTy::getFromOpaquePtr(Arg); } /// \brief Retrieve the location of the template argument. @@ -128,8 +129,8 @@ namespace clang { OverloadedOperatorKind Operator; /// The declaration of the template corresponding to the - /// template-name. This is an Action::TemplateTy. - void *Template; + /// template-name. + ParsedTemplateTy Template; /// The kind of template that Template refers to. TemplateNameKind Kind; @@ -161,18 +162,6 @@ namespace clang { void Destroy() { free(this); } }; -#if !defined(DISABLE_SMART_POINTERS) - inline void ASTTemplateArgsPtr::destroy() { - if (!Count) - return; - - for (unsigned I = 0; I != Count; ++I) - if (Args[I].getKind() == ParsedTemplateArgument::NonType) - Actions.DeleteExpr(Args[I].getAsExpr()); - - Count = 0; - } -#endif inline const ParsedTemplateArgument & ASTTemplateArgsPtr::operator[](unsigned Arg) const { diff --git a/include/clang/Sema/PrettyDeclStackTrace.h b/include/clang/Sema/PrettyDeclStackTrace.h new file mode 100644 index 000000000000..b78a1c01e5e3 --- /dev/null +++ b/include/clang/Sema/PrettyDeclStackTrace.h @@ -0,0 +1,46 @@ +//===- PrettyDeclStackTrace.h - Stack trace for decl processing -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an llvm::PrettyStackTraceEntry object for showing +// that a particular declaration was being processed when a crash +// occurred. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H +#define LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H + +#include "clang/Basic/SourceLocation.h" +#include "llvm/Support/PrettyStackTrace.h" + +namespace clang { + +class Decl; +class Sema; +class SourceManager; + +/// PrettyDeclStackTraceEntry - If a crash occurs in the parser while +/// parsing something related to a declaration, include that +/// declaration in the stack trace. +class PrettyDeclStackTraceEntry : public llvm::PrettyStackTraceEntry { + Sema &S; + Decl *TheDecl; + SourceLocation Loc; + const char *Message; + +public: + PrettyDeclStackTraceEntry(Sema &S, Decl *D, SourceLocation Loc, const char *Msg) + : S(S), TheDecl(D), Loc(Loc), Message(Msg) {} + + virtual void print(llvm::raw_ostream &OS) const; +}; + +} + +#endif diff --git a/include/clang/Parse/Scope.h b/include/clang/Sema/Scope.h index 023f40d3957c..4229c6c62748 100644 --- a/include/clang/Parse/Scope.h +++ b/include/clang/Sema/Scope.h @@ -11,14 +11,16 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PARSE_SCOPE_H -#define LLVM_CLANG_PARSE_SCOPE_H +#ifndef LLVM_CLANG_SEMA_SCOPE_H +#define LLVM_CLANG_SEMA_SCOPE_H -#include "clang/Parse/Action.h" #include "llvm/ADT/SmallPtrSet.h" namespace clang { +class Decl; +class UsingDirectiveDecl; + /// Scope - A scope is a transient data structure that is used while parsing the /// program. It assists with resolving identifiers to the appropriate /// declaration. @@ -72,11 +74,7 @@ public: /// ObjCMethodScope - This scope corresponds to an Objective-C method body. /// It always has FnScope and DeclScope set as well. - ObjCMethodScope = 0x400, - - /// ElseScope - This scope corresponds to an 'else' scope of an if/then/else - /// statement. - ElseScope = 0x800 + ObjCMethodScope = 0x400 }; private: /// The parent scope for this scope. This is null for the translation-unit @@ -121,7 +119,7 @@ private: /// popped, these declarations are removed from the IdentifierTable's notion /// of current declaration. It is up to the current Action implementation to /// implement these semantics. - typedef llvm::SmallPtrSet<Action::DeclPtrTy, 32> DeclSetTy; + typedef llvm::SmallPtrSet<Decl *, 32> DeclSetTy; DeclSetTy DeclsInScope; /// Entity - The entity with which this scope is associated. For @@ -130,7 +128,7 @@ private: /// maintained by the Action implementation. void *Entity; - typedef llvm::SmallVector<Action::DeclPtrTy, 2> UsingDirectivesTy; + typedef llvm::SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy; UsingDirectivesTy UsingDirectives; /// \brief The number of errors at the start of the given scope. @@ -199,17 +197,17 @@ public: decl_iterator decl_end() const { return DeclsInScope.end(); } bool decl_empty() const { return DeclsInScope.empty(); } - void AddDecl(Action::DeclPtrTy D) { + void AddDecl(Decl *D) { DeclsInScope.insert(D); } - void RemoveDecl(Action::DeclPtrTy D) { + void RemoveDecl(Decl *D) { DeclsInScope.erase(D); } /// isDeclScope - Return true if this is the scope that the specified decl is /// declared in. - bool isDeclScope(Action::DeclPtrTy D) { + bool isDeclScope(Decl *D) { return DeclsInScope.count(D) != 0; } @@ -270,7 +268,7 @@ public: typedef UsingDirectivesTy::iterator udir_iterator; typedef UsingDirectivesTy::const_iterator const_udir_iterator; - void PushUsingDirective(Action::DeclPtrTy UDir) { + void PushUsingDirective(UsingDirectiveDecl *UDir) { UsingDirectives.push_back(UDir); } diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h new file mode 100644 index 000000000000..50cfa9bb5672 --- /dev/null +++ b/include/clang/Sema/ScopeInfo.h @@ -0,0 +1,137 @@ +//===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines FunctionScopeInfo and BlockScopeInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H +#define LLVM_CLANG_SEMA_SCOPE_INFO_H + +#include "clang/AST/Type.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + +class BlockDecl; +class IdentifierInfo; +class LabelStmt; +class ReturnStmt; +class Scope; +class SwitchStmt; + +namespace sema { + +/// \brief Retains information about a function, method, or block that is +/// currently being parsed. +class FunctionScopeInfo { +public: + + /// \brief Whether this scope information structure defined information for + /// a block. + bool IsBlockInfo; + + /// \brief Whether this function contains a VLA, @try, try, C++ + /// initializer, or anything else that can't be jumped past. + bool HasBranchProtectedScope; + + /// \brief Whether this function contains any switches or direct gotos. + bool HasBranchIntoScope; + + /// \brief Whether this function contains any indirect gotos. + bool HasIndirectGoto; + + /// \brief The number of errors that had occurred before starting this + /// function or block. + unsigned NumErrorsAtStartOfFunction; + + /// LabelMap - This is a mapping from label identifiers to the LabelStmt for + /// it (which acts like the label decl in some ways). Forward referenced + /// labels have a LabelStmt created for them with a null location & SubStmt. + llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap; + + /// SwitchStack - This is the current set of active switch statements in the + /// block. + llvm::SmallVector<SwitchStmt*, 8> SwitchStack; + + /// \brief The list of return statements that occur within the function or + /// block, if there is any chance of applying the named return value + /// optimization. + llvm::SmallVector<ReturnStmt *, 4> Returns; + + void setHasBranchIntoScope() { + HasBranchIntoScope = true; + } + + void setHasBranchProtectedScope() { + HasBranchProtectedScope = true; + } + + void setHasIndirectGoto() { + HasIndirectGoto = true; + } + + bool NeedsScopeChecking() const { + return HasIndirectGoto || + (HasBranchProtectedScope && HasBranchIntoScope); + } + + FunctionScopeInfo(unsigned NumErrors) + : IsBlockInfo(false), + HasBranchProtectedScope(false), + HasBranchIntoScope(false), + HasIndirectGoto(false), + NumErrorsAtStartOfFunction(NumErrors) { } + + virtual ~FunctionScopeInfo(); + + /// \brief Clear out the information in this function scope, making it + /// suitable for reuse. + void Clear(unsigned NumErrors); + + static bool classof(const FunctionScopeInfo *FSI) { return true; } +}; + +/// \brief Retains information about a block that is currently being parsed. +class BlockScopeInfo : public FunctionScopeInfo { +public: + bool hasBlockDeclRefExprs; + + BlockDecl *TheDecl; + + /// TheScope - This is the scope for the block itself, which contains + /// arguments etc. + Scope *TheScope; + + /// ReturnType - The return type of the block, or null if the block + /// signature didn't provide an explicit return type. + QualType ReturnType; + + /// BlockType - The function type of the block, if one was given. + /// Its return type may be BuiltinType::Dependent. + QualType FunctionType; + + BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block) + : FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false), + TheDecl(Block), TheScope(BlockScope) + { + IsBlockInfo = true; + } + + virtual ~BlockScopeInfo(); + + static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; } + static bool classof(const BlockScopeInfo *BSI) { return true; } +}; + +} +} + +#endif diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h new file mode 100644 index 000000000000..4741028cb0c9 --- /dev/null +++ b/include/clang/Sema/Sema.h @@ -0,0 +1,4457 @@ +//===--- Sema.h - Semantic Analysis & AST Building --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Sema class, which performs semantic analysis and +// builds ASTs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMA_H +#define LLVM_CLANG_SEMA_SEMA_H + +#include "clang/Sema/Ownership.h" +#include "clang/Sema/AnalysisBasedWarnings.h" +#include "clang/Sema/IdentifierResolver.h" +#include "clang/Sema/ObjCMethodList.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TemplateKinds.h" +#include "clang/Basic/TypeTraits.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include <deque> +#include <string> + +namespace llvm { + class APSInt; + template <typename ValueT> struct DenseMapInfo; + template <typename ValueT, typename ValueInfoT> class DenseSet; +} + +namespace clang { + class ADLResult; + class ASTConsumer; + class ASTContext; + class ArrayType; + class AttributeList; + class BlockDecl; + class CXXBasePath; + class CXXBasePaths; + typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; + class CXXConstructorDecl; + class CXXConversionDecl; + class CXXDestructorDecl; + class CXXFieldCollector; + class CXXMemberCallExpr; + class CXXMethodDecl; + class CXXScopeSpec; + class CXXTemporary; + class CXXTryStmt; + class CallExpr; + class ClassTemplateDecl; + class ClassTemplatePartialSpecializationDecl; + class ClassTemplateSpecializationDecl; + class CodeCompleteConsumer; + class CodeCompletionResult; + class Decl; + class DeclAccessPair; + class DeclContext; + class DeclRefExpr; + class DeclaratorDecl; + class DeducedTemplateArgument; + class DependentDiagnostic; + class DesignatedInitExpr; + class Designation; + class EnumConstantDecl; + class Expr; + class ExtVectorType; + class ExternalSemaSource; + class FormatAttr; + class FriendDecl; + class FullExpr; + class FunctionDecl; + class FunctionProtoType; + class FunctionTemplateDecl; + class ImplicitConversionSequence; + class InitListExpr; + class InitializationKind; + class InitializationSequence; + class InitializedEntity; + class IntegerLiteral; + class LabelStmt; + class LangOptions; + class LocalInstantiationScope; + class LookupResult; + class MacroInfo; + class MultiLevelTemplateArgumentList; + class NamedDecl; + class NonNullAttr; + class ObjCCategoryDecl; + class ObjCCategoryImplDecl; + class ObjCCompatibleAliasDecl; + class ObjCContainerDecl; + class ObjCImplDecl; + class ObjCImplementationDecl; + class ObjCInterfaceDecl; + class ObjCIvarDecl; + template <class T> class ObjCList; + class ObjCMethodDecl; + class ObjCPropertyDecl; + class ObjCProtocolDecl; + class OverloadCandidateSet; + class ParenListExpr; + class ParmVarDecl; + class Preprocessor; + class PseudoDestructorTypeStorage; + class QualType; + class StandardConversionSequence; + class Stmt; + class StringLiteral; + class SwitchStmt; + class TargetAttributesSema; + class TemplateArgument; + class TemplateArgumentList; + class TemplateArgumentListBuilder; + class TemplateArgumentLoc; + class TemplateDecl; + class TemplateParameterList; + class TemplatePartialOrderingContext; + class TemplateTemplateParmDecl; + class Token; + class TypedefDecl; + class UnqualifiedId; + class UnresolvedLookupExpr; + class UnresolvedMemberExpr; + class UnresolvedSetImpl; + class UnresolvedSetIterator; + class UsingDecl; + class UsingShadowDecl; + class ValueDecl; + class VarDecl; + class VisibilityAttr; + class VisibleDeclConsumer; + +namespace sema { + class AccessedEntity; + class BlockScopeInfo; + class DelayedDiagnostic; + class FunctionScopeInfo; + class TemplateDeductionInfo; +} + +/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator +/// parsing. +/// +/// LocInfoType is a "transient" type, only needed for passing to/from Parser +/// and Sema, when we want to preserve type source info for a parsed type. +/// It will not participate in the type system semantics in any way. +class LocInfoType : public Type { + enum { + // The last number that can fit in Type's TC. + // Avoids conflict with an existing Type class. + LocInfo = Type::TypeLast + 1 + }; + + TypeSourceInfo *DeclInfo; + + LocInfoType(QualType ty, TypeSourceInfo *TInfo) + : Type((TypeClass)LocInfo, ty, ty->isDependentType()), DeclInfo(TInfo) { + assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?"); + } + friend class Sema; + +public: + QualType getType() const { return getCanonicalTypeInternal(); } + TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; } + + void getAsStringInternal(std::string &Str, + const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == (TypeClass)LocInfo; + } + static bool classof(const LocInfoType *) { return true; } +}; + +/// Sema - This implements semantic analysis and AST building for C. +class Sema { + Sema(const Sema&); // DO NOT IMPLEMENT + void operator=(const Sema&); // DO NOT IMPLEMENT + mutable const TargetAttributesSema* TheTargetAttributesSema; +public: + typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy; + typedef OpaquePtr<TemplateName> TemplateTy; + typedef OpaquePtr<QualType> TypeTy; + typedef Attr AttrTy; + typedef CXXBaseSpecifier BaseTy; + typedef CXXBaseOrMemberInitializer MemInitTy; + typedef Expr ExprTy; + typedef Stmt StmtTy; + typedef TemplateParameterList TemplateParamsTy; + typedef NestedNameSpecifier CXXScopeTy; + + const LangOptions &LangOpts; + Preprocessor &PP; + ASTContext &Context; + ASTConsumer &Consumer; + Diagnostic &Diags; + SourceManager &SourceMgr; + + /// \brief Source of additional semantic information. + ExternalSemaSource *ExternalSource; + + /// \brief Code-completion consumer. + CodeCompleteConsumer *CodeCompleter; + + /// CurContext - This is the current declaration context of parsing. + DeclContext *CurContext; + + /// VAListTagName - The declaration name corresponding to __va_list_tag. + /// This is used as part of a hack to omit that class from ADL results. + DeclarationName VAListTagName; + + /// A RAII object to temporarily push a declaration context. + class ContextRAII { + private: + Sema &S; + DeclContext *SavedContext; + + public: + ContextRAII(Sema &S, DeclContext *ContextToPush) + : S(S), SavedContext(S.CurContext) { + assert(ContextToPush && "pushing null context"); + S.CurContext = ContextToPush; + } + + void pop() { + if (!SavedContext) return; + S.CurContext = SavedContext; + SavedContext = 0; + } + + ~ContextRAII() { + pop(); + } + }; + + /// PackContext - Manages the stack for #pragma pack. An alignment + /// of 0 indicates default alignment. + void *PackContext; // Really a "PragmaPackStack*" + + /// VisContext - Manages the stack for #pragma GCC visibility. + void *VisContext; // Really a "PragmaVisStack*" + + /// \brief Stack containing information about each of the nested + /// function, block, and method scopes that are currently active. + /// + /// This array is never empty. Clients should ignore the first + /// element, which is used to cache a single FunctionScopeInfo + /// that's used to parse every top-level function. + llvm::SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes; + + /// ExprTemporaries - This is the stack of temporaries that are created by + /// the current full expression. + llvm::SmallVector<CXXTemporary*, 8> ExprTemporaries; + + /// ExtVectorDecls - This is a list all the extended vector types. This allows + /// us to associate a raw vector type with one of the ext_vector type names. + /// This is only necessary for issuing pretty diagnostics. + llvm::SmallVector<TypedefDecl*, 24> ExtVectorDecls; + + /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. + llvm::OwningPtr<CXXFieldCollector> FieldCollector; + + typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy; + + /// PureVirtualClassDiagSet - a set of class declarations which we have + /// emitted a list of pure virtual functions. Used to prevent emitting the + /// same list more than once. + llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet; + + /// \brief A mapping from external names to the most recent + /// locally-scoped external declaration with that name. + /// + /// This map contains external declarations introduced in local + /// scoped, e.g., + /// + /// \code + /// void f() { + /// void foo(int, int); + /// } + /// \endcode + /// + /// Here, the name "foo" will be associated with the declaration on + /// "foo" within f. This name is not visible outside of + /// "f". However, we still find it in two cases: + /// + /// - If we are declaring another external with the name "foo", we + /// can find "foo" as a previous declaration, so that the types + /// of this external declaration can be checked for + /// compatibility. + /// + /// - If we would implicitly declare "foo" (e.g., due to a call to + /// "foo" in C when no prototype or definition is visible), then + /// we find this declaration of "foo" and complain that it is + /// not visible. + llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls; + + /// \brief All the tentative definitions encountered in the TU. + llvm::SmallVector<VarDecl *, 2> TentativeDefinitions; + + /// \brief The set of file scoped decls seen so far that have not been used + /// and must warn if not used. Only contains the first declaration. + llvm::SmallVector<const DeclaratorDecl*, 4> UnusedFileScopedDecls; + + /// \brief The stack of diagnostics that were delayed due to being + /// produced during the parsing of a declaration. + llvm::SmallVector<sema::DelayedDiagnostic, 0> DelayedDiagnostics; + + /// \brief The depth of the current ParsingDeclaration stack. + /// If nonzero, we are currently parsing a declaration (and + /// hence should delay deprecation warnings). + unsigned ParsingDeclDepth; + + /// WeakUndeclaredIdentifiers - Identifiers contained in + /// #pragma weak before declared. rare. may alias another + /// identifier, declared or undeclared + class WeakInfo { + IdentifierInfo *alias; // alias (optional) + SourceLocation loc; // for diagnostics + bool used; // identifier later declared? + public: + WeakInfo() + : alias(0), loc(SourceLocation()), used(false) {} + WeakInfo(IdentifierInfo *Alias, SourceLocation Loc) + : alias(Alias), loc(Loc), used(false) {} + inline IdentifierInfo * getAlias() const { return alias; } + inline SourceLocation getLocation() const { return loc; } + void setUsed(bool Used=true) { used = Used; } + inline bool getUsed() { return used; } + bool operator==(WeakInfo RHS) const { + return alias == RHS.getAlias() && loc == RHS.getLocation(); + } + bool operator!=(WeakInfo RHS) const { return !(*this == RHS); } + }; + llvm::DenseMap<IdentifierInfo*,WeakInfo> WeakUndeclaredIdentifiers; + + /// WeakTopLevelDecl - Translation-unit scoped declarations generated by + /// #pragma weak during processing of other Decls. + /// I couldn't figure out a clean way to generate these in-line, so + /// we store them here and handle separately -- which is a hack. + /// It would be best to refactor this. + llvm::SmallVector<Decl*,2> WeakTopLevelDecl; + + IdentifierResolver IdResolver; + + /// Translation Unit Scope - useful to Objective-C actions that need + /// to lookup file scope declarations in the "ordinary" C decl namespace. + /// For example, user-defined classes, built-in "id" type, etc. + Scope *TUScope; + + /// \brief The C++ "std" namespace, where the standard library resides. + LazyDeclPtr StdNamespace; + + /// \brief The C++ "std::bad_alloc" class, which is defined by the C++ + /// standard library. + LazyDeclPtr StdBadAlloc; + + /// A flag to remember whether the implicit forms of operator new and delete + /// have been declared. + bool GlobalNewDeleteDeclared; + + /// \brief The set of declarations that have been referenced within + /// a potentially evaluated expression. + typedef llvm::SmallVector<std::pair<SourceLocation, Decl *>, 10> + PotentiallyReferencedDecls; + + /// \brief A set of diagnostics that may be emitted. + typedef llvm::SmallVector<std::pair<SourceLocation, PartialDiagnostic>, 10> + PotentiallyEmittedDiagnostics; + + /// \brief Describes how the expressions currently being parsed are + /// evaluated at run-time, if at all. + enum ExpressionEvaluationContext { + /// \brief The current expression and its subexpressions occur within an + /// unevaluated operand (C++0x [expr]p8), such as a constant expression + /// or the subexpression of \c sizeof, where the type or the value of the + /// expression may be significant but no code will be generated to evaluate + /// the value of the expression at run time. + Unevaluated, + + /// \brief The current expression is potentially evaluated at run time, + /// which means that code may be generated to evaluate the value of the + /// expression at run time. + PotentiallyEvaluated, + + /// \brief The current expression may be potentially evaluated or it may + /// be unevaluated, but it is impossible to tell from the lexical context. + /// This evaluation context is used primary for the operand of the C++ + /// \c typeid expression, whose argument is potentially evaluated only when + /// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2). + PotentiallyPotentiallyEvaluated + }; + + /// \brief Data structure used to record current or nested + /// expression evaluation contexts. + struct ExpressionEvaluationContextRecord { + /// \brief The expression evaluation context. + ExpressionEvaluationContext Context; + + /// \brief The number of temporaries that were active when we + /// entered this expression evaluation context. + unsigned NumTemporaries; + + /// \brief The set of declarations referenced within a + /// potentially potentially-evaluated context. + /// + /// When leaving a potentially potentially-evaluated context, each + /// of these elements will be as referenced if the corresponding + /// potentially potentially evaluated expression is potentially + /// evaluated. + PotentiallyReferencedDecls *PotentiallyReferenced; + + /// \brief The set of diagnostics to emit should this potentially + /// potentially-evaluated context become evaluated. + PotentiallyEmittedDiagnostics *PotentiallyDiagnosed; + + ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, + unsigned NumTemporaries) + : Context(Context), NumTemporaries(NumTemporaries), + PotentiallyReferenced(0), PotentiallyDiagnosed(0) { } + + void addReferencedDecl(SourceLocation Loc, Decl *Decl) { + if (!PotentiallyReferenced) + PotentiallyReferenced = new PotentiallyReferencedDecls; + PotentiallyReferenced->push_back(std::make_pair(Loc, Decl)); + } + + void addDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) { + if (!PotentiallyDiagnosed) + PotentiallyDiagnosed = new PotentiallyEmittedDiagnostics; + PotentiallyDiagnosed->push_back(std::make_pair(Loc, PD)); + } + + void Destroy() { + delete PotentiallyReferenced; + delete PotentiallyDiagnosed; + PotentiallyReferenced = 0; + PotentiallyDiagnosed = 0; + } + }; + + /// A stack of expression evaluation contexts. + llvm::SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts; + + /// \brief Whether the code handled by Sema should be considered a + /// complete translation unit or not. + /// + /// When true (which is generally the case), Sema will perform + /// end-of-translation-unit semantic tasks (such as creating + /// initializers for tentative definitions in C) once parsing has + /// completed. This flag will be false when building PCH files, + /// since a PCH file is by definition not a complete translation + /// unit. + bool CompleteTranslationUnit; + + llvm::BumpPtrAllocator BumpAlloc; + + /// \brief The number of SFINAE diagnostics that have been trapped. + unsigned NumSFINAEErrors; + + typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods; + typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool; + + /// Method Pool - allows efficient lookup when typechecking messages to "id". + /// We need to maintain a list, since selectors can have differing signatures + /// across classes. In Cocoa, this happens to be extremely uncommon (only 1% + /// of selectors are "overloaded"). + GlobalMethodPool MethodPool; + + /// Method selectors used in a @selector expression. Used for implementation + /// of -Wselector. + llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors; + + + GlobalMethodPool::iterator ReadMethodPool(Selector Sel); + + /// Private Helper predicate to check for 'self'. + bool isSelfExpr(Expr *RExpr); +public: + Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, + bool CompleteTranslationUnit = true, + CodeCompleteConsumer *CompletionConsumer = 0); + ~Sema(); + + /// \brief Perform initialization that occurs after the parser has been + /// initialized but before it parses anything. + void Initialize(); + + const LangOptions &getLangOptions() const { return LangOpts; } + Diagnostic &getDiagnostics() const { return Diags; } + SourceManager &getSourceManager() const { return SourceMgr; } + const TargetAttributesSema &getTargetAttributesSema() const; + Preprocessor &getPreprocessor() const { return PP; } + ASTContext &getASTContext() const { return Context; } + ASTConsumer &getASTConsumer() const { return Consumer; } + + /// \brief Helper class that creates diagnostics with optional + /// template instantiation stacks. + /// + /// This class provides a wrapper around the basic DiagnosticBuilder + /// class that emits diagnostics. SemaDiagnosticBuilder is + /// responsible for emitting the diagnostic (as DiagnosticBuilder + /// does) and, if the diagnostic comes from inside a template + /// instantiation, printing the template instantiation stack as + /// well. + class SemaDiagnosticBuilder : public DiagnosticBuilder { + Sema &SemaRef; + unsigned DiagID; + + public: + SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID) + : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { } + + explicit SemaDiagnosticBuilder(Sema &SemaRef) + : DiagnosticBuilder(DiagnosticBuilder::Suppress), SemaRef(SemaRef) { } + + ~SemaDiagnosticBuilder(); + }; + + /// \brief Emit a diagnostic. + SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + + /// \brief Emit a partial diagnostic. + SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD); + + /// \brief Build a partial diagnostic. + PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h + + ExprResult Owned(Expr* E) { return E; } + ExprResult Owned(ExprResult R) { return R; } + StmtResult Owned(Stmt* S) { return S; } + + void ActOnEndOfTranslationUnit(); + + Scope *getScopeForContext(DeclContext *Ctx); + + void PushFunctionScope(); + void PushBlockScope(Scope *BlockScope, BlockDecl *Block); + void PopFunctionOrBlockScope(); + + sema::FunctionScopeInfo *getCurFunction() const { + return FunctionScopes.back(); + } + + bool hasAnyErrorsInThisFunction() const; + + /// \brief Retrieve the current block, if any. + sema::BlockScopeInfo *getCurBlock(); + + /// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls + llvm::SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; } + + //===--------------------------------------------------------------------===// + // Type Analysis / Processing: SemaType.cpp. + // + + QualType adjustParameterType(QualType T); + QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs); + QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR) { + return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR)); + } + QualType BuildPointerType(QualType T, + SourceLocation Loc, DeclarationName Entity); + QualType BuildReferenceType(QualType T, bool LValueRef, + SourceLocation Loc, DeclarationName Entity); + QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, + Expr *ArraySize, unsigned Quals, + SourceRange Brackets, DeclarationName Entity); + QualType BuildExtVectorType(QualType T, Expr *ArraySize, + SourceLocation AttrLoc); + QualType BuildFunctionType(QualType T, + QualType *ParamTypes, unsigned NumParamTypes, + bool Variadic, unsigned Quals, + SourceLocation Loc, DeclarationName Entity, + const FunctionType::ExtInfo &Info); + QualType BuildMemberPointerType(QualType T, QualType Class, + SourceLocation Loc, + DeclarationName Entity); + QualType BuildBlockPointerType(QualType T, + SourceLocation Loc, DeclarationName Entity); + TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S, + TagDecl **OwnedDecl = 0); + TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, + TypeSourceInfo *ReturnTypeInfo); + /// \brief Package the given type and TSI into a ParsedType. + ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo); + DeclarationNameInfo GetNameForDeclarator(Declarator &D); + DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name); + static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo = 0); + bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range); + bool CheckDistantExceptionSpec(QualType T); + bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); + bool CheckEquivalentExceptionSpec( + const FunctionProtoType *Old, SourceLocation OldLoc, + const FunctionProtoType *New, SourceLocation NewLoc); + bool CheckEquivalentExceptionSpec( + const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, + const FunctionProtoType *Old, SourceLocation OldLoc, + const FunctionProtoType *New, SourceLocation NewLoc, + bool *MissingExceptionSpecification = 0, + bool *MissingEmptyExceptionSpecification = 0); + bool CheckExceptionSpecSubset( + const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, + const FunctionProtoType *Superset, SourceLocation SuperLoc, + const FunctionProtoType *Subset, SourceLocation SubLoc); + bool CheckParamExceptionSpec(const PartialDiagnostic & NoteID, + const FunctionProtoType *Target, SourceLocation TargetLoc, + const FunctionProtoType *Source, SourceLocation SourceLoc); + + TypeResult ActOnTypeName(Scope *S, Declarator &D); + + bool RequireCompleteType(SourceLocation Loc, QualType T, + const PartialDiagnostic &PD, + std::pair<SourceLocation, PartialDiagnostic> Note); + bool RequireCompleteType(SourceLocation Loc, QualType T, + const PartialDiagnostic &PD); + bool RequireCompleteType(SourceLocation Loc, QualType T, + unsigned DiagID); + + QualType getElaboratedType(ElaboratedTypeKeyword Keyword, + const CXXScopeSpec &SS, QualType T); + + QualType BuildTypeofExprType(Expr *E); + QualType BuildDecltypeType(Expr *E); + + //===--------------------------------------------------------------------===// + // Symbol table / Decl tracking callbacks: SemaDecl.cpp. + // + + DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr); + + void DiagnoseUseOfUnimplementedSelectors(); + + ParsedType getTypeName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec *SS = 0, + bool isClassName = false, + ParsedType ObjectType = ParsedType()); + TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); + bool DiagnoseUnknownTypeName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + CXXScopeSpec *SS, + ParsedType &SuggestedType); + + Decl *ActOnDeclarator(Scope *S, Declarator &D); + + Decl *HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + bool IsFunctionDefinition); + void RegisterLocallyScopedExternCDecl(NamedDecl *ND, + const LookupResult &Previous, + Scope *S); + void DiagnoseFunctionSpecifiers(Declarator& D); + void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); + void CheckShadow(Scope *S, VarDecl *D); + void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); + NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, + QualType R, TypeSourceInfo *TInfo, + LookupResult &Previous, bool &Redeclaration); + NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, + QualType R, TypeSourceInfo *TInfo, + LookupResult &Previous, + MultiTemplateParamsArg TemplateParamLists, + bool &Redeclaration); + void CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous, + bool &Redeclaration); + NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, + QualType R, TypeSourceInfo *TInfo, + LookupResult &Previous, + MultiTemplateParamsArg TemplateParamLists, + bool IsFunctionDefinition, + bool &Redeclaration); + void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); + void CheckFunctionDeclaration(Scope *S, + FunctionDecl *NewFD, LookupResult &Previous, + bool IsExplicitSpecialization, + bool &Redeclaration, + bool &OverloadableAttrRequired); + void CheckMain(FunctionDecl *FD); + Decl *ActOnParamDeclarator(Scope *S, Declarator &D); + ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, + SourceLocation Loc, + QualType T); + ParmVarDecl *CheckParameter(DeclContext *DC, + TypeSourceInfo *TSInfo, QualType T, + IdentifierInfo *Name, + SourceLocation NameLoc, + StorageClass SC, + StorageClass SCAsWritten); + void ActOnParamDefaultArgument(Decl *param, + SourceLocation EqualLoc, + Expr *defarg); + void ActOnParamUnparsedDefaultArgument(Decl *param, + SourceLocation EqualLoc, + SourceLocation ArgLoc); + void ActOnParamDefaultArgumentError(Decl *param); + bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, + SourceLocation EqualLoc); + + + // Contains the locations of the beginning of unparsed default + // argument locations. + llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs; + + void AddInitializerToDecl(Decl *dcl, Expr *init); + void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit); + void ActOnUninitializedDecl(Decl *dcl, bool TypeContainsUndeducedAuto); + void ActOnInitializerError(Decl *Dcl); + void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); + DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, + Decl **Group, + unsigned NumDecls); + void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, + SourceLocation LocAfterDecls); + Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D); + Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D); + void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); + + Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); + Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation); + + /// \brief Diagnose any unused parameters in the given sequence of + /// ParmVarDecl pointers. + void DiagnoseUnusedParameters(ParmVarDecl * const *Begin, + ParmVarDecl * const *End); + + void DiagnoseInvalidJumps(Stmt *Body); + Decl *ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr); + + /// Scope actions. + void ActOnPopScope(SourceLocation Loc, Scope *S); + void ActOnTranslationUnitScope(Scope *S); + + /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with + /// no declarator (e.g. "struct foo;") is parsed. + Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS); + + Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, + AccessSpecifier AS, + RecordDecl *Record); + + bool isAcceptableTagRedeclaration(const TagDecl *Previous, + TagTypeKind NewTag, + SourceLocation NewTagLoc, + const IdentifierInfo &Name); + + enum TagUseKind { + TUK_Reference, // Reference to a tag: 'struct foo *X;' + TUK_Declaration, // Fwd decl of a tag: 'struct foo;' + TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;' + TUK_Friend // Friend declaration: 'friend struct foo;' + }; + + Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, AccessSpecifier AS, + MultiTemplateParamsArg TemplateParameterLists, + bool &OwnedDecl, bool &IsDependent); + + TypeResult ActOnDependentTag(Scope *S, + unsigned TagSpec, + TagUseKind TUK, + const CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation TagLoc, + SourceLocation NameLoc); + + void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, + IdentifierInfo *ClassName, + llvm::SmallVectorImpl<Decl *> &Decls); + Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, + Declarator &D, Expr *BitfieldWidth); + + FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart, + Declarator &D, Expr *BitfieldWidth, + AccessSpecifier AS); + + FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, + TypeSourceInfo *TInfo, + RecordDecl *Record, SourceLocation Loc, + bool Mutable, Expr *BitfieldWidth, + SourceLocation TSSL, + AccessSpecifier AS, NamedDecl *PrevDecl, + Declarator *D = 0); + + enum CXXSpecialMember { + CXXInvalid = -1, + CXXConstructor = 0, + CXXCopyConstructor = 1, + CXXCopyAssignment = 2, + CXXDestructor = 3 + }; + bool CheckNontrivialField(FieldDecl *FD); + void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem); + CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD); + void ActOnLastBitfield(SourceLocation DeclStart, Decl *IntfDecl, + llvm::SmallVectorImpl<Decl *> &AllIvarDecls); + Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Decl *IntfDecl, + Declarator &D, Expr *BitfieldWidth, + tok::ObjCKeywordKind visibility); + + // This is used for both record definitions and ObjC interface declarations. + void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl, + Decl **Fields, unsigned NumFields, + SourceLocation LBrac, SourceLocation RBrac, + AttributeList *AttrList); + + /// ActOnTagStartDefinition - Invoked when we have entered the + /// scope of a tag's definition (e.g., for an enumeration, class, + /// struct, or union). + void ActOnTagStartDefinition(Scope *S, Decl *TagDecl); + + /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a + /// C++ record definition's base-specifiers clause and are starting its + /// member declarations. + void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl, + SourceLocation LBraceLoc); + + /// ActOnTagFinishDefinition - Invoked once we have finished parsing + /// the definition of a tag (enumeration, class, struct, or union). + void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl, + SourceLocation RBraceLoc); + + /// ActOnTagDefinitionError - Invoked when there was an unrecoverable + /// error parsing the definition of a tag. + void ActOnTagDefinitionError(Scope *S, Decl *TagDecl); + + EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum, + EnumConstantDecl *LastEnumConst, + SourceLocation IdLoc, + IdentifierInfo *Id, + Expr *val); + + Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant, + SourceLocation IdLoc, IdentifierInfo *Id, + SourceLocation EqualLoc, Expr *Val); + void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, + SourceLocation RBraceLoc, Decl *EnumDecl, + Decl **Elements, unsigned NumElements, + Scope *S, AttributeList *Attr); + + DeclContext *getContainingDC(DeclContext *DC); + + /// Set the current declaration context until it gets popped. + void PushDeclContext(Scope *S, DeclContext *DC); + void PopDeclContext(); + + /// EnterDeclaratorContext - Used when we must lookup names in the context + /// of a declarator's nested name specifier. + void EnterDeclaratorContext(Scope *S, DeclContext *DC); + void ExitDeclaratorContext(Scope *S); + + DeclContext *getFunctionLevelDeclContext(); + + /// getCurFunctionDecl - If inside of a function body, this returns a pointer + /// to the function decl for the function being parsed. If we're currently + /// in a 'block', this returns the containing context. + FunctionDecl *getCurFunctionDecl(); + + /// getCurMethodDecl - If inside of a method body, this returns a pointer to + /// the method decl for the method being parsed. If we're currently + /// in a 'block', this returns the containing context. + ObjCMethodDecl *getCurMethodDecl(); + + /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method + /// or C function we're in, otherwise return null. If we're currently + /// in a 'block', this returns the containing context. + NamedDecl *getCurFunctionOrMethodDecl(); + + /// Add this decl to the scope shadowed decl chains. + void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true); + + /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true + /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns + /// true if 'D' belongs to the given declaration context. + bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0); + + /// Finds the scope corresponding to the given decl context, if it + /// happens to be an enclosing scope. Otherwise return NULL. + static Scope *getScopeForDeclContext(Scope *S, DeclContext *DC); + + /// Subroutines of ActOnDeclarator(). + TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, + TypeSourceInfo *TInfo); + void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls); + bool MergeFunctionDecl(FunctionDecl *New, Decl *Old); + bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old); + void MergeVarDecl(VarDecl *New, LookupResult &OldDecls); + bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old); + + // AssignmentAction - This is used by all the assignment diagnostic functions + // to represent what is actually causing the operation + enum AssignmentAction { + AA_Assigning, + AA_Passing, + AA_Returning, + AA_Converting, + AA_Initializing, + AA_Sending, + AA_Casting + }; + + /// C++ Overloading. + enum OverloadKind { + /// This is a legitimate overload: the existing declarations are + /// functions or function templates with different signatures. + Ovl_Overload, + + /// This is not an overload because the signature exactly matches + /// an existing declaration. + Ovl_Match, + + /// This is not an overload because the lookup results contain a + /// non-function. + Ovl_NonFunction + }; + OverloadKind CheckOverload(Scope *S, + FunctionDecl *New, + const LookupResult &OldDecls, + NamedDecl *&OldDecl, + bool IsForUsingDecl); + bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl); + + bool TryImplicitConversion(InitializationSequence &Sequence, + const InitializedEntity &Entity, + Expr *From, + bool SuppressUserConversions, + bool AllowExplicit, + bool InOverloadResolution); + + bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType); + bool IsFloatingPointPromotion(QualType FromType, QualType ToType); + bool IsComplexPromotion(QualType FromType, QualType ToType); + bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType, + bool InOverloadResolution, + QualType& ConvertedType, bool &IncompatibleObjC); + bool isObjCPointerConversion(QualType FromType, QualType ToType, + QualType& ConvertedType, bool &IncompatibleObjC); + bool FunctionArgTypesAreEqual (FunctionProtoType* OldType, + FunctionProtoType* NewType); + + bool CheckPointerConversion(Expr *From, QualType ToType, + CastKind &Kind, + CXXCastPath& BasePath, + bool IgnoreBaseAccess); + bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType, + bool InOverloadResolution, + QualType &ConvertedType); + bool CheckMemberPointerConversion(Expr *From, QualType ToType, + CastKind &Kind, + CXXCastPath &BasePath, + bool IgnoreBaseAccess); + bool IsQualificationConversion(QualType FromType, QualType ToType); + bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); + + + ExprResult PerformCopyInitialization(const InitializedEntity &Entity, + SourceLocation EqualLoc, + ExprResult Init); + bool PerformObjectArgumentInitialization(Expr *&From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + CXXMethodDecl *Method); + + bool PerformContextuallyConvertToBool(Expr *&From); + bool PerformContextuallyConvertToObjCId(Expr *&From); + + ExprResult + ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE, + const PartialDiagnostic &NotIntDiag, + const PartialDiagnostic &IncompleteDiag, + const PartialDiagnostic &ExplicitConvDiag, + const PartialDiagnostic &ExplicitConvNote, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &AmbigNote, + const PartialDiagnostic &ConvDiag); + + bool PerformObjectMemberConversion(Expr *&From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + NamedDecl *Member); + + // Members have to be NamespaceDecl* or TranslationUnitDecl*. + // TODO: make this is a typesafe union. + typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet; + typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet; + + void AddOverloadCandidate(NamedDecl *Function, + DeclAccessPair FoundDecl, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet); + + void AddOverloadCandidate(FunctionDecl *Function, + DeclAccessPair FoundDecl, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions = false, + bool PartialOverloading = false); + void AddFunctionCandidates(const UnresolvedSetImpl &Functions, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions = false); + void AddMethodCandidate(DeclAccessPair FoundDecl, + QualType ObjectType, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversion = false); + void AddMethodCandidate(CXXMethodDecl *Method, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions = false); + void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + QualType ObjectType, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions = false); + void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, + DeclAccessPair FoundDecl, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions = false); + void AddConversionCandidate(CXXConversionDecl *Conversion, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + Expr *From, QualType ToType, + OverloadCandidateSet& CandidateSet); + void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + Expr *From, QualType ToType, + OverloadCandidateSet &CandidateSet); + void AddSurrogateCandidate(CXXConversionDecl *Conversion, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + const FunctionProtoType *Proto, + QualType ObjectTy, Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet); + void AddMemberOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + SourceRange OpRange = SourceRange()); + void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool IsAssignmentOperator = false, + unsigned NumContextualBoolArguments = 0); + void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet); + void AddArgumentDependentLookupCandidates(DeclarationName Name, + bool Operator, + Expr **Args, unsigned NumArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + OverloadCandidateSet& CandidateSet, + bool PartialOverloading = false); + + void NoteOverloadCandidate(FunctionDecl *Fn); + + FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, + bool Complain, + DeclAccessPair &Found); + FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From); + + Expr *FixOverloadedFunctionReference(Expr *E, + DeclAccessPair FoundDecl, + FunctionDecl *Fn); + ExprResult FixOverloadedFunctionReference(ExprResult, + DeclAccessPair FoundDecl, + FunctionDecl *Fn); + + void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet, + bool PartialOverloading = false); + + ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn, + UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc); + + ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, + unsigned Opc, + const UnresolvedSetImpl &Fns, + Expr *input); + + ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, + unsigned Opc, + const UnresolvedSetImpl &Fns, + Expr *LHS, Expr *RHS); + + ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, + SourceLocation RLoc, + Expr *Base,Expr *Idx); + + ExprResult + BuildCallToMemberFunction(Scope *S, Expr *MemExpr, + SourceLocation LParenLoc, Expr **Args, + unsigned NumArgs, SourceLocation *CommaLocs, + SourceLocation RParenLoc); + ExprResult + BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc); + + ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, + SourceLocation OpLoc); + + /// CheckCallReturnType - Checks that a call expression's return type is + /// complete. Returns true on failure. The location passed in is the location + /// that best represents the call. + bool CheckCallReturnType(QualType ReturnType, SourceLocation Loc, + CallExpr *CE, FunctionDecl *FD); + + /// Helpers for dealing with blocks and functions. + bool CheckParmsForFunctionDef(FunctionDecl *FD); + void CheckCXXDefaultArguments(FunctionDecl *FD); + void CheckExtraCXXDefaultArguments(Declarator &D); + Scope *getNonFieldDeclScope(Scope *S); + + /// \name Name lookup + /// + /// These routines provide name lookup that is used during semantic + /// analysis to resolve the various kinds of names (identifiers, + /// overloaded operator names, constructor names, etc.) into zero or + /// more declarations within a particular scope. The major entry + /// points are LookupName, which performs unqualified name lookup, + /// and LookupQualifiedName, which performs qualified name lookup. + /// + /// All name lookup is performed based on some specific criteria, + /// which specify what names will be visible to name lookup and how + /// far name lookup should work. These criteria are important both + /// for capturing language semantics (certain lookups will ignore + /// certain names, for example) and for performance, since name + /// lookup is often a bottleneck in the compilation of C++. Name + /// lookup criteria is specified via the LookupCriteria enumeration. + /// + /// The results of name lookup can vary based on the kind of name + /// lookup performed, the current language, and the translation + /// unit. In C, for example, name lookup will either return nothing + /// (no entity found) or a single declaration. In C++, name lookup + /// can additionally refer to a set of overloaded functions or + /// result in an ambiguity. All of the possible results of name + /// lookup are captured by the LookupResult class, which provides + /// the ability to distinguish among them. + //@{ + + /// @brief Describes the kind of name lookup to perform. + enum LookupNameKind { + /// Ordinary name lookup, which finds ordinary names (functions, + /// variables, typedefs, etc.) in C and most kinds of names + /// (functions, variables, members, types, etc.) in C++. + LookupOrdinaryName = 0, + /// Tag name lookup, which finds the names of enums, classes, + /// structs, and unions. + LookupTagName, + /// Member name lookup, which finds the names of + /// class/struct/union members. + LookupMemberName, + // Look up of an operator name (e.g., operator+) for use with + // operator overloading. This lookup is similar to ordinary name + // lookup, but will ignore any declarations that are class + // members. + LookupOperatorName, + /// Look up of a name that precedes the '::' scope resolution + /// operator in C++. This lookup completely ignores operator, object, + /// function, and enumerator names (C++ [basic.lookup.qual]p1). + LookupNestedNameSpecifierName, + /// Look up a namespace name within a C++ using directive or + /// namespace alias definition, ignoring non-namespace names (C++ + /// [basic.lookup.udir]p1). + LookupNamespaceName, + /// Look up all declarations in a scope with the given name, + /// including resolved using declarations. This is appropriate + /// for checking redeclarations for a using declaration. + LookupUsingDeclName, + /// Look up an ordinary name that is going to be redeclared as a + /// name with linkage. This lookup ignores any declarations that + /// are outside of the current scope unless they have linkage. See + /// C99 6.2.2p4-5 and C++ [basic.link]p6. + LookupRedeclarationWithLinkage, + /// Look up the name of an Objective-C protocol. + LookupObjCProtocolName, + /// \brief Look up any declaration with any name. + LookupAnyName + }; + + /// \brief Specifies whether (or how) name lookup is being performed for a + /// redeclaration (vs. a reference). + enum RedeclarationKind { + /// \brief The lookup is a reference to this name that is not for the + /// purpose of redeclaring the name. + NotForRedeclaration = 0, + /// \brief The lookup results will be used for redeclaration of a name, + /// if an entity by that name already exists. + ForRedeclaration + }; + +private: + bool CppLookupName(LookupResult &R, Scope *S); + +public: + /// \brief Look up a name, looking for a single declaration. Return + /// null if the results were absent, ambiguous, or overloaded. + /// + /// It is preferable to use the elaborated form and explicitly handle + /// ambiguity and overloaded. + NamedDecl *LookupSingleName(Scope *S, DeclarationName Name, + SourceLocation Loc, + LookupNameKind NameKind, + RedeclarationKind Redecl + = NotForRedeclaration); + bool LookupName(LookupResult &R, Scope *S, + bool AllowBuiltinCreation = false); + bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, + bool InUnqualifiedLookup = false); + bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, + bool AllowBuiltinCreation = false, + bool EnteringContext = false); + ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc); + + void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, + QualType T1, QualType T2, + UnresolvedSetImpl &Functions); + + DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class); + CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); + + void ArgumentDependentLookup(DeclarationName Name, bool Operator, + Expr **Args, unsigned NumArgs, + ADLResult &Functions); + + void LookupVisibleDecls(Scope *S, LookupNameKind Kind, + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope = true); + void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope = true); + + /// \brief The context in which typo-correction occurs. + /// + /// The typo-correction context affects which keywords (if any) are + /// considered when trying to correct for typos. + enum CorrectTypoContext { + /// \brief An unknown context, where any keyword might be valid. + CTC_Unknown, + /// \brief A context where no keywords are used (e.g. we expect an actual + /// name). + CTC_NoKeywords, + /// \brief A context where we're correcting a type name. + CTC_Type, + /// \brief An expression context. + CTC_Expression, + /// \brief A type cast, or anything else that can be followed by a '<'. + CTC_CXXCasts, + /// \brief A member lookup context. + CTC_MemberLookup, + /// \brief The receiver of an Objective-C message send within an + /// Objective-C method where 'super' is a valid keyword. + CTC_ObjCMessageReceiver + }; + + DeclarationName CorrectTypo(LookupResult &R, Scope *S, CXXScopeSpec *SS, + DeclContext *MemberContext = 0, + bool EnteringContext = false, + CorrectTypoContext CTC = CTC_Unknown, + const ObjCObjectPointerType *OPT = 0); + + void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, + AssociatedNamespaceSet &AssociatedNamespaces, + AssociatedClassSet &AssociatedClasses); + + bool DiagnoseAmbiguousLookup(LookupResult &Result); + //@} + + ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id, + SourceLocation IdLoc, + bool TypoCorrection = false); + NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, + Scope *S, bool ForRedeclaration, + SourceLocation Loc); + NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, + Scope *S); + void AddKnownFunctionAttributes(FunctionDecl *FD); + + // More parsing and symbol table subroutines. + + // Decl attributes - this routine is the top level dispatcher. + void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); + void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL); + + void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, + bool &IncompleteImpl, unsigned DiagID); + void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod, + ObjCMethodDecl *IntfMethod); + + bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl, + ObjCInterfaceDecl *IDecl); + + typedef llvm::DenseSet<Selector, llvm::DenseMapInfo<Selector> > SelectorSet; + + /// CheckProtocolMethodDefs - This routine checks unimplemented + /// methods declared in protocol, and those referenced by it. + /// \param IDecl - Used for checking for methods which may have been + /// inherited. + void CheckProtocolMethodDefs(SourceLocation ImpLoc, + ObjCProtocolDecl *PDecl, + bool& IncompleteImpl, + const SelectorSet &InsMap, + const SelectorSet &ClsMap, + ObjCContainerDecl *CDecl); + + /// CheckImplementationIvars - This routine checks if the instance variables + /// listed in the implelementation match those listed in the interface. + void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, + ObjCIvarDecl **Fields, unsigned nIvars, + SourceLocation Loc); + + /// ImplMethodsVsClassMethods - This is main routine to warn if any method + /// remains unimplemented in the class or category @implementation. + void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, + ObjCContainerDecl* IDecl, + bool IncompleteImpl = false); + + /// DiagnoseUnimplementedProperties - This routine warns on those properties + /// which must be implemented by this implementation. + void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, + ObjCContainerDecl *CDecl, + const SelectorSet &InsMap); + + /// DefaultSynthesizeProperties - This routine default synthesizes all + /// properties which must be synthesized in class's @implementation. + void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, + ObjCInterfaceDecl *IDecl); + + /// CollectImmediateProperties - This routine collects all properties in + /// the class and its conforming protocols; but not those it its super class. + void CollectImmediateProperties(ObjCContainerDecl *CDecl, + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap); + + + /// LookupPropertyDecl - Looks up a property in the current class and all + /// its protocols. + ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl, + IdentifierInfo *II); + + /// Called by ActOnProperty to handle @property declarations in + //// class extensions. + Decl *HandlePropertyInClassExtension(Scope *S, + ObjCCategoryDecl *CDecl, + SourceLocation AtLoc, + FieldDeclarator &FD, + Selector GetterSel, + Selector SetterSel, + const bool isAssign, + const bool isReadWrite, + const unsigned Attributes, + bool *isOverridingProperty, + TypeSourceInfo *T, + tok::ObjCKeywordKind MethodImplKind); + + /// Called by ActOnProperty and HandlePropertyInClassExtension to + /// handle creating the ObjcPropertyDecl for a category or @interface. + ObjCPropertyDecl *CreatePropertyDecl(Scope *S, + ObjCContainerDecl *CDecl, + SourceLocation AtLoc, + FieldDeclarator &FD, + Selector GetterSel, + Selector SetterSel, + const bool isAssign, + const bool isReadWrite, + const unsigned Attributes, + TypeSourceInfo *T, + tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC = 0); + + /// AtomicPropertySetterGetterRules - This routine enforces the rule (via + /// warning) when atomic property has one but not the other user-declared + /// setter or getter. + void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl, + ObjCContainerDecl* IDecl); + + void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID); + + /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns + /// true, or false, accordingly. + bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, + const ObjCMethodDecl *PrevMethod, + bool matchBasedOnSizeAndAlignment = false, + bool matchBasedOnStrictEqulity = false); + + /// MatchAllMethodDeclarations - Check methods declaraed in interface or + /// or protocol against those declared in their implementations. + void MatchAllMethodDeclarations(const SelectorSet &InsMap, + const SelectorSet &ClsMap, + SelectorSet &InsMapSeen, + SelectorSet &ClsMapSeen, + ObjCImplDecl* IMPDecl, + ObjCContainerDecl* IDecl, + bool &IncompleteImpl, + bool ImmediateClass); + +private: + /// AddMethodToGlobalPool - Add an instance or factory method to the global + /// pool. See descriptoin of AddInstanceMethodToGlobalPool. + void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance); + + /// LookupMethodInGlobalPool - Returns the instance or factory method and + /// optionally warns if there are multiple signatures. + ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass, + bool warn, bool instance); + +public: + /// AddInstanceMethodToGlobalPool - All instance methods in a translation + /// unit are added to a global pool. This allows us to efficiently associate + /// a selector with a method declaraation for purposes of typechecking + /// messages sent to "id" (where the class of the object is unknown). + void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) { + AddMethodToGlobalPool(Method, impl, /*instance*/true); + } + + /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. + void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) { + AddMethodToGlobalPool(Method, impl, /*instance*/false); + } + + /// LookupInstanceMethodInGlobalPool - Returns the method and warns if + /// there are multiple signatures. + ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass=false, + bool warn=true) { + return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, + warn, /*instance*/true); + } + + /// LookupFactoryMethodInGlobalPool - Returns the method and warns if + /// there are multiple signatures. + ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass=false, + bool warn=true) { + return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, + warn, /*instance*/false); + } + + /// LookupImplementedMethodInGlobalPool - Returns the method which has an + /// implementation. + ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel); + + /// CollectIvarsToConstructOrDestruct - Collect those ivars which require + /// initialization. + void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + //===--------------------------------------------------------------------===// + // Statement Parsing Callbacks: SemaStmt.cpp. +public: + class FullExprArg { + public: + FullExprArg(Sema &actions) : E(0) { } + + // FIXME: The const_cast here is ugly. RValue references would make this + // much nicer (or we could duplicate a bunch of the move semantics + // emulation code from Ownership.h). + FullExprArg(const FullExprArg& Other): E(Other.E) {} + + ExprResult release() { + return move(E); + } + + Expr *get() const { return E; } + + Expr *operator->() { + return E; + } + + private: + // FIXME: No need to make the entire Sema class a friend when it's just + // Sema::FullExpr that needs access to the constructor below. + friend class Sema; + + explicit FullExprArg(Expr *expr) : E(expr) {} + + Expr *E; + }; + + FullExprArg MakeFullExpr(Expr *Arg) { + return FullExprArg(ActOnFinishFullExpr(Arg).release()); + } + + StmtResult ActOnExprStmt(FullExprArg Expr); + + StmtResult ActOnNullStmt(SourceLocation SemiLoc); + StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, + MultiStmtArg Elts, + bool isStmtExpr); + StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, + SourceLocation StartLoc, + SourceLocation EndLoc); + void ActOnForEachDeclStmt(DeclGroupPtrTy Decl); + StmtResult ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, + SourceLocation DotDotDotLoc, Expr *RHSVal, + SourceLocation ColonLoc); + void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt); + + StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, + SourceLocation ColonLoc, + Stmt *SubStmt, Scope *CurScope); + StmtResult ActOnLabelStmt(SourceLocation IdentLoc, + IdentifierInfo *II, + SourceLocation ColonLoc, + Stmt *SubStmt); + StmtResult ActOnIfStmt(SourceLocation IfLoc, + FullExprArg CondVal, Decl *CondVar, + Stmt *ThenVal, + SourceLocation ElseLoc, Stmt *ElseVal); + StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, + Expr *Cond, + Decl *CondVar); + StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, + Stmt *Switch, Stmt *Body); + StmtResult ActOnWhileStmt(SourceLocation WhileLoc, + FullExprArg Cond, + Decl *CondVar, Stmt *Body); + StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, + SourceLocation WhileLoc, + SourceLocation CondLParen, Expr *Cond, + SourceLocation CondRParen); + + StmtResult ActOnForStmt(SourceLocation ForLoc, + SourceLocation LParenLoc, + Stmt *First, FullExprArg Second, + Decl *SecondVar, + FullExprArg Third, + SourceLocation RParenLoc, + Stmt *Body); + StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, + SourceLocation LParenLoc, + Stmt *First, Expr *Second, + SourceLocation RParenLoc, Stmt *Body); + + StmtResult ActOnGotoStmt(SourceLocation GotoLoc, + SourceLocation LabelLoc, + IdentifierInfo *LabelII); + StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, + SourceLocation StarLoc, + Expr *DestExp); + StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope); + StmtResult ActOnBreakStmt(SourceLocation GotoLoc, Scope *CurScope); + + StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); + StmtResult ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); + + StmtResult ActOnAsmStmt(SourceLocation AsmLoc, + bool IsSimple, bool IsVolatile, + unsigned NumOutputs, unsigned NumInputs, + IdentifierInfo **Names, + MultiExprArg Constraints, + MultiExprArg Exprs, + Expr *AsmString, + MultiExprArg Clobbers, + SourceLocation RParenLoc, + bool MSAsm = false); + + + VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, + IdentifierInfo *Name, SourceLocation NameLoc, + bool Invalid = false); + + Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D); + + StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, + Decl *Parm, Stmt *Body); + + StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body); + + StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, + MultiStmtArg Catch, Stmt *Finally); + + StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw); + StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, + Scope *CurScope); + StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, + Expr *SynchExpr, + Stmt *SynchBody); + + VarDecl *BuildExceptionDeclaration(Scope *S, QualType ExDeclType, + TypeSourceInfo *TInfo, + IdentifierInfo *Name, + SourceLocation Loc, + SourceRange Range); + Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D); + + StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, + Decl *ExDecl, Stmt *HandlerBlock); + StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, + MultiStmtArg Handlers); + void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock); + + bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const; + + /// \brief If it's a file scoped decl that must warn if not used, keep track + /// of it. + void MarkUnusedFileScopedDecl(const DeclaratorDecl *D); + + /// DiagnoseUnusedExprResult - If the statement passed in is an expression + /// whose result is unused, warn. + void DiagnoseUnusedExprResult(const Stmt *S); + void DiagnoseUnusedDecl(const NamedDecl *ND); + + typedef uintptr_t ParsingDeclStackState; + + ParsingDeclStackState PushParsingDeclaration(); + void PopParsingDeclaration(ParsingDeclStackState S, Decl *D); + void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc); + + void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); + + //===--------------------------------------------------------------------===// + // Expression Parsing Callbacks: SemaExpr.cpp. + + bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc); + bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, + ObjCMethodDecl *Getter, + SourceLocation Loc); + void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, + Expr **Args, unsigned NumArgs); + + void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext); + + void PopExpressionEvaluationContext(); + + void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); + void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); + bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD); + + // Primary Expressions. + SourceRange getExprRange(Expr *E) const; + + ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name, + bool HasTrailingLParen, bool IsAddressOfOperand); + + bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, + CorrectTypoContext CTC = CTC_Unknown); + + ExprResult LookupInObjCMethod(LookupResult &R, Scope *S, IdentifierInfo *II, + bool AllowBuiltinCreation=false); + + ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + bool isAddressOfOperand, + const TemplateArgumentListInfo *TemplateArgs); + + ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, + SourceLocation Loc, + const CXXScopeSpec *SS = 0); + ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, + const DeclarationNameInfo &NameInfo, + const CXXScopeSpec *SS = 0); + VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field, + llvm::SmallVectorImpl<FieldDecl *> &Path); + ExprResult + BuildAnonymousStructUnionMemberReference(SourceLocation Loc, + FieldDecl *Field, + Expr *BaseObjectExpr = 0, + SourceLocation OpLoc = SourceLocation()); + ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs); + ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, + bool IsDefiniteInstance); + bool UseArgumentDependentLookup(const CXXScopeSpec &SS, + const LookupResult &R, + bool HasTrailingLParen); + + ExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo); + ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs); + + ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool ADL); + ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + NamedDecl *D); + + ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); + ExprResult ActOnNumericConstant(const Token &); + ExprResult ActOnCharacterConstant(const Token &); + ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *Val); + ExprResult ActOnParenOrParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val, + ParsedType TypeOfCast = ParsedType()); + + /// ActOnStringLiteral - The specified tokens were lexed as pasted string + /// fragments (e.g. "foo" "bar" L"baz"). + ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks); + + // Binary/Unary Operators. 'Tok' is the token for the operator. + ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, unsigned OpcIn, + Expr *InputArg); + ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, + UnaryOperatorKind Opc, Expr *input); + ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Op, Expr *Input); + + ExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T, + SourceLocation OpLoc, + bool isSizeOf, SourceRange R); + ExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, + bool isSizeOf, SourceRange R); + ExprResult + ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, + void *TyOrEx, const SourceRange &ArgRange); + + bool CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, const SourceRange &R); + bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc, + const SourceRange &R, bool isSizeof); + + ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Kind, Expr *Input); + + ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, + Expr *Idx, SourceLocation RLoc); + ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, + Expr *Idx, SourceLocation RLoc); + + ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, + SourceLocation OpLoc, bool IsArrow, + CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs); + + ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, + SourceLocation OpLoc, bool IsArrow, + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, + bool SuppressQualifierCheck = false); + + ExprResult LookupMemberExpr(LookupResult &R, Expr *&Base, + bool &IsArrow, SourceLocation OpLoc, + CXXScopeSpec &SS, + Decl *ObjCImpDecl, + bool HasTemplateArgs); + + bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, + const CXXScopeSpec &SS, + const LookupResult &R); + + ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType, + bool IsArrow, SourceLocation OpLoc, + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs); + + ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + UnqualifiedId &Member, + Decl *ObjCImpDecl, + bool HasTrailingLParen); + + void ActOnDefaultCtorInitializers(Decl *CDtorDecl); + bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc); + + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. + /// This provides the location of the left/right parens and a list of comma + /// locations. + ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, + MultiExprArg Args, SourceLocation *CommaLocs, + SourceLocation RParenLoc); + ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc); + + ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, + ParsedType Ty, SourceLocation RParenLoc, + Expr *Op); + ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, + TypeSourceInfo *Ty, + SourceLocation RParenLoc, + Expr *Op); + + bool TypeIsVectorType(ParsedType Ty) { + return GetTypeFromParser(Ty)->isVectorType(); + } + + ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME); + ExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, + SourceLocation RParenLoc, Expr *E, + TypeSourceInfo *TInfo); + + ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, + ParsedType Ty, + SourceLocation RParenLoc, + Expr *Op); + + ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc, + TypeSourceInfo *TInfo, + SourceLocation RParenLoc, + Expr *InitExpr); + + ExprResult ActOnInitList(SourceLocation LParenLoc, + MultiExprArg InitList, + SourceLocation RParenLoc); + + ExprResult ActOnDesignatedInitializer(Designation &Desig, + SourceLocation Loc, + bool GNUSyntax, + ExprResult Init); + + ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, + tok::TokenKind Kind, Expr *LHS, Expr *RHS); + ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, + BinaryOperatorKind Opc, Expr *lhs, Expr *rhs); + ExprResult CreateBuiltinBinOp(SourceLocation TokLoc, + unsigned Opc, Expr *lhs, Expr *rhs); + + /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null + /// in the case of a the GNU conditional expr extension. + ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, + SourceLocation ColonLoc, + Expr *Cond, Expr *LHS, Expr *RHS); + + /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". + ExprResult ActOnAddrLabel(SourceLocation OpLoc, + SourceLocation LabLoc, + IdentifierInfo *LabelII); + + ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, + SourceLocation RPLoc); // "({..})" + + // __builtin_offsetof(type, identifier(.identifier|[expr])*) + struct OffsetOfComponent { + SourceLocation LocStart, LocEnd; + bool isBrackets; // true if [expr], false if .ident + union { + IdentifierInfo *IdentInfo; + ExprTy *E; + } U; + }; + + /// __builtin_offsetof(type, a.b[123][456].c) + ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, + TypeSourceInfo *TInfo, + OffsetOfComponent *CompPtr, + unsigned NumComponents, + SourceLocation RParenLoc); + ExprResult ActOnBuiltinOffsetOf(Scope *S, + SourceLocation BuiltinLoc, + SourceLocation TypeLoc, + ParsedType Arg1, + OffsetOfComponent *CompPtr, + unsigned NumComponents, + SourceLocation RParenLoc); + + // __builtin_types_compatible_p(type1, type2) + ExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, + ParsedType arg1, + ParsedType arg2, + SourceLocation RPLoc); + ExprResult BuildTypesCompatibleExpr(SourceLocation BuiltinLoc, + TypeSourceInfo *argTInfo1, + TypeSourceInfo *argTInfo2, + SourceLocation RPLoc); + + // __builtin_choose_expr(constExpr, expr1, expr2) + ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, + Expr *cond, Expr *expr1, + Expr *expr2, SourceLocation RPLoc); + + // __builtin_va_arg(expr, type) + ExprResult ActOnVAArg(SourceLocation BuiltinLoc, + Expr *expr, ParsedType type, + SourceLocation RPLoc); + ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, + Expr *expr, TypeSourceInfo *TInfo, + SourceLocation RPLoc); + + // __null + ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc); + + //===------------------------- "Block" Extension ------------------------===// + + /// ActOnBlockStart - This callback is invoked when a block literal is + /// started. + void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope); + + /// ActOnBlockArguments - This callback allows processing of block arguments. + /// If there are no arguments, this is still invoked. + void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope); + + /// ActOnBlockError - If there is an error parsing a block, this callback + /// is invoked to pop the information about the block from the action impl. + void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope); + + /// ActOnBlockStmtExpr - This is called when the body of a block statement + /// literal was successfully completed. ^(int x){...} + ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, + Stmt *Body, Scope *CurScope); + + //===---------------------------- C++ Features --------------------------===// + + // Act on C++ namespaces + Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc, + SourceLocation IdentLoc, + IdentifierInfo *Ident, + SourceLocation LBrace, + AttributeList *AttrList); + void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace); + + NamespaceDecl *getStdNamespace() const; + NamespaceDecl *getOrCreateStdNamespace(); + + CXXRecordDecl *getStdBadAlloc() const; + + Decl *ActOnUsingDirective(Scope *CurScope, + SourceLocation UsingLoc, + SourceLocation NamespcLoc, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + AttributeList *AttrList); + + void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir); + + Decl *ActOnNamespaceAliasDef(Scope *CurScope, + SourceLocation NamespaceLoc, + SourceLocation AliasLoc, + IdentifierInfo *Alias, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *Ident); + + void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow); + bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target, + const LookupResult &PreviousDecls); + UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD, + NamedDecl *Target); + + bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc, + bool isTypeName, + const CXXScopeSpec &SS, + SourceLocation NameLoc, + const LookupResult &Previous); + bool CheckUsingDeclQualifier(SourceLocation UsingLoc, + const CXXScopeSpec &SS, + SourceLocation NameLoc); + + NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, + CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + AttributeList *AttrList, + bool IsInstantiation, + bool IsTypeName, + SourceLocation TypenameLoc); + + Decl *ActOnUsingDeclaration(Scope *CurScope, + AccessSpecifier AS, + bool HasUsingKeyword, + SourceLocation UsingLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + AttributeList *AttrList, + bool IsTypeName, + SourceLocation TypenameLoc); + + /// AddCXXDirectInitializerToDecl - This action is called immediately after + /// ActOnDeclarator, when a C++ direct initializer is present. + /// e.g: "int x(1);" + void AddCXXDirectInitializerToDecl(Decl *Dcl, + SourceLocation LParenLoc, + MultiExprArg Exprs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc); + + /// InitializeVarWithConstructor - Creates an CXXConstructExpr + /// and sets it as the initializer for the the passed in VarDecl. + bool InitializeVarWithConstructor(VarDecl *VD, + CXXConstructorDecl *Constructor, + MultiExprArg Exprs); + + /// BuildCXXConstructExpr - Creates a complete call to a constructor, + /// including handling of its default argument expressions. + /// + /// \param ConstructKind - a CXXConstructExpr::ConstructionKind + ExprResult + BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + CXXConstructorDecl *Constructor, MultiExprArg Exprs, + bool RequiresZeroInit, unsigned ConstructKind); + + // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if + // the constructor can be elidable? + ExprResult + BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + CXXConstructorDecl *Constructor, bool Elidable, + MultiExprArg Exprs, bool RequiresZeroInit, + unsigned ConstructKind); + + /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating + /// the default expr if needed. + ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, + FunctionDecl *FD, + ParmVarDecl *Param); + + /// FinalizeVarWithDestructor - Prepare for calling destructor on the + /// constructed variable. + void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType); + + /// \brief Declare the implicit default constructor for the given class. + /// + /// \param ClassDecl The class declaration into which the implicit + /// default constructor will be added. + /// + /// \returns The implicitly-declared default constructor. + CXXConstructorDecl *DeclareImplicitDefaultConstructor( + CXXRecordDecl *ClassDecl); + + /// DefineImplicitDefaultConstructor - Checks for feasibility of + /// defining this constructor as the default constructor. + void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor); + + /// \brief Declare the implicit destructor for the given class. + /// + /// \param ClassDecl The class declaration into which the implicit + /// destructor will be added. + /// + /// \returns The implicitly-declared destructor. + CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl); + + /// DefineImplicitDestructor - Checks for feasibility of + /// defining this destructor as the default destructor. + void DefineImplicitDestructor(SourceLocation CurrentLocation, + CXXDestructorDecl *Destructor); + + /// \brief Declare the implicit copy constructor for the given class. + /// + /// \param S The scope of the class, which may be NULL if this is a + /// template instantiation. + /// + /// \param ClassDecl The class declaration into which the implicit + /// copy constructor will be added. + /// + /// \returns The implicitly-declared copy constructor. + CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl); + + /// DefineImplicitCopyConstructor - Checks for feasibility of + /// defining this constructor as the copy constructor. + void DefineImplicitCopyConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor, + unsigned TypeQuals); + + /// \brief Declare the implicit copy assignment operator for the given class. + /// + /// \param S The scope of the class, which may be NULL if this is a + /// template instantiation. + /// + /// \param ClassDecl The class declaration into which the implicit + /// copy-assignment operator will be added. + /// + /// \returns The implicitly-declared copy assignment operator. + CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl); + + /// \brief Defined an implicitly-declared copy assignment operator. + void DefineImplicitCopyAssignment(SourceLocation CurrentLocation, + CXXMethodDecl *MethodDecl); + + /// \brief Force the declaration of any implicitly-declared members of this + /// class. + void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class); + + /// MaybeBindToTemporary - If the passed in expression has a record type with + /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise + /// it simply returns the passed in expression. + ExprResult MaybeBindToTemporary(Expr *E); + + bool CompleteConstructorCall(CXXConstructorDecl *Constructor, + MultiExprArg ArgsPtr, + SourceLocation Loc, + ASTOwningVector<Expr*> &ConvertedArgs); + + ParsedType getDestructorName(SourceLocation TildeLoc, + IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS, + ParsedType ObjectType, + bool EnteringContext); + + /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. + ExprResult ActOnCXXNamedCast(SourceLocation OpLoc, + tok::TokenKind Kind, + SourceLocation LAngleBracketLoc, + ParsedType Ty, + SourceLocation RAngleBracketLoc, + SourceLocation LParenLoc, + Expr *E, + SourceLocation RParenLoc); + + ExprResult BuildCXXNamedCast(SourceLocation OpLoc, + tok::TokenKind Kind, + TypeSourceInfo *Ty, + Expr *E, + SourceRange AngleBrackets, + SourceRange Parens); + + ExprResult BuildCXXTypeId(QualType TypeInfoType, + SourceLocation TypeidLoc, + TypeSourceInfo *Operand, + SourceLocation RParenLoc); + ExprResult BuildCXXTypeId(QualType TypeInfoType, + SourceLocation TypeidLoc, + Expr *Operand, + SourceLocation RParenLoc); + + /// ActOnCXXTypeid - Parse typeid( something ). + ExprResult ActOnCXXTypeid(SourceLocation OpLoc, + SourceLocation LParenLoc, bool isType, + void *TyOrExpr, + SourceLocation RParenLoc); + + //// ActOnCXXThis - Parse 'this' pointer. + ExprResult ActOnCXXThis(SourceLocation ThisLoc); + + /// ActOnCXXBoolLiteral - Parse {true,false} literals. + ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); + + /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. + ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc); + + //// ActOnCXXThrow - Parse throw expressions. + ExprResult ActOnCXXThrow(SourceLocation OpLoc, Expr *expr); + bool CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E); + + /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. + /// Can be interpreted either as function-style casting ("int(x)") + /// or class type construction ("ClassType(x,y,z)") + /// or creation of a value-initialized type ("int()"). + ExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange, + ParsedType TypeRep, + SourceLocation LParenLoc, + MultiExprArg Exprs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc); + + /// ActOnCXXNew - Parsed a C++ 'new' expression. + ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, + SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, + SourceRange TypeIdParens, Declarator &D, + SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen); + ExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, + SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, + SourceRange TypeIdParens, + QualType AllocType, + SourceLocation TypeLoc, + SourceRange TypeRange, + Expr *ArraySize, + SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen); + + bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, + SourceRange R); + bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, + bool UseGlobal, QualType AllocType, bool IsArray, + Expr **PlaceArgs, unsigned NumPlaceArgs, + FunctionDecl *&OperatorNew, + FunctionDecl *&OperatorDelete); + bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, + DeclarationName Name, Expr** Args, + unsigned NumArgs, DeclContext *Ctx, + bool AllowMissing, FunctionDecl *&Operator); + void DeclareGlobalNewDelete(); + void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, + QualType Argument, + bool addMallocAttr = false); + + bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, + DeclarationName Name, FunctionDecl* &Operator); + + /// ActOnCXXDelete - Parsed a C++ 'delete' expression + ExprResult ActOnCXXDelete(SourceLocation StartLoc, + bool UseGlobal, bool ArrayForm, + Expr *Operand); + + DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D); + ExprResult CheckConditionVariable(VarDecl *ConditionVar, + SourceLocation StmtLoc, + bool ConvertToBoolean); + + /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support + /// pseudo-functions. + ExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT, + SourceLocation KWLoc, + SourceLocation LParen, + ParsedType Ty, + SourceLocation RParen); + + ExprResult ActOnStartCXXMemberReference(Scope *S, + Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + ParsedType &ObjectType, + bool &MayBePseudoDestructor); + + ExprResult DiagnoseDtorReference(SourceLocation NameLoc, Expr *MemExpr); + + ExprResult BuildPseudoDestructorExpr(Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + TypeSourceInfo *ScopeType, + SourceLocation CCLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage DestroyedType, + bool HasTrailingLParen); + + ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + UnqualifiedId &FirstTypeName, + SourceLocation CCLoc, + SourceLocation TildeLoc, + UnqualifiedId &SecondTypeName, + bool HasTrailingLParen); + + /// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is + /// non-empty, will create a new CXXExprWithTemporaries expression. + /// Otherwise, just returs the passed in expression. + Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr); + ExprResult MaybeCreateCXXExprWithTemporaries(ExprResult SubExpr); + FullExpr CreateFullExpr(Expr *SubExpr); + + ExprResult ActOnFinishFullExpr(Expr *Expr); + + // Marks SS invalid if it represents an incomplete type. + bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC); + + DeclContext *computeDeclContext(QualType T); + DeclContext *computeDeclContext(const CXXScopeSpec &SS, + bool EnteringContext = false); + bool isDependentScopeSpecifier(const CXXScopeSpec &SS); + CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); + bool isUnknownSpecialization(const CXXScopeSpec &SS); + + /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the + /// global scope ('::'). + NestedNameSpecifier * + ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc); + + bool isAcceptableNestedNameSpecifier(NamedDecl *SD); + NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); + + bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, + SourceLocation IdLoc, + IdentifierInfo &II, + ParsedType ObjectType); + + NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S, + CXXScopeSpec &SS, + SourceLocation IdLoc, + SourceLocation CCLoc, + IdentifierInfo &II, + QualType ObjectType, + NamedDecl *ScopeLookupResult, + bool EnteringContext, + bool ErrorRecoveryLookup); + + NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S, + CXXScopeSpec &SS, + SourceLocation IdLoc, + SourceLocation CCLoc, + IdentifierInfo &II, + ParsedType ObjectType, + bool EnteringContext); + + bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, + IdentifierInfo &II, + ParsedType ObjectType, + bool EnteringContext); + + /// ActOnCXXNestedNameSpecifier - Called during parsing of a + /// nested-name-specifier that involves a template-id, e.g., + /// "foo::bar<int, float>::", and now we need to build a scope + /// specifier. \p SS is empty or the previously parsed nested-name + /// part ("foo::"), \p Type is the already-parsed class template + /// specialization (or other template-id that names a type), \p + /// TypeRange is the source range where the type is located, and \p + /// CCLoc is the location of the trailing '::'. + CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, + const CXXScopeSpec &SS, + ParsedType Type, + SourceRange TypeRange, + SourceLocation CCLoc); + + bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS); + + /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global + /// scope or nested-name-specifier) is parsed, part of a declarator-id. + /// After this method is called, according to [C++ 3.4.3p3], names should be + /// looked up in the declarator-id's scope, until the declarator is parsed and + /// ActOnCXXExitDeclaratorScope is called. + /// The 'SS' should be a non-empty valid CXXScopeSpec. + bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS); + + /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously + /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same + /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. + /// Used to indicate that names should revert to being looked up in the + /// defining scope. + void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS); + + /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an + /// initializer for the declaration 'Dcl'. + /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a + /// static data member of class X, names should be looked up in the scope of + /// class X. + void ActOnCXXEnterDeclInitializer(Scope *S, Decl *Dcl); + + /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an + /// initializer for the declaration 'Dcl'. + void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl); + + // ParseObjCStringLiteral - Parse Objective-C string literals. + ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, + Expr **Strings, + unsigned NumStrings); + + Expr *BuildObjCEncodeExpression(SourceLocation AtLoc, + TypeSourceInfo *EncodedTypeInfo, + SourceLocation RParenLoc); + CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp, + NamedDecl *FoundDecl, + CXXMethodDecl *Method); + + ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, + SourceLocation EncodeLoc, + SourceLocation LParenLoc, + ParsedType Ty, + SourceLocation RParenLoc); + + // ParseObjCSelectorExpression - Build selector expression for @selector + ExprResult ParseObjCSelectorExpression(Selector Sel, + SourceLocation AtLoc, + SourceLocation SelLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc); + + // ParseObjCProtocolExpression - Build protocol expression for @protocol + ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc); + + //===--------------------------------------------------------------------===// + // C++ Declarations + // + Decl *ActOnStartLinkageSpecification(Scope *S, + SourceLocation ExternLoc, + SourceLocation LangLoc, + llvm::StringRef Lang, + SourceLocation LBraceLoc); + Decl *ActOnFinishLinkageSpecification(Scope *S, + Decl *LinkageSpec, + SourceLocation RBraceLoc); + + + //===--------------------------------------------------------------------===// + // C++ Classes + // + bool isCurrentClassName(const IdentifierInfo &II, Scope *S, + const CXXScopeSpec *SS = 0); + + Decl *ActOnAccessSpecifier(AccessSpecifier Access, + SourceLocation ASLoc, + SourceLocation ColonLoc); + + Decl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, + Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + Expr *BitfieldWidth, + Expr *Init, bool IsDefinition, + bool Deleted = false); + + MemInitResult ActOnMemInitializer(Decl *ConstructorD, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + SourceLocation IdLoc, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc); + + MemInitResult BuildMemberInitializer(FieldDecl *Member, Expr **Args, + unsigned NumArgs, SourceLocation IdLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc); + + MemInitResult BuildBaseInitializer(QualType BaseType, + TypeSourceInfo *BaseTInfo, + Expr **Args, unsigned NumArgs, + SourceLocation LParenLoc, + SourceLocation RParenLoc, + CXXRecordDecl *ClassDecl); + + bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers, bool AnyErrors); + + void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation); + + + /// MarkBaseAndMemberDestructorsReferenced - Given a record decl, + /// mark all the non-trivial destructors of its members and bases as + /// referenced. + void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc, + CXXRecordDecl *Record); + + /// \brief The list of classes whose vtables have been used within + /// this translation unit, and the source locations at which the + /// first use occurred. + llvm::SmallVector<std::pair<CXXRecordDecl *, SourceLocation>, 16> + VTableUses; + + /// \brief The set of classes whose vtables have been used within + /// this translation unit, and a bit that will be true if the vtable is + /// required to be emitted (otherwise, it should be emitted only if needed + /// by code generation). + llvm::DenseMap<CXXRecordDecl *, bool> VTablesUsed; + + /// \brief A list of all of the dynamic classes in this translation + /// unit. + llvm::SmallVector<CXXRecordDecl *, 16> DynamicClasses; + + /// \brief Note that the vtable for the given class was used at the + /// given location. + void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, + bool DefinitionRequired = false); + + /// MarkVirtualMembersReferenced - Will mark all members of the given + /// CXXRecordDecl referenced. + void MarkVirtualMembersReferenced(SourceLocation Loc, + const CXXRecordDecl *RD); + + /// \brief Define all of the vtables that have been used in this + /// translation unit and reference any virtual members used by those + /// vtables. + /// + /// \returns true if any work was done, false otherwise. + bool DefineUsedVTables(); + + void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); + + void ActOnMemInitializers(Decl *ConstructorDecl, + SourceLocation ColonLoc, + MemInitTy **MemInits, unsigned NumMemInits, + bool AnyErrors); + + void CheckCompletedCXXClass(CXXRecordDecl *Record); + void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, + Decl *TagDecl, + SourceLocation LBrac, + SourceLocation RBrac, + AttributeList *AttrList); + + void ActOnReenterTemplateScope(Scope *S, Decl *Template); + void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record); + void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method); + void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param); + void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method); + void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record); + + Decl *ActOnStaticAssertDeclaration(SourceLocation AssertLoc, + Expr *AssertExpr, + Expr *AssertMessageExpr); + + FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc, + TypeSourceInfo *TSInfo); + Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, + MultiTemplateParamsArg TemplateParams); + Decl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, + MultiTemplateParamsArg TemplateParams); + + QualType CheckConstructorDeclarator(Declarator &D, QualType R, + StorageClass& SC); + void CheckConstructor(CXXConstructorDecl *Constructor); + QualType CheckDestructorDeclarator(Declarator &D, QualType R, + StorageClass& SC); + bool CheckDestructor(CXXDestructorDecl *Destructor); + void CheckConversionDeclarator(Declarator &D, QualType &R, + StorageClass& SC); + Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); + + //===--------------------------------------------------------------------===// + // C++ Derived Classes + // + + /// ActOnBaseSpecifier - Parsed a base specifier + CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class, + SourceRange SpecifierRange, + bool Virtual, AccessSpecifier Access, + TypeSourceInfo *TInfo); + + /// SetClassDeclAttributesFromBase - Copies class decl traits + /// (such as whether the class has a trivial constructor, + /// trivial destructor etc) from the given base class. + void SetClassDeclAttributesFromBase(CXXRecordDecl *Class, + const CXXRecordDecl *BaseClass, + bool BaseIsVirtual); + + BaseResult ActOnBaseSpecifier(Decl *classdecl, + SourceRange SpecifierRange, + bool Virtual, AccessSpecifier Access, + ParsedType basetype, SourceLocation + BaseLoc); + + bool AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, + unsigned NumBases); + void ActOnBaseSpecifiers(Decl *ClassDecl, BaseTy **Bases, unsigned NumBases); + + bool IsDerivedFrom(QualType Derived, QualType Base); + bool IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths); + + // FIXME: I don't like this name. + void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath); + + bool BasePathInvolvesVirtualBase(const CXXCastPath &BasePath); + + bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, + SourceLocation Loc, SourceRange Range, + CXXCastPath *BasePath = 0, + bool IgnoreAccess = false); + bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, + unsigned InaccessibleBaseID, + unsigned AmbigiousBaseConvID, + SourceLocation Loc, SourceRange Range, + DeclarationName Name, + CXXCastPath *BasePath); + + std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths); + + /// CheckOverridingFunctionReturnType - Checks whether the return types are + /// covariant, according to C++ [class.virtual]p5. + bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New, + const CXXMethodDecl *Old); + + /// CheckOverridingFunctionExceptionSpec - Checks whether the exception + /// spec is a subset of base spec. + bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, + const CXXMethodDecl *Old); + + /// CheckOverridingFunctionAttributes - Checks whether attributes are + /// incompatible or prevent overriding. + bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New, + const CXXMethodDecl *Old); + + bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange); + + //===--------------------------------------------------------------------===// + // C++ Access Control + // + + enum AccessResult { + AR_accessible, + AR_inaccessible, + AR_dependent, + AR_delayed + }; + + bool SetMemberAccessSpecifier(NamedDecl *MemberDecl, + NamedDecl *PrevMemberDecl, + AccessSpecifier LexicalAS); + + AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, + DeclAccessPair FoundDecl); + AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, + DeclAccessPair FoundDecl); + AccessResult CheckAllocationAccess(SourceLocation OperatorLoc, + SourceRange PlacementRange, + CXXRecordDecl *NamingClass, + DeclAccessPair FoundDecl); + AccessResult CheckConstructorAccess(SourceLocation Loc, + CXXConstructorDecl *D, + const InitializedEntity &Entity, + AccessSpecifier Access, + bool IsCopyBindingRefToTemp = false); + AccessResult CheckDestructorAccess(SourceLocation Loc, + CXXDestructorDecl *Dtor, + const PartialDiagnostic &PDiag); + AccessResult CheckDirectMemberAccess(SourceLocation Loc, + NamedDecl *D, + const PartialDiagnostic &PDiag); + AccessResult CheckMemberOperatorAccess(SourceLocation Loc, + Expr *ObjectExpr, + Expr *ArgExpr, + DeclAccessPair FoundDecl); + AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr, + DeclAccessPair FoundDecl); + AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, + QualType Base, QualType Derived, + const CXXBasePath &Path, + unsigned DiagID, + bool ForceCheck = false, + bool ForceUnprivileged = false); + void CheckLookupAccess(const LookupResult &R); + + void HandleDependentAccessCheck(const DependentDiagnostic &DD, + const MultiLevelTemplateArgumentList &TemplateArgs); + void PerformDependentDiagnostics(const DeclContext *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs); + + void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); + + /// A flag to suppress access checking. + bool SuppressAccessChecking; + + void ActOnStartSuppressingAccessChecks(); + void ActOnStopSuppressingAccessChecks(); + + enum AbstractDiagSelID { + AbstractNone = -1, + AbstractReturnType, + AbstractParamType, + AbstractVariableType, + AbstractFieldType, + AbstractArrayType + }; + + bool RequireNonAbstractType(SourceLocation Loc, QualType T, + const PartialDiagnostic &PD); + void DiagnoseAbstractType(const CXXRecordDecl *RD); + + bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, + AbstractDiagSelID SelID = AbstractNone); + + //===--------------------------------------------------------------------===// + // C++ Overloaded Operators [C++ 13.5] + // + + bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl); + + bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl); + + //===--------------------------------------------------------------------===// + // C++ Templates [C++ 14] + // + void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS, + QualType ObjectType, bool EnteringContext, + bool &MemberOfUnknownSpecialization); + + TemplateNameKind isTemplateName(Scope *S, + CXXScopeSpec &SS, + bool hasTemplateKeyword, + UnqualifiedId &Name, + ParsedType ObjectType, + bool EnteringContext, + TemplateTy &Template, + bool &MemberOfUnknownSpecialization); + + bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + const CXXScopeSpec *SS, + TemplateTy &SuggestedTemplate, + TemplateNameKind &SuggestedKind); + + bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); + TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl); + + Decl *ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, + SourceLocation EllipsisLoc, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, unsigned Position, + SourceLocation EqualLoc, + ParsedType DefaultArg); + + QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc); + Decl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, + unsigned Depth, + unsigned Position, + SourceLocation EqualLoc, + Expr *DefaultArg); + Decl *ActOnTemplateTemplateParameter(Scope *S, + SourceLocation TmpLoc, + TemplateParamsTy *Params, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, + unsigned Position, + SourceLocation EqualLoc, + const ParsedTemplateArgument &DefaultArg); + + TemplateParamsTy * + ActOnTemplateParameterList(unsigned Depth, + SourceLocation ExportLoc, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + Decl **Params, unsigned NumParams, + SourceLocation RAngleLoc); + + /// \brief The context in which we are checking a template parameter + /// list. + enum TemplateParamListContext { + TPC_ClassTemplate, + TPC_FunctionTemplate, + TPC_ClassTemplateMember, + TPC_FriendFunctionTemplate + }; + + bool CheckTemplateParameterList(TemplateParameterList *NewParams, + TemplateParameterList *OldParams, + TemplateParamListContext TPC); + TemplateParameterList * + MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, + const CXXScopeSpec &SS, + TemplateParameterList **ParamLists, + unsigned NumParamLists, + bool IsFriend, + bool &IsExplicitSpecialization, + bool &Invalid); + + DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, + TemplateParameterList *TemplateParams, + AccessSpecifier AS); + + void translateTemplateArguments(const ASTTemplateArgsPtr &In, + TemplateArgumentListInfo &Out); + + QualType CheckTemplateIdType(TemplateName Template, + SourceLocation TemplateLoc, + const TemplateArgumentListInfo &TemplateArgs); + + TypeResult + ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc); + + TypeResult ActOnTagTemplateIdType(TypeResult Type, + TagUseKind TUK, + TypeSpecifierType TagSpec, + SourceLocation TagLoc); + + ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo &TemplateArgs); + ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo &TemplateArgs); + + TemplateNameKind ActOnDependentTemplateName(Scope *S, + SourceLocation TemplateKWLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + ParsedType ObjectType, + bool EnteringContext, + TemplateTy &Template); + + bool CheckClassTemplatePartialSpecializationArgs( + TemplateParameterList *TemplateParams, + const TemplateArgumentListBuilder &TemplateArgs, + bool &MirrorsPrimaryTemplate); + + DeclResult + ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, + SourceLocation KWLoc, + CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, + AttributeList *Attr, + MultiTemplateParamsArg TemplateParameterLists); + + Decl *ActOnTemplateDeclarator(Scope *S, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D); + + Decl *ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D); + + bool + CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, + TemplateSpecializationKind NewTSK, + NamedDecl *PrevDecl, + TemplateSpecializationKind PrevTSK, + SourceLocation PrevPtOfInstantiation, + bool &SuppressNew); + + bool CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, + const TemplateArgumentListInfo &ExplicitTemplateArgs, + LookupResult &Previous); + + bool CheckFunctionTemplateSpecialization(FunctionDecl *FD, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + LookupResult &Previous); + bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); + + DeclResult + ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + const CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, + AttributeList *Attr); + + DeclResult + ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + AttributeList *Attr); + + DeclResult ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + Declarator &D); + + TemplateArgumentLoc + SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + Decl *Param, + TemplateArgumentListBuilder &Converted); + + /// \brief Specifies the context in which a particular template + /// argument is being checked. + enum CheckTemplateArgumentKind { + /// \brief The template argument was specified in the code or was + /// instantiated with some deduced template arguments. + CTAK_Specified, + + /// \brief The template argument was deduced via template argument + /// deduction. + CTAK_Deduced, + + /// \brief The template argument was deduced from an array bound + /// via template argument deduction. + CTAK_DeducedFromArrayBound + }; + + bool CheckTemplateArgument(NamedDecl *Param, + const TemplateArgumentLoc &Arg, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + TemplateArgumentListBuilder &Converted, + CheckTemplateArgumentKind CTAK = CTAK_Specified); + + bool CheckTemplateArgumentList(TemplateDecl *Template, + SourceLocation TemplateLoc, + const TemplateArgumentListInfo &TemplateArgs, + bool PartialTemplateArgs, + TemplateArgumentListBuilder &Converted); + + bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, + const TemplateArgumentLoc &Arg, + TemplateArgumentListBuilder &Converted); + + bool CheckTemplateArgument(TemplateTypeParmDecl *Param, + TypeSourceInfo *Arg); + bool CheckTemplateArgumentPointerToMember(Expr *Arg, + TemplateArgument &Converted); + bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param, + QualType InstantiatedParamType, Expr *&Arg, + TemplateArgument &Converted, + CheckTemplateArgumentKind CTAK = CTAK_Specified); + bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, + const TemplateArgumentLoc &Arg); + + ExprResult + BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, + QualType ParamType, + SourceLocation Loc); + ExprResult + BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, + SourceLocation Loc); + + /// \brief Enumeration describing how template parameter lists are compared + /// for equality. + enum TemplateParameterListEqualKind { + /// \brief We are matching the template parameter lists of two templates + /// that might be redeclarations. + /// + /// \code + /// template<typename T> struct X; + /// template<typename T> struct X; + /// \endcode + TPL_TemplateMatch, + + /// \brief We are matching the template parameter lists of two template + /// template parameters as part of matching the template parameter lists + /// of two templates that might be redeclarations. + /// + /// \code + /// template<template<int I> class TT> struct X; + /// template<template<int Value> class Other> struct X; + /// \endcode + TPL_TemplateTemplateParmMatch, + + /// \brief We are matching the template parameter lists of a template + /// template argument against the template parameter lists of a template + /// template parameter. + /// + /// \code + /// template<template<int Value> class Metafun> struct X; + /// template<int Value> struct integer_c; + /// X<integer_c> xic; + /// \endcode + TPL_TemplateTemplateArgumentMatch + }; + + bool TemplateParameterListsAreEqual(TemplateParameterList *New, + TemplateParameterList *Old, + bool Complain, + TemplateParameterListEqualKind Kind, + SourceLocation TemplateArgLoc + = SourceLocation()); + + bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams); + + /// \brief Called when the parser has parsed a C++ typename + /// specifier, e.g., "typename T::type". + /// + /// \param S The scope in which this typename type occurs. + /// \param TypenameLoc the location of the 'typename' keyword + /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). + /// \param II the identifier we're retrieving (e.g., 'type' in the example). + /// \param IdLoc the location of the identifier. + TypeResult + ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, const IdentifierInfo &II, + SourceLocation IdLoc); + + /// \brief Called when the parser has parsed a C++ typename + /// specifier that ends in a template-id, e.g., + /// "typename MetaFun::template apply<T1, T2>". + /// + /// \param S The scope in which this typename type occurs. + /// \param TypenameLoc the location of the 'typename' keyword + /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). + /// \param TemplateLoc the location of the 'template' keyword, if any. + /// \param Ty the type that the typename specifier refers to. + TypeResult + ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, SourceLocation TemplateLoc, + ParsedType Ty); + + QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo &II, + SourceLocation KeywordLoc, + SourceRange NNSRange, + SourceLocation IILoc); + + TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, + SourceLocation Loc, + DeclarationName Name); + bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS); + + ExprResult RebuildExprInCurrentInstantiation(Expr *E); + + std::string + getTemplateArgumentBindingsText(const TemplateParameterList *Params, + const TemplateArgumentList &Args); + + std::string + getTemplateArgumentBindingsText(const TemplateParameterList *Params, + const TemplateArgument *Args, + unsigned NumArgs); + + /// \brief Describes the result of template argument deduction. + /// + /// The TemplateDeductionResult enumeration describes the result of + /// template argument deduction, as returned from + /// DeduceTemplateArguments(). The separate TemplateDeductionInfo + /// structure provides additional information about the results of + /// template argument deduction, e.g., the deduced template argument + /// list (if successful) or the specific template parameters or + /// deduced arguments that were involved in the failure. + enum TemplateDeductionResult { + /// \brief Template argument deduction was successful. + TDK_Success = 0, + /// \brief Template argument deduction exceeded the maximum template + /// instantiation depth (which has already been diagnosed). + TDK_InstantiationDepth, + /// \brief Template argument deduction did not deduce a value + /// for every template parameter. + TDK_Incomplete, + /// \brief Template argument deduction produced inconsistent + /// deduced values for the given template parameter. + TDK_Inconsistent, + /// \brief Template argument deduction failed due to inconsistent + /// cv-qualifiers on a template parameter type that would + /// otherwise be deduced, e.g., we tried to deduce T in "const T" + /// but were given a non-const "X". + TDK_Underqualified, + /// \brief Substitution of the deduced template argument values + /// resulted in an error. + TDK_SubstitutionFailure, + /// \brief Substitution of the deduced template argument values + /// into a non-deduced context produced a type or value that + /// produces a type that does not match the original template + /// arguments provided. + TDK_NonDeducedMismatch, + /// \brief When performing template argument deduction for a function + /// template, there were too many call arguments. + TDK_TooManyArguments, + /// \brief When performing template argument deduction for a function + /// template, there were too few call arguments. + TDK_TooFewArguments, + /// \brief The explicitly-specified template arguments were not valid + /// template arguments for the given template. + TDK_InvalidExplicitArguments, + /// \brief The arguments included an overloaded function name that could + /// not be resolved to a suitable function. + TDK_FailedOverloadResolution + }; + + TemplateDeductionResult + DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, + const TemplateArgumentList &TemplateArgs, + sema::TemplateDeductionInfo &Info); + + TemplateDeductionResult + SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + const TemplateArgumentListInfo &ExplicitTemplateArgs, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + llvm::SmallVectorImpl<QualType> &ParamTypes, + QualType *FunctionType, + sema::TemplateDeductionInfo &Info); + + TemplateDeductionResult + FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned NumExplicitlySpecified, + FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info); + + TemplateDeductionResult + DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + Expr **Args, unsigned NumArgs, + FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info); + + TemplateDeductionResult + DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + QualType ArgFunctionType, + FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info); + + TemplateDeductionResult + DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + QualType ToType, + CXXConversionDecl *&Specialization, + sema::TemplateDeductionInfo &Info); + + TemplateDeductionResult + DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info); + + FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, + FunctionTemplateDecl *FT2, + SourceLocation Loc, + TemplatePartialOrderingContext TPOC); + UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin, + UnresolvedSetIterator SEnd, + TemplatePartialOrderingContext TPOC, + SourceLocation Loc, + const PartialDiagnostic &NoneDiag, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &CandidateDiag); + + ClassTemplatePartialSpecializationDecl * + getMoreSpecializedPartialSpecialization( + ClassTemplatePartialSpecializationDecl *PS1, + ClassTemplatePartialSpecializationDecl *PS2, + SourceLocation Loc); + + void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, + bool OnlyDeduced, + unsigned Depth, + llvm::SmallVectorImpl<bool> &Used); + void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, + llvm::SmallVectorImpl<bool> &Deduced); + + //===--------------------------------------------------------------------===// + // C++ Template Instantiation + // + + MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D, + const TemplateArgumentList *Innermost = 0, + bool RelativeToPrimary = false, + const FunctionDecl *Pattern = 0); + + /// \brief A template instantiation that is currently in progress. + struct ActiveTemplateInstantiation { + /// \brief The kind of template instantiation we are performing + enum InstantiationKind { + /// We are instantiating a template declaration. The entity is + /// the declaration we're instantiating (e.g., a CXXRecordDecl). + TemplateInstantiation, + + /// We are instantiating a default argument for a template + /// parameter. The Entity is the template, and + /// TemplateArgs/NumTemplateArguments provides the template + /// arguments as specified. + /// FIXME: Use a TemplateArgumentList + DefaultTemplateArgumentInstantiation, + + /// We are instantiating a default argument for a function. + /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs + /// provides the template arguments as specified. + DefaultFunctionArgumentInstantiation, + + /// We are substituting explicit template arguments provided for + /// a function template. The entity is a FunctionTemplateDecl. + ExplicitTemplateArgumentSubstitution, + + /// We are substituting template argument determined as part of + /// template argument deduction for either a class template + /// partial specialization or a function template. The + /// Entity is either a ClassTemplatePartialSpecializationDecl or + /// a FunctionTemplateDecl. + DeducedTemplateArgumentSubstitution, + + /// We are substituting prior template arguments into a new + /// template parameter. The template parameter itself is either a + /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl. + PriorTemplateArgumentSubstitution, + + /// We are checking the validity of a default template argument that + /// has been used when naming a template-id. + DefaultTemplateArgumentChecking + } Kind; + + /// \brief The point of instantiation within the source code. + SourceLocation PointOfInstantiation; + + /// \brief The template in which we are performing the instantiation, + /// for substitutions of prior template arguments. + TemplateDecl *Template; + + /// \brief The entity that is being instantiated. + uintptr_t Entity; + + /// \brief The list of template arguments we are substituting, if they + /// are not part of the entity. + const TemplateArgument *TemplateArgs; + + /// \brief The number of template arguments in TemplateArgs. + unsigned NumTemplateArgs; + + /// \brief The source range that covers the construct that cause + /// the instantiation, e.g., the template-id that causes a class + /// template instantiation. + SourceRange InstantiationRange; + + ActiveTemplateInstantiation() + : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0), + NumTemplateArgs(0) {} + + /// \brief Determines whether this template is an actual instantiation + /// that should be counted toward the maximum instantiation depth. + bool isInstantiationRecord() const; + + friend bool operator==(const ActiveTemplateInstantiation &X, + const ActiveTemplateInstantiation &Y) { + if (X.Kind != Y.Kind) + return false; + + if (X.Entity != Y.Entity) + return false; + + switch (X.Kind) { + case TemplateInstantiation: + return true; + + case PriorTemplateArgumentSubstitution: + case DefaultTemplateArgumentChecking: + if (X.Template != Y.Template) + return false; + + // Fall through + + case DefaultTemplateArgumentInstantiation: + case ExplicitTemplateArgumentSubstitution: + case DeducedTemplateArgumentSubstitution: + case DefaultFunctionArgumentInstantiation: + return X.TemplateArgs == Y.TemplateArgs; + + } + + return true; + } + + friend bool operator!=(const ActiveTemplateInstantiation &X, + const ActiveTemplateInstantiation &Y) { + return !(X == Y); + } + }; + + /// \brief List of active template instantiations. + /// + /// This vector is treated as a stack. As one template instantiation + /// requires another template instantiation, additional + /// instantiations are pushed onto the stack up to a + /// user-configurable limit LangOptions::InstantiationDepth. + llvm::SmallVector<ActiveTemplateInstantiation, 16> + ActiveTemplateInstantiations; + + /// \brief The number of ActiveTemplateInstantiation entries in + /// \c ActiveTemplateInstantiations that are not actual instantiations and, + /// therefore, should not be counted as part of the instantiation depth. + unsigned NonInstantiationEntries; + + /// \brief The last template from which a template instantiation + /// error or warning was produced. + /// + /// This value is used to suppress printing of redundant template + /// instantiation backtraces when there are multiple errors in the + /// same instantiation. FIXME: Does this belong in Sema? It's tough + /// to implement it anywhere else. + ActiveTemplateInstantiation LastTemplateInstantiationErrorContext; + + /// \brief The stack of calls expression undergoing template instantiation. + /// + /// The top of this stack is used by a fixit instantiating unresolved + /// function calls to fix the AST to match the textual change it prints. + llvm::SmallVector<CallExpr *, 8> CallsUndergoingInstantiation; + + /// \brief A stack object to be created when performing template + /// instantiation. + /// + /// Construction of an object of type \c InstantiatingTemplate + /// pushes the current instantiation onto the stack of active + /// instantiations. If the size of this stack exceeds the maximum + /// number of recursive template instantiations, construction + /// produces an error and evaluates true. + /// + /// Destruction of this object will pop the named instantiation off + /// the stack. + struct InstantiatingTemplate { + /// \brief Note that we are instantiating a class template, + /// function template, or a member thereof. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + Decl *Entity, + SourceRange InstantiationRange = SourceRange()); + + /// \brief Note that we are instantiating a default argument in a + /// template-id. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange = SourceRange()); + + /// \brief Note that we are instantiating a default argument in a + /// template-id. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + FunctionTemplateDecl *FunctionTemplate, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + ActiveTemplateInstantiation::InstantiationKind Kind, + SourceRange InstantiationRange = SourceRange()); + + /// \brief Note that we are instantiating as part of template + /// argument deduction for a class template partial + /// specialization. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + ClassTemplatePartialSpecializationDecl *PartialSpec, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange = SourceRange()); + + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + ParmVarDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange = SourceRange()); + + /// \brief Note that we are substituting prior template arguments into a + /// non-type or template template parameter. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + NonTypeTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange); + + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + TemplateTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange); + + /// \brief Note that we are checking the default template argument + /// against the template parameter for a given template-id. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + NamedDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange); + + + /// \brief Note that we have finished instantiating this template. + void Clear(); + + ~InstantiatingTemplate() { Clear(); } + + /// \brief Determines whether we have exceeded the maximum + /// recursive template instantiations. + operator bool() const { return Invalid; } + + private: + Sema &SemaRef; + bool Invalid; + + bool CheckInstantiationDepth(SourceLocation PointOfInstantiation, + SourceRange InstantiationRange); + + InstantiatingTemplate(const InstantiatingTemplate&); // not implemented + + InstantiatingTemplate& + operator=(const InstantiatingTemplate&); // not implemented + }; + + void PrintInstantiationStack(); + + /// \brief Determines whether we are currently in a context where + /// template argument substitution failures are not considered + /// errors. + /// + /// When this routine returns true, the emission of most diagnostics + /// will be suppressed and there will be no local error recovery. + bool isSFINAEContext() const; + + /// \brief RAII class used to determine whether SFINAE has + /// trapped any errors that occur during template argument + /// deduction. + class SFINAETrap { + Sema &SemaRef; + unsigned PrevSFINAEErrors; + public: + explicit SFINAETrap(Sema &SemaRef) + : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors) { } + + ~SFINAETrap() { SemaRef.NumSFINAEErrors = PrevSFINAEErrors; } + + /// \brief Determine whether any SFINAE errors have been trapped. + bool hasErrorOccurred() const { + return SemaRef.NumSFINAEErrors > PrevSFINAEErrors; + } + }; + + /// \brief RAII class that determines when any errors have occurred + /// between the time the instance was created and the time it was + /// queried. + class ErrorTrap { + Sema &SemaRef; + unsigned PrevErrors; + + public: + explicit ErrorTrap(Sema &SemaRef) + : SemaRef(SemaRef), PrevErrors(SemaRef.getDiagnostics().getNumErrors()) {} + + /// \brief Determine whether any errors have occurred since this + /// object instance was created. + bool hasErrorOccurred() const { + return SemaRef.getDiagnostics().getNumErrors() > PrevErrors; + } + }; + + /// \brief The current instantiation scope used to store local + /// variables. + LocalInstantiationScope *CurrentInstantiationScope; + + /// \brief The number of typos corrected by CorrectTypo. + unsigned TyposCorrected; + + /// \brief Worker object for performing CFG-based warnings. + sema::AnalysisBasedWarnings AnalysisWarnings; + + /// \brief An entity for which implicit template instantiation is required. + /// + /// The source location associated with the declaration is the first place in + /// the source code where the declaration was "used". It is not necessarily + /// the point of instantiation (which will be either before or after the + /// namespace-scope declaration that triggered this implicit instantiation), + /// However, it is the location that diagnostics should generally refer to, + /// because users will need to know what code triggered the instantiation. + typedef std::pair<ValueDecl *, SourceLocation> PendingImplicitInstantiation; + + /// \brief The queue of implicit template instantiations that are required + /// but have not yet been performed. + std::deque<PendingImplicitInstantiation> PendingInstantiations; + + /// \brief The queue of implicit template instantiations that are required + /// and must be performed within the current local scope. + /// + /// This queue is only used for member functions of local classes in + /// templates, which must be instantiated in the same scope as their + /// enclosing function, so that they can reference function-local + /// types, static variables, enumerators, etc. + std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations; + + void PerformPendingInstantiations(bool LocalOnly = false); + + TypeSourceInfo *SubstType(TypeSourceInfo *T, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, DeclarationName Entity); + + QualType SubstType(QualType T, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, DeclarationName Entity); + + TypeSourceInfo *SubstFunctionDeclType(TypeSourceInfo *T, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, + DeclarationName Entity); + ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs); + ExprResult SubstExpr(Expr *E, + const MultiLevelTemplateArgumentList &TemplateArgs); + + StmtResult SubstStmt(Stmt *S, + const MultiLevelTemplateArgumentList &TemplateArgs); + + Decl *SubstDecl(Decl *D, DeclContext *Owner, + const MultiLevelTemplateArgumentList &TemplateArgs); + + bool + SubstBaseSpecifiers(CXXRecordDecl *Instantiation, + CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs); + + bool + InstantiateClass(SourceLocation PointOfInstantiation, + CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateSpecializationKind TSK, + bool Complain = true); + + void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, + Decl *Pattern, Decl *Inst); + + bool + InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation, + ClassTemplateSpecializationDecl *ClassTemplateSpec, + TemplateSpecializationKind TSK, + bool Complain = true); + + void InstantiateClassMembers(SourceLocation PointOfInstantiation, + CXXRecordDecl *Instantiation, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateSpecializationKind TSK); + + void InstantiateClassTemplateSpecializationMembers( + SourceLocation PointOfInstantiation, + ClassTemplateSpecializationDecl *ClassTemplateSpec, + TemplateSpecializationKind TSK); + + NestedNameSpecifier * + SubstNestedNameSpecifier(NestedNameSpecifier *NNS, + SourceRange Range, + const MultiLevelTemplateArgumentList &TemplateArgs); + DeclarationNameInfo + SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, + const MultiLevelTemplateArgumentList &TemplateArgs); + TemplateName + SubstTemplateName(TemplateName Name, SourceLocation Loc, + const MultiLevelTemplateArgumentList &TemplateArgs); + bool Subst(const TemplateArgumentLoc &Arg, TemplateArgumentLoc &Result, + const MultiLevelTemplateArgumentList &TemplateArgs); + + void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, + FunctionDecl *Function, + bool Recursive = false, + bool DefinitionRequired = false); + void InstantiateStaticDataMemberDefinition( + SourceLocation PointOfInstantiation, + VarDecl *Var, + bool Recursive = false, + bool DefinitionRequired = false); + + void InstantiateMemInitializers(CXXConstructorDecl *New, + const CXXConstructorDecl *Tmpl, + const MultiLevelTemplateArgumentList &TemplateArgs); + + NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs); + DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC, + const MultiLevelTemplateArgumentList &TemplateArgs); + + // Objective-C declarations. + Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *SuperName, + SourceLocation SuperLoc, + Decl * const *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, + AttributeList *AttrList); + + Decl *ActOnCompatiblityAlias( + SourceLocation AtCompatibilityAliasLoc, + IdentifierInfo *AliasName, SourceLocation AliasLocation, + IdentifierInfo *ClassName, SourceLocation ClassLocation); + + void CheckForwardProtocolDeclarationForCircularDependency( + IdentifierInfo *PName, + SourceLocation &PLoc, SourceLocation PrevLoc, + const ObjCList<ObjCProtocolDecl> &PList); + + Decl *ActOnStartProtocolInterface( + SourceLocation AtProtoInterfaceLoc, + IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, + Decl * const *ProtoRefNames, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, + AttributeList *AttrList); + + Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *CategoryName, + SourceLocation CategoryLoc, + Decl * const *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc); + + Decl *ActOnStartClassImplementation( + SourceLocation AtClassImplLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperClassname, + SourceLocation SuperClassLoc); + + Decl *ActOnStartCategoryImplementation(SourceLocation AtCatImplLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *CatName, + SourceLocation CatLoc); + + Decl *ActOnForwardClassDeclaration(SourceLocation Loc, + IdentifierInfo **IdentList, + SourceLocation *IdentLocs, + unsigned NumElts); + + Decl *ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, + const IdentifierLocPair *IdentList, + unsigned NumElts, + AttributeList *attrList); + + void FindProtocolDeclaration(bool WarnOnDeclarations, + const IdentifierLocPair *ProtocolId, + unsigned NumProtocols, + llvm::SmallVectorImpl<Decl *> &Protocols); + + /// Ensure attributes are consistent with type. + /// \param [in, out] Attributes The attributes to check; they will + /// be modified to be consistent with \arg PropertyTy. + void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, + SourceLocation Loc, + unsigned &Attributes); + void ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCContainerDecl *DC); + void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, + ObjCPropertyDecl *SuperProperty, + const IdentifierInfo *Name); + void ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl); + + void CompareMethodParamsInBaseAndSuper(Decl *IDecl, + ObjCMethodDecl *MethodDecl, + bool IsInstance); + + void CompareProperties(Decl *CDecl, Decl *MergeProtocols); + + void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, + ObjCInterfaceDecl *ID); + + void MatchOneProtocolPropertiesInClass(Decl *CDecl, + ObjCProtocolDecl *PDecl); + + void ActOnAtEnd(Scope *S, SourceRange AtEnd, Decl *classDecl, + Decl **allMethods = 0, unsigned allNum = 0, + Decl **allProperties = 0, unsigned pNum = 0, + DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0); + + Decl *ActOnProperty(Scope *S, SourceLocation AtLoc, + FieldDeclarator &FD, ObjCDeclSpec &ODS, + Selector GetterSel, Selector SetterSel, + Decl *ClassCategory, + bool *OverridingProperty, + tok::ObjCKeywordKind MethodImplKind); + + Decl *ActOnPropertyImplDecl(Scope *S, + SourceLocation AtLoc, + SourceLocation PropertyLoc, + bool ImplKind,Decl *ClassImplDecl, + IdentifierInfo *PropertyId, + IdentifierInfo *PropertyIvar); + + struct ObjCArgInfo { + IdentifierInfo *Name; + SourceLocation NameLoc; + // The Type is null if no type was specified, and the DeclSpec is invalid + // in this case. + ParsedType Type; + ObjCDeclSpec DeclSpec; + + /// ArgAttrs - Attribute list for this argument. + AttributeList *ArgAttrs; + }; + + Decl *ActOnMethodDeclaration( + SourceLocation BeginLoc, // location of the + or -. + SourceLocation EndLoc, // location of the ; or {. + tok::TokenKind MethodType, + Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + Selector Sel, + // optional arguments. The number of types/arguments is obtained + // from the Sel.getNumArgs(). + ObjCArgInfo *ArgInfo, + DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args + AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, + bool isVariadic = false); + + // Helper method for ActOnClassMethod/ActOnInstanceMethod. + // Will search "local" class/category implementations for a method decl. + // Will also search in class's root looking for instance method. + // Returns 0 if no method is found. + ObjCMethodDecl *LookupPrivateClassMethod(Selector Sel, + ObjCInterfaceDecl *CDecl); + ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel, + ObjCInterfaceDecl *ClassDecl); + + ExprResult + HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, + Expr *BaseExpr, + DeclarationName MemberName, + SourceLocation MemberLoc); + + ExprResult + ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, + IdentifierInfo &propertyName, + SourceLocation receiverNameLoc, + SourceLocation propertyNameLoc); + + /// \brief Describes the kind of message expression indicated by a message + /// send that starts with an identifier. + enum ObjCMessageKind { + /// \brief The message is sent to 'super'. + ObjCSuperMessage, + /// \brief The message is an instance message. + ObjCInstanceMessage, + /// \brief The message is a class message, and the identifier is a type + /// name. + ObjCClassMessage + }; + + ObjCMessageKind getObjCMessageKind(Scope *S, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool IsSuper, + bool HasTrailingDot, + ParsedType &ReceiverType); + + ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + + ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + + ExprResult ActOnClassMessage(Scope *S, + ParsedType Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + + ExprResult BuildInstanceMessage(Expr *Receiver, + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + + ExprResult ActOnInstanceMessage(Scope *S, + Expr *Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + + + enum PragmaOptionsAlignKind { + POAK_Native, // #pragma options align=native + POAK_Natural, // #pragma options align=natural + POAK_Packed, // #pragma options align=packed + POAK_Power, // #pragma options align=power + POAK_Mac68k, // #pragma options align=mac68k + POAK_Reset // #pragma options align=reset + }; + + /// ActOnPragmaOptionsAlign - Called on well formed #pragma options align. + void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, + SourceLocation PragmaLoc, + SourceLocation KindLoc); + + enum PragmaPackKind { + PPK_Default, // #pragma pack([n]) + PPK_Show, // #pragma pack(show), only supported by MSVC. + PPK_Push, // #pragma pack(push, [identifier], [n]) + PPK_Pop // #pragma pack(pop, [identifier], [n]) + }; + + /// ActOnPragmaPack - Called on well formed #pragma pack(...). + void ActOnPragmaPack(PragmaPackKind Kind, + IdentifierInfo *Name, + Expr *Alignment, + SourceLocation PragmaLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc); + + /// ActOnPragmaUnused - Called on well-formed '#pragma unused'. + void ActOnPragmaUnused(const Token *Identifiers, + unsigned NumIdentifiers, Scope *curScope, + SourceLocation PragmaLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc); + + /// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... . + void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, + SourceLocation PragmaLoc); + + NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II); + void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W); + + /// ActOnPragmaWeakID - Called on well formed #pragma weak ident. + void ActOnPragmaWeakID(IdentifierInfo* WeakName, + SourceLocation PragmaLoc, + SourceLocation WeakNameLoc); + + /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident. + void ActOnPragmaWeakAlias(IdentifierInfo* WeakName, + IdentifierInfo* AliasName, + SourceLocation PragmaLoc, + SourceLocation WeakNameLoc, + SourceLocation AliasNameLoc); + + /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to + /// a the record decl, to handle '#pragma pack' and '#pragma options align'. + void AddAlignmentAttributesForRecord(RecordDecl *RD); + + /// FreePackedContext - Deallocate and null out PackContext. + void FreePackedContext(); + + /// PushVisibilityAttr - Note that we've entered a context with a + /// visibility attribute. + void PushVisibilityAttr(const VisibilityAttr *Attr); + + /// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used, + /// add an appropriate visibility attribute. + void AddPushedVisibilityAttribute(Decl *RD); + + /// PopPragmaVisibility - Pop the top element of the visibility stack; used + /// for '#pragma GCC visibility' and visibility attributes on namespaces. + void PopPragmaVisibility(); + + /// FreeVisContext - Deallocate and null out VisContext. + void FreeVisContext(); + + /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. + void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E); + void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *T); + + /// CastCategory - Get the correct forwarded implicit cast result category + /// from the inner expression. + ExprValueKind CastCategory(Expr *E); + + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit + /// cast. If there is already an implicit cast, merge into the existing one. + /// If isLvalue, the result of the cast is an lvalue. + void ImpCastExprToType(Expr *&Expr, QualType Type, CastKind CK, + ExprValueKind VK = VK_RValue, + const CXXCastPath *BasePath = 0); + + // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts + // functions and arrays to their respective pointers (C99 6.3.2.1). + Expr *UsualUnaryConversions(Expr *&expr); + + // DefaultFunctionArrayConversion - converts functions and arrays + // to their respective pointers (C99 6.3.2.1). + void DefaultFunctionArrayConversion(Expr *&expr); + + // DefaultFunctionArrayLvalueConversion - converts functions and + // arrays to their respective pointers and performs the + // lvalue-to-rvalue conversion. + void DefaultFunctionArrayLvalueConversion(Expr *&expr); + + // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that + // do not have a prototype. Integer promotions are performed on each + // argument, and arguments that have type float are promoted to double. + void DefaultArgumentPromotion(Expr *&Expr); + + // Used for emitting the right warning by DefaultVariadicArgumentPromotion + enum VariadicCallType { + VariadicFunction, + VariadicBlock, + VariadicMethod, + VariadicConstructor, + VariadicDoesNotApply + }; + + /// GatherArgumentsForCall - Collector argument expressions for various + /// form of call prototypes. + bool GatherArgumentsForCall(SourceLocation CallLoc, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + unsigned FirstProtoArg, + Expr **Args, unsigned NumArgs, + llvm::SmallVector<Expr *, 8> &AllArgs, + VariadicCallType CallType = VariadicDoesNotApply); + + // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but + // will warn if the resulting type is not a POD type. + bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, + FunctionDecl *FDecl); + + // UsualArithmeticConversions - performs the UsualUnaryConversions on it's + // operands and then handles various conversions that are common to binary + // operators (C99 6.3.1.8). If both operands aren't arithmetic, this + // routine returns the first non-arithmetic type found. The client is + // responsible for emitting appropriate error diagnostics. + QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr, + bool isCompAssign = false); + + /// AssignConvertType - All of the 'assignment' semantic checks return this + /// enum to indicate whether the assignment was allowed. These checks are + /// done for simple assignments, as well as initialization, return from + /// function, argument passing, etc. The query is phrased in terms of a + /// source and destination type. + enum AssignConvertType { + /// Compatible - the types are compatible according to the standard. + Compatible, + + /// PointerToInt - The assignment converts a pointer to an int, which we + /// accept as an extension. + PointerToInt, + + /// IntToPointer - The assignment converts an int to a pointer, which we + /// accept as an extension. + IntToPointer, + + /// FunctionVoidPointer - The assignment is between a function pointer and + /// void*, which the standard doesn't allow, but we accept as an extension. + FunctionVoidPointer, + + /// IncompatiblePointer - The assignment is between two pointers types that + /// are not compatible, but we accept them as an extension. + IncompatiblePointer, + + /// IncompatiblePointer - The assignment is between two pointers types which + /// point to integers which have a different sign, but are otherwise identical. + /// This is a subset of the above, but broken out because it's by far the most + /// common case of incompatible pointers. + IncompatiblePointerSign, + + /// CompatiblePointerDiscardsQualifiers - The assignment discards + /// c/v/r qualifiers, which we accept as an extension. + CompatiblePointerDiscardsQualifiers, + + /// IncompatibleNestedPointerQualifiers - The assignment is between two + /// nested pointer types, and the qualifiers other than the first two + /// levels differ e.g. char ** -> const char **, but we accept them as an + /// extension. + IncompatibleNestedPointerQualifiers, + + /// IncompatibleVectors - The assignment is between two vector types that + /// have the same size, which we accept as an extension. + IncompatibleVectors, + + /// IntToBlockPointer - The assignment converts an int to a block + /// pointer. We disallow this. + IntToBlockPointer, + + /// IncompatibleBlockPointer - The assignment is between two block + /// pointers types that are not compatible. + IncompatibleBlockPointer, + + /// IncompatibleObjCQualifiedId - The assignment is between a qualified + /// id type and something else (that is incompatible with it). For example, + /// "id <XXX>" = "Foo *", where "Foo *" doesn't implement the XXX protocol. + IncompatibleObjCQualifiedId, + + /// Incompatible - We reject this conversion outright, it is invalid to + /// represent it in the AST. + Incompatible + }; + + /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the + /// assignment conversion type specified by ConvTy. This returns true if the + /// conversion was invalid or false if the conversion was accepted. + bool DiagnoseAssignmentResult(AssignConvertType ConvTy, + SourceLocation Loc, + QualType DstType, QualType SrcType, + Expr *SrcExpr, AssignmentAction Action, + bool *Complained = 0); + + /// CheckAssignmentConstraints - Perform type checking for assignment, + /// argument passing, variable initialization, and function return values. + /// This routine is only used by the following two methods. C99 6.5.16. + AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs); + + // CheckSingleAssignmentConstraints - Currently used by + // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking, + // this routine performs the default function/array converions. + AssignConvertType CheckSingleAssignmentConstraints(QualType lhs, + Expr *&rExpr); + + // \brief If the lhs type is a transparent union, check whether we + // can initialize the transparent union with the given expression. + AssignConvertType CheckTransparentUnionArgumentConstraints(QualType lhs, + Expr *&rExpr); + + // Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1) + AssignConvertType CheckPointerTypesForAssignment(QualType lhsType, + QualType rhsType); + + AssignConvertType CheckObjCPointerTypesForAssignment(QualType lhsType, + QualType rhsType); + + // Helper function for CheckAssignmentConstraints involving two + // block pointer types. + AssignConvertType CheckBlockPointerTypesForAssignment(QualType lhsType, + QualType rhsType); + + bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType); + + bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType); + + bool PerformImplicitConversion(Expr *&From, QualType ToType, + AssignmentAction Action, + bool AllowExplicit = false); + bool PerformImplicitConversion(Expr *&From, QualType ToType, + AssignmentAction Action, + bool AllowExplicit, + ImplicitConversionSequence& ICS); + bool PerformImplicitConversion(Expr *&From, QualType ToType, + const ImplicitConversionSequence& ICS, + AssignmentAction Action, + bool IgnoreBaseAccess = false); + bool PerformImplicitConversion(Expr *&From, QualType ToType, + const StandardConversionSequence& SCS, + AssignmentAction Action,bool IgnoreBaseAccess); + + /// the following "Check" methods will return a valid/converted QualType + /// or a null QualType (indicating an error diagnostic was issued). + + /// type checking binary operators (subroutines of CreateBuiltinBinOp). + QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex); + QualType CheckPointerToMemberOperands( // C++ 5.5 + Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isIndirect); + QualType CheckMultiplyDivideOperands( // C99 6.5.5 + Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign, + bool isDivide); + QualType CheckRemainderOperands( // C99 6.5.5 + Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); + QualType CheckAdditionOperands( // C99 6.5.6 + Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); + QualType CheckSubtractionOperands( // C99 6.5.6 + Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); + QualType CheckShiftOperands( // C99 6.5.7 + Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); + QualType CheckCompareOperands( // C99 6.5.8/9 + Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, + bool isRelational); + QualType CheckBitwiseOperands( // C99 6.5.[10...12] + Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); + QualType CheckLogicalOperands( // C99 6.5.[13,14] + Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc); + // CheckAssignmentOperands is used for both simple and compound assignment. + // For simple assignment, pass both expressions and a null converted type. + // For compound assignment, pass both expressions and the converted type. + QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] + Expr *lex, Expr *&rex, SourceLocation OpLoc, QualType convertedType); + QualType CheckCommaOperands( // C99 6.5.17 + Expr *lex, Expr *&rex, SourceLocation OpLoc); + QualType CheckConditionalOperands( // C99 6.5.15 + Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc); + QualType CXXCheckConditionalOperands( // C++ 5.16 + Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc); + QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, + bool *NonStandardCompositeType = 0); + + QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, + SourceLocation questionLoc); + + /// type checking for vector binary operators. + QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex); + QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx, + SourceLocation l, bool isRel); + + /// type checking unary operators (subroutines of ActOnUnaryOp). + /// C99 6.5.3.1, 6.5.3.2, 6.5.3.4 + QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc, + bool isInc, bool isPrefix); + QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc); + QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc); + QualType CheckRealImagOperand(Expr *&Op, SourceLocation OpLoc, bool isReal); + + /// type checking primary expressions. + QualType CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, + const IdentifierInfo *Comp, + SourceLocation CmpLoc); + + /// type checking declaration initializers (C99 6.7.8) + bool CheckInitList(const InitializedEntity &Entity, + InitListExpr *&InitList, QualType &DeclType); + bool CheckForConstantInitializer(Expr *e, QualType t); + + // type checking C++ declaration initializers (C++ [dcl.init]). + + /// ReferenceCompareResult - Expresses the result of comparing two + /// types (cv1 T1 and cv2 T2) to determine their compatibility for the + /// purposes of initialization by reference (C++ [dcl.init.ref]p4). + enum ReferenceCompareResult { + /// Ref_Incompatible - The two types are incompatible, so direct + /// reference binding is not possible. + Ref_Incompatible = 0, + /// Ref_Related - The two types are reference-related, which means + /// that their unqualified forms (T1 and T2) are either the same + /// or T1 is a base class of T2. + Ref_Related, + /// Ref_Compatible_With_Added_Qualification - The two types are + /// reference-compatible with added qualification, meaning that + /// they are reference-compatible and the qualifiers on T1 (cv1) + /// are greater than the qualifiers on T2 (cv2). + Ref_Compatible_With_Added_Qualification, + /// Ref_Compatible - The two types are reference-compatible and + /// have equivalent qualifiers (cv1 == cv2). + Ref_Compatible + }; + + ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc, + QualType T1, QualType T2, + bool &DerivedToBase, + bool &ObjCConversion); + + /// CheckCastTypes - Check type constraints for casting between types under + /// C semantics, or forward to CXXCheckCStyleCast in C++. + bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr, + CastKind &Kind, CXXCastPath &BasePath, + bool FunctionalStyle = false); + + // CheckVectorCast - check type constraints for vectors. + // Since vectors are an extension, there are no C standard reference for this. + // We allow casting between vectors and integer datatypes of the same size. + // returns true if the cast is invalid + bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, + CastKind &Kind); + + // CheckExtVectorCast - check type constraints for extended vectors. + // Since vectors are an extension, there are no C standard reference for this. + // We allow casting between vectors and integer datatypes of the same size, + // or vectors and the element type of that vector. + // returns true if the cast is invalid + bool CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *&CastExpr, + CastKind &Kind); + + /// CXXCheckCStyleCast - Check constraints of a C-style or function-style + /// cast under C++ semantics. + bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, + CastKind &Kind, CXXCastPath &BasePath, + bool FunctionalStyle); + + /// CheckMessageArgumentTypes - Check types in an Obj-C message send. + /// \param Method - May be null. + /// \param [out] ReturnType - The return type of the send. + /// \return true iff there were any incompatible types. + bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel, + ObjCMethodDecl *Method, bool isClassMessage, + SourceLocation lbrac, SourceLocation rbrac, + QualType &ReturnType); + + /// CheckBooleanCondition - Diagnose problems involving the use of + /// the given expression as a boolean condition (e.g. in an if + /// statement). Also performs the standard function and array + /// decays, possibly changing the input variable. + /// + /// \param Loc - A location associated with the condition, e.g. the + /// 'if' keyword. + /// \return true iff there were any errors + bool CheckBooleanCondition(Expr *&CondExpr, SourceLocation Loc); + + ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, + Expr *SubExpr); + + /// DiagnoseAssignmentAsCondition - Given that an expression is + /// being used as a boolean condition, warn if it's an assignment. + void DiagnoseAssignmentAsCondition(Expr *E); + + /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. + bool CheckCXXBooleanCondition(Expr *&CondExpr); + + /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have + /// the specified width and sign. If an overflow occurs, detect it and emit + /// the specified diagnostic. + void ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &OldVal, + unsigned NewWidth, bool NewSign, + SourceLocation Loc, unsigned DiagID); + + /// Checks that the Objective-C declaration is declared in the global scope. + /// Emits an error and marks the declaration as invalid if it's not declared + /// in the global scope. + bool CheckObjCDeclScope(Decl *D); + + void InitBuiltinVaListType(); + + /// VerifyIntegerConstantExpression - verifies that an expression is an ICE, + /// and reports the appropriate diagnostics. Returns false on success. + /// Can optionally return the value of the expression. + bool VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result = 0); + + /// VerifyBitField - verifies that a bit field expression is an ICE and has + /// the correct width, and that the field type is valid. + /// Returns false on success. + /// Can optionally return whether the bit-field is of width 0 + bool VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, + QualType FieldTy, const Expr *BitWidth, + bool *ZeroWidth = 0); + + /// \name Code completion + //@{ + /// \brief Describes the context in which code completion occurs. + enum ParserCompletionContext { + /// \brief Code completion occurs at top-level or namespace context. + PCC_Namespace, + /// \brief Code completion occurs within a class, struct, or union. + PCC_Class, + /// \brief Code completion occurs within an Objective-C interface, protocol, + /// or category. + PCC_ObjCInterface, + /// \brief Code completion occurs within an Objective-C implementation or + /// category implementation + PCC_ObjCImplementation, + /// \brief Code completion occurs within the list of instance variables + /// in an Objective-C interface, protocol, category, or implementation. + PCC_ObjCInstanceVariableList, + /// \brief Code completion occurs following one or more template + /// headers. + PCC_Template, + /// \brief Code completion occurs following one or more template + /// headers within a class. + PCC_MemberTemplate, + /// \brief Code completion occurs within an expression. + PCC_Expression, + /// \brief Code completion occurs within a statement, which may + /// also be an expression or a declaration. + PCC_Statement, + /// \brief Code completion occurs at the beginning of the + /// initialization statement (or expression) in a for loop. + PCC_ForInit, + /// \brief Code completion occurs within the condition of an if, + /// while, switch, or for statement. + PCC_Condition, + /// \brief Code completion occurs within the body of a function on a + /// recovery path, where we do not have a specific handle on our position + /// in the grammar. + PCC_RecoveryInFunction, + /// \brief Code completion occurs where only a type is permitted. + PCC_Type + }; + + void CodeCompleteOrdinaryName(Scope *S, + ParserCompletionContext CompletionContext); + void CodeCompleteDeclarator(Scope *S, + bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers); + + struct CodeCompleteExpressionData; + void CodeCompleteExpression(Scope *S, + const CodeCompleteExpressionData &Data); + void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + bool IsArrow); + void CodeCompleteTag(Scope *S, unsigned TagSpec); + void CodeCompleteTypeQualifiers(DeclSpec &DS); + void CodeCompleteCase(Scope *S); + void CodeCompleteCall(Scope *S, Expr *Fn, Expr **Args, unsigned NumArgs); + void CodeCompleteInitializer(Scope *S, Decl *D); + void CodeCompleteReturn(Scope *S); + void CodeCompleteAssignmentRHS(Scope *S, Expr *LHS); + + void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, + bool EnteringContext); + void CodeCompleteUsing(Scope *S); + void CodeCompleteUsingDirective(Scope *S); + void CodeCompleteNamespaceDecl(Scope *S); + void CodeCompleteNamespaceAliasDecl(Scope *S); + void CodeCompleteOperatorName(Scope *S); + void CodeCompleteConstructorInitializer(Decl *Constructor, + CXXBaseOrMemberInitializer** Initializers, + unsigned NumInitializers); + + void CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl, + bool InInterface); + void CodeCompleteObjCAtVisibility(Scope *S); + void CodeCompleteObjCAtStatement(Scope *S); + void CodeCompleteObjCAtExpression(Scope *S); + void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); + void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl, + Decl **Methods, + unsigned NumMethods); + void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl, + Decl **Methods, + unsigned NumMethods); + void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS); + void CodeCompleteObjCMessageReceiver(Scope *S); + void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, + IdentifierInfo **SelIdents, + unsigned NumSelIdents); + void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents); + void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool IsSuper); + void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents); + void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool IsSuper); + void CodeCompleteObjCForCollection(Scope *S, + DeclGroupPtrTy IterationVar); + void CodeCompleteObjCSelector(Scope *S, + IdentifierInfo **SelIdents, + unsigned NumSelIdents); + void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, + unsigned NumProtocols); + void CodeCompleteObjCProtocolDecl(Scope *S); + void CodeCompleteObjCInterfaceDecl(Scope *S); + void CodeCompleteObjCSuperclass(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc); + void CodeCompleteObjCImplementationDecl(Scope *S); + void CodeCompleteObjCInterfaceCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc); + void CodeCompleteObjCImplementationCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc); + void CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl); + void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, + IdentifierInfo *PropertyName, + Decl *ObjCImpDecl); + void CodeCompleteObjCMethodDecl(Scope *S, + bool IsInstanceMethod, + ParsedType ReturnType, + Decl *IDecl); + void CodeCompleteObjCMethodDeclSelector(Scope *S, + bool IsInstanceMethod, + bool AtParameterName, + ParsedType ReturnType, + IdentifierInfo **SelIdents, + unsigned NumSelIdents); + void CodeCompletePreprocessorDirective(bool InConditional); + void CodeCompleteInPreprocessorConditionalExclusion(Scope *S); + void CodeCompletePreprocessorMacroName(bool IsDefinition); + void CodeCompletePreprocessorExpression(); + void CodeCompletePreprocessorMacroArgument(Scope *S, + IdentifierInfo *Macro, + MacroInfo *MacroInfo, + unsigned Argument); + void CodeCompleteNaturalLanguage(); + void GatherGlobalCodeCompletions( + llvm::SmallVectorImpl<CodeCompletionResult> &Results); + //@} + + void PrintStats() const {} + + //===--------------------------------------------------------------------===// + // Extra semantic analysis beyond the C type system + +public: + SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL, + unsigned ByteNo) const; + +private: + bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall); + bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall); + + bool CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall); + bool CheckObjCString(Expr *Arg); + + ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + + bool SemaBuiltinVAStart(CallExpr *TheCall); + bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); + bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs); + +public: + // Used by C++ template instantiation. + ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); + +private: + bool SemaBuiltinPrefetch(CallExpr *TheCall); + bool SemaBuiltinObjectSize(CallExpr *TheCall); + bool SemaBuiltinLongjmp(CallExpr *TheCall); + ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult); + bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, + llvm::APSInt &Result); + + bool SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, + bool HasVAListArg, unsigned format_idx, + unsigned firstDataArg, bool isPrintf); + + void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr, + const CallExpr *TheCall, bool HasVAListArg, + unsigned format_idx, unsigned firstDataArg, + bool isPrintf); + + void CheckNonNullArguments(const NonNullAttr *NonNull, + const CallExpr *TheCall); + + void CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg, + unsigned format_idx, unsigned firstDataArg, + bool isPrintf); + + void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, + SourceLocation ReturnLoc); + void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex); + void CheckImplicitConversions(Expr *E); + + /// \brief The parser's current scope. + /// + /// The parser maintains this state here. + Scope *CurScope; + +protected: + friend class Parser; + + /// \brief Retrieve the parser's current scope. + Scope *getCurScope() const { return CurScope; } +}; + +/// \brief RAII object that enters a new expression evaluation context. +class EnterExpressionEvaluationContext { + Sema &Actions; + +public: + EnterExpressionEvaluationContext(Sema &Actions, + Sema::ExpressionEvaluationContext NewContext) + : Actions(Actions) { + Actions.PushExpressionEvaluationContext(NewContext); + } + + ~EnterExpressionEvaluationContext() { + Actions.PopExpressionEvaluationContext(); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h new file mode 100644 index 000000000000..64b83e3bf612 --- /dev/null +++ b/include/clang/Sema/SemaInternal.h @@ -0,0 +1,30 @@ +//===--- SemaInternal.h - Internal Sema Interfaces --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides common API and #includes for the internal +// implementation of Sema. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMA_INTERNAL_H +#define LLVM_CLANG_SEMA_SEMA_INTERNAL_H + +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "clang/AST/ASTContext.h" + +namespace clang { + +inline PartialDiagnostic Sema::PDiag(unsigned DiagID) { + return PartialDiagnostic(DiagID, Context.getDiagAllocator()); +} + +} + +#endif diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h new file mode 100644 index 000000000000..a7b3b8461854 --- /dev/null +++ b/include/clang/Sema/Template.h @@ -0,0 +1,244 @@ +//===------- SemaTemplate.h - C++ Templates ---------------------*- C++ -*-===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file provides types used in the semantic analysis of C++ templates. +// +//===----------------------------------------------------------------------===/ +#ifndef LLVM_CLANG_SEMA_TEMPLATE_H +#define LLVM_CLANG_SEMA_TEMPLATE_H + +#include "clang/AST/DeclTemplate.h" +#include "llvm/ADT/SmallVector.h" +#include <cassert> + +namespace clang { + /// \brief Data structure that captures multiple levels of template argument + /// lists for use in template instantiation. + /// + /// Multiple levels of template arguments occur when instantiating the + /// definitions of member templates. For example: + /// + /// \code + /// template<typename T> + /// struct X { + /// template<T Value> + /// struct Y { + /// void f(); + /// }; + /// }; + /// \endcode + /// + /// When instantiating X<int>::Y<17>::f, the multi-level template argument + /// list will contain a template argument list (int) at depth 0 and a + /// template argument list (17) at depth 1. + class MultiLevelTemplateArgumentList { + public: + typedef std::pair<const TemplateArgument *, unsigned> ArgList; + + private: + /// \brief The template argument lists, stored from the innermost template + /// argument list (first) to the outermost template argument list (last). + llvm::SmallVector<ArgList, 4> TemplateArgumentLists; + + public: + /// \brief Construct an empty set of template argument lists. + MultiLevelTemplateArgumentList() { } + + /// \brief Construct a single-level template argument list. + explicit + MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) { + addOuterTemplateArguments(&TemplateArgs); + } + + /// \brief Determine the number of levels in this template argument + /// list. + unsigned getNumLevels() const { return TemplateArgumentLists.size(); } + + /// \brief Retrieve the template argument at a given depth and index. + const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { + assert(Depth < TemplateArgumentLists.size()); + assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second); + return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index]; + } + + /// \brief Determine whether there is a non-NULL template argument at the + /// given depth and index. + /// + /// There must exist a template argument list at the given depth. + bool hasTemplateArgument(unsigned Depth, unsigned Index) const { + assert(Depth < TemplateArgumentLists.size()); + + if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second) + return false; + + return !(*this)(Depth, Index).isNull(); + } + + /// \brief Add a new outermost level to the multi-level template argument + /// list. + void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) { + TemplateArgumentLists.push_back( + ArgList(TemplateArgs->getFlatArgumentList(), + TemplateArgs->flat_size())); + } + + /// \brief Add a new outmost level to the multi-level template argument + /// list. + void addOuterTemplateArguments(const TemplateArgument *Args, + unsigned NumArgs) { + TemplateArgumentLists.push_back(ArgList(Args, NumArgs)); + } + + /// \brief Retrieve the innermost template argument list. + const ArgList &getInnermost() const { + return TemplateArgumentLists.front(); + } + }; + + /// \brief The context in which partial ordering of function templates occurs. + enum TPOC { + /// \brief Partial ordering of function templates for a function call. + TPOC_Call, + /// \brief Partial ordering of function templates for a call to a + /// conversion function. + TPOC_Conversion, + /// \brief Partial ordering of function templates in other contexts, e.g., + /// taking the address of a function template or matching a function + /// template specialization to a function template. + TPOC_Other + }; + + // This is lame but unavoidable in a world without forward + // declarations of enums. The alternatives are to either pollute + // Sema.h (by including this file) or sacrifice type safety (by + // making Sema.h declare things as enums). + class TemplatePartialOrderingContext { + TPOC Value; + public: + TemplatePartialOrderingContext(TPOC Value) : Value(Value) {} + operator TPOC() const { return Value; } + }; + + /// \brief Captures a template argument whose value has been deduced + /// via c++ template argument deduction. + class DeducedTemplateArgument : public TemplateArgument { + /// \brief For a non-type template argument, whether the value was + /// deduced from an array bound. + bool DeducedFromArrayBound; + + public: + DeducedTemplateArgument() + : TemplateArgument(), DeducedFromArrayBound(false) { } + + DeducedTemplateArgument(const TemplateArgument &Arg, + bool DeducedFromArrayBound = false) + : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { } + + /// \brief Construct an integral non-type template argument that + /// has been deduced, possible from an array bound. + DeducedTemplateArgument(const llvm::APSInt &Value, + QualType ValueType, + bool DeducedFromArrayBound) + : TemplateArgument(Value, ValueType), + DeducedFromArrayBound(DeducedFromArrayBound) { } + + /// \brief For a non-type template argument, determine whether the + /// template argument was deduced from an array bound. + bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; } + + /// \brief Specify whether the given non-type template argument + /// was deduced from an array bound. + void setDeducedFromArrayBound(bool Deduced) { + DeducedFromArrayBound = Deduced; + } + }; + + /// \brief A stack-allocated class that identifies which local + /// variable declaration instantiations are present in this scope. + /// + /// A new instance of this class type will be created whenever we + /// instantiate a new function declaration, which will have its own + /// set of parameter declarations. + class LocalInstantiationScope { + /// \brief Reference to the semantic analysis that is performing + /// this template instantiation. + Sema &SemaRef; + + /// \brief A mapping from local declarations that occur + /// within a template to their instantiations. + /// + /// This mapping is used during instantiation to keep track of, + /// e.g., function parameter and variable declarations. For example, + /// given: + /// + /// \code + /// template<typename T> T add(T x, T y) { return x + y; } + /// \endcode + /// + /// when we instantiate add<int>, we will introduce a mapping from + /// the ParmVarDecl for 'x' that occurs in the template to the + /// instantiated ParmVarDecl for 'x'. + llvm::DenseMap<const Decl *, Decl *> LocalDecls; + + /// \brief The outer scope, which contains local variable + /// definitions from some other instantiation (that may not be + /// relevant to this particular scope). + LocalInstantiationScope *Outer; + + /// \brief Whether we have already exited this scope. + bool Exited; + + /// \brief Whether to combine this scope with the outer scope, such that + /// lookup will search our outer scope. + bool CombineWithOuterScope; + + // This class is non-copyable + LocalInstantiationScope(const LocalInstantiationScope &); + LocalInstantiationScope &operator=(const LocalInstantiationScope &); + + public: + LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) + : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), + Exited(false), CombineWithOuterScope(CombineWithOuterScope) + { + SemaRef.CurrentInstantiationScope = this; + } + + ~LocalInstantiationScope() { + Exit(); + } + + /// \brief Exit this local instantiation scope early. + void Exit() { + if (Exited) + return; + + SemaRef.CurrentInstantiationScope = Outer; + Exited = true; + } + + Decl *getInstantiationOf(const Decl *D); + + VarDecl *getInstantiationOf(const VarDecl *Var) { + return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var))); + } + + ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) { + return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var))); + } + + NonTypeTemplateParmDecl *getInstantiationOf( + const NonTypeTemplateParmDecl *Var) { + return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var))); + } + + void InstantiatedLocal(const Decl *D, Decl *Inst); + }; +} + +#endif // LLVM_CLANG_SEMA_TEMPLATE_H diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h new file mode 100644 index 000000000000..ac32e9c24f6d --- /dev/null +++ b/include/clang/Sema/TemplateDeduction.h @@ -0,0 +1,111 @@ +//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file provides types used with Sema's template argument deduction +// routines. +// +//===----------------------------------------------------------------------===/ +#ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H +#define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H + +#include "clang/AST/DeclTemplate.h" + +namespace clang { + +class ASTContext; +class TemplateArgumentList; + +namespace sema { + +/// \brief Provides information about an attempted template argument +/// deduction, whose success or failure was described by a +/// TemplateDeductionResult value. +class TemplateDeductionInfo { + /// \brief The context in which the template arguments are stored. + ASTContext &Context; + + /// \brief The deduced template argument list. + /// + TemplateArgumentList *Deduced; + + /// \brief The source location at which template argument + /// deduction is occurring. + SourceLocation Loc; + + // do not implement these + TemplateDeductionInfo(const TemplateDeductionInfo&); + TemplateDeductionInfo &operator=(const TemplateDeductionInfo&); + +public: + TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc) + : Context(Context), Deduced(0), Loc(Loc) { } + + ~TemplateDeductionInfo() { + // FIXME: if (Deduced) Deduced->Destroy(Context); + } + + /// \brief Returns the location at which template argument is + /// occuring. + SourceLocation getLocation() const { + return Loc; + } + + /// \brief Take ownership of the deduced template argument list. + TemplateArgumentList *take() { + TemplateArgumentList *Result = Deduced; + Deduced = 0; + return Result; + } + + /// \brief Provide a new template argument list that contains the + /// results of template argument deduction. + void reset(TemplateArgumentList *NewDeduced) { + // FIXME: if (Deduced) Deduced->Destroy(Context); + Deduced = NewDeduced; + } + + /// \brief The template parameter to which a template argument + /// deduction failure refers. + /// + /// Depending on the result of template argument deduction, this + /// template parameter may have different meanings: + /// + /// TDK_Incomplete: this is the first template parameter whose + /// corresponding template argument was not deduced. + /// + /// TDK_Inconsistent: this is the template parameter for which + /// two different template argument values were deduced. + TemplateParameter Param; + + /// \brief The first template argument to which the template + /// argument deduction failure refers. + /// + /// Depending on the result of the template argument deduction, + /// this template argument may have different meanings: + /// + /// TDK_Inconsistent: this argument is the first value deduced + /// for the corresponding template parameter. + /// + /// TDK_SubstitutionFailure: this argument is the template + /// argument we were instantiating when we encountered an error. + /// + /// TDK_NonDeducedMismatch: this is the template argument + /// provided in the source code. + TemplateArgument FirstArg; + + /// \brief The second template argument to which the template + /// argument deduction failure refers. + /// + /// FIXME: Finish documenting this. + TemplateArgument SecondArg; +}; + +} +} + +#endif diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 27a2b7d0b951..0fa446dd34de 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -1,4 +1,4 @@ -//===- PCHBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===// +//===- ASTBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This header defines Bitcode enum values for Clang precompiled header files. +// This header defines Bitcode enum values for Clang serialized AST files. // // The enum values defined in this file should be considered permanent. If // new features are added, they should have values added at the end of the @@ -17,42 +17,44 @@ #ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H #define LLVM_CLANG_FRONTEND_PCHBITCODES_H +#include "clang/AST/Type.h" #include "llvm/Bitcode/BitCodes.h" #include "llvm/System/DataTypes.h" +#include "llvm/ADT/DenseMap.h" namespace clang { - namespace pch { - /// \brief PCH major version number supported by this version of + namespace serialization { + /// \brief AST file major version number supported by this version of /// Clang. /// - /// Whenever the PCH format changes in a way that makes it + /// Whenever the AST file format changes in a way that makes it /// incompatible with previous versions (such that a reader /// designed for the previous version could not support reading /// the new version), this number should be increased. /// - /// Version 4 of PCH files also requires that the version control branch and + /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of - /// PCH files at this time. + /// AST files at this time. const unsigned VERSION_MAJOR = 4; - /// \brief PCH minor version number supported by this version of + /// \brief AST file minor version number supported by this version of /// Clang. /// - /// Whenever the PCH format changes in a way that is still + /// Whenever the AST format changes in a way that is still /// compatible with previous versions (such that a reader designed /// for the previous version could still support reading the new /// version by ignoring new kinds of subblocks), this number /// should be increased. const unsigned VERSION_MINOR = 0; - /// \brief An ID number that refers to a declaration in a PCH file. + /// \brief An ID number that refers to a declaration in an AST file. /// /// The ID numbers of declarations are consecutive (in order of /// discovery) and start at 2. 0 is reserved for NULL, and 1 is /// reserved for the translation unit declaration. typedef uint32_t DeclID; - /// \brief An ID number that refers to a type in a PCH file. + /// \brief An ID number that refers to a type in an AST file. /// /// The ID of a type is partitioned into two parts: the lower /// three bits are used to store the const/volatile/restrict @@ -64,18 +66,64 @@ namespace clang { /// other types that have serialized representations. typedef uint32_t TypeID; - /// \brief An ID number that refers to an identifier in a PCH + /// \brief A type index; the type ID with the qualifier bits removed. + class TypeIdx { + uint32_t Idx; + public: + TypeIdx() : Idx(0) { } + explicit TypeIdx(uint32_t index) : Idx(index) { } + + uint32_t getIndex() const { return Idx; } + TypeID asTypeID(unsigned FastQuals) const { + return (Idx << Qualifiers::FastWidth) | FastQuals; + } + static TypeIdx fromTypeID(TypeID ID) { + return TypeIdx(ID >> Qualifiers::FastWidth); + } + }; + + /// A structure for putting "fast"-unqualified QualTypes into a + /// DenseMap. This uses the standard pointer hash function. + struct UnsafeQualTypeDenseMapInfo { + static inline bool isEqual(QualType A, QualType B) { return A == B; } + static inline QualType getEmptyKey() { + return QualType::getFromOpaquePtr((void*) 1); + } + static inline QualType getTombstoneKey() { + return QualType::getFromOpaquePtr((void*) 2); + } + static inline unsigned getHashValue(QualType T) { + assert(!T.getLocalFastQualifiers() && + "hash invalid for types with fast quals"); + uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + return (unsigned(v) >> 4) ^ (unsigned(v) >> 9); + } + }; + + /// \brief Map that provides the ID numbers of each type within the + /// output stream, plus those deserialized from a chained PCH. + /// + /// The ID numbers of types are consecutive (in order of discovery) + /// and start at 1. 0 is reserved for NULL. When types are actually + /// stored in the stream, the ID number is shifted by 2 bits to + /// allow for the const/volatile qualifiers. + /// + /// Keys in the map never have const/volatile qualifiers. + typedef llvm::DenseMap<QualType, TypeIdx, UnsafeQualTypeDenseMapInfo> + TypeIdxMap; + + /// \brief An ID number that refers to an identifier in an AST /// file. typedef uint32_t IdentID; typedef uint32_t SelectorID; /// \brief Describes the various kinds of blocks that occur within - /// a PCH file. + /// an AST file. enum BlockIDs { - /// \brief The PCH block, which acts as a container around the - /// full PCH block. - PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, + /// \brief The AST block, which acts as a container around the + /// full AST block. + AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, /// \brief The block containing information about the source /// manager. @@ -86,16 +134,16 @@ namespace clang { PREPROCESSOR_BLOCK_ID, /// \brief The block containing the definitions of all of the - /// types and decls used within the PCH file. + /// types and decls used within the AST file. DECLTYPES_BLOCK_ID }; - /// \brief Record types that occur within the PCH block itself. - enum PCHRecordTypes { + /// \brief Record types that occur within the AST block itself. + enum ASTRecordTypes { /// \brief Record code for the offsets of each type. /// /// The TYPE_OFFSET constant describes the record that occurs - /// within the PCH block. The record itself is an array of offsets that + /// within the AST block. The record itself is an array of offsets that /// point into the declarations and types block (identified by /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID /// of a type. For a given type ID @c T, the lower three bits of @@ -110,7 +158,7 @@ namespace clang { /// /// The DECL_OFFSET constant describes the record that occurs /// within the block identified by DECL_OFFSETS_BLOCK_ID within - /// the PCH block. The record itself is an array of offsets that + /// the AST block. The record itself is an array of offsets that /// point into the declarations and types block (identified by /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this /// record, after subtracting one to account for the use of @@ -126,8 +174,8 @@ namespace clang { /// actually important to check. LANGUAGE_OPTIONS = 3, - /// \brief PCH metadata, including the PCH file version number - /// and the target triple used to build the PCH file. + /// \brief AST file metadata, including the AST file version number + /// and the target triple used to build the AST file. METADATA = 4, /// \brief Record code for the table of offsets of each @@ -142,7 +190,7 @@ namespace clang { /// /// The identifier table is a simple blob that contains /// NULL-terminated strings for all of the identifiers - /// referenced by the PCH file. The IDENTIFIER_OFFSET table + /// referenced by the AST file. The IDENTIFIER_OFFSET table /// contains the mapping from identifier IDs to the characters /// in this blob. Note that the starting offsets of all of the /// identifiers are odd, so that, when the identifier offset @@ -154,10 +202,10 @@ namespace clang { /// \brief Record code for the array of external definitions. /// - /// The PCH file contains a list of all of the unnamed external + /// The AST file contains a list of all of the unnamed external /// definitions present within the parsed headers, stored as an /// array of declaration IDs. These external definitions will be - /// reported to the AST consumer after the PCH file has been + /// reported to the AST consumer after the AST file has been /// read, since their presence can affect the semantics of the /// program (e.g., for code generation). EXTERNAL_DEFINITIONS = 7, @@ -172,7 +220,7 @@ namespace clang { SPECIAL_TYPES = 8, /// \brief Record code for the extra statistics we gather while - /// generating a PCH file. + /// generating an AST file. STATISTICS = 9, /// \brief Record code for the array of tentative definitions. @@ -198,7 +246,7 @@ namespace clang { SOURCE_LOCATION_OFFSETS = 15, /// \brief Record code for the set of source location entries - /// that need to be preloaded by the PCH reader. + /// that need to be preloaded by the AST reader. /// /// This set contains the source location entry for the /// predefines buffer and for any file entries that need to be @@ -212,17 +260,17 @@ namespace clang { EXT_VECTOR_DECLS = 18, /// \brief Record code for the original file that was used to - /// generate the precompiled header. + /// generate the AST file. ORIGINAL_FILE_NAME = 19, /// Record #20 intentionally left blank. /// \brief Record code for the version control branch and revision - /// information of the compiler used to build this PCH file. + /// information of the compiler used to build this AST file. VERSION_CONTROL_BRANCH_REVISION = 21, - /// \brief Record code for the array of unused static functions. - UNUSED_STATIC_FUNCS = 22, + /// \brief Record code for the array of unused file scoped decls. + UNUSED_FILESCOPED_DECLS = 22, /// \brief Record code for the table of offsets to macro definition /// entries in the preprocessing record. @@ -234,10 +282,45 @@ namespace clang { /// \brief Record code for the array of dynamic classes. DYNAMIC_CLASSES = 25, - /// \brief Record code for the chained PCH metadata, including the - /// PCH version and the name of the PCH this is chained to. - CHAINED_METADATA = 26 + /// \brief Record code for the chained AST metadata, including the + /// AST file version and the name of the PCH this depends on. + CHAINED_METADATA = 26, + + /// \brief Record code for referenced selector pool. + REFERENCED_SELECTOR_POOL = 27, + + /// \brief Record code for an update to the TU's lexically contained + /// declarations. + TU_UPDATE_LEXICAL = 28, + /// \brief Record code for an update to first decls pointing to the + /// latest redeclarations. + REDECLS_UPDATE_LATEST = 29, + + /// \brief Record code for declarations that Sema keeps references of. + SEMA_DECL_REFS = 30, + + /// \brief Record code for weak undeclared identifiers. + WEAK_UNDECLARED_IDENTIFIERS = 31, + + /// \brief Record code for pending implicit instantiations. + PENDING_IMPLICIT_INSTANTIATIONS = 32, + + /// \brief Record code for a decl replacement block. + /// + /// If a declaration is modified after having been deserialized, and then + /// written to a dependent AST file, its ID and offset must be added to + /// the replacement block. + DECL_REPLACEMENTS = 33, + + /// \brief Record code for an update to a decl context's lookup table. + /// + /// In practice, this should only be used for the TU and namespaces. + UPDATE_VISIBLE = 34, + + /// \brief Record code for template specializations introduced after + /// serializations of the original template decl. + ADDITIONAL_TEMPLATE_SPECIALIZATIONS = 35 }; /// \brief Record types used within a source manager block. @@ -286,10 +369,10 @@ namespace clang { PP_MACRO_DEFINITION = 5 }; - /// \defgroup PCHAST Precompiled header AST constants + /// \defgroup ASTAST AST file AST constants /// /// The constants in this group describe various components of the - /// abstract syntax tree within a precompiled header. + /// abstract syntax tree within an AST file. /// /// @{ @@ -371,7 +454,7 @@ namespace clang { /// \brief Record codes for each kind of type. /// /// These constants describe the type records that can occur within a - /// block identified by DECLTYPES_BLOCK_ID in the PCH file. Each + /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each /// constant describes a record for a specific type class in the /// AST. enum TypeCode { @@ -545,8 +628,8 @@ namespace clang { /// \brief A record that stores the set of declarations that are /// lexically stored within a given DeclContext. /// - /// The record itself is an array of declaration IDs, in the - /// order in which those declarations were added to the + /// The record itself is a blob that is an array of declaration IDs, + /// in the order in which those declarations were added to the /// declaration context. This data is used when iterating over /// the contents of a DeclContext, e.g., via /// DeclContext::decls_begin()/DeclContext::decls_end(). @@ -588,17 +671,25 @@ namespace clang { /// \brief An AccessSpecDecl record. DECL_ACCESS_SPEC, - // FIXME: Implement serialization for these decl types. This just - // allocates the order in which + /// \brief A FriendDecl record. DECL_FRIEND, + /// \brief A FriendTemplateDecl record. DECL_FRIEND_TEMPLATE, + /// \brief A ClassTemplateDecl record. DECL_CLASS_TEMPLATE, + /// \brief A ClassTemplateSpecializationDecl record. DECL_CLASS_TEMPLATE_SPECIALIZATION, + /// \brief A ClassTemplatePartialSpecializationDecl record. DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, + /// \brief A FunctionTemplateDecl record. DECL_FUNCTION_TEMPLATE, + /// \brief A TemplateTypeParmDecl record. DECL_TEMPLATE_TYPE_PARM, + /// \brief A NonTypeTemplateParmDecl record. DECL_NON_TYPE_TEMPLATE_PARM, + /// \brief A TemplateTemplateParmDecl record. DECL_TEMPLATE_TEMPLATE_PARM, + /// \brief A StaticAssertDecl record. DECL_STATIC_ASSERT }; @@ -755,6 +846,11 @@ namespace clang { STMT_OBJC_AT_THROW, // C++ + + /// \brief A CXXCatchStmt record. + STMT_CXX_CATCH, + /// \brief A CXXTryStmt record. + STMT_CXX_TRY, /// \brief A CXXOperatorCallExpr record. EXPR_CXX_OPERATOR_CALL, @@ -764,17 +860,17 @@ namespace clang { EXPR_CXX_CONSTRUCT, /// \brief A CXXTemporaryObjectExpr record. EXPR_CXX_TEMPORARY_OBJECT, - // \brief A CXXStaticCastExpr record. + /// \brief A CXXStaticCastExpr record. EXPR_CXX_STATIC_CAST, - // \brief A CXXDynamicCastExpr record. + /// \brief A CXXDynamicCastExpr record. EXPR_CXX_DYNAMIC_CAST, - // \brief A CXXReinterpretCastExpr record. + /// \brief A CXXReinterpretCastExpr record. EXPR_CXX_REINTERPRET_CAST, - // \brief A CXXConstCastExpr record. + /// \brief A CXXConstCastExpr record. EXPR_CXX_CONST_CAST, - // \brief A CXXFunctionalCastExpr record. + /// \brief A CXXFunctionalCastExpr record. EXPR_CXX_FUNCTIONAL_CAST, - // \brief A CXXBoolLiteralExpr record. + /// \brief A CXXBoolLiteralExpr record. EXPR_CXX_BOOL_LITERAL, EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr). @@ -783,7 +879,6 @@ namespace clang { EXPR_CXX_THROW, // CXXThrowExpr EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr - EXPR_CXX_BIND_REFERENCE, // CXXBindReferenceExpr EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr EXPR_CXX_NEW, // CXXNewExpr diff --git a/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h new file mode 100644 index 000000000000..f8114de5f15a --- /dev/null +++ b/include/clang/Serialization/ASTDeserializationListener.h @@ -0,0 +1,49 @@ +//===- ASTDeserializationListener.h - Decl/Type PCH Read Events -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ASTDeserializationListener class, which is notified +// by the ASTReader whenever a type or declaration is deserialized. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H +#define LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H + +#include "clang/Serialization/ASTBitCodes.h" + +namespace clang { + +class Decl; +class ASTReader; +class QualType; + +class ASTDeserializationListener { +protected: + virtual ~ASTDeserializationListener() {} + +public: + /// \brief Tell the listener about the reader. + virtual void SetReader(ASTReader *Reader) = 0; + + /// \brief An identifier was deserialized from the AST file. + virtual void IdentifierRead(serialization::IdentID ID, + IdentifierInfo *II) = 0; + /// \brief A type was deserialized from the AST file. The ID here has the + /// qualifier bits already removed, and T is guaranteed to be locally + /// unqualified. + virtual void TypeRead(serialization::TypeIdx Idx, QualType T) = 0; + /// \brief A decl was deserialized from the AST file. + virtual void DeclRead(serialization::DeclID ID, const Decl *D) = 0; + /// \brief A selector was read from the AST file. + virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) = 0; +}; + +} + +#endif diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Serialization/ASTReader.h index 47e871f50aeb..d31be88a3e3d 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1,4 +1,4 @@ -//===--- PCHReader.h - Precompiled Headers Reader ---------------*- C++ -*-===// +//===--- ASTReader.h - AST File Reader --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,18 +7,17 @@ // //===----------------------------------------------------------------------===// // -// This file defines the PCHReader class, which reads a precompiled header. +// This file defines the ASTReader class, which reads AST files. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_PCH_READER_H -#define LLVM_CLANG_FRONTEND_PCH_READER_H +#ifndef LLVM_CLANG_FRONTEND_AST_READER_H +#define LLVM_CLANG_FRONTEND_AST_READER_H -#include "clang/Frontend/PCHBitCodes.h" -#include "clang/AST/DeclarationName.h" +#include "clang/Serialization/ASTBitCodes.h" #include "clang/Sema/ExternalSemaSource.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/Type.h" #include "clang/AST/TemplateBase.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/PreprocessingRecord.h" @@ -28,7 +27,6 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -59,11 +57,12 @@ class GotoStmt; class LabelStmt; class MacroDefinition; class NamedDecl; -class PCHDeserializationListener; +class ASTDeserializationListener; class Preprocessor; class Sema; class SwitchCase; -class PCHReader; +class ASTReader; +class ASTDeclReader; struct HeaderFileInfo; struct PCHPredefinesBlock { @@ -75,15 +74,15 @@ struct PCHPredefinesBlock { }; typedef llvm::SmallVector<PCHPredefinesBlock, 2> PCHPredefinesBlocks; -/// \brief Abstract interface for callback invocations by the PCHReader. +/// \brief Abstract interface for callback invocations by the ASTReader. /// -/// While reading a PCH file, the PCHReader will call the methods of the +/// While reading an AST file, the ASTReader will call the methods of the /// listener to pass on specific information. Some of the listener methods can -/// return true to indicate to the PCHReader that the information (and -/// consequently the PCH file) is invalid. -class PCHReaderListener { +/// return true to indicate to the ASTReader that the information (and +/// consequently the AST file) is invalid. +class ASTReaderListener { public: - virtual ~PCHReaderListener(); + virtual ~ASTReaderListener(); /// \brief Receives the language options. /// @@ -103,8 +102,8 @@ public: /// /// \param Buffers Information about the predefines buffers. /// - /// \param OriginalFileName The original file name for the PCH, which will - /// appear as an entry in the predefines buffer. + /// \param OriginalFileName The original file name for the AST file, which + /// will appear as an entry in the predefines buffer. /// /// \param SuggestedPredefines If necessary, additional definitions are added /// here. @@ -123,16 +122,16 @@ public: virtual void ReadCounter(unsigned Value) {} }; -/// \brief PCHReaderListener implementation to validate the information of +/// \brief ASTReaderListener implementation to validate the information of /// the PCH file against an initialized Preprocessor. -class PCHValidator : public PCHReaderListener { +class PCHValidator : public ASTReaderListener { Preprocessor &PP; - PCHReader &Reader; + ASTReader &Reader; unsigned NumHeaderInfos; public: - PCHValidator(Preprocessor &PP, PCHReader &Reader) + PCHValidator(Preprocessor &PP, ASTReader &Reader) : PP(PP), Reader(Reader), NumHeaderInfos(0) {} virtual bool ReadLanguageOptions(const LangOptions &LangOpts); @@ -147,19 +146,19 @@ private: void Error(const char *Msg); }; -/// \brief Reads a precompiled head containing the contents of a -/// translation unit. +/// \brief Reads an AST files chain containing the contents of a translation +/// unit. /// -/// The PCHReader class reads a bitstream (produced by the PCHWriter +/// The ASTReader class reads bitstreams (produced by the ASTWriter /// class) containing the serialized representation of a given /// abstract syntax tree and its supporting data structures. An -/// instance of the PCHReader can be attached to an ASTContext object, -/// which will provide access to the contents of the PCH file. +/// instance of the ASTReader can be attached to an ASTContext object, +/// which will provide access to the contents of the AST files. /// -/// The PCH reader provides lazy de-serialization of declarations, as +/// The AST reader provides lazy de-serialization of declarations, as /// required when traversing the AST. Only those AST nodes that are /// actually required will be de-serialized. -class PCHReader +class ASTReader : public ExternalPreprocessorSource, public ExternalPreprocessingRecordSource, public ExternalSemaSource, @@ -167,110 +166,226 @@ class PCHReader public ExternalIdentifierLookup, public ExternalSLocEntrySource { public: - enum PCHReadResult { Success, Failure, IgnorePCH }; + enum ASTReadResult { Success, Failure, IgnorePCH }; friend class PCHValidator; + friend class ASTDeclReader; private: - /// \brief The receiver of some callbacks invoked by PCHReader. - llvm::OwningPtr<PCHReaderListener> Listener; + /// \brief The receiver of some callbacks invoked by ASTReader. + llvm::OwningPtr<ASTReaderListener> Listener; /// \brief The receiver of deserialization events. - PCHDeserializationListener *DeserializationListener; + ASTDeserializationListener *DeserializationListener; SourceManager &SourceMgr; FileManager &FileMgr; Diagnostic &Diags; /// \brief The semantic analysis object that will be processing the - /// PCH file and the translation unit that uses it. + /// AST files and the translation unit that uses it. Sema *SemaObj; /// \brief The preprocessor that will be loading the source file. Preprocessor *PP; - /// \brief The AST context into which we'll read the PCH file. + /// \brief The AST context into which we'll read the AST files. ASTContext *Context; - - /// \brief The PCH stat cache installed by this PCHReader, if any. - /// - /// The dynamic type of this stat cache is always PCHStatCache - void *StatCache; /// \brief The AST consumer. ASTConsumer *Consumer; - /// \brief The bitstream reader from which we'll read the PCH file. - llvm::BitstreamReader StreamFile; - llvm::BitstreamCursor Stream; + /// \brief Information that is needed for every file in the chain. + struct PerFileData { + PerFileData(); + ~PerFileData(); + + /// \brief The AST stat cache installed for this file, if any. + /// + /// The dynamic type of this stat cache is always ASTStatCache + void *StatCache; + + /// \brief The bitstream reader from which we'll read the AST file. + llvm::BitstreamReader StreamFile; + llvm::BitstreamCursor Stream; + + /// \brief The size of this file, in bits. + uint64_t SizeInBits; - /// \brief The cursor to the start of the preprocessor block, which stores - /// all of the macro definitions. - llvm::BitstreamCursor MacroCursor; + /// \brief The cursor to the start of the preprocessor block, which stores + /// all of the macro definitions. + llvm::BitstreamCursor MacroCursor; - /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It - /// has read all the abbreviations at the start of the block and is ready to - /// jump around with these in context. - llvm::BitstreamCursor DeclsCursor; + /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It + /// has read all the abbreviations at the start of the block and is ready to + /// jump around with these in context. + llvm::BitstreamCursor DeclsCursor; - /// \brief The file name of the PCH file. - std::string FileName; + /// \brief The file name of the AST file. + std::string FileName; - /// \brief The memory buffer that stores the data associated with - /// this PCH file. - llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + /// \brief The memory buffer that stores the data associated with + /// this AST file. + llvm::OwningPtr<llvm::MemoryBuffer> Buffer; - /// \brief Offset type for all of the source location entries in the - /// PCH file. - const uint32_t *SLocOffsets; + /// \brief Cursor used to read source location entries. + llvm::BitstreamCursor SLocEntryCursor; - /// \brief The number of source location entries in the PCH file. - unsigned TotalNumSLocEntries; + /// \brief The number of source location entries in this AST file. + unsigned LocalNumSLocEntries; + + /// \brief Offsets for all of the source location entries in the + /// AST file. + const uint32_t *SLocOffsets; + + /// \brief The number of types in this AST file. + unsigned LocalNumTypes; + + /// \brief Offset of each type within the bitstream, indexed by the + /// type ID, or the representation of a Type*. + const uint32_t *TypeOffsets; + + /// \brief The number of declarations in this AST file. + unsigned LocalNumDecls; + + /// \brief Offset of each declaration within the bitstream, indexed + /// by the declaration ID (-1). + const uint32_t *DeclOffsets; + + /// \brief The number of identifiers in this AST file. + unsigned LocalNumIdentifiers; - /// \brief Cursor used to read source location entries. - llvm::BitstreamCursor SLocEntryCursor; + /// \brief Offsets into the identifier table data. + /// + /// This array is indexed by the identifier ID (-1), and provides + /// the offset into IdentifierTableData where the string data is + /// stored. + const uint32_t *IdentifierOffsets; - /// \brief Offset of each type within the bitstream, indexed by the - /// type ID, or the representation of a Type*. - const uint32_t *TypeOffsets; + /// \brief Actual data for the on-disk hash table. + /// + // This pointer points into a memory buffer, where the on-disk hash + // table for identifiers actually lives. + const char *IdentifierTableData; - /// \brief Types that have already been loaded from the PCH file. + /// \brief A pointer to an on-disk hash table of opaque type + /// IdentifierHashTable. + void *IdentifierLookupTable; + + /// \brief The number of macro definitions in this file. + unsigned LocalNumMacroDefinitions; + + /// \brief Offsets of all of the macro definitions in the preprocessing + /// record in the AST file. + const uint32_t *MacroDefinitionOffsets; + + /// \brief The number of preallocated preprocessing entities in the + /// preprocessing record. + unsigned NumPreallocatedPreprocessingEntities; + + /// \brief A pointer to an on-disk hash table of opaque type + /// ASTSelectorLookupTable. + /// + /// This hash table provides the IDs of all selectors, and the associated + /// instance and factory methods. + void *SelectorLookupTable; + + /// \brief A pointer to the character data that comprises the selector table + /// + /// The SelectorOffsets table refers into this memory. + const unsigned char *SelectorLookupTableData; + + /// \brief Offsets into the method pool lookup table's data array + /// where each selector resides. + const uint32_t *SelectorOffsets; + + /// \brief The number of selectors new to this file. + /// + /// This is the number of entries in SelectorOffsets. + unsigned LocalNumSelectors; + }; + + /// \brief The chain of AST files. The first entry is the one named by the + /// user, the last one is the one that doesn't depend on anything further. + /// That is, the entry I was created with -include-pch I+1. + llvm::SmallVector<PerFileData*, 2> Chain; + + /// \brief Types that have already been loaded from the chain. /// /// When the pointer at index I is non-NULL, the type with - /// ID = (I + 1) << 3 has already been loaded from the PCH file. + /// ID = (I + 1) << FastQual::Width has already been loaded std::vector<QualType> TypesLoaded; - /// \brief Offset of each declaration within the bitstream, indexed - /// by the declaration ID (-1). - const uint32_t *DeclOffsets; + /// \brief Map that provides the ID numbers of each type within the + /// output stream, plus those deserialized from a chained PCH. + /// + /// The ID numbers of types are consecutive (in order of discovery) + /// and start at 1. 0 is reserved for NULL. When types are actually + /// stored in the stream, the ID number is shifted by 2 bits to + /// allow for the const/volatile qualifiers. + /// + /// Keys in the map never have const/volatile qualifiers. + serialization::TypeIdxMap TypeIdxs; - /// \brief Declarations that have already been loaded from the PCH file. + /// \brief Declarations that have already been loaded from the chain. /// /// When the pointer at index I is non-NULL, the declaration with ID /// = I + 1 has already been loaded. std::vector<Decl *> DeclsLoaded; - typedef llvm::DenseMap<const DeclContext *, std::pair<uint64_t, uint64_t> > - DeclContextOffsetsMap; + typedef llvm::DenseMap<serialization::DeclID, + std::pair<PerFileData *, uint64_t> > + DeclReplacementMap; + /// \brief Declarations that have been replaced in a later file in the chain. + DeclReplacementMap ReplacedDecls; + + /// \brief Information about the contents of a DeclContext. + struct DeclContextInfo { + void *NameLookupTableData; // a ASTDeclContextNameLookupTable. + const serialization::DeclID *LexicalDecls; + unsigned NumLexicalDecls; + }; + // In a full chain, there could be multiple updates to every decl context, + // so this is a vector. However, typically a chain is only two elements long, + // with only one file containing updates, so there will be only one update + // per decl context. + typedef llvm::SmallVector<DeclContextInfo, 1> DeclContextInfos; + typedef llvm::DenseMap<const DeclContext *, DeclContextInfos> + DeclContextOffsetsMap; + // Updates for visible decls can occur for other contexts than just the + // TU, and when we read those update records, the actual context will not + // be available yet (unless it's the TU), so have this pending map using the + // ID as a key. It will be realized when the context is actually loaded. + typedef llvm::SmallVector<void *, 1> DeclContextVisibleUpdates; + typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates> + DeclContextVisibleUpdatesPending; /// \brief Offsets of the lexical and visible declarations for each /// DeclContext. DeclContextOffsetsMap DeclContextOffsets; - /// \brief Actual data for the on-disk hash table. - /// - // This pointer points into a memory buffer, where the on-disk hash - // table for identifiers actually lives. - const char *IdentifierTableData; + /// \brief Updates to the visible declarations of declaration contexts that + /// haven't been loaded yet. + DeclContextVisibleUpdatesPending PendingVisibleUpdates; - /// \brief A pointer to an on-disk hash table of opaque type - /// IdentifierHashTable. - void *IdentifierLookupTable; + typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID> + FirstLatestDeclIDMap; + /// \brief Map of first declarations from a chained PCH that point to the + /// most recent declarations in another AST file. + FirstLatestDeclIDMap FirstLatestDeclIDs; - /// \brief Offsets into the identifier table data. - /// - /// This array is indexed by the identifier ID (-1), and provides - /// the offset into IdentifierTableData where the string data is - /// stored. - const uint32_t *IdentifierOffsets; + typedef llvm::SmallVector<serialization::DeclID, 4> + AdditionalTemplateSpecializations; + typedef llvm::DenseMap<serialization::DeclID, + AdditionalTemplateSpecializations> + AdditionalTemplateSpecializationsMap; + + /// \brief Additional specializations (including partial) of templates that + /// were introduced after the template was serialized. + AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializationsPending; + + /// \brief Read the records that describe the contents of declcontexts. + bool ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, + const std::pair<uint64_t, uint64_t> &Offsets, + DeclContextInfo &Info); /// \brief A vector containing identifiers that have already been /// loaded. @@ -280,29 +395,6 @@ private: /// been loaded. std::vector<IdentifierInfo *> IdentifiersLoaded; - /// \brief A pointer to an on-disk hash table of opaque type - /// PCHMethodPoolLookupTable. - /// - /// This hash table provides the instance and factory methods - /// associated with every selector known in the PCH file. - void *MethodPoolLookupTable; - - /// \brief A pointer to the character data that comprises the method - /// pool. - /// - /// The SelectorOffsets table refers into this memory. - const unsigned char *MethodPoolLookupTableData; - - /// \brief The number of selectors stored in the method pool itself. - unsigned TotalSelectorsInMethodPool; - - /// \brief Offsets into the method pool lookup table's data array - /// where each selector resides. - const uint32_t *SelectorOffsets; - - /// \brief The total number of selectors stored in the PCH file. - unsigned TotalNumSelectors; - /// \brief A vector containing selectors that have already been loaded. /// /// This vector is indexed by the Selector ID (-1). NULL selector @@ -310,52 +402,102 @@ private: /// been loaded. llvm::SmallVector<Selector, 16> SelectorsLoaded; - /// \brief Offsets of all of the macro definitions in the preprocessing - /// record in the PCH file. - const uint32_t *MacroDefinitionOffsets; - /// \brief The macro definitions we have already loaded. llvm::SmallVector<MacroDefinition *, 16> MacroDefinitionsLoaded; - - /// \brief The number of preallocated preprocessing entities in the - /// preprocessing record. - unsigned NumPreallocatedPreprocessingEntities; - - /// \brief The set of external definitions stored in the the PCH - /// file. + + /// \name CodeGen-relevant special data + /// \brief Fields containing data that is relevant to CodeGen. + //@{ + + /// \brief The IDs of all declarations that fulfill the criteria of + /// "interesting" decls. + /// + /// This contains the data loaded from all EXTERNAL_DEFINITIONS blocks in the + /// chain. The referenced declarations are deserialized and passed to the + /// consumer eagerly. llvm::SmallVector<uint64_t, 16> ExternalDefinitions; - /// \brief The set of tentative definitions stored in the the PCH - /// file. + /// \brief The IDs of all tentative definitions stored in the the chain. + /// + /// Sema keeps track of all tentative definitions in a TU because it has to + /// complete them and pass them on to CodeGen. Thus, tentative definitions in + /// the PCH chain must be eagerly deserialized. llvm::SmallVector<uint64_t, 16> TentativeDefinitions; - - /// \brief The set of unused static functions stored in the the PCH - /// file. - llvm::SmallVector<uint64_t, 16> UnusedStaticFuncs; - /// \brief The set of locally-scoped external declarations stored in - /// the the PCH file. - llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls; + /// \brief The IDs of all CXXRecordDecls stored in the chain whose VTables are + /// used. + /// + /// CodeGen has to emit VTables for these records, so they have to be eagerly + /// deserialized. + llvm::SmallVector<uint64_t, 64> VTableUses; + + //@} + + /// \name Diagnostic-relevant special data + /// \brief Fields containing data that is used for generating diagnostics + //@{ - /// \brief The set of ext_vector type declarations stored in the the - /// PCH file. + /// \brief Method selectors used in a @selector expression. Used for + /// implementation of -Wselector. + llvm::SmallVector<uint64_t, 64> ReferencedSelectorsData; + + /// \brief A snapshot of Sema's unused file-scoped variable tracking, for + /// generating warnings. + llvm::SmallVector<uint64_t, 16> UnusedFileScopedDecls; + + /// \brief A snapshot of Sema's weak undeclared identifier tracking, for + /// generating warnings. + llvm::SmallVector<uint64_t, 64> WeakUndeclaredIdentifiers; + + /// \brief The IDs of type aliases for ext_vectors that exist in the chain. + /// + /// Used by Sema for finding sugared names for ext_vectors in diagnostics. llvm::SmallVector<uint64_t, 4> ExtVectorDecls; - /// \brief The set of VTable uses of CXXRecordDecls stored in the PCH file. - llvm::SmallVector<uint64_t, 64> VTableUses; + //@} + + /// \name Sema-relevant special data + /// \brief Fields containing data that is used for semantic analysis + //@{ - /// \brief The set of dynamic CXXRecord declarations stored in the PCH file. + /// \brief The IDs of all locally scoped external decls in the chain. + /// + /// Sema tracks these to validate that the types are consistent across all + /// local external declarations. + llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls; + + /// \brief A snapshot of the pwnsinf instantiations in the chain. + /// + /// This record tracks the instantiations that Sema has to perform at the end + /// of the TU. It consists of a pair of values for every pending instantiation + /// where the first value is the ID of the decl and the second is the + /// instantiation location. + llvm::SmallVector<uint64_t, 64> PendingInstantiations; + + /// \brief The IDs of all dynamic class declarations in the chain. + /// + /// Sema tracks these because it checks for the key functions being defined + /// at the end of the TU, in which case it directs CodeGen to emit the VTable. llvm::SmallVector<uint64_t, 16> DynamicClasses; - /// \brief The set of Objective-C category definitions stored in the - /// the PCH file. - llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls; + /// \brief The IDs of the declarations Sema stores directly. + /// + /// Sema tracks a few important decls, such as namespace std, directly. + llvm::SmallVector<uint64_t, 4> SemaDeclRefs; + + /// \brief The IDs of the types ASTContext stores directly. + /// + /// The AST context tracks a few important types, such as va_list, directly. + llvm::SmallVector<uint64_t, 16> SpecialTypes; - /// \brief The original file name that was used to build the PCH file, which - /// may have been modified for relocatable-pch support. + //@} + + /// \brief The original file name that was used to build the primary AST file, + /// which may have been modified for relocatable-pch support. std::string OriginalFileName; - /// \brief The actual original file name that was used to build the PCH file. + /// \brief The actual original file name that was used to build the primary + /// AST file. std::string ActualOriginalFileName; /// \brief Whether this precompiled header is a relocatable PCH file. @@ -365,12 +507,20 @@ private: /// precompiled header. const char *isysroot; - /// \brief Mapping from switch-case IDs in the PCH file to - /// switch-case statements. + /// \brief Whether to disable the normal validation performed on precompiled + /// headers when they are loaded. + bool DisableValidation; + + /// \brief Mapping from switch-case IDs in the chain to switch-case statements + /// + /// Statements usually don't have IDs, but switch cases need them, so that the + /// switch statement can refer to them. std::map<unsigned, SwitchCase *> SwitchCaseStmts; - /// \brief Mapping from label statement IDs in the PCH file to label - /// statements. + /// \brief Mapping from label statement IDs in the chain to label statements. + /// + /// Statements usually don't have IDs, but labeled statements need them, so + /// that goto statements and address-of-label expressions can refer to them. std::map<unsigned, LabelStmt *> LabelStmts; /// \brief Mapping from label IDs to the set of "goto" statements @@ -391,52 +541,44 @@ private: /// the PCH file. unsigned NumSLocEntriesRead; + /// \brief The number of source location entries in the chain. + unsigned TotalNumSLocEntries; + /// \brief The number of statements (and expressions) de-serialized - /// from the PCH file. + /// from the chain. unsigned NumStatementsRead; /// \brief The total number of statements (and expressions) stored - /// in the PCH file. + /// in the chain. unsigned TotalNumStatements; - /// \brief The number of macros de-serialized from the PCH file. + /// \brief The number of macros de-serialized from the chain. unsigned NumMacrosRead; + /// \brief The total number of macros stored in the chain. + unsigned TotalNumMacros; + + /// \brief The number of selectors that have been read. + unsigned NumSelectorsRead; + /// \brief The number of method pool entries that have been read. - unsigned NumMethodPoolSelectorsRead; + unsigned NumMethodPoolEntriesRead; - /// \brief The number of times we have looked into the global method - /// pool and not found anything. + /// \brief The number of times we have looked up a selector in the method + /// pool and not found anything interesting. unsigned NumMethodPoolMisses; - /// \brief The total number of macros stored in the PCH file. - unsigned TotalNumMacros; + /// \brief The total number of method pool entries in the selector table. + unsigned TotalNumMethodPoolEntries; /// Number of lexical decl contexts read/total. unsigned NumLexicalDeclContextsRead, TotalLexicalDeclContexts; /// Number of visible decl contexts read/total. unsigned NumVisibleDeclContextsRead, TotalVisibleDeclContexts; - - /// \brief When a type or declaration is being loaded from the PCH file, an - /// instantance of this RAII object will be available on the stack to - /// indicate when we are in a recursive-loading situation. - class LoadingTypeOrDecl { - PCHReader &Reader; - LoadingTypeOrDecl *Parent; - - LoadingTypeOrDecl(const LoadingTypeOrDecl&); // do not implement - LoadingTypeOrDecl &operator=(const LoadingTypeOrDecl&); // do not implement - - public: - explicit LoadingTypeOrDecl(PCHReader &Reader); - ~LoadingTypeOrDecl(); - }; - friend class LoadingTypeOrDecl; - - /// \brief If we are currently loading a type or declaration, points to the - /// most recent LoadingTypeOrDecl object on the stack. - LoadingTypeOrDecl *CurrentlyLoadingTypeOrDecl; + + /// \brief Number of Decl/types that are currently deserializing. + unsigned NumCurrentElementsDeserializing; /// \brief An IdentifierInfo that has been loaded but whose top-level /// declarations of the same name have not (yet) been loaded. @@ -445,16 +587,13 @@ private: llvm::SmallVector<uint32_t, 4> DeclIDs; }; - /// \brief The set of identifiers that were read while the PCH reader was + /// \brief The set of identifiers that were read while the AST reader was /// (recursively) loading declarations. /// /// The declarations on the identifier chain for these identifiers will be /// loaded once the recursive loading has completed. std::deque<PendingIdentifierInfo> PendingIdentifierInfos; - /// \brief FIXME: document! - llvm::SmallVector<uint64_t, 16> SpecialTypes; - /// \brief Contains declarations and definitions that will be /// "interesting" to the ASTConsumer, when we get that AST consumer. /// @@ -476,14 +615,14 @@ private: /// \brief RAII object to change the reading kind. class ReadingKindTracker { - PCHReader &Reader; + ASTReader &Reader; enum ReadingKind PrevKind; ReadingKindTracker(const ReadingKindTracker&); // do not implement ReadingKindTracker &operator=(const ReadingKindTracker&);// do not implement public: - ReadingKindTracker(enum ReadingKind newKind, PCHReader &reader) + ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader) : Reader(reader), PrevKind(Reader.ReadingKind) { Reader.ReadingKind = newKind; } @@ -491,7 +630,7 @@ private: ~ReadingKindTracker() { Reader.ReadingKind = PrevKind; } }; - /// \brief All predefines buffers in all PCH files, to be treated as if + /// \brief All predefines buffers in the chain, to be treated as if /// concatenated. PCHPredefinesBlocks PCHPredefinesBuffers; @@ -510,31 +649,37 @@ private: void MaybeAddSystemRootToFilename(std::string &Filename); - PCHReadResult ReadPCHBlock(); + ASTReadResult ReadASTCore(llvm::StringRef FileName); + ASTReadResult ReadASTBlock(PerFileData &F); bool CheckPredefinesBuffers(); bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record); - PCHReadResult ReadSourceManagerBlock(); - PCHReadResult ReadSLocEntryRecord(unsigned ID); - + ASTReadResult ReadSourceManagerBlock(PerFileData &F); + ASTReadResult ReadSLocEntryRecord(unsigned ID); + llvm::BitstreamCursor &SLocCursorForID(unsigned ID); bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record); - QualType ReadTypeRecord(uint64_t Offset); + + typedef std::pair<llvm::BitstreamCursor *, uint64_t> RecordLocation; + + QualType ReadTypeRecord(unsigned Index); + RecordLocation TypeCursorForIndex(unsigned Index); void LoadedDecl(unsigned Index, Decl *D); - Decl *ReadDeclRecord(uint64_t Offset, unsigned Index); + Decl *ReadDeclRecord(unsigned Index, serialization::DeclID ID); + RecordLocation DeclCursorForIndex(unsigned Index, serialization::DeclID ID); void PassInterestingDeclsToConsumer(); /// \brief Produce an error diagnostic and return true. /// /// This routine should only be used for fatal errors that have to - /// do with non-routine failures (e.g., corrupted PCH file). + /// do with non-routine failures (e.g., corrupted AST file). void Error(const char *Msg); - PCHReader(const PCHReader&); // do not implement - PCHReader &operator=(const PCHReader &); // do not implement + ASTReader(const ASTReader&); // do not implement + ASTReader &operator=(const ASTReader &); // do not implement public: typedef llvm::SmallVector<uint64_t, 64> RecordData; - /// \brief Load the PCH file and validate its contents against the given + /// \brief Load the AST file and validate its contents against the given /// Preprocessor. /// /// \param PP the preprocessor associated with the context in which this @@ -546,41 +691,48 @@ public: /// \param isysroot If non-NULL, the system include path specified by the /// user. This is only used with relocatable PCH files. If non-NULL, /// a relocatable PCH file will use the default path "/". - PCHReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0); + /// + /// \param DisableValidation If true, the AST reader will suppress most + /// of its regular consistency checking, allowing the use of precompiled + /// headers that cannot be determined to be compatible. + ASTReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0, + bool DisableValidation = false); - /// \brief Load the PCH file without using any pre-initialized Preprocessor. + /// \brief Load the AST file without using any pre-initialized Preprocessor. /// /// The necessary information to initialize a Preprocessor later can be - /// obtained by setting a PCHReaderListener. + /// obtained by setting a ASTReaderListener. /// - /// \param SourceMgr the source manager into which the precompiled header - /// will be loaded. + /// \param SourceMgr the source manager into which the AST file will be loaded /// - /// \param FileMgr the file manager into which the precompiled header will - /// be loaded. + /// \param FileMgr the file manager into which the AST file will be loaded. /// /// \param Diags the diagnostics system to use for reporting errors and - /// warnings relevant to loading the precompiled header. + /// warnings relevant to loading the AST file. /// /// \param isysroot If non-NULL, the system include path specified by the /// user. This is only used with relocatable PCH files. If non-NULL, /// a relocatable PCH file will use the default path "/". - PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, - Diagnostic &Diags, const char *isysroot = 0); - ~PCHReader(); + /// + /// \param DisableValidation If true, the AST reader will suppress most + /// of its regular consistency checking, allowing the use of precompiled + /// headers that cannot be determined to be compatible. + ASTReader(SourceManager &SourceMgr, FileManager &FileMgr, + Diagnostic &Diags, const char *isysroot = 0, + bool DisableValidation = false); + ~ASTReader(); /// \brief Load the precompiled header designated by the given file /// name. - PCHReadResult ReadPCH(const std::string &FileName); + ASTReadResult ReadAST(const std::string &FileName); - /// \brief Set the PCH callbacks listener. - void setListener(PCHReaderListener *listener) { + /// \brief Set the AST callbacks listener. + void setListener(ASTReaderListener *listener) { Listener.reset(listener); } - void setDeserializationListener(PCHDeserializationListener *Listener) { - DeserializationListener = Listener; - } + /// \brief Set the AST deserialization listener. + void setDeserializationListener(ASTDeserializationListener *Listener); /// \brief Set the Preprocessor to use. void setPreprocessor(Preprocessor &pp); @@ -588,16 +740,15 @@ public: /// \brief Sets and initializes the given Context. void InitializeContext(ASTContext &Context); - /// \brief Retrieve the name of the PCH file - const std::string &getFileName() const { return FileName; } + /// \brief Retrieve the name of the named (primary) AST file + const std::string &getFileName() const { return Chain[0]->FileName; } /// \brief Retrieve the name of the original source file name const std::string &getOriginalSourceFile() { return OriginalFileName; } - /// \brief Retrieve the name of the original source file name - /// directly from the PCH file, without actually loading the PCH - /// file. - static std::string getOriginalSourceFile(const std::string &PCHFileName, + /// \brief Retrieve the name of the original source file name directly from + /// the AST file, without actually loading the AST file. + static std::string getOriginalSourceFile(const std::string &ASTFileName, Diagnostic &Diags); /// \brief Returns the suggested contents of the predefines buffer, @@ -608,40 +759,67 @@ public: /// \brief Read preprocessed entities into the virtual void ReadPreprocessedEntities(); - /// \brief Returns the number of types found in this file. + /// \brief Returns the number of source locations found in the chain. + unsigned getTotalNumSLocs() const { + return TotalNumSLocEntries; + } + + /// \brief Returns the number of identifiers found in the chain. + unsigned getTotalNumIdentifiers() const { + return static_cast<unsigned>(IdentifiersLoaded.size()); + } + + /// \brief Returns the number of types found in the chain. unsigned getTotalNumTypes() const { return static_cast<unsigned>(TypesLoaded.size()); } - /// \brief Returns the number of declarations found in this file. + /// \brief Returns the number of declarations found in the chain. unsigned getTotalNumDecls() const { return static_cast<unsigned>(DeclsLoaded.size()); } + /// \brief Returns the number of selectors found in the chain. + unsigned getTotalNumSelectors() const { + return static_cast<unsigned>(SelectorsLoaded.size()); + } + /// \brief Reads a TemplateArgumentLocInfo appropriate for the /// given TemplateArgument kind. TemplateArgumentLocInfo GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, + llvm::BitstreamCursor &DeclsCursor, const RecordData &Record, unsigned &Idx); /// \brief Reads a TemplateArgumentLoc. - TemplateArgumentLoc ReadTemplateArgumentLoc(const RecordData &Record, - unsigned &Idx); + TemplateArgumentLoc + ReadTemplateArgumentLoc(llvm::BitstreamCursor &DeclsCursor, + const RecordData &Record, unsigned &Idx); /// \brief Reads a declarator info from the given record. - TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record, - unsigned &Idx); + TypeSourceInfo *GetTypeSourceInfo(llvm::BitstreamCursor &DeclsCursor, + const RecordData &Record, unsigned &Idx); /// \brief Resolve and return the translation unit declaration. TranslationUnitDecl *GetTranslationUnitDecl(); /// \brief Resolve a type ID into a type, potentially building a new /// type. - QualType GetType(pch::TypeID ID); + QualType GetType(serialization::TypeID ID); + + /// \brief Returns the type ID associated with the given type. + /// If the type didn't come from the AST file the ID that is returned is + /// marked as "doesn't exist in AST". + serialization::TypeID GetTypeID(QualType T) const; + + /// \brief Returns the type index associated with the given type. + /// If the type didn't come from the AST file the index that is returned is + /// marked as "doesn't exist in AST". + serialization::TypeIdx GetTypeIdx(QualType T) const; /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. - Decl *GetDecl(pch::DeclID ID); + Decl *GetDecl(serialization::DeclID ID); virtual Decl *GetExternalDecl(uint32_t ID); /// \brief Resolve the offset of a statement into a statement. @@ -663,6 +841,8 @@ public: FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); + virtual void MaterializeVisibleDecls(const DeclContext *DC); + /// \brief Read all of the declarations lexically stored in a /// declaration context. /// @@ -679,6 +859,15 @@ public: virtual bool FindExternalLexicalDecls(const DeclContext *DC, llvm::SmallVectorImpl<Decl*> &Decls); + /// \brief Notify ASTReader that we started deserialization of + /// a decl or type so until FinishedDeserializing is called there may be + /// decls that are initializing. Must be paired with FinishedDeserializing. + virtual void StartedDeserializing() { ++NumCurrentElementsDeserializing; } + + /// \brief Notify ASTReader that we finished the deserialization of + /// a decl or type. Must be paired with StartedDeserializing. + virtual void FinishedDeserializing(); + /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. /// @@ -686,7 +875,7 @@ public: /// the ASTConsumer. virtual void StartTranslationUnit(ASTConsumer *Consumer); - /// \brief Print some statistics about PCH usage. + /// \brief Print some statistics about AST usage. virtual void PrintStats(); /// \brief Initialize the semantic source with the Sema instance @@ -716,6 +905,9 @@ public: virtual std::pair<ObjCMethodList, ObjCMethodList> ReadMethodPool(Selector Sel); + /// \brief Load a selector from disk, registering its ID if it exists. + void LoadSelector(Selector Sel); + void SetIdentifierInfo(unsigned ID, IdentifierInfo *II); void SetGloballyVisibleDecls(IdentifierInfo *II, const llvm::SmallVectorImpl<uint32_t> &DeclIDs, @@ -759,7 +951,8 @@ public: TemplateName ReadTemplateName(const RecordData &Record, unsigned &Idx); /// \brief Read a template argument. - TemplateArgument ReadTemplateArgument(const RecordData &Record,unsigned &Idx); + TemplateArgument ReadTemplateArgument(llvm::BitstreamCursor &DeclsCursor, + const RecordData &Record,unsigned &Idx); /// \brief Read a template parameter list. TemplateParameterList *ReadTemplateParameterList(const RecordData &Record, @@ -768,6 +961,7 @@ public: /// \brief Read a template argument array. void ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs, + llvm::BitstreamCursor &DeclsCursor, const RecordData &Record, unsigned &Idx); /// \brief Read a UnresolvedSet structure. @@ -775,7 +969,13 @@ public: const RecordData &Record, unsigned &Idx); /// \brief Read a C++ base specifier. - CXXBaseSpecifier ReadCXXBaseSpecifier(const RecordData &Record,unsigned &Idx); + CXXBaseSpecifier ReadCXXBaseSpecifier(llvm::BitstreamCursor &DeclsCursor, + const RecordData &Record,unsigned &Idx); + + /// \brief Read a CXXBaseOrMemberInitializer array. + std::pair<CXXBaseOrMemberInitializer **, unsigned> + ReadCXXBaseOrMemberInitializers(llvm::BitstreamCursor &DeclsCursor, + const RecordData &Record, unsigned &Idx); /// \brief Read a source location. SourceLocation ReadSourceLocation(const RecordData &Record, unsigned& Idx) { @@ -800,13 +1000,13 @@ public: CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx); /// \brief Reads attributes from the current stream position. - Attr *ReadAttributes(); + void ReadAttributes(llvm::BitstreamCursor &DeclsCursor, AttrVec &Attrs); /// \brief Reads a statement. - Stmt *ReadStmt(); + Stmt *ReadStmt(llvm::BitstreamCursor &Cursor); /// \brief Reads an expression. - Expr *ReadExpr(); + Expr *ReadExpr(llvm::BitstreamCursor &Cursor); /// \brief Reads a sub-statement operand during statement reading. Stmt *ReadSubStmt() { @@ -822,16 +1022,15 @@ public: Expr *ReadSubExpr(); /// \brief Reads the macro record located at the given offset. - void ReadMacroRecord(uint64_t Offset); + void ReadMacroRecord(llvm::BitstreamCursor &Stream, uint64_t Offset); /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros(); /// \brief Retrieve the macro definition with the given ID. - MacroDefinition *getMacroDefinition(pch::IdentID ID); - - /// \brief Retrieve the AST context that this PCH reader - /// supplements. + MacroDefinition *getMacroDefinition(serialization::IdentID ID); + + /// \brief Retrieve the AST context that this AST reader supplements. ASTContext *getContext() { return Context; } // \brief Contains declarations that were loaded before we have @@ -843,10 +1042,6 @@ public: /// imported. Sema *getSema() { return SemaObj; } - /// \brief Retrieve the stream that this PCH reader is reading from. - llvm::BitstreamCursor &getStream() { return Stream; } - llvm::BitstreamCursor &getDeclsCursor() { return DeclsCursor; } - /// \brief Retrieve the identifier table associated with the /// preprocessor. IdentifierTable &getIdentifierTable(); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Serialization/ASTWriter.h index 70ad1d7c7e78..426fc4780148 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -1,4 +1,4 @@ -//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- C++ -*-===// +//===--- ASTWriter.h - AST File Writer --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,23 +7,25 @@ // //===----------------------------------------------------------------------===// // -// This file defines the PCHWriter class, which writes a precompiled -// header containing a serialized representation of a translation -// unit. +// This file defines the ASTWriter class, which writes an AST file +// containing a serialized representation of a translation unit. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_PCH_WRITER_H -#define LLVM_CLANG_FRONTEND_PCH_WRITER_H +#ifndef LLVM_CLANG_FRONTEND_AST_WRITER_H +#define LLVM_CLANG_FRONTEND_AST_WRITER_H #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/TemplateBase.h" -#include "clang/Frontend/PCHBitCodes.h" -#include "clang/Frontend/PCHDeserializationListener.h" -#include "llvm/ADT/DenseMap.h" +#include "clang/Serialization/ASTBitCodes.h" +#include "clang/Serialization/ASTDeserializationListener.h" +#include "clang/Sema/SemaConsumer.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Bitcode/BitstreamWriter.h" #include <map> #include <queue> +#include <vector> namespace llvm { class APFloat; @@ -40,50 +42,32 @@ class CXXBaseOrMemberInitializer; class LabelStmt; class MacroDefinition; class MemorizeStatCalls; -class PCHReader; +class ASTReader; class Preprocessor; class Sema; class SourceManager; class SwitchCase; class TargetInfo; -/// A structure for putting "fast"-unqualified QualTypes into a -/// DenseMap. This uses the standard pointer hash function. -struct UnsafeQualTypeDenseMapInfo { - static inline bool isEqual(QualType A, QualType B) { return A == B; } - static inline QualType getEmptyKey() { - return QualType::getFromOpaquePtr((void*) 1); - } - static inline QualType getTombstoneKey() { - return QualType::getFromOpaquePtr((void*) 2); - } - static inline unsigned getHashValue(QualType T) { - assert(!T.getLocalFastQualifiers() && - "hash invalid for types with fast quals"); - uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); - return (unsigned(v) >> 4) ^ (unsigned(v) >> 9); - } -}; - -/// \brief Writes a precompiled header containing the contents of a -/// translation unit. +/// \brief Writes an AST file containing the contents of a translation unit. /// -/// The PCHWriter class produces a bitstream containing the serialized +/// The ASTWriter class produces a bitstream containing the serialized /// representation of a given abstract syntax tree and its supporting /// data structures. This bitstream can be de-serialized via an -/// instance of the PCHReader class. -class PCHWriter : public PCHDeserializationListener { +/// instance of the ASTReader class. +class ASTWriter : public ASTDeserializationListener { public: typedef llvm::SmallVector<uint64_t, 64> RecordData; + friend class ASTDeclWriter; private: /// \brief The bitstream writer used to emit this precompiled header. llvm::BitstreamWriter &Stream; - /// \brief The reader of existing PCH files, if we're chaining. - PCHReader *Chain; + /// \brief The reader of existing AST files, if we're chaining. + ASTReader *Chain; - /// \brief Stores a declaration or a type to be written to the PCH file. + /// \brief Stores a declaration or a type to be written to the AST file. class DeclOrType { public: DeclOrType(Decl *D) : Stored(D), IsType(false) { } @@ -106,24 +90,36 @@ private: void *Stored; bool IsType; }; - + /// \brief The declarations and types to emit. std::queue<DeclOrType> DeclTypesToEmit; - + + /// \brief The first ID number we can use for our own declarations. + serialization::DeclID FirstDeclID; + + /// \brief The decl ID that will be assigned to the next new decl. + serialization::DeclID NextDeclID; + /// \brief Map that provides the ID numbers of each declaration within - /// the output stream. + /// the output stream, as well as those deserialized from a chained PCH. /// /// The ID numbers of declarations are consecutive (in order of /// discovery) and start at 2. 1 is reserved for the translation /// unit, while 0 is reserved for NULL. - llvm::DenseMap<const Decl *, pch::DeclID> DeclIDs; + llvm::DenseMap<const Decl *, serialization::DeclID> DeclIDs; /// \brief Offset of each declaration in the bitstream, indexed by /// the declaration's ID. std::vector<uint32_t> DeclOffsets; + /// \brief The first ID number we can use for our own types. + serialization::TypeID FirstTypeID; + + /// \brief The type ID that will be assigned to the next new type. + serialization::TypeID NextTypeID; + /// \brief Map that provides the ID numbers of each type within the - /// output stream. + /// output stream, plus those deserialized from a chained PCH. /// /// The ID numbers of types are consecutive (in order of discovery) /// and start at 1. 0 is reserved for NULL. When types are actually @@ -131,14 +127,17 @@ private: /// allow for the const/volatile qualifiers. /// /// Keys in the map never have const/volatile qualifiers. - llvm::DenseMap<QualType, pch::TypeID, UnsafeQualTypeDenseMapInfo> TypeIDs; + serialization::TypeIdxMap TypeIdxs; /// \brief Offset of each type in the bitstream, indexed by /// the type's ID. std::vector<uint32_t> TypeOffsets; - /// \brief The type ID that will be assigned to the next new type. - pch::TypeID NextTypeID; + /// \brief The first ID number we can use for our own identifiers. + serialization::IdentID FirstIdentID; + + /// \brief The identifier ID that will be assigned to the next new identifier. + serialization::IdentID NextIdentID; /// \brief Map that provides the ID numbers of each identifier in /// the output stream. @@ -146,22 +145,25 @@ private: /// The ID numbers for identifiers are consecutive (in order of /// discovery), starting at 1. An ID of zero refers to a NULL /// IdentifierInfo. - llvm::DenseMap<const IdentifierInfo *, pch::IdentID> IdentifierIDs; + llvm::DenseMap<const IdentifierInfo *, serialization::IdentID> IdentifierIDs; /// \brief Offsets of each of the identifier IDs into the identifier /// table. std::vector<uint32_t> IdentifierOffsets; + /// \brief The first ID number we can use for our own selectors. + serialization::SelectorID FirstSelectorID; + + /// \brief The selector ID that will be assigned to the next new identifier. + serialization::SelectorID NextSelectorID; + /// \brief Map that provides the ID numbers of each Selector. - llvm::DenseMap<Selector, pch::SelectorID> SelectorIDs; + llvm::DenseMap<Selector, serialization::SelectorID> SelectorIDs; /// \brief Offset of each selector within the method pool/selector /// table, indexed by the Selector ID (-1). std::vector<uint32_t> SelectorOffsets; - /// \brief A vector of all Selectors (ordered by ID). - std::vector<Selector> SelVector; - /// \brief Offsets of each of the macro identifiers into the /// bitstream. /// @@ -172,19 +174,25 @@ private: /// \brief Mapping from macro definitions (as they occur in the preprocessing /// record) to the index into the macro definitions table. - llvm::DenseMap<const MacroDefinition *, pch::IdentID> MacroDefinitions; + llvm::DenseMap<const MacroDefinition *, serialization::IdentID> + MacroDefinitions; /// \brief Mapping from the macro definition indices in \c MacroDefinitions /// to the corresponding offsets within the preprocessor block. std::vector<uint32_t> MacroDefinitionOffsets; + + typedef llvm::DenseMap<Decl *, Decl *> FirstLatestDeclMap; + /// \brief Map of first declarations from a chained PCH that point to the + /// most recent declarations in another PCH. + FirstLatestDeclMap FirstLatestDecls; /// \brief Declarations encountered that might be external /// definitions. /// /// We keep track of external definitions (as well as tentative - /// definitions) as we are emitting declarations to the PCH - /// file. The PCH file contains a separate record for these external - /// definitions, which are provided to the AST consumer by the PCH + /// definitions) as we are emitting declarations to the AST + /// file. The AST file contains a separate record for these external + /// definitions, which are provided to the AST consumer by the AST /// reader. This is behavior is required to properly cope with, /// e.g., tentative variable definitions that occur within /// headers. The declarations themselves are stored as declaration @@ -192,11 +200,38 @@ private: /// record. llvm::SmallVector<uint64_t, 16> ExternalDefinitions; + /// \brief Namespaces that have received extensions since their serialized + /// form. + /// + /// Basically, when we're chaining and encountering a namespace, we check if + /// its primary namespace comes from the chain. If it does, we add the primary + /// to this set, so that we can write out lexical content updates for it. + llvm::SmallPtrSet<const NamespaceDecl *, 16> UpdatedNamespaces; + + /// \brief Decls that have been replaced in the current dependent AST file. + /// + /// When a decl changes fundamentally after being deserialized (this shouldn't + /// happen, but the ObjC AST nodes are designed this way), it will be + /// serialized again. In this case, it is registered here, so that the reader + /// knows to read the updated version. + llvm::SmallVector<std::pair<serialization::DeclID, uint64_t>, 16> + ReplacedDecls; + + typedef llvm::SmallVector<serialization::DeclID, 4> + AdditionalTemplateSpecializationsList; + typedef llvm::DenseMap<serialization::DeclID, + AdditionalTemplateSpecializationsList> + AdditionalTemplateSpecializationsMap; + + /// \brief Additional specializations (including partial) of templates that + /// were introduced after the template was serialized. + AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializations; + /// \brief Statements that we've encountered while serializing a /// declaration or type. llvm::SmallVector<Stmt *, 16> StmtsToEmit; - - /// \brief Statements collection to use for PCHWriter::AddStmt(). + + /// \brief Statements collection to use for ASTWriter::AddStmt(). /// It will point to StmtsToEmit unless it is overriden. llvm::SmallVector<Stmt *, 16> *CollectedStmts; @@ -206,17 +241,17 @@ private: /// \brief Mapping from LabelStmt statements to IDs. std::map<LabelStmt *, unsigned> LabelIDs; - /// \brief The number of statements written to the PCH file. + /// \brief The number of statements written to the AST file. unsigned NumStatements; - /// \brief The number of macros written to the PCH file. + /// \brief The number of macros written to the AST file. unsigned NumMacros; - /// \brief The number of lexical declcontexts written to the PCH + /// \brief The number of lexical declcontexts written to the AST /// file. unsigned NumLexicalDeclContexts; - /// \brief The number of visible declcontexts written to the PCH + /// \brief The number of visible declcontexts written to the AST /// file. unsigned NumVisibleDeclContexts; @@ -234,24 +269,31 @@ private: void WriteType(QualType T); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); - - void WriteMethodPool(Sema &SemaRef); + void WriteTypeDeclOffsets(); + void WriteSelectors(Sema &SemaRef); + void WriteReferencedSelectorsPool(Sema &SemaRef); void WriteIdentifierTable(Preprocessor &PP); - void WriteAttributeRecord(const Attr *Attr); + void WriteAttributeRecord(const AttrVec &Attrs); + void WriteDeclUpdateBlock(); + void WriteDeclContextVisibleUpdate(const DeclContext *DC); + void WriteAdditionalTemplateSpecializations(); unsigned ParmVarDeclAbbrev; + unsigned DeclContextLexicalAbbrev; + unsigned DeclContextVisibleLookupAbbrev; + unsigned UpdateVisibleAbbrev; void WriteDeclsBlockAbbrevs(); void WriteDecl(ASTContext &Context, Decl *D); - void WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, + void WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, const char* isysroot); - void WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, + void WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, const char* isysroot); public: /// \brief Create a new precompiled header writer that outputs to /// the given bitstream. - PCHWriter(llvm::BitstreamWriter &Stream, PCHReader *Chain); + ASTWriter(llvm::BitstreamWriter &Stream); /// \brief Write a precompiled header for the given semantic analysis. /// @@ -266,7 +308,7 @@ public: /// /// \param PPRec Record of the preprocessing actions that occurred while /// preprocessing this file, e.g., macro instantiations - void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, + void WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, const char* isysroot); /// \brief Emit a source location. @@ -292,10 +334,12 @@ public: /// \brief Emit a CXXTemporary. void AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record); + + /// \brief Get the unique number used to refer to the given selector. + serialization::SelectorID getSelectorRef(Selector Sel); - /// \brief Get the unique number used to refer to the given - /// identifier. - pch::IdentID getIdentifierRef(const IdentifierInfo *II); + /// \brief Get the unique number used to refer to the given identifier. + serialization::IdentID getIdentifierRef(const IdentifierInfo *II); /// \brief Retrieve the offset of the macro definition for the given /// identifier. @@ -309,11 +353,23 @@ public: /// \brief Retrieve the ID number corresponding to the given macro /// definition. - pch::IdentID getMacroDefinitionID(MacroDefinition *MD); + serialization::IdentID getMacroDefinitionID(MacroDefinition *MD); /// \brief Emit a reference to a type. void AddTypeRef(QualType T, RecordData &Record); + /// \brief Force a type to be emitted and get its ID. + serialization::TypeID GetOrCreateTypeID(QualType T); + + /// \brief Determine the type ID of an already-emitted type. + serialization::TypeID getTypeID(QualType T) const; + + /// \brief Force a type to be emitted and get its index. + serialization::TypeIdx GetOrCreateTypeIdx(QualType T); + + /// \brief Determine the type index of an already-emitted type. + serialization::TypeIdx getTypeIdx(QualType T) const; + /// \brief Emits a reference to a declarator info. void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record); @@ -329,9 +385,12 @@ public: /// \brief Emit a reference to a declaration. void AddDeclRef(const Decl *D, RecordData &Record); + /// \brief Force a declaration to be emitted and get its ID. + serialization::DeclID GetDeclRef(const Decl *D); + /// \brief Determine the declaration ID of an already-emitted /// declaration. - pch::DeclID getDeclID(const Decl *D); + serialization::DeclID getDeclID(const Decl *D); /// \brief Emit a declaration name. void AddDeclarationName(DeclarationName Name, RecordData &Record); @@ -356,11 +415,28 @@ public: /// \brief Emit a UnresolvedSet structure. void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record); - /// brief Emit a C++ base specifier. + /// \brief Emit a C++ base specifier. void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, RecordData &Record); + /// \brief Emit a CXXBaseOrMemberInitializer array. + void AddCXXBaseOrMemberInitializers( + const CXXBaseOrMemberInitializer * const *BaseOrMembers, + unsigned NumBaseOrMembers, RecordData &Record); + /// \brief Add a string to the given record. - void AddString(const std::string &Str, RecordData &Record); + void AddString(llvm::StringRef Str, RecordData &Record); + + /// \brief Mark a namespace as needing an update. + void AddUpdatedNamespace(const NamespaceDecl *NS) { + UpdatedNamespaces.insert(NS); + } + + /// \brief Record a template specialization or partial specialization of + /// a template from a previous PCH file. + void AddAdditionalTemplateSpecialization(serialization::DeclID Templ, + serialization::DeclID Spec) { + AdditionalTemplateSpecializations[Templ].push_back(Spec); + } /// \brief Note that the identifier II occurs at the given offset /// within the identifier table. @@ -398,9 +474,38 @@ public: unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; } - // PCHDeserializationListener implementation - void TypeRead(pch::TypeID ID, QualType T); - void DeclRead(pch::DeclID ID, const Decl *D); + bool hasChain() const { return Chain; } + + // ASTDeserializationListener implementation + void SetReader(ASTReader *Reader); + void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II); + void TypeRead(serialization::TypeIdx Idx, QualType T); + void DeclRead(serialization::DeclID ID, const Decl *D); + void SelectorRead(serialization::SelectorID iD, Selector Sel); +}; + +/// \brief AST and semantic-analysis consumer that generates a +/// precompiled header from the parsed source code. +class PCHGenerator : public SemaConsumer { + const Preprocessor &PP; + const char *isysroot; + llvm::raw_ostream *Out; + Sema *SemaPtr; + MemorizeStatCalls *StatCalls; // owned by the FileManager + std::vector<unsigned char> Buffer; + llvm::BitstreamWriter Stream; + ASTWriter Writer; + +protected: + ASTWriter &getWriter() { return Writer; } + const ASTWriter &getWriter() const { return Writer; } + +public: + PCHGenerator(const Preprocessor &PP, bool Chaining, + const char *isysroot, llvm::raw_ostream *Out); + virtual void InitializeSema(Sema &S) { SemaPtr = &S; } + virtual void HandleTranslationUnit(ASTContext &Ctx); + virtual ASTDeserializationListener *GetASTDeserializationListener(); }; } // end namespace clang diff --git a/include/clang/Serialization/CMakeLists.txt b/include/clang/Serialization/CMakeLists.txt new file mode 100644 index 000000000000..3712009bf37d --- /dev/null +++ b/include/clang/Serialization/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td) +tablegen(AttrPCHRead.inc + -gen-clang-attr-pch-read + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) +add_custom_target(ClangAttrPCHRead + DEPENDS AttrPCHRead.inc) + +tablegen(AttrPCHWrite.inc + -gen-clang-attr-pch-write + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) +add_custom_target(ClangAttrPCHWrite + DEPENDS AttrPCHWrite.inc) diff --git a/include/clang/Serialization/Makefile b/include/clang/Serialization/Makefile new file mode 100644 index 000000000000..79486b11bc68 --- /dev/null +++ b/include/clang/Serialization/Makefile @@ -0,0 +1,19 @@ +CLANG_LEVEL := ../../.. +TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic +BUILT_SOURCES = AttrPCHRead.inc AttrPCHWrite.inc + +TABLEGEN_INC_FILES_COMMON = 1 + +include $(CLANG_LEVEL)/Makefile + +$(ObjDir)/AttrPCHRead.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang PCH reader with tblgen" + $(Verb) $(TableGen) -gen-clang-attr-pch-read -o $(call SYSPATH, $@) \ + -I $(PROJ_SRC_DIR)/../../ $< + +$(ObjDir)/AttrPCHWrite.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang PCH writer with tblgen" + $(Verb) $(TableGen) -gen-clang-attr-pch-write -o $(call SYSPATH, $@) \ + -I $(PROJ_SRC_DIR)/../../ $< |