From 36c49e3f258dced101949edabd72e9bc3f1dedc4 Mon Sep 17 00:00:00 2001 From: dim Date: Fri, 17 Sep 2010 15:54:40 +0000 Subject: Vendor import of clang r114020 (from the release_28 branch): http://llvm.org/svn/llvm-project/cfe/branches/release_28@114020 Approved by: rpaulo (mentor) --- include/clang-c/Index.h | 554 ++- include/clang/AST/ASTConsumer.h | 14 +- include/clang/AST/ASTContext.h | 81 +- include/clang/AST/ASTImporter.h | 2 +- include/clang/AST/Attr.h | 607 +-- include/clang/AST/CMakeLists.txt | 6 + include/clang/AST/CanonicalType.h | 9 +- include/clang/AST/Decl.h | 238 +- include/clang/AST/DeclBase.h | 181 +- include/clang/AST/DeclCXX.h | 279 +- include/clang/AST/DeclContextInternals.h | 160 +- include/clang/AST/DeclFriend.h | 16 +- include/clang/AST/DeclGroup.h | 1 - include/clang/AST/DeclObjC.h | 150 +- include/clang/AST/DeclTemplate.h | 679 ++- include/clang/AST/DeclarationName.h | 147 + include/clang/AST/Expr.h | 748 ++-- include/clang/AST/ExprCXX.h | 405 +- include/clang/AST/ExternalASTSource.h | 93 +- include/clang/AST/FullExpr.h | 1 - include/clang/AST/Makefile | 8 +- include/clang/AST/NestedNameSpecifier.h | 2 - include/clang/AST/OperationKinds.h | 158 + include/clang/AST/RecursiveASTVisitor.h | 318 +- include/clang/AST/Redeclarable.h | 3 + include/clang/AST/Stmt.h | 37 +- include/clang/AST/StmtCXX.h | 38 +- include/clang/AST/StmtVisitor.h | 107 +- include/clang/AST/Type.h | 143 +- include/clang/AST/TypeLoc.h | 4 + include/clang/AST/TypeOrdering.h | 21 + include/clang/Analysis/Analyses/FormatString.h | 595 +++ include/clang/Analysis/Analyses/LiveVariables.h | 5 +- .../clang/Analysis/Analyses/PrintfFormatString.h | 445 -- .../Analysis/Analyses/PseudoConstantAnalysis.h | 45 + include/clang/Analysis/AnalysisContext.h | 53 +- include/clang/Analysis/CFG.h | 19 +- include/clang/Analysis/CFGStmtMap.h | 52 + .../clang/Analysis/FlowSensitive/DataflowSolver.h | 17 +- include/clang/Analysis/ProgramPoint.h | 39 +- include/clang/Analysis/Visitors/CFGStmtVisitor.h | 4 +- include/clang/Basic/Attr.td | 90 +- include/clang/Basic/Builtins.def | 149 +- include/clang/Basic/Builtins.h | 5 + include/clang/Basic/BuiltinsARM.def | 14 +- include/clang/Basic/BuiltinsX86.def | 221 +- include/clang/Basic/DeclNodes.td | 5 +- include/clang/Basic/Diagnostic.h | 71 +- include/clang/Basic/DiagnosticCommonKinds.td | 3 +- include/clang/Basic/DiagnosticDriverKinds.td | 2 + include/clang/Basic/DiagnosticFrontendKinds.td | 2 +- include/clang/Basic/DiagnosticGroups.td | 27 +- include/clang/Basic/DiagnosticLexKinds.td | 26 +- include/clang/Basic/DiagnosticParseKinds.td | 20 +- include/clang/Basic/DiagnosticSemaKinds.td | 150 +- include/clang/Basic/IdentifierTable.h | 74 +- include/clang/Basic/LangOptions.h | 3 +- include/clang/Basic/Linkage.h | 11 + include/clang/Basic/Makefile | 1 + include/clang/Basic/OnDiskHashTable.h | 83 +- include/clang/Basic/SourceManager.h | 48 +- include/clang/Basic/Specifiers.h | 62 + include/clang/Basic/StmtNodes.td | 1 - include/clang/Basic/TargetInfo.h | 43 +- include/clang/Basic/TargetOptions.h | 8 +- include/clang/Basic/TokenKinds.def | 13 +- include/clang/Basic/arm_neon.td | 2 + include/clang/CMakeLists.txt | 1 + include/clang/Checker/BugReporter/BugReporter.h | 3 + .../clang/Checker/PathSensitive/AnalysisManager.h | 52 +- include/clang/Checker/PathSensitive/Checker.h | 31 +- .../clang/Checker/PathSensitive/CheckerHelpers.h | 40 + .../Checker/PathSensitive/ConstraintManager.h | 3 - include/clang/Checker/PathSensitive/Environment.h | 8 +- include/clang/Checker/PathSensitive/GRCoreEngine.h | 168 +- include/clang/Checker/PathSensitive/GRExprEngine.h | 196 +- include/clang/Checker/PathSensitive/GRState.h | 99 +- include/clang/Checker/PathSensitive/GRSubEngine.h | 33 +- .../clang/Checker/PathSensitive/GRTransferFuncs.h | 6 +- include/clang/Checker/PathSensitive/GRWorkList.h | 10 +- include/clang/Checker/PathSensitive/MemRegion.h | 127 +- include/clang/Checker/PathSensitive/SVals.h | 27 +- include/clang/Checker/PathSensitive/Store.h | 41 +- .../clang/Checker/PathSensitive/SymbolManager.h | 79 +- include/clang/Checker/PathSensitive/ValueManager.h | 3 + include/clang/Driver/CC1Options.td | 45 +- include/clang/Driver/Compilation.h | 2 + include/clang/Driver/Driver.h | 29 +- include/clang/Driver/HostInfo.h | 9 +- include/clang/Driver/Job.h | 34 - include/clang/Driver/OptParser.td | 3 + include/clang/Driver/OptTable.h | 11 +- include/clang/Driver/Option.h | 10 +- include/clang/Driver/Options.td | 13 +- include/clang/Driver/Tool.h | 4 - include/clang/Driver/ToolChain.h | 18 + include/clang/Frontend/ASTConsumers.h | 9 - include/clang/Frontend/ASTUnit.h | 341 +- include/clang/Frontend/AnalyzerOptions.h | 3 + include/clang/Frontend/CodeGenOptions.h | 15 +- include/clang/Frontend/CompilerInstance.h | 59 +- include/clang/Frontend/DeclXML.def | 20 +- include/clang/Frontend/DiagnosticOptions.h | 2 + include/clang/Frontend/DocumentXML.h | 1 - include/clang/Frontend/FrontendAction.h | 14 +- include/clang/Frontend/FrontendActions.h | 33 +- include/clang/Frontend/FrontendOptions.h | 16 +- include/clang/Frontend/HeaderSearchOptions.h | 20 +- include/clang/Frontend/PCHBitCodes.h | 822 ---- .../clang/Frontend/PCHDeserializationListener.h | 36 - include/clang/Frontend/PCHReader.h | 905 ---- include/clang/Frontend/PCHWriter.h | 408 -- include/clang/Frontend/PreprocessorOptions.h | 67 +- include/clang/Frontend/PreprocessorOutputOptions.h | 16 +- include/clang/Frontend/StmtXML.def | 99 +- include/clang/Frontend/TypeXML.def | 8 - include/clang/Frontend/Utils.h | 7 +- include/clang/FrontendTool/Utils.h | 30 + include/clang/Index/TranslationUnit.h | 2 + include/clang/Index/Utils.h | 36 - include/clang/Lex/CodeCompletionHandler.h | 67 + include/clang/Lex/ExternalPreprocessorSource.h | 2 +- include/clang/Lex/HeaderSearch.h | 2 +- include/clang/Lex/Lexer.h | 29 + include/clang/Lex/MacroInfo.h | 37 +- include/clang/Lex/PPCallbacks.h | 10 +- include/clang/Lex/PTHLexer.h | 2 + include/clang/Lex/PreprocessingRecord.h | 3 +- include/clang/Lex/Preprocessor.h | 73 +- include/clang/Lex/Token.h | 1 + include/clang/Makefile | 2 +- include/clang/Parse/Action.h | 3309 --------------- include/clang/Parse/AttributeList.h | 228 - include/clang/Parse/DeclSpec.h | 1333 ------ include/clang/Parse/Designator.h | 239 -- include/clang/Parse/Ownership.h | 845 ---- include/clang/Parse/ParseAST.h | 47 + include/clang/Parse/Parser.h | 509 ++- include/clang/Parse/Scope.h | 329 -- include/clang/Parse/Template.h | 183 - include/clang/Rewrite/FixItRewriter.h | 11 +- include/clang/Rewrite/FrontendActions.h | 4 +- include/clang/Sema/AnalysisBasedWarnings.h | 64 + include/clang/Sema/AttributeList.h | 234 + include/clang/Sema/CXXFieldCollector.h | 79 + include/clang/Sema/CodeCompleteConsumer.h | 495 ++- include/clang/Sema/DeclSpec.h | 1386 ++++++ include/clang/Sema/DelayedDiagnostic.h | 168 + include/clang/Sema/Designator.h | 218 + include/clang/Sema/ExternalSemaSource.h | 2 +- include/clang/Sema/IdentifierResolver.h | 198 + include/clang/Sema/Initialization.h | 780 ++++ include/clang/Sema/Lookup.h | 679 +++ include/clang/Sema/ObjCMethodList.h | 38 + include/clang/Sema/Overload.h | 648 +++ include/clang/Sema/Ownership.h | 462 ++ include/clang/Sema/ParseAST.h | 43 - include/clang/Sema/ParsedTemplate.h | 172 + include/clang/Sema/PrettyDeclStackTrace.h | 46 + include/clang/Sema/Scope.h | 327 ++ include/clang/Sema/ScopeInfo.h | 137 + include/clang/Sema/Sema.h | 4457 ++++++++++++++++++++ include/clang/Sema/SemaInternal.h | 30 + include/clang/Sema/Template.h | 244 ++ include/clang/Sema/TemplateDeduction.h | 111 + include/clang/Serialization/ASTBitCodes.h | 917 ++++ .../Serialization/ASTDeserializationListener.h | 49 + include/clang/Serialization/ASTReader.h | 1100 +++++ include/clang/Serialization/ASTWriter.h | 513 +++ include/clang/Serialization/CMakeLists.txt | 12 + include/clang/Serialization/Makefile | 19 + 171 files changed, 20109 insertions(+), 12476 deletions(-) create mode 100644 include/clang/AST/OperationKinds.h create mode 100644 include/clang/Analysis/Analyses/FormatString.h delete mode 100644 include/clang/Analysis/Analyses/PrintfFormatString.h create mode 100644 include/clang/Analysis/Analyses/PseudoConstantAnalysis.h create mode 100644 include/clang/Analysis/CFGStmtMap.h create mode 100644 include/clang/Checker/PathSensitive/CheckerHelpers.h delete mode 100644 include/clang/Frontend/PCHBitCodes.h delete mode 100644 include/clang/Frontend/PCHDeserializationListener.h delete mode 100644 include/clang/Frontend/PCHReader.h delete mode 100644 include/clang/Frontend/PCHWriter.h create mode 100644 include/clang/FrontendTool/Utils.h delete mode 100644 include/clang/Index/Utils.h create mode 100644 include/clang/Lex/CodeCompletionHandler.h delete mode 100644 include/clang/Parse/Action.h delete mode 100644 include/clang/Parse/AttributeList.h delete mode 100644 include/clang/Parse/DeclSpec.h delete mode 100644 include/clang/Parse/Designator.h delete mode 100644 include/clang/Parse/Ownership.h create mode 100644 include/clang/Parse/ParseAST.h delete mode 100644 include/clang/Parse/Scope.h delete mode 100644 include/clang/Parse/Template.h create mode 100644 include/clang/Sema/AnalysisBasedWarnings.h create mode 100644 include/clang/Sema/AttributeList.h create mode 100644 include/clang/Sema/CXXFieldCollector.h create mode 100644 include/clang/Sema/DeclSpec.h create mode 100644 include/clang/Sema/DelayedDiagnostic.h create mode 100644 include/clang/Sema/Designator.h create mode 100644 include/clang/Sema/IdentifierResolver.h create mode 100644 include/clang/Sema/Initialization.h create mode 100644 include/clang/Sema/Lookup.h create mode 100644 include/clang/Sema/ObjCMethodList.h create mode 100644 include/clang/Sema/Overload.h create mode 100644 include/clang/Sema/Ownership.h delete mode 100644 include/clang/Sema/ParseAST.h create mode 100644 include/clang/Sema/ParsedTemplate.h create mode 100644 include/clang/Sema/PrettyDeclStackTrace.h create mode 100644 include/clang/Sema/Scope.h create mode 100644 include/clang/Sema/ScopeInfo.h create mode 100644 include/clang/Sema/Sema.h create mode 100644 include/clang/Sema/SemaInternal.h create mode 100644 include/clang/Sema/Template.h create mode 100644 include/clang/Sema/TemplateDeduction.h create mode 100644 include/clang/Serialization/ASTBitCodes.h create mode 100644 include/clang/Serialization/ASTDeserializationListener.h create mode 100644 include/clang/Serialization/ASTReader.h create mode 100644 include/clang/Serialization/ASTWriter.h create mode 100644 include/clang/Serialization/CMakeLists.txt create mode 100644 include/clang/Serialization/Makefile (limited to 'include') diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index b377b6d..4631c65 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 '. + * + * \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), 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 0611395..84833c0 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 3799451..ae4ee94 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 DeclAttrs; + llvm::DenseMap 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 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 &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 &Fields); - void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl &Ivars); - void CollectNonClassIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl &Ivars); + + void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, + llvm::SmallVectorImpl &Ivars); + unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI); void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet &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 7975c43..9380058 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 9faa62e..62ca49f 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 #include #include @@ -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 const T *getNext() const { - for (const Attr *attr = getNext(); attr; attr = attr->getNext()) - if (const T *V = dyn_cast(attr)) - return V; - return 0; + attr::Kind getKind() const { + return static_cast(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 AttrVec; +typedef llvm::SmallVector 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 +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(); - if (Next) - return std::max(Next->getMaxAlignment(), getAlignment()); - else - return getAlignment(); + void AdvanceToNext() const { + while (!llvm::isa(*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(*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(*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(*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 +inline specific_attr_iterator specific_attr_begin(const AttrVec& vec) { + return specific_attr_iterator(vec.begin()); +} +template +inline specific_attr_iterator specific_attr_end(const AttrVec& vec) { + return specific_attr_iterator(vec.end()); +} -DEF_SIMPLE_ATTR(X86ForceAlignArgPointer); +template +inline bool hasSpecificAttr(const AttrVec& vec) { + return specific_attr_begin(vec) != specific_attr_end(vec); +} +template +inline T *getSpecificAttr(const AttrVec& vec) { + specific_attr_iterator i = specific_attr_begin(vec); + if (i != specific_attr_end(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 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 3b09071..800c583 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 9f97fd8..dad4dfc 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 CanQual::getNonReferenceType() const { template CanQual CanQual::getFromOpaquePtr(void *Ptr) { CanQual 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 39cd51f..6749255 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(const_cast(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 { 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(Ctx) || isa(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 { 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 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(const_cast(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 { IdentifierInfo *Id, TypeSourceInfo *TInfo) : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} - virtual ~TypedefDecl(); - protected: typedef Redeclarable 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(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(const_cast(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(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 be30b8e..1369c2b 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(const_cast(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 const T *getAttr() const { - for (const Attr *attr = getAttrs(); attr; attr = attr->getNext()) - if (const T *V = dyn_cast(attr)) - return V; - return 0; + template + specific_attr_iterator specific_attr_begin() const { + return specific_attr_iterator(attr_begin()); + } + template + specific_attr_iterator specific_attr_end() const { + return specific_attr_iterator(attr_end()); } + template T *getAttr() const { + return hasAttrs() ? getSpecificAttr(getAttrs()) : 0; + } template bool hasAttr() const { - return getAttr() != 0; + return hasAttrs() && hasSpecificAttr(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 { +public: + DeclContextLookupResult(NamedDecl **I, NamedDecl **E) + : std::pair(I, E) {} + DeclContextLookupResult() + : std::pair() {} + + using std::pair::operator=; +}; + +class DeclContextLookupConstResult + : public std::pair { +public: + DeclContextLookupConstResult(std::pair R) + : std::pair(R) {} + DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E) + : std::pair(I, E) {} + DeclContextLookupConstResult() + : std::pair() {} + + using std::pair::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(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(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(this)->getRedeclContext(); } /// \brief Retrieve the nearest enclosing namespace context. @@ -782,6 +842,14 @@ public: return const_cast(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_result; - typedef std::pair - 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 ::value> diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 41474ab..a9802bf 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(); } @@ -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(); else @@ -1363,7 +1362,7 @@ public: reinterpret_cast(this + 1)[I] = Index; } - Expr *getInit() { return static_cast(Init); } + Expr *getInit() const { return static_cast(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(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(ND) || isa(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 9602b67..97da6ca 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 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 DeclsTy; + + /// \brief The stored data, which will be either a pointer to a NamedDecl, + /// or a pointer to a vector. + llvm::PointerUnion 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(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(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(Data & ~0x03); + return Data.dyn_cast(); } - VectorTy *getAsVector() const { - if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector) - return 0; - - return reinterpret_cast(Data & ~0x03); + DeclsTy *getAsVector() const { + return Data.dyn_cast(); } void setOnlyValue(NamedDecl *ND) { assert(!getAsVector() && "Not inline"); - Data = reinterpret_cast(ND); - } - - void setFromDeclIDs(const llvm::SmallVectorImpl &Vec) { - if (Vec.size() > 1) { - VectorTy *Vector = getAsVector(); - if (!Vector) { - Vector = new VectorTy; - Data = reinterpret_cast(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(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(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(*OD); + NamedDecl *OldD = *OD; if (D->declarationReplaces(OldD)) { - *OD = reinterpret_cast(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(OldD)); - Data = reinterpret_cast(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(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(*I) - ->getIdentifierNamespace() == Decl::IDNS_Using) + (*I)->getIdentifierNamespace() == Decl::IDNS_Using) ++I; } - Vec.insert(I, reinterpret_cast(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(Vec.back()) - ->hasTagIdentifierNamespace()) { - uintptr_t TagD = Vec.back(); - Vec.back() = reinterpret_cast(D); + } else if (Vec.back()->hasTagIdentifierNamespace()) { + NamedDecl *TagD = Vec.back(); + Vec.back() = D; Vec.push_back(TagD); } else - Vec.push_back(reinterpret_cast(D)); + Vec.push_back(D); } }; diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 2807d16..4b5e6fd 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(); } - /// 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(); } @@ -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 e1fae8f..030291e 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 30f63d8..ad26748 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 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 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::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 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 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 135dd3a..b532668 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 *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 struct SpecEntryTraits { + typedef EntryType DeclType; - /// \brief The function template specializations for this function - /// template, including explicit specializations and instantiations. - llvm::FoldingSet Specializations; + static DeclType *getMostRecentDeclaration(EntryType *D) { + return D->getMostRecentDeclaration(); + } + }; + + template , + typename _DeclType = typename _SETraits::DeclType> + class SpecIterator : public std::iterator { + typedef _SETraits SETraits; + typedef _DeclType DeclType; + + typedef typename llvm::FoldingSet::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 + SpecIterator makeSpecIterator(llvm::FoldingSet &Specs, + bool isEnd) { + return SpecIterator(isEnd ? Specs.end() : Specs.begin()); + } + + template typename SpecEntryTraits::DeclType* + findSpecializationImpl(llvm::FoldingSet &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 InstantiatedFromMember; + llvm::PointerIntPair + 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 CommonOrPrev; + /// or to the data that is common to all declarations of this template. + llvm::PointerUnion 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(TemplatedDecl); - } +public: + template friend class RedeclarableTemplate; - /// \brief Retrieve the set of function template specializations of this - /// function template. - llvm::FoldingSet &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(); + 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(); + const RedeclarableTemplateDecl *getPreviousDeclaration() const { + return + const_cast(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(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 - /// struct X { - /// template void f(); - /// }; - /// \endcode - /// - /// X::A is a CXXMethodDecl (whose parent is X, a - /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will - /// return X::f, a FunctionTemplateDecl (whose parent is again - /// X) for which getInstantiatedFromMemberTemplate() will return - /// X::f, a FunctionTemplateDecl (whose parent is X, 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(this)->getMostRecentDeclaration(); } /// \brief Determines whether this template was a specialization of a /// member template. /// - /// In the following example, the function template \c X::f is a - /// member specialization. + /// In the following example, the function template \c X::f and the + /// member template \c X::Inner are member specializations. /// /// \code /// template /// struct X { /// template void f(T, U); + /// template struct Inner; /// }; /// /// template<> template /// void X::f(int, T); + /// template<> template + /// struct X::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 RedeclarableTemplate { + RedeclarableTemplateDecl *thisDecl() { + return static_cast(this); + } + +public: + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + decl_type *getPreviousDeclaration() { + return static_cast(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(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(thisDecl()->getCanonicalDeclImpl()); + } + + const decl_type *getCanonicalDecl() const { + return const_cast(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 + /// struct X { + /// template void f(); + /// template struct A {}; + /// }; + /// \endcode + /// + /// X::f is a CXXMethodDecl (whose parent is X, a + /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will + /// return X::f, a FunctionTemplateDecl (whose parent is again + /// X) for which getInstantiatedFromMemberTemplate() will return + /// X::f, a FunctionTemplateDecl (whose parent is X, a + /// ClassTemplateDecl). + /// + /// X::A is a ClassTemplateSpecializationDecl (whose parent + /// is X, also a CTSD) for which getSpecializedTemplate() will + /// return X::A, a ClassTemplateDecl (whose parent is again + /// X) for which getInstantiatedFromMemberTemplate() will return + /// X::A, a ClassTemplateDecl (whose parent is X, also a CTD). + /// + /// \returns NULL if this is not an instantiation of a member template. + decl_type *getInstantiatedFromMemberTemplate() { + return static_cast( + thisDecl()->getInstantiatedFromMemberTemplateImpl()); + } + + void setInstantiatedFromMemberTemplate(decl_type *TD) { + thisDecl()->setInstantiatedFromMemberTemplateImpl(TD); + } +}; + +template <> struct RedeclarableTemplateDecl:: +SpecEntryTraits { + typedef FunctionDecl DeclType; + + static DeclType * + getMostRecentDeclaration(FunctionTemplateSpecializationInfo *I) { + return I->Function->getMostRecentDeclaration(); + } +}; + +/// Declaration of a template function. +class FunctionTemplateDecl : public RedeclarableTemplateDecl, + public RedeclarableTemplate { + static void DeallocateCommon(void *Ptr); + +protected: + typedef RedeclarableTemplate 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 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(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 &getSpecializations() { + return getCommonPtr()->Specializations; + } + +public: + /// Get the underlying function declaration of the template. + FunctionDecl *getTemplatedDecl() const { + return static_cast(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 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::getMostRecentDeclaration()); + if (!isa(Recent)) { + // FIXME: Does injected class name need to be in the redeclarations chain? + assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration()); + Recent = Recent->getPreviousDeclaration(); + } + return cast(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(); if (SpecializedPartialSpecialization *PartialSpec = SpecializedTemplate.dyn_cast()) @@ -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( + 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 { static void DeallocateCommon(void *Ptr); protected: + typedef RedeclarableTemplate 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 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 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 CommonOrPrev; + /// \brief Retrieve the set of specializations of this class template. + llvm::FoldingSet &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 & + 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(RedeclarableTemplateDecl::getCommonPtr()); + } public: /// Get the underlying class declarations of the template. @@ -1404,48 +1671,71 @@ public: return static_cast(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(); + /// 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(); + 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(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 &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 & - 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 - /// struct X { - /// template struct A {}; - /// }; - /// \endcode - /// - /// X::A is a ClassTemplateSpecializationDecl (whose parent - /// is X, also a CTSD) for which getSpecializedTemplate() will - /// return X::A, a TemplateClassDecl (whose parent is again - /// X) for which getInstantiatedFromMemberTemplate() will return - /// X::A, a TemplateClassDecl (whose parent is X, also a TCD). - /// - /// \returns null if this is not an instantiation of a member class template. - ClassTemplateDecl *getInstantiatedFromMemberTemplate() { - return getCommonPtr()->InstantiatedFromMember.getPointer(); + typedef SpecIterator 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::Inner is a - /// member specialization. - /// - /// \code - /// template - /// struct X { - /// template struct Inner; - /// }; - /// - /// template<> template - /// struct X::Inner { /* ... */ }; - /// \endcode - bool isMemberSpecialization() { - return getCommonPtr()->InstantiatedFromMember.getInt(); + typedef SpecIterator + 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 class A { /// friend class MyVector; // not a friend template -/// template friend class B; // friend template +/// template friend class B; // not a friend template /// template friend class Foo::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 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 8a771d5..8bb6275 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 ade2b09..48130be 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 CXXBaseSpecifierArray; +typedef llvm::SmallVector 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 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(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(this + 1); - - return reinterpret_cast( - getNameQualifier() + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { - return const_cast(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. - 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(this + 1); + + return *reinterpret_cast( + getNameQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + return const_cast(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(Opc); } void setOpcode(Opcode O) { Opc = O; } Expr *getSubExpr() const { return cast(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(SubExprs[FN]); } Expr *getCallee() { return cast(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(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(this + 1); - - return reinterpret_cast( - getMemberQualifier() + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { - return const_cast(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. - 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(this + 1); + + return *reinterpret_cast( + 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(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(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(Kind); } void setCastKind(CastKind K) { Kind = K; } const char *getCastKindName() const; @@ -2024,8 +2041,16 @@ public: return const_cast(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(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(Opc); } void setOpcode(Opcode O) { Opc = O; } Expr *getLHS() const { return cast(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(SubExprs[LHS] ? SubExprs[LHS] : SubExprs[COND]); + return cast(!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(SubExprs[RHS]); } - - Expr *getLHS() const { return cast_or_null(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(Save) : (Expr*)0; } + + Expr *getLHS() const { return Save ? 0 : cast(SubExprs[LHS]); } void setLHS(Expr *E) { SubExprs[LHS] = E; } Expr *getRHS() const { return cast(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } + Expr *getSAVE() const { return Save? cast(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(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 b955381..0a94354 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(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(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(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(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(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(SubExpr); } - Expr *getSubExpr() { return cast(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()->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 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(E)) - op = true, E = cast(E)->getSubExpr()->IgnoreParens(); - return llvm::PointerIntPair(cast(E), op); + if (isa(E)) { + assert(cast(E)->getOpcode() == UO_AddrOf); + E = cast(E)->getSubExpr(); + OverloadExpr *Ovl = cast(E->IgnoreParens()); + + Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier()); + Result.IsAddressOfOperand = true; + Result.Expression = Ovl; + } else { + Result.HasFormOfMemberPointer = false; + Result.IsAddressOfOperand = false; + Result.Expression = cast(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(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(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(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. @@ -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(this + 1); + return *reinterpret_cast(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(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(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 def9ced..a8ef005 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 #include + +namespace llvm { +template 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 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 &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 &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 &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 &Decls); - static DeclContext::lookup_result + static DeclContextLookupResult SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name); + + void MaterializeVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name, + llvm::SmallVectorImpl &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 +template 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 +typedef LazyOffsetPtr LazyDeclStmtPtr; +/// \brief A lazy pointer to a declaration. +typedef LazyOffsetPtr + 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 bb81bf0..6ceefed 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()) diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile index 00a1e1b..6ba6e89 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 1594b09..3b25f3b 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 0000000..8045311 --- /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 0853ddd..232e47b 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 class RecursiveASTVisitor { public: /// \brief Return a reference to the derived class. Derived &getDerived() { return *static_cast(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::TraverseStmt(Stmt *S) { if (BinaryOperator *BinOp = dyn_cast(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::TraverseStmt(Stmt *S) { } else if (UnaryOperator *UnOp = dyn_cast(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::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 +bool RecursiveASTVisitor::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::TraverseTemplateParameterListHelper( return true; } +// A helper method for traversing the implicit instantiations of a +// class. +template +bool RecursiveASTVisitor::TraverseClassInstantiations( + ClassTemplateDecl* D, Decl *Pattern) { + assert(isa(Pattern) || + isa(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 U + = SD->getInstantiatedFrom(); + + bool ShouldVisit; + if (U.is()) + ShouldVisit = (U.get() == Pattern); + else + ShouldVisit + = (U.get() == 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 +bool RecursiveASTVisitor::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 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::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;"), 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 @@ -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::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(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(D)) { // Constructor initializers. @@ -1356,9 +1540,6 @@ DEF_TRAVERSE_DECL(CXXDestructorDecl, { template bool RecursiveASTVisitor::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 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 55e1f84..ba77829 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -177,6 +177,9 @@ public: static_cast(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 a0c95b1..62a6b64 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 4e87c27..0508f35 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(this + 1); + } + Stmt **getStmts() { + return reinterpret_cast(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(this + 1); - return Stmts[NumHandlers]->getLocEnd(); + return getStmts()[NumHandlers]->getLocEnd(); } CompoundStmt *getTryBlock() { - Stmt **Stmts = reinterpret_cast(this + 1); - return llvm::cast(Stmts[0]); + return llvm::cast(getStmts()[0]); } const CompoundStmt *getTryBlock() const { - Stmt const * const*Stmts = reinterpret_cast(this + 1); - return llvm::cast(Stmts[0]); + return llvm::cast(getStmts()[0]); } unsigned getNumHandlers() const { return NumHandlers; } CXXCatchStmt *getHandler(unsigned i) { - Stmt **Stmts = reinterpret_cast(this + 1); - return llvm::cast(Stmts[i + 1]); + return llvm::cast(getStmts()[i + 1]); } const CXXCatchStmt *getHandler(unsigned i) const { - Stmt const * const*Stmts = reinterpret_cast(this + 1); - return llvm::cast(Stmts[i + 1]); + return llvm::cast(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 8078451..b8c141d 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -37,68 +37,57 @@ public: if (BinaryOperator *BinOp = dyn_cast(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(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 4c148e8..92e62a5 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(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 bool isObjCQualifiedIdType() const; // id bool isObjCQualifiedClassType() const; // Class + 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'. This scheme will eventually + // Member-template getAs'. Look through sugar for + // an instance of . 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 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(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(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()) - return T->getPointeeType()->isFunctionType(); + return T->isMemberFunctionPointer(); + else + return false; +} +inline bool Type::isMemberDataPointerType() const { + if (const MemberPointerType* T = getAs()) + return T->isMemberDataPointer(); else return false; } @@ -3523,6 +3549,11 @@ inline bool Type::isObjCObjectPointerType() const { inline bool Type::isObjCObjectType() const { return isa(CanonicalType); } +inline bool Type::isObjCObjectOrInterfaceType() const { + return isa(CanonicalType) || + isa(CanonicalType); +} + inline bool Type::isObjCQualifiedIdType() const { if (const ObjCObjectPointerType *OPT = getAs()) return OPT->isObjCQualifiedIdType(); diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 842c068..f1c64bd 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -341,6 +341,10 @@ private: template 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 1a050d2..7cf0d5e 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 namespace clang { @@ -51,6 +52,26 @@ namespace llvm { return LHS == RHS; } }; + + template<> struct DenseMapInfo { + static inline clang::CanQualType getEmptyKey() { + return clang::CanQualType(); + } + + static inline clang::CanQualType getTombstoneKey() { + using clang::CanQualType; + return CanQualType::getFromOpaquePtr(reinterpret_cast(-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 0000000..280b126 --- /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(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(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 44ab080..237fe14 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= 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 0000000..cb73850 --- /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 9ebd93b..7d4d25f 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 *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 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 b7256c9..b7a8e11 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 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(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(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 0000000..6e8e140 --- /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(this)->getBlock(const_cast(S)); + } +}; + +} // end clang namespace +#endif diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h index 3c76201..9375db0 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 075838d..ba303de 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 Data; @@ -107,16 +109,16 @@ public: const void *tag = 0) : ProgramPoint(B, BlockEntranceKind, L, tag) {} - CFGBlock* getBlock() const { - return const_cast(reinterpret_cast(getData1())); + const CFGBlock* getBlock() const { + return reinterpret_cast(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(reinterpret_cast(getData1())); + const CFGBlock* getBlock() const { + return reinterpret_cast(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(static_cast(getData1())); + const CFGBlock* getSrc() const { + return static_cast(getData1()); } - CFGBlock* getDst() const { - return const_cast(static_cast(getData2())); + const CFGBlock* getDst() const { + return static_cast(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(getData1()); } - const FunctionDecl *getCallee() const { - return static_cast(getData2()); + AnalysisContext *getCalleeContext() const { + return const_cast( + static_cast(getData2())); } static bool classof(const ProgramPoint *Location) { diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h index 8a85ec1..6421f18 100644 --- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -86,7 +86,7 @@ public: BinaryOperator* B = cast(S); if (B->isLogicalOp()) return static_cast(this)->BlockStmt_VisitLogicalOp(B); - else if (B->getOpcode() == BinaryOperator::Comma) + else if (B->getOpcode() == BO_Comma) return static_cast(this)->BlockStmt_VisitComma(B); // Fall through. } @@ -149,7 +149,7 @@ public: case Stmt::BinaryOperatorClass: { BinaryOperator* B = cast(S); - if (B->getOpcode() != BinaryOperator::Comma) break; + if (B->getOpcode() != BO_Comma) break; static_cast(this)->Visit(B->getRHS()); return; } diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 98871d2..2f2267f 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -33,8 +33,8 @@ class SubsetSubject // a possible subject. def NormalVar : SubsetSubjectgetStorageClass() != VarDecl::Register && - S->getKind() != Decl::ImplicitParam - S->getKind() != Decl::ParmVar + S->getKind() != Decl::ImplicitParam && + S->getKind() != Decl::ParmVar && S->getKind() != Decl::NonTypeTemplateParm}]>; def CXXVirtualMethod : SubsetSubjectisVirtual()}]>; @@ -51,18 +51,27 @@ class IntArgument : Argument; class StringArgument : Argument; class ExprArgument : Argument; class FunctionArgument : Argument; -class ObjCInterfaceArgument : Argument; -class UnsignedIntArgument : Argument; -class UnsignedIntOrTypeArgument : Argument; +class TypeArgument : Argument; +class UnsignedArgument : Argument; +class VariadicUnsignedArgument : Argument; + +// 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 : Argument; // An integer argument with a default value class DefaultIntArgument : IntArgument { int Default = default; } -// Zero or more arguments of a type -class VariadicArgument : Argument { - 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 values, + list enums> : Argument { + string Type = type; + list Values = values; + list 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 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>]; + 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 eff4f5e..0da8938 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 07f091a..94d5e69 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 54e4c2b..080d17f 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 a878dd1..5ad64b9 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 203fb45..e2f93e0 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -43,8 +43,9 @@ def Named : Decl<1>; def ParmVar : DDecl; def NonTypeTemplateParm : DDecl; def Template : DDecl; - def FunctionTemplate : DDecl