aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/clang-c/CXCompilationDatabase.h146
-rw-r--r--include/clang-c/CXString.h61
-rw-r--r--include/clang-c/Index.h932
-rw-r--r--include/clang-c/Platform.h45
-rw-r--r--include/clang/AST/ASTContext.h152
-rw-r--r--include/clang/AST/ASTImporter.h3
-rw-r--r--include/clang/AST/ASTVector.h4
-rw-r--r--include/clang/AST/Attr.h46
-rw-r--r--include/clang/AST/BaseSubobject.h6
-rw-r--r--include/clang/AST/CMakeLists.txt5
-rw-r--r--include/clang/AST/CXXInheritance.h3
-rw-r--r--include/clang/AST/Comment.h1059
-rw-r--r--include/clang/AST/CommentBriefParser.h56
-rw-r--r--include/clang/AST/CommentCommandTraits.h156
-rw-r--r--include/clang/AST/CommentDiagnostic.h29
-rw-r--r--include/clang/AST/CommentLexer.h353
-rw-r--r--include/clang/AST/CommentParser.h124
-rw-r--r--include/clang/AST/CommentSema.h230
-rw-r--r--include/clang/AST/CommentVisitor.h66
-rw-r--r--include/clang/AST/Decl.h114
-rw-r--r--include/clang/AST/DeclBase.h64
-rw-r--r--include/clang/AST/DeclCXX.h193
-rw-r--r--include/clang/AST/DeclContextInternals.h4
-rw-r--r--include/clang/AST/DeclFriend.h8
-rw-r--r--include/clang/AST/DeclObjC.h233
-rw-r--r--include/clang/AST/DeclTemplate.h160
-rw-r--r--include/clang/AST/DeclarationName.h39
-rw-r--r--include/clang/AST/EvaluatedExprVisitor.h2
-rw-r--r--include/clang/AST/Expr.h94
-rw-r--r--include/clang/AST/ExprCXX.h179
-rw-r--r--include/clang/AST/ExprObjC.h84
-rw-r--r--include/clang/AST/ExternalASTSource.h3
-rw-r--r--include/clang/AST/Makefile8
-rw-r--r--include/clang/AST/Mangle.h4
-rw-r--r--include/clang/AST/NSAPI.h74
-rw-r--r--include/clang/AST/NestedNameSpecifier.h15
-rw-r--r--include/clang/AST/OperationKinds.h2
-rw-r--r--include/clang/AST/RawCommentList.h220
-rw-r--r--include/clang/AST/RecordLayout.h88
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h180
-rw-r--r--include/clang/AST/Redeclarable.h29
-rw-r--r--include/clang/AST/Stmt.h122
-rw-r--r--include/clang/AST/StmtObjC.h56
-rw-r--r--include/clang/AST/TemplateBase.h101
-rw-r--r--include/clang/AST/Type.h137
-rw-r--r--include/clang/AST/TypeLoc.h13
-rw-r--r--include/clang/ASTMatchers/ASTMatchFinder.h141
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h1799
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h901
-rw-r--r--include/clang/ASTMatchers/ASTMatchersMacros.h224
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h65
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafety.h9
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValues.h60
-rw-r--r--include/clang/Analysis/AnalysisContext.h50
-rw-r--r--include/clang/Analysis/CFG.h12
-rw-r--r--include/clang/Analysis/CallGraph.h10
-rw-r--r--include/clang/Analysis/ProgramPoint.h169
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h2
-rw-r--r--include/clang/Basic/ABI.h43
-rw-r--r--include/clang/Basic/AddressSpaces.h18
-rw-r--r--include/clang/Basic/AllDiagnostics.h9
-rw-r--r--include/clang/Basic/Attr.td397
-rw-r--r--include/clang/Basic/AttrKinds.h9
-rw-r--r--include/clang/Basic/Builtins.def80
-rw-r--r--include/clang/Basic/Builtins.h35
-rw-r--r--include/clang/Basic/BuiltinsHexagon.def1531
-rw-r--r--include/clang/Basic/BuiltinsMips.def125
-rw-r--r--include/clang/Basic/BuiltinsNVPTX.def (renamed from include/clang/Basic/BuiltinsPTX.def)0
-rw-r--r--include/clang/Basic/BuiltinsX86.def125
-rw-r--r--include/clang/Basic/CMakeLists.txt1
-rw-r--r--include/clang/Basic/CommentNodes.td27
-rw-r--r--include/clang/Basic/ConvertUTF.h35
-rw-r--r--include/clang/Basic/Diagnostic.h490
-rw-r--r--include/clang/Basic/Diagnostic.td1
-rw-r--r--include/clang/Basic/DiagnosticCommentKinds.td125
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td6
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td21
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td16
-rw-r--r--include/clang/Basic/DiagnosticGroups.td44
-rw-r--r--include/clang/Basic/DiagnosticIDs.h96
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td30
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td65
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td1131
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td4
-rw-r--r--include/clang/Basic/ExceptionSpecificationType.h15
-rw-r--r--include/clang/Basic/ExpressionTraits.h7
-rw-r--r--include/clang/Basic/FileManager.h93
-rw-r--r--include/clang/Basic/FileSystemOptions.h7
-rw-r--r--include/clang/Basic/FileSystemStatCache.h18
-rw-r--r--include/clang/Basic/IdentifierTable.h103
-rw-r--r--include/clang/Basic/LLVM.h7
-rw-r--r--include/clang/Basic/Lambda.h15
-rw-r--r--include/clang/Basic/LangOptions.def10
-rw-r--r--include/clang/Basic/LangOptions.h29
-rw-r--r--include/clang/Basic/Linkage.h23
-rw-r--r--include/clang/Basic/MacroBuilder.h13
-rw-r--r--include/clang/Basic/Makefile1
-rw-r--r--include/clang/Basic/Module.h13
-rw-r--r--include/clang/Basic/ObjCRuntime.h264
-rw-r--r--include/clang/Basic/OnDiskHashTable.h8
-rw-r--r--include/clang/Basic/OpenCL.h9
-rw-r--r--include/clang/Basic/OperatorKinds.h13
-rw-r--r--include/clang/Basic/PartialDiagnostic.h61
-rw-r--r--include/clang/Basic/PrettyStackTrace.h15
-rw-r--r--include/clang/Basic/SourceLocation.h102
-rw-r--r--include/clang/Basic/SourceManager.h659
-rw-r--r--include/clang/Basic/SourceManagerInternals.h55
-rw-r--r--include/clang/Basic/Specifiers.h52
-rw-r--r--include/clang/Basic/StmtNodes.td5
-rw-r--r--include/clang/Basic/TargetBuiltins.h36
-rw-r--r--include/clang/Basic/TargetInfo.h273
-rw-r--r--include/clang/Basic/TargetOptions.h7
-rw-r--r--include/clang/Basic/TemplateKinds.h7
-rw-r--r--include/clang/Basic/TokenKinds.def64
-rw-r--r--include/clang/Basic/TokenKinds.h21
-rw-r--r--include/clang/Basic/TypeTraits.h15
-rw-r--r--include/clang/Basic/Version.h38
-rw-r--r--include/clang/Basic/VersionTuple.h45
-rw-r--r--include/clang/Basic/Visibility.h19
-rw-r--r--include/clang/Basic/arm_neon.td1
-rw-r--r--include/clang/Driver/Arg.h42
-rw-r--r--include/clang/Driver/ArgList.h8
-rw-r--r--include/clang/Driver/CC1Options.h32
-rw-r--r--include/clang/Driver/CC1Options.td366
-rw-r--r--include/clang/Driver/CMakeLists.txt4
-rw-r--r--include/clang/Driver/Compilation.h2
-rw-r--r--include/clang/Driver/Driver.h8
-rw-r--r--include/clang/Driver/Makefile8
-rw-r--r--include/clang/Driver/ObjCRuntime.h49
-rw-r--r--include/clang/Driver/OptParser.td5
-rw-r--r--include/clang/Driver/OptTable.h50
-rw-r--r--include/clang/Driver/Option.h6
-rw-r--r--include/clang/Driver/Options.td566
-rw-r--r--include/clang/Driver/ToolChain.h21
-rw-r--r--include/clang/Driver/Types.def12
-rw-r--r--include/clang/Driver/Types.h6
-rw-r--r--include/clang/Frontend/ASTConsumers.h8
-rw-r--r--include/clang/Frontend/ASTUnit.h42
-rw-r--r--include/clang/Frontend/Analyses.def4
-rw-r--r--include/clang/Frontend/AnalyzerOptions.h2
-rw-r--r--include/clang/Frontend/CodeGenOptions.h180
-rw-r--r--include/clang/Frontend/CompilerInstance.h3
-rw-r--r--include/clang/Frontend/CompilerInvocation.h42
-rw-r--r--include/clang/Frontend/DiagnosticOptions.h3
-rw-r--r--include/clang/Frontend/DiagnosticRenderer.h34
-rw-r--r--include/clang/Frontend/FrontendAction.h2
-rw-r--r--include/clang/Frontend/FrontendActions.h6
-rw-r--r--include/clang/Frontend/FrontendOptions.h20
-rw-r--r--include/clang/Frontend/HeaderSearchOptions.h28
-rw-r--r--include/clang/Frontend/LangStandards.def6
-rw-r--r--include/clang/Frontend/PreprocessorOutputOptions.h4
-rw-r--r--include/clang/Frontend/TextDiagnostic.h26
-rw-r--r--include/clang/Frontend/TextDiagnosticPrinter.h2
-rw-r--r--include/clang/Frontend/VerifyDiagnosticConsumer.h138
-rw-r--r--include/clang/Lex/CodeCompletionHandler.h6
-rw-r--r--include/clang/Lex/DirectoryLookup.h10
-rw-r--r--include/clang/Lex/HeaderMap.h2
-rw-r--r--include/clang/Lex/HeaderSearch.h138
-rw-r--r--include/clang/Lex/Lexer.h35
-rw-r--r--include/clang/Lex/LiteralSupport.h1
-rw-r--r--include/clang/Lex/MacroInfo.h15
-rw-r--r--include/clang/Lex/ModuleMap.h6
-rw-r--r--include/clang/Lex/MultipleIncludeOpt.h43
-rw-r--r--include/clang/Lex/PPCallbacks.h123
-rw-r--r--include/clang/Lex/Pragma.h10
-rw-r--r--include/clang/Lex/PreprocessingRecord.h18
-rw-r--r--include/clang/Lex/Preprocessor.h134
-rw-r--r--include/clang/Lex/PreprocessorLexer.h55
-rw-r--r--include/clang/Lex/Token.h53
-rw-r--r--include/clang/Parse/Parser.h281
-rw-r--r--include/clang/Rewrite/FrontendActions.h5
-rw-r--r--include/clang/Rewrite/Rewriter.h7
-rw-r--r--include/clang/Rewrite/Rewriters.h5
-rw-r--r--include/clang/Rewrite/TokenRewriter.h2
-rw-r--r--include/clang/Sema/AttributeList.h81
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h142
-rw-r--r--include/clang/Sema/CodeCompleteOptions.h37
-rw-r--r--include/clang/Sema/DeclSpec.h188
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h66
-rw-r--r--include/clang/Sema/Designator.h8
-rw-r--r--include/clang/Sema/Initialization.h8
-rw-r--r--include/clang/Sema/Overload.h23
-rw-r--r--include/clang/Sema/ParsedTemplate.h10
-rw-r--r--include/clang/Sema/Scope.h4
-rw-r--r--include/clang/Sema/ScopeInfo.h19
-rw-r--r--include/clang/Sema/Sema.h1016
-rw-r--r--include/clang/Sema/Template.h11
-rw-r--r--include/clang/Sema/TemplateDeduction.h39
-rw-r--r--include/clang/Sema/Weak.h2
-rw-r--r--include/clang/Serialization/ASTBitCodes.h63
-rw-r--r--include/clang/Serialization/ASTReader.h36
-rw-r--r--include/clang/Serialization/ASTWriter.h13
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h20
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h36
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h65
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h71
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h106
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h39
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h962
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h19
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h94
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h7
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h86
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h293
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h102
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h25
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h42
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h70
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h14
-rw-r--r--include/clang/Tooling/ArgumentsAdjusters.h59
-rw-r--r--include/clang/Tooling/CommandLineClangTool.h80
-rw-r--r--include/clang/Tooling/CompilationDatabase.h28
-rw-r--r--include/clang/Tooling/Refactoring.h151
-rw-r--r--include/clang/Tooling/RefactoringCallbacks.h90
-rw-r--r--include/clang/Tooling/Tooling.h85
220 files changed, 16846 insertions, 5912 deletions
diff --git a/include/clang-c/CXCompilationDatabase.h b/include/clang-c/CXCompilationDatabase.h
new file mode 100644
index 000000000000..d11133cf9328
--- /dev/null
+++ b/include/clang-c/CXCompilationDatabase.h
@@ -0,0 +1,146 @@
+/*===-- clang-c/CXCompilationDatabase.h - Compilation database ---*- C -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides a public inferface to use CompilationDatabase without *|
+|* the full Clang C++ API. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef CLANG_CXCOMPILATIONDATABASE_H
+#define CLANG_CXCOMPILATIONDATABASE_H
+
+#include "clang-c/Platform.h"
+#include "clang-c/CXString.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \defgroup COMPILATIONDB CompilationDatabase functions
+ * \ingroup CINDEX
+ *
+ * @{
+ */
+
+/**
+ * A compilation database holds all information used to compile files in a
+ * project. For each file in the database, it can be queried for the working
+ * directory or the command line used for the compiler invocation.
+ *
+ * Must be freed by \c clang_CompilationDatabase_dispose
+ */
+typedef void * CXCompilationDatabase;
+
+/**
+ * \brief Contains the results of a search in the compilation database
+ *
+ * When searching for the compile command for a file, the compilation db can
+ * return several commands, as the file may have been compiled with
+ * different options in different places of the project. This choice of compile
+ * commands is wrapped in this opaque data structure. It must be freed by
+ * \c clang_CompileCommands_dispose.
+ */
+typedef void * CXCompileCommands;
+
+/**
+ * \brief Represents the command line invocation to compile a specific file.
+ */
+typedef void * CXCompileCommand;
+
+/**
+ * \brief Error codes for Compilation Database
+ */
+typedef enum {
+ /*
+ * \brief No error occured
+ */
+ CXCompilationDatabase_NoError = 0,
+
+ /*
+ * \brief Database can not be loaded
+ */
+ CXCompilationDatabase_CanNotLoadDatabase = 1
+
+} CXCompilationDatabase_Error;
+
+/**
+ * \brief Creates a compilation database from the database found in directory
+ * buildDir. For example, CMake can output a compile_commands.json which can
+ * be used to build the database.
+ *
+ * It must be freed by \c clang_CompilationDatabase_dispose.
+ */
+CINDEX_LINKAGE CXCompilationDatabase
+clang_CompilationDatabase_fromDirectory(const char *BuildDir,
+ CXCompilationDatabase_Error *ErrorCode);
+
+/**
+ * \brief Free the given compilation database
+ */
+CINDEX_LINKAGE void
+clang_CompilationDatabase_dispose(CXCompilationDatabase);
+
+/**
+ * \brief Find the compile commands used for a file. The compile commands
+ * must be freed by \c clang_CompileCommands_dispose.
+ */
+CINDEX_LINKAGE CXCompileCommands
+clang_CompilationDatabase_getCompileCommands(CXCompilationDatabase,
+ const char *CompleteFileName);
+
+/**
+ * \brief Free the given CompileCommands
+ */
+CINDEX_LINKAGE void clang_CompileCommands_dispose(CXCompileCommands);
+
+/**
+ * \brief Get the number of CompileCommand we have for a file
+ */
+CINDEX_LINKAGE unsigned
+clang_CompileCommands_getSize(CXCompileCommands);
+
+/**
+ * \brief Get the I'th CompileCommand for a file
+ *
+ * Note : 0 <= i < clang_CompileCommands_getSize(CXCompileCommands)
+ */
+CINDEX_LINKAGE CXCompileCommand
+clang_CompileCommands_getCommand(CXCompileCommands, unsigned I);
+
+/**
+ * \brief Get the working directory where the CompileCommand was executed from
+ */
+CINDEX_LINKAGE CXString
+clang_CompileCommand_getDirectory(CXCompileCommand);
+
+/**
+ * \brief Get the number of arguments in the compiler invocation.
+ *
+ */
+CINDEX_LINKAGE unsigned
+clang_CompileCommand_getNumArgs(CXCompileCommand);
+
+/**
+ * \brief Get the I'th argument value in the compiler invocations
+ *
+ * Invariant :
+ * - argument 0 is the compiler executable
+ */
+CINDEX_LINKAGE CXString
+clang_CompileCommand_getArg(CXCompileCommand, unsigned I);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/include/clang-c/CXString.h b/include/clang-c/CXString.h
new file mode 100644
index 000000000000..74c31660ef10
--- /dev/null
+++ b/include/clang-c/CXString.h
@@ -0,0 +1,61 @@
+/*===-- clang-c/CXString.h - C Index strings --------------------*- C -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides the interface to C Index strings. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef CLANG_CXSTRING_H
+#define CLANG_CXSTRING_H
+
+#include "clang-c/Platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup CINDEX_STRING String manipulation routines
+ * \ingroup CINDEX
+ *
+ * @{
+ */
+
+/**
+ * \brief A character string.
+ *
+ * The \c CXString type is used to return strings from the interface when
+ * the ownership of that string might different from one call to the next.
+ * Use \c clang_getCString() to retrieve the string data and, once finished
+ * with the string data, call \c clang_disposeString() to free the string.
+ */
+typedef struct {
+ void *data;
+ unsigned private_flags;
+} CXString;
+
+/**
+ * \brief Retrieve the character data associated with the given string.
+ */
+CINDEX_LINKAGE const char *clang_getCString(CXString string);
+
+/**
+ * \brief Free the given string,
+ */
+CINDEX_LINKAGE void clang_disposeString(CXString string);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 13ba6ba2ae16..edd3cbb4a7f4 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -20,31 +20,13 @@
#include <time.h>
#include <stdio.h>
+#include "clang-c/Platform.h"
+#include "clang-c/CXString.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-/* MSVC DLL import/export. */
-#ifdef _MSC_VER
- #ifdef _CINDEX_LIB_
- #define CINDEX_LINKAGE __declspec(dllexport)
- #else
- #define CINDEX_LINKAGE __declspec(dllimport)
- #endif
-#else
- #define CINDEX_LINKAGE
-#endif
-
-#ifdef __GNUC__
- #define CINDEX_DEPRECATED __attribute__((deprecated))
-#else
- #ifdef _MSC_VER
- #define CINDEX_DEPRECATED __declspec(deprecated)
- #else
- #define CINDEX_DEPRECATED
- #endif
-#endif
-
/** \defgroup CINDEX libclang: C Interface to Clang
*
* The C Interface to Clang provides a relatively small API that exposes
@@ -132,43 +114,34 @@ enum CXAvailabilityKind {
*/
CXAvailability_NotAccessible
};
-
-/**
- * \defgroup CINDEX_STRING String manipulation routines
- *
- * @{
- */
-
-/**
- * \brief A character string.
- *
- * The \c CXString type is used to return strings from the interface when
- * the ownership of that string might different from one call to the next.
- * Use \c clang_getCString() to retrieve the string data and, once finished
- * with the string data, call \c clang_disposeString() to free the string.
- */
-typedef struct {
- void *data;
- unsigned private_flags;
-} CXString;
-
-/**
- * \brief Retrieve the character data associated with the given string.
- */
-CINDEX_LINKAGE const char *clang_getCString(CXString string);
-
-/**
- * \brief Free the given string,
- */
-CINDEX_LINKAGE void clang_disposeString(CXString string);
/**
- * @}
+ * \brief Describes a version number of the form major.minor.subminor.
*/
-
+typedef struct CXVersion {
+ /**
+ * \brief The major version number, e.g., the '10' in '10.7.3'. A negative
+ * value indicates that there is no version number at all.
+ */
+ int Major;
+ /**
+ * \brief The minor version number, e.g., the '7' in '10.7.3'. This value
+ * will be negative if no minor version number was provided, e.g., for
+ * version '10'.
+ */
+ int Minor;
+ /**
+ * \brief The subminor version number, e.g., the '3' in '10.7.3'. This value
+ * will be negative if no minor or subminor version number was provided,
+ * e.g., in version '10' or '10.7'.
+ */
+ int Subminor;
+} CXVersion;
+
/**
- * \brief clang_createIndex() provides a shared context for creating
- * translation units. It provides two options:
+ * \brief Provides a shared context for creating translation units.
+ *
+ * It provides two options:
*
* - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local"
* declarations (when loading any new translation units). A "local" declaration
@@ -178,6 +151,7 @@ CINDEX_LINKAGE void clang_disposeString(CXString string);
*
* Here is an example:
*
+ * \code
* // excludeDeclsFromPCH = 1, displayDiagnostics=1
* Idx = clang_createIndex(1, 1);
*
@@ -198,6 +172,7 @@ CINDEX_LINKAGE void clang_disposeString(CXString string);
* clang_visitChildren(clang_getTranslationUnitCursor(TU),
* TranslationUnitVisitor, 0);
* clang_disposeTranslationUnit(TU);
+ * \endcode
*
* This process of creating the 'pch', loading it separately, and using it (via
* -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
@@ -223,16 +198,18 @@ typedef enum {
/**
* \brief Used to indicate that threads that libclang creates for indexing
* purposes should use background priority.
- * Affects \see clang_indexSourceFile, \see clang_indexTranslationUnit,
- * \see clang_parseTranslationUnit, \see clang_saveTranslationUnit.
+ *
+ * Affects #clang_indexSourceFile, #clang_indexTranslationUnit,
+ * #clang_parseTranslationUnit, #clang_saveTranslationUnit.
*/
CXGlobalOpt_ThreadBackgroundPriorityForIndexing = 0x1,
/**
* \brief Used to indicate that threads that libclang creates for editing
* purposes should use background priority.
- * Affects \see clang_reparseTranslationUnit, \see clang_codeCompleteAt,
- * \see clang_annotateTokens
+ *
+ * Affects #clang_reparseTranslationUnit, #clang_codeCompleteAt,
+ * #clang_annotateTokens
*/
CXGlobalOpt_ThreadBackgroundPriorityForEditing = 0x2,
@@ -247,7 +224,7 @@ typedef enum {
} CXGlobalOptFlags;
/**
- * \brief Sets general options associated with a CXIndex.
+ * \brief Sets general options associated with a CXIndex.
*
* For example:
* \code
@@ -294,7 +271,7 @@ CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/**
* \brief Determine whether the given header is guarded against
* multiple inclusions, either with the conventional
- * #ifndef/#define/#endif macro guards or with #pragma once.
+ * \#ifndef/\#define/\#endif macro guards or with \#pragma once.
*/
CINDEX_LINKAGE unsigned
clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
@@ -359,7 +336,7 @@ typedef struct {
CINDEX_LINKAGE CXSourceLocation clang_getNullLocation();
/**
- * \determine Determine whether two source locations, which must refer into
+ * \brief Determine whether two source locations, which must refer into
* the same translation unit, refer to exactly the same point in the source
* code.
*
@@ -444,12 +421,14 @@ CINDEX_LINKAGE void clang_getExpansionLocation(CXSourceLocation location,
*
* Example: given the following source code in a file somefile.c
*
+ * \code
* #123 "dummy.c" 1
*
* static int func(void)
* {
* return 0;
* }
+ * \endcode
*
* the location information returned by this function would be
*
@@ -486,7 +465,7 @@ CINDEX_LINKAGE void clang_getPresumedLocation(CXSourceLocation location,
* by the given source location.
*
* This interface has been replaced by the newer interface
- * \see clang_getExpansionLocation(). See that interface's documentation for
+ * #clang_getExpansionLocation(). See that interface's documentation for
* details.
*/
CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
@@ -599,7 +578,7 @@ CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
/**
* \brief Retrieve a diagnostic associated with the given CXDiagnosticSet.
*
- * \param Unit the CXDiagnosticSet to query.
+ * \param Diags the CXDiagnosticSet to query.
* \param Index the zero-based diagnostic number to retrieve.
*
* \returns the requested diagnostic. This diagnostic must be freed
@@ -633,23 +612,23 @@ enum CXLoadDiag_Error {
/**
* \brief Indicates that the serialized diagnostics file is invalid or
- * corrupt.
+ * corrupt.
*/
CXLoadDiag_InvalidFile = 3
};
/**
* \brief Deserialize a set of diagnostics from a Clang diagnostics bitcode
- * file.
+ * file.
*
- * \param The name of the file to deserialize.
- * \param A pointer to a enum value recording if there was a problem
+ * \param file The name of the file to deserialize.
+ * \param error A pointer to a enum value recording if there was a problem
* deserializing the diagnostics.
- * \param A pointer to a CXString for recording the error string
+ * \param errorString A pointer to a CXString for recording the error string
* if the file was not successfully loaded.
*
* \returns A loaded CXDiagnosticSet if successful, and NULL otherwise. These
- * diagnostics should be released using clang_disposeDiagnosticSet().
+ * diagnostics should be released using clang_disposeDiagnosticSet().
*/
CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(const char *file,
enum CXLoadDiag_Error *error,
@@ -661,8 +640,10 @@ CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(const char *file,
CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
/**
- * \brief Retrieve the child diagnostics of a CXDiagnostic. This
- * CXDiagnosticSet does not need to be released by clang_diposeDiagnosticSet.
+ * \brief Retrieve the child diagnostics of a CXDiagnostic.
+ *
+ * This CXDiagnosticSet does not need to be released by
+ * clang_diposeDiagnosticSet.
*/
CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
@@ -855,7 +836,6 @@ CXString clang_getDiagnosticCategoryName(unsigned Category);
/**
* \brief Retrieve the diagnostic category text for a given diagnostic.
*
- *
* \returns The text of the given diagnostic category.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic);
@@ -951,12 +931,12 @@ clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
* '-c'
* '-emit-ast'
* '-fsyntax-only'
- * '-o <output file>' (both '-o' and '<output file>' are ignored)
+ * '-o \<output file>' (both '-o' and '\<output file>' are ignored)
*
* \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
+ * \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 num_clang_command_line_args The number of command-line arguments in
@@ -966,7 +946,7 @@ clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
* passed to the \c clang executable if it were being invoked out-of-process.
* These command-line options will be parsed and will affect how the translation
* unit is parsed. Note that the following options are ignored: '-c',
- * '-emit-ast', '-fsyntex-only' (which is the default), and '-o <output file>'.
+ * '-emit-ast', '-fsyntax-only' (which is the default), and '-o \<output file>'.
*
* \param num_unsaved_files the number of unsaved file entries in \p
* unsaved_files.
@@ -1078,7 +1058,14 @@ enum CXTranslationUnit_Flags {
* This option can be used to search for declarations/definitions while
* ignoring the usages.
*/
- CXTranslationUnit_SkipFunctionBodies = 0x40
+ CXTranslationUnit_SkipFunctionBodies = 0x40,
+
+ /**
+ * \brief Used to indicate that brief documentation comments should be
+ * included into the set of code completions returned from this translation
+ * unit.
+ */
+ CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 0x80
};
/**
@@ -1115,7 +1102,7 @@ CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);
* passed to the \c clang executable if it were being invoked out-of-process.
* These command-line options will be parsed and will affect how the translation
* unit is parsed. Note that the following options are ignored: '-c',
- * '-emit-ast', '-fsyntex-only' (which is the default), and '-o <output file>'.
+ * '-emit-ast', '-fsyntax-only' (which is the default), and '-o \<output file>'.
*
* \param num_command_line_args The number of command-line arguments in
* \p command_line_args.
@@ -1411,13 +1398,13 @@ enum CXCursorKind {
CXCursor_VarDecl = 9,
/** \brief A function or method parameter. */
CXCursor_ParmDecl = 10,
- /** \brief An Objective-C @interface. */
+ /** \brief An Objective-C \@interface. */
CXCursor_ObjCInterfaceDecl = 11,
- /** \brief An Objective-C @interface for a category. */
+ /** \brief An Objective-C \@interface for a category. */
CXCursor_ObjCCategoryDecl = 12,
- /** \brief An Objective-C @protocol declaration. */
+ /** \brief An Objective-C \@protocol declaration. */
CXCursor_ObjCProtocolDecl = 13,
- /** \brief An Objective-C @property declaration. */
+ /** \brief An Objective-C \@property declaration. */
CXCursor_ObjCPropertyDecl = 14,
/** \brief An Objective-C instance variable. */
CXCursor_ObjCIvarDecl = 15,
@@ -1425,9 +1412,9 @@ enum CXCursorKind {
CXCursor_ObjCInstanceMethodDecl = 16,
/** \brief An Objective-C class method. */
CXCursor_ObjCClassMethodDecl = 17,
- /** \brief An Objective-C @implementation. */
+ /** \brief An Objective-C \@implementation. */
CXCursor_ObjCImplementationDecl = 18,
- /** \brief An Objective-C @implementation for a category. */
+ /** \brief An Objective-C \@implementation for a category. */
CXCursor_ObjCCategoryImplDecl = 19,
/** \brief A typedef */
CXCursor_TypedefDecl = 20,
@@ -1463,9 +1450,9 @@ enum CXCursorKind {
CXCursor_UsingDeclaration = 35,
/** \brief A C++ alias declaration */
CXCursor_TypeAliasDecl = 36,
- /** \brief An Objective-C @synthesize definition. */
+ /** \brief An Objective-C \@synthesize definition. */
CXCursor_ObjCSynthesizeDecl = 37,
- /** \brief An Objective-C @dynamic definition. */
+ /** \brief An Objective-C \@dynamic definition. */
CXCursor_ObjCDynamicDecl = 38,
/** \brief An access specifier. */
CXCursor_CXXAccessSpecifier = 39,
@@ -1768,15 +1755,15 @@ enum CXCursorKind {
*/
CXCursor_ObjCStringLiteral = 137,
- /** \brief An Objective-C @encode expression.
+ /** \brief An Objective-C \@encode expression.
*/
CXCursor_ObjCEncodeExpr = 138,
- /** \brief An Objective-C @selector expression.
+ /** \brief An Objective-C \@selector expression.
*/
CXCursor_ObjCSelectorExpr = 139,
- /** \brief An Objective-C @protocol expression.
+ /** \brief An Objective-C \@protocol expression.
*/
CXCursor_ObjCProtocolExpr = 140,
@@ -1921,23 +1908,23 @@ enum CXCursorKind {
*/
CXCursor_AsmStmt = 215,
- /** \brief Objective-C's overall @try-@catch-@finally statement.
+ /** \brief Objective-C's overall \@try-\@catch-\@finally statement.
*/
CXCursor_ObjCAtTryStmt = 216,
- /** \brief Objective-C's @catch statement.
+ /** \brief Objective-C's \@catch statement.
*/
CXCursor_ObjCAtCatchStmt = 217,
- /** \brief Objective-C's @finally statement.
+ /** \brief Objective-C's \@finally statement.
*/
CXCursor_ObjCAtFinallyStmt = 218,
- /** \brief Objective-C's @throw statement.
+ /** \brief Objective-C's \@throw statement.
*/
CXCursor_ObjCAtThrowStmt = 219,
- /** \brief Objective-C's @synchronized statement.
+ /** \brief Objective-C's \@synchronized statement.
*/
CXCursor_ObjCAtSynchronizedStmt = 220,
@@ -1973,6 +1960,10 @@ enum CXCursorKind {
*/
CXCursor_SEHFinallyStmt = 228,
+ /** \brief A MS inline assembly statement extension.
+ */
+ CXCursor_MSAsmStmt = 229,
+
/** \brief The null satement ";": C99 6.8.3p3.
*
* This cursor kind is used to describe the null statement.
@@ -2046,6 +2037,13 @@ typedef struct {
} CXCursor;
/**
+ * \brief A comment AST node.
+ */
+typedef struct {
+ const void *Data;
+} CXComment;
+
+/**
* \defgroup CINDEX_CURSOR_MANIP Cursor manipulations
*
* @{
@@ -2165,7 +2163,8 @@ enum CXLinkageKind {
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
/**
- * \brief Determine the availability of the entity that this cursor refers to.
+ * \brief Determine the availability of the entity that this cursor refers to,
+ * taking the current target platform into account.
*
* \param cursor The cursor to query.
*
@@ -2175,6 +2174,94 @@ CINDEX_LINKAGE enum CXAvailabilityKind
clang_getCursorAvailability(CXCursor cursor);
/**
+ * Describes the availability of a given entity on a particular platform, e.g.,
+ * a particular class might only be available on Mac OS 10.7 or newer.
+ */
+typedef struct CXPlatformAvailability {
+ /**
+ * \brief A string that describes the platform for which this structure
+ * provides availability information.
+ *
+ * Possible values are "ios" or "macosx".
+ */
+ CXString Platform;
+ /**
+ * \brief The version number in which this entity was introduced.
+ */
+ CXVersion Introduced;
+ /**
+ * \brief The version number in which this entity was deprecated (but is
+ * still available).
+ */
+ CXVersion Deprecated;
+ /**
+ * \brief The version number in which this entity was obsoleted, and therefore
+ * is no longer available.
+ */
+ CXVersion Obsoleted;
+ /**
+ * \brief Whether the entity is unconditionally unavailable on this platform.
+ */
+ int Unavailable;
+ /**
+ * \brief An optional message to provide to a user of this API, e.g., to
+ * suggest replacement APIs.
+ */
+ CXString Message;
+} CXPlatformAvailability;
+
+/**
+ * \brief Determine the availability of the entity that this cursor refers to
+ * on any platforms for which availability information is known.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \param always_deprecated If non-NULL, will be set to indicate whether the
+ * entity is deprecated on all platforms.
+ *
+ * \param deprecated_message If non-NULL, will be set to the message text
+ * provided along with the unconditional deprecation of this entity. The client
+ * is responsible for deallocating this string.
+ *
+ * \param always_unavailable If non-NULL, will be set to indicate whether the
+ * entity is unavailable on all platforms.
+ *
+ * \param unavailable_message If non-NULL, will be set to the message text
+ * provided along with the unconditional unavailability of this entity. The
+ * client is responsible for deallocating this string.
+ *
+ * \param availability If non-NULL, an array of CXPlatformAvailability instances
+ * that will be populated with platform availability information, up to either
+ * the number of platforms for which availability information is available (as
+ * returned by this function) or \c availability_size, whichever is smaller.
+ *
+ * \param availability_size The number of elements available in the
+ * \c availability array.
+ *
+ * \returns The number of platforms (N) for which availability information is
+ * available (which is unrelated to \c availability_size).
+ *
+ * Note that the client is responsible for calling
+ * \c clang_disposeCXPlatformAvailability to free each of the
+ * platform-availability structures returned. There are
+ * \c min(N, availability_size) such structures.
+ */
+CINDEX_LINKAGE int
+clang_getCursorPlatformAvailability(CXCursor cursor,
+ int *always_deprecated,
+ CXString *deprecated_message,
+ int *always_unavailable,
+ CXString *unavailable_message,
+ CXPlatformAvailability *availability,
+ int availability_size);
+
+/**
+ * \brief Free the memory associated with a \c CXPlatformAvailability structure.
+ */
+CINDEX_LINKAGE void
+clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability);
+
+/**
* \brief Describe the "language" of the entity referred to by a cursor.
*/
CINDEX_LINKAGE enum CXLanguageKind {
@@ -2571,10 +2658,10 @@ CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C);
CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i);
/**
- * \determine Determine whether two CXTypes represent the same type.
+ * \brief Determine whether two CXTypes represent the same type.
*
- * \returns non-zero if the CXTypes represent the same type and
- zero otherwise.
+ * \returns non-zero if the CXTypes represent the same type and
+ * zero otherwise.
*/
CINDEX_LINKAGE unsigned clang_equalTypes(CXType A, CXType B);
@@ -2589,26 +2676,28 @@ CINDEX_LINKAGE unsigned clang_equalTypes(CXType A, CXType B);
CINDEX_LINKAGE CXType clang_getCanonicalType(CXType T);
/**
- * \determine Determine whether a CXType has the "const" qualifier set,
- * without looking through typedefs that may have added "const" at a different level.
+ * \brief Determine whether a CXType has the "const" qualifier set,
+ * without looking through typedefs that may have added "const" at a
+ * different level.
*/
CINDEX_LINKAGE unsigned clang_isConstQualifiedType(CXType T);
/**
- * \determine Determine whether a CXType has the "volatile" qualifier set,
- * without looking through typedefs that may have added "volatile" at a different level.
+ * \brief Determine whether a CXType has the "volatile" qualifier set,
+ * without looking through typedefs that may have added "volatile" at
+ * a different level.
*/
CINDEX_LINKAGE unsigned clang_isVolatileQualifiedType(CXType T);
/**
- * \determine Determine whether a CXType has the "restrict" qualifier set,
- * without looking through typedefs that may have added "restrict" at a different level.
+ * \brief Determine whether a CXType has the "restrict" qualifier set,
+ * without looking through typedefs that may have added "restrict" at a
+ * different level.
*/
CINDEX_LINKAGE unsigned clang_isRestrictQualifiedType(CXType T);
/**
* \brief For pointer types, returns the type of the pointee.
- *
*/
CINDEX_LINKAGE CXType clang_getPointeeType(CXType T);
@@ -2642,7 +2731,8 @@ CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T);
CINDEX_LINKAGE CXType clang_getResultType(CXType T);
/**
- * \brief Retrieve the number of non-variadic arguments associated with a function type.
+ * \brief Retrieve the number of non-variadic arguments associated with a
+ * function type.
*
* If a non-function type is passed in, -1 is returned.
*/
@@ -2651,14 +2741,13 @@ CINDEX_LINKAGE int clang_getNumArgTypes(CXType T);
/**
* \brief Retrieve the type of an argument of a function type.
*
- * If a non-function type is passed in or the function does not have enough parameters,
- * an invalid type is returned.
+ * If a non-function type is passed in or the function does not have enough
+ * parameters, an invalid type is returned.
*/
CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i);
/**
* \brief Return 1 if the CXType is a variadic function type, and 0 otherwise.
- *
*/
CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T);
@@ -2699,7 +2788,7 @@ CINDEX_LINKAGE long long clang_getNumElements(CXType T);
CINDEX_LINKAGE CXType clang_getArrayElementType(CXType T);
/**
- * \brief Return the the array size of a constant array.
+ * \brief Return the array size of a constant array.
*
* If a non-array type is passed in, -1 is returned.
*/
@@ -3052,7 +3141,7 @@ CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor);
* \brief If the cursor points to a selector identifier in a objc method or
* message expression, this returns the selector index.
*
- * After getting a cursor with \see clang_getCursor, this can be called to
+ * After getting a cursor with #clang_getCursor, this can be called to
* determine if the location points to a selector identifier.
*
* \returns The selector index if the cursor is an objc method or message
@@ -3062,6 +3151,557 @@ CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor);
CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
/**
+ * \brief Given a cursor pointing to a C++ method call or an ObjC message,
+ * returns non-zero if the method/message is "dynamic", meaning:
+ *
+ * For a C++ method: the call is virtual.
+ * For an ObjC message: the receiver is an object instance, not 'super' or a
+ * specific class.
+ *
+ * If the method/message is "static" or the cursor does not point to a
+ * method/message, it will return zero.
+ */
+CINDEX_LINKAGE int clang_Cursor_isDynamicCall(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents a declaration, return the associated
+ * comment's source range. The range may include multiple consecutive comments
+ * with whitespace in between.
+ */
+CINDEX_LINKAGE CXSourceRange clang_Cursor_getCommentRange(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents a declaration, return the associated
+ * comment text, including comment markers.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getRawCommentText(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents a documentable entity (e.g.,
+ * declaration), return the associated \\brief paragraph; otherwise return the
+ * first paragraph.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents a documentable entity (e.g.,
+ * declaration), return the associated parsed comment as a
+ * \c CXComment_FullComment AST node.
+ */
+CINDEX_LINKAGE CXComment clang_Cursor_getParsedComment(CXCursor C);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_COMMENT Comment AST introspection
+ *
+ * The routines in this group provide access to information in the
+ * documentation comment ASTs.
+ *
+ * @{
+ */
+
+/**
+ * \brief Describes the type of the comment AST node (\c CXComment). A comment
+ * node can be considered block content (e. g., paragraph), inline content
+ * (plain text) or neither (the root AST node).
+ */
+enum CXCommentKind {
+ /**
+ * \brief Null comment. No AST node is constructed at the requested location
+ * because there is no text or a syntax error.
+ */
+ CXComment_Null = 0,
+
+ /**
+ * \brief Plain text. Inline content.
+ */
+ CXComment_Text = 1,
+
+ /**
+ * \brief A command with word-like arguments that is considered inline content.
+ *
+ * For example: \\c command.
+ */
+ CXComment_InlineCommand = 2,
+
+ /**
+ * \brief HTML start tag with attributes (name-value pairs). Considered
+ * inline content.
+ *
+ * For example:
+ * \verbatim
+ * <br> <br /> <a href="http://example.org/">
+ * \endverbatim
+ */
+ CXComment_HTMLStartTag = 3,
+
+ /**
+ * \brief HTML end tag. Considered inline content.
+ *
+ * For example:
+ * \verbatim
+ * </a>
+ * \endverbatim
+ */
+ CXComment_HTMLEndTag = 4,
+
+ /**
+ * \brief A paragraph, contains inline comment. The paragraph itself is
+ * block content.
+ */
+ CXComment_Paragraph = 5,
+
+ /**
+ * \brief A command that has zero or more word-like arguments (number of
+ * word-like arguments depends on command name) and a paragraph as an
+ * argument. Block command is block content.
+ *
+ * Paragraph argument is also a child of the block command.
+ *
+ * For example: \\brief has 0 word-like arguments and a paragraph argument.
+ *
+ * AST nodes of special kinds that parser knows about (e. g., \\param
+ * command) have their own node kinds.
+ */
+ CXComment_BlockCommand = 6,
+
+ /**
+ * \brief A \\param or \\arg command that describes the function parameter
+ * (name, passing direction, description).
+ *
+ * \brief For example: \\param [in] ParamName description.
+ */
+ CXComment_ParamCommand = 7,
+
+ /**
+ * \brief A \\tparam command that describes a template parameter (name and
+ * description).
+ *
+ * \brief For example: \\tparam T description.
+ */
+ CXComment_TParamCommand = 8,
+
+ /**
+ * \brief A verbatim block command (e. g., preformatted code). Verbatim
+ * block has an opening and a closing command and contains multiple lines of
+ * text (\c CXComment_VerbatimBlockLine child nodes).
+ *
+ * For example:
+ * \\verbatim
+ * aaa
+ * \\endverbatim
+ */
+ CXComment_VerbatimBlockCommand = 9,
+
+ /**
+ * \brief A line of text that is contained within a
+ * CXComment_VerbatimBlockCommand node.
+ */
+ CXComment_VerbatimBlockLine = 10,
+
+ /**
+ * \brief A verbatim line command. Verbatim line has an opening command,
+ * a single line of text (up to the newline after the opening command) and
+ * has no closing command.
+ */
+ CXComment_VerbatimLine = 11,
+
+ /**
+ * \brief A full comment attached to a declaration, contains block content.
+ */
+ CXComment_FullComment = 12
+};
+
+/**
+ * \brief The most appropriate rendering mode for an inline command, chosen on
+ * command semantics in Doxygen.
+ */
+enum CXCommentInlineCommandRenderKind {
+ /**
+ * \brief Command argument should be rendered in a normal font.
+ */
+ CXCommentInlineCommandRenderKind_Normal,
+
+ /**
+ * \brief Command argument should be rendered in a bold font.
+ */
+ CXCommentInlineCommandRenderKind_Bold,
+
+ /**
+ * \brief Command argument should be rendered in a monospaced font.
+ */
+ CXCommentInlineCommandRenderKind_Monospaced,
+
+ /**
+ * \brief Command argument should be rendered emphasized (typically italic
+ * font).
+ */
+ CXCommentInlineCommandRenderKind_Emphasized
+};
+
+/**
+ * \brief Describes parameter passing direction for \\param or \\arg command.
+ */
+enum CXCommentParamPassDirection {
+ /**
+ * \brief The parameter is an input parameter.
+ */
+ CXCommentParamPassDirection_In,
+
+ /**
+ * \brief The parameter is an output parameter.
+ */
+ CXCommentParamPassDirection_Out,
+
+ /**
+ * \brief The parameter is an input and output parameter.
+ */
+ CXCommentParamPassDirection_InOut
+};
+
+/**
+ * \param Comment AST node of any kind.
+ *
+ * \returns the type of the AST node.
+ */
+CINDEX_LINKAGE enum CXCommentKind clang_Comment_getKind(CXComment Comment);
+
+/**
+ * \param Comment AST node of any kind.
+ *
+ * \returns number of children of the AST node.
+ */
+CINDEX_LINKAGE unsigned clang_Comment_getNumChildren(CXComment Comment);
+
+/**
+ * \param Comment AST node of any kind.
+ *
+ * \param ArgIdx argument index (zero-based).
+ *
+ * \returns the specified child of the AST node.
+ */
+CINDEX_LINKAGE
+CXComment clang_Comment_getChild(CXComment Comment, unsigned ChildIdx);
+
+/**
+ * \brief A \c CXComment_Paragraph node is considered whitespace if it contains
+ * only \c CXComment_Text nodes that are empty or whitespace.
+ *
+ * Other AST nodes (except \c CXComment_Paragraph and \c CXComment_Text) are
+ * never considered whitespace.
+ *
+ * \returns non-zero if \c Comment is whitespace.
+ */
+CINDEX_LINKAGE unsigned clang_Comment_isWhitespace(CXComment Comment);
+
+/**
+ * \returns non-zero if \c Comment is inline content and has a newline
+ * immediately following it in the comment text. Newlines between paragraphs
+ * do not count.
+ */
+CINDEX_LINKAGE
+unsigned clang_InlineContentComment_hasTrailingNewline(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_Text AST node.
+ *
+ * \returns text contained in the AST node.
+ */
+CINDEX_LINKAGE CXString clang_TextComment_getText(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \returns name of the inline command.
+ */
+CINDEX_LINKAGE
+CXString clang_InlineCommandComment_getCommandName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \returns the most appropriate rendering mode, chosen on command
+ * semantics in Doxygen.
+ */
+CINDEX_LINKAGE enum CXCommentInlineCommandRenderKind
+clang_InlineCommandComment_getRenderKind(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \returns number of command arguments.
+ */
+CINDEX_LINKAGE
+unsigned clang_InlineCommandComment_getNumArgs(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \param ArgIdx argument index (zero-based).
+ *
+ * \returns text of the specified argument.
+ */
+CINDEX_LINKAGE
+CXString clang_InlineCommandComment_getArgText(CXComment Comment,
+ unsigned ArgIdx);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST
+ * node.
+ *
+ * \returns HTML tag name.
+ */
+CINDEX_LINKAGE CXString clang_HTMLTagComment_getTagName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \returns non-zero if tag is self-closing (for example, &lt;br /&gt;).
+ */
+CINDEX_LINKAGE
+unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \returns number of attributes (name-value pairs) attached to the start tag.
+ */
+CINDEX_LINKAGE unsigned clang_HTMLStartTag_getNumAttrs(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \param AttrIdx attribute index (zero-based).
+ *
+ * \returns name of the specified attribute.
+ */
+CINDEX_LINKAGE
+CXString clang_HTMLStartTag_getAttrName(CXComment Comment, unsigned AttrIdx);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \param AttrIdx attribute index (zero-based).
+ *
+ * \returns value of the specified attribute.
+ */
+CINDEX_LINKAGE
+CXString clang_HTMLStartTag_getAttrValue(CXComment Comment, unsigned AttrIdx);
+
+/**
+ * \param Comment a \c CXComment_BlockCommand AST node.
+ *
+ * \returns name of the block command.
+ */
+CINDEX_LINKAGE
+CXString clang_BlockCommandComment_getCommandName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_BlockCommand AST node.
+ *
+ * \returns number of word-like arguments.
+ */
+CINDEX_LINKAGE
+unsigned clang_BlockCommandComment_getNumArgs(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_BlockCommand AST node.
+ *
+ * \param ArgIdx argument index (zero-based).
+ *
+ * \returns text of the specified word-like argument.
+ */
+CINDEX_LINKAGE
+CXString clang_BlockCommandComment_getArgText(CXComment Comment,
+ unsigned ArgIdx);
+
+/**
+ * \param Comment a \c CXComment_BlockCommand or
+ * \c CXComment_VerbatimBlockCommand AST node.
+ *
+ * \returns paragraph argument of the block command.
+ */
+CINDEX_LINKAGE
+CXComment clang_BlockCommandComment_getParagraph(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns parameter name.
+ */
+CINDEX_LINKAGE
+CXString clang_ParamCommandComment_getParamName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns non-zero if the parameter that this AST node represents was found
+ * in the function prototype and \c clang_ParamCommandComment_getParamIndex
+ * function will return a meaningful value.
+ */
+CINDEX_LINKAGE
+unsigned clang_ParamCommandComment_isParamIndexValid(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns zero-based parameter index in function prototype.
+ */
+CINDEX_LINKAGE
+unsigned clang_ParamCommandComment_getParamIndex(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns non-zero if parameter passing direction was specified explicitly in
+ * the comment.
+ */
+CINDEX_LINKAGE
+unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns parameter passing direction.
+ */
+CINDEX_LINKAGE
+enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(
+ CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns template parameter name.
+ */
+CINDEX_LINKAGE
+CXString clang_TParamCommandComment_getParamName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns non-zero if the parameter that this AST node represents was found
+ * in the template parameter list and
+ * \c clang_TParamCommandComment_getDepth and
+ * \c clang_TParamCommandComment_getIndex functions will return a meaningful
+ * value.
+ */
+CINDEX_LINKAGE
+unsigned clang_TParamCommandComment_isParamPositionValid(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns zero-based nesting depth of this parameter in the template parameter list.
+ *
+ * For example,
+ * \verbatim
+ * template<typename C, template<typename T> class TT>
+ * void test(TT<int> aaa);
+ * \endverbatim
+ * for C and TT nesting depth is 0,
+ * for T nesting depth is 1.
+ */
+CINDEX_LINKAGE
+unsigned clang_TParamCommandComment_getDepth(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns zero-based parameter index in the template parameter list at a
+ * given nesting depth.
+ *
+ * For example,
+ * \verbatim
+ * template<typename C, template<typename T> class TT>
+ * void test(TT<int> aaa);
+ * \endverbatim
+ * for C and TT nesting depth is 0, so we can ask for index at depth 0:
+ * at depth 0 C's index is 0, TT's index is 1.
+ *
+ * For T nesting depth is 1, so we can ask for index at depth 0 and 1:
+ * at depth 0 T's index is 1 (same as TT's),
+ * at depth 1 T's index is 0.
+ */
+CINDEX_LINKAGE
+unsigned clang_TParamCommandComment_getIndex(CXComment Comment, unsigned Depth);
+
+/**
+ * \param Comment a \c CXComment_VerbatimBlockLine AST node.
+ *
+ * \returns text contained in the AST node.
+ */
+CINDEX_LINKAGE
+CXString clang_VerbatimBlockLineComment_getText(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_VerbatimLine AST node.
+ *
+ * \returns text contained in the AST node.
+ */
+CINDEX_LINKAGE CXString clang_VerbatimLineComment_getText(CXComment Comment);
+
+/**
+ * \brief Convert an HTML tag AST node to string.
+ *
+ * \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST
+ * node.
+ *
+ * \returns string containing an HTML tag.
+ */
+CINDEX_LINKAGE CXString clang_HTMLTagComment_getAsString(CXComment Comment);
+
+/**
+ * \brief Convert a given full parsed comment to an HTML fragment.
+ *
+ * Specific details of HTML layout are subject to change. Don't try to parse
+ * this HTML back into an AST, use other APIs instead.
+ *
+ * Currently the following CSS classes are used:
+ * \li "para-brief" for \\brief paragraph and equivalent commands;
+ * \li "para-returns" for \\returns paragraph and equivalent commands;
+ * \li "word-returns" for the "Returns" word in \\returns paragraph.
+ *
+ * Function argument documentation is rendered as a \<dl\> list with arguments
+ * sorted in function prototype order. CSS classes used:
+ * \li "param-name-index-NUMBER" for parameter name (\<dt\>);
+ * \li "param-descr-index-NUMBER" for parameter description (\<dd\>);
+ * \li "param-name-index-invalid" and "param-descr-index-invalid" are used if
+ * parameter index is invalid.
+ *
+ * Template parameter documentation is rendered as a \<dl\> list with
+ * parameters sorted in template parameter list order. CSS classes used:
+ * \li "tparam-name-index-NUMBER" for parameter name (\<dt\>);
+ * \li "tparam-descr-index-NUMBER" for parameter description (\<dd\>);
+ * \li "tparam-name-index-other" and "tparam-descr-index-other" are used for
+ * names inside template template parameters;
+ * \li "tparam-name-index-invalid" and "tparam-descr-index-invalid" are used if
+ * parameter position is invalid.
+ *
+ * \param Comment a \c CXComment_FullComment AST node.
+ *
+ * \returns string containing an HTML fragment.
+ */
+CINDEX_LINKAGE CXString clang_FullComment_getAsHTML(CXComment Comment);
+
+/**
+ * \brief Convert a given full parsed comment to an XML document.
+ *
+ * A Relax NG schema for the XML can be found in comment-xml-schema.rng file
+ * inside clang source tree.
+ *
+ * \param TU the translation unit \c Comment belongs to.
+ *
+ * \param Comment a \c CXComment_FullComment AST node.
+ *
+ * \returns string containing an XML document.
+ */
+CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXTranslationUnit TU,
+ CXComment Comment);
+
+/**
* @}
*/
@@ -3148,7 +3788,7 @@ CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
* \param PieceIndex For contiguous names or when passing the flag
* CXNameRange_WantSinglePiece, only one piece with index 0 is
* available. When the CXNameRange_WantSinglePiece flag is not passed for a
- * non-contiguous names, this index can be used to retreive the individual
+ * non-contiguous names, this index can be used to retrieve the individual
* pieces of the name. See also CXNameRange_WantSinglePiece.
*
* \returns The piece of the name pointed to by the given cursor. If there is no
@@ -3166,8 +3806,8 @@ enum CXNameRefFlags {
CXNameRange_WantQualifier = 0x1,
/**
- * \brief Include the explicit template arguments, e.g. <int> in x.f<int>, in
- * the range.
+ * \brief Include the explicit template arguments, e.g. \<int> in x.f<int>,
+ * in the range.
*/
CXNameRange_WantTemplateArgs = 0x2,
@@ -3686,12 +4326,20 @@ clang_getCompletionAnnotation(CXCompletionString completion_string,
* \param kind If non-NULL, will be set to the kind of the parent context,
* or CXCursor_NotImplemented if there is no context.
*
- * \param Returns the name of the completion parent, e.g., "NSObject" if
+ * \returns The name of the completion parent, e.g., "NSObject" if
* the completion string represents a method in the NSObject class.
*/
CINDEX_LINKAGE CXString
clang_getCompletionParent(CXCompletionString completion_string,
enum CXCursorKind *kind);
+
+/**
+ * \brief Retrieve the brief documentation comment attached to the declaration
+ * that corresponds to the given completion string.
+ */
+CINDEX_LINKAGE CXString
+clang_getCompletionBriefComment(CXCompletionString completion_string);
+
/**
* \brief Retrieve a completion string for an arbitrary declaration or macro
* definition cursor.
@@ -3742,7 +4390,13 @@ enum CXCodeComplete_Flags {
* \brief Whether to include code patterns for language constructs
* within the set of code completions, e.g., for loops.
*/
- CXCodeComplete_IncludeCodePatterns = 0x02
+ CXCodeComplete_IncludeCodePatterns = 0x02,
+
+ /**
+ * \brief Whether to include brief documentation within the set of code
+ * completions returned.
+ */
+ CXCodeComplete_IncludeBriefComments = 0x04
};
/**
@@ -3986,7 +4640,7 @@ unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results);
/**
* \brief Retrieve a diagnostic associated with the given code completion.
*
- * \param Result the code completion results to query.
+ * \param Results the code completion results to query.
* \param Index the zero-based diagnostic number to retrieve.
*
* \returns the requested diagnostic. This diagnostic must be freed
@@ -4078,8 +4732,8 @@ CINDEX_LINKAGE CXString clang_getClangVersion();
/**
* \brief Enable/disable crash recovery.
*
- * \param Flag to indicate if crash recovery is enabled. A non-zero value
- * enables crash recovery, while 0 disables it.
+ * \param isEnabled Flag to indicate if crash recovery is enabled. A non-zero
+ * value enables crash recovery, while 0 disables it.
*/
CINDEX_LINKAGE void clang_toggleCrashRecovery(unsigned isEnabled);
@@ -4088,7 +4742,7 @@ CINDEX_LINKAGE void clang_toggleCrashRecovery(unsigned isEnabled);
* (used with clang_getInclusions()).
*
* This visitor function will be invoked by clang_getInclusions() for each
- * file included (either at the top-level or by #include directives) within
+ * file included (either at the top-level or by \#include directives) within
* a translation unit. The first argument is the file being included, and
* the second and third arguments provide the inclusion stack. The
* array is sorted in order of immediate inclusion. For example,
@@ -4246,19 +4900,19 @@ typedef struct {
} CXIdxLoc;
/**
- * \brief Data for \see ppIncludedFile callback.
+ * \brief Data for ppIncludedFile callback.
*/
typedef struct {
/**
- * \brief Location of '#' in the #include/#import directive.
+ * \brief Location of '#' in the \#include/\#import directive.
*/
CXIdxLoc hashLoc;
/**
- * \brief Filename as written in the #include/#import directive.
+ * \brief Filename as written in the \#include/\#import directive.
*/
const char *filename;
/**
- * \brief The actual file that the #include/#import directive resolved to.
+ * \brief The actual file that the \#include/\#import directive resolved to.
*/
CXFile file;
int isImport;
@@ -4266,7 +4920,7 @@ typedef struct {
} CXIdxIncludedFileInfo;
/**
- * \brief Data for \see importedASTFile callback.
+ * \brief Data for IndexerCallbacks#importedASTFile.
*/
typedef struct {
CXFile file;
@@ -4380,7 +5034,7 @@ typedef struct {
CXIdxLoc loc;
const CXIdxContainerInfo *semanticContainer;
/**
- * \brief Generally same as \see semanticContainer but can be different in
+ * \brief Generally same as #semanticContainer but can be different in
* cases like out-of-line C++ member functions.
*/
const CXIdxContainerInfo *lexicalContainer;
@@ -4452,7 +5106,7 @@ typedef struct {
} CXIdxCXXClassDeclInfo;
/**
- * \brief Data for \see indexEntityReference callback.
+ * \brief Data for IndexerCallbacks#indexEntityReference.
*/
typedef enum {
/**
@@ -4467,7 +5121,7 @@ typedef enum {
} CXIdxEntityRefKind;
/**
- * \brief Data for \see indexEntityReference callback.
+ * \brief Data for IndexerCallbacks#indexEntityReference.
*/
typedef struct {
CXIdxEntityRefKind kind;
@@ -4498,6 +5152,10 @@ typedef struct {
const CXIdxContainerInfo *container;
} CXIdxEntityRefInfo;
+/**
+ * \brief A group of callbacks used by #clang_indexSourceFile and
+ * #clang_indexTranslationUnit.
+ */
typedef struct {
/**
* \brief Called periodically to check whether indexing should be aborted.
@@ -4512,10 +5170,10 @@ typedef struct {
CXDiagnosticSet, void *reserved);
CXIdxClientFile (*enteredMainFile)(CXClientData client_data,
- CXFile mainFile, void *reserved);
+ CXFile mainFile, void *reserved);
/**
- * \brief Called when a file gets #included/#imported.
+ * \brief Called when a file gets \#included/\#imported.
*/
CXIdxClientFile (*ppIncludedFile)(CXClientData client_data,
const CXIdxIncludedFileInfo *);
@@ -4628,9 +5286,9 @@ typedef enum {
CXIndexOpt_None = 0x0,
/**
- * \brief Used to indicate that \see indexEntityReference should be invoked
- * for only one reference of an entity per source file that does not also
- * include a declaration/definition of the entity.
+ * \brief Used to indicate that IndexerCallbacks#indexEntityReference should
+ * be invoked for only one reference of an entity per source file that does
+ * not also include a declaration/definition of the entity.
*/
CXIndexOpt_SuppressRedundantRefs = 0x1,
@@ -4654,7 +5312,7 @@ typedef enum {
/**
* \brief Index the given source file and the translation unit corresponding
- * to that file via callbacks implemented through \see IndexerCallbacks.
+ * to that file via callbacks implemented through #IndexerCallbacks.
*
* \param client_data pointer data supplied by the client, which will
* be passed to the invoked callbacks.
@@ -4662,7 +5320,7 @@ typedef enum {
* \param index_callbacks Pointer to indexing callbacks that the client
* implements.
*
- * \param index_callbacks_size Size of \see IndexerCallbacks structure that gets
+ * \param index_callbacks_size Size of #IndexerCallbacks structure that gets
* passed in index_callbacks.
*
* \param index_options A bitmask of options that affects how indexing is
@@ -4674,7 +5332,7 @@ typedef enum {
* \returns If there is a failure from which the there is no recovery, returns
* non-zero, otherwise returns 0.
*
- * The rest of the parameters are the same as \see clang_parseTranslationUnit.
+ * The rest of the parameters are the same as #clang_parseTranslationUnit.
*/
CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction,
CXClientData client_data,
@@ -4691,7 +5349,7 @@ CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction,
/**
* \brief Index the given translation unit via callbacks implemented through
- * \see IndexerCallbacks.
+ * #IndexerCallbacks.
*
* The order of callback invocations is not guaranteed to be the same as
* when indexing a source file. The high level order will be:
@@ -4700,7 +5358,7 @@ CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction,
* -Declaration/reference callbacks invocations
* -Diagnostic callback invocations
*
- * The parameters are the same as \see clang_indexSourceFile.
+ * The parameters are the same as #clang_indexSourceFile.
*
* \returns If there is a failure from which the there is no recovery, returns
* non-zero, otherwise returns 0.
diff --git a/include/clang-c/Platform.h b/include/clang-c/Platform.h
new file mode 100644
index 000000000000..0f866c64563c
--- /dev/null
+++ b/include/clang-c/Platform.h
@@ -0,0 +1,45 @@
+/*===-- clang-c/Platform.h - C Index platform decls -------------*- C -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides platform specific macros (dllimport, deprecated, ...) *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef CLANG_C_PLATFORM_H
+#define CLANG_C_PLATFORM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* MSVC DLL import/export. */
+#ifdef _MSC_VER
+ #ifdef _CINDEX_LIB_
+ #define CINDEX_LINKAGE __declspec(dllexport)
+ #else
+ #define CINDEX_LINKAGE __declspec(dllimport)
+ #endif
+#else
+ #define CINDEX_LINKAGE
+#endif
+
+#ifdef __GNUC__
+ #define CINDEX_DEPRECATED __attribute__((deprecated))
+#else
+ #ifdef _MSC_VER
+ #define CINDEX_DEPRECATED __declspec(deprecated)
+ #else
+ #define CINDEX_DEPRECATED
+ #endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 96e41c5d0357..8fd7d6ef4233 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -27,6 +27,7 @@
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/CanonicalType.h"
+#include "clang/AST/RawCommentList.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -51,7 +52,6 @@ namespace clang {
class ASTMutationListener;
class IdentifierTable;
class SelectorTable;
- class SourceManager;
class TargetInfo;
class CXXABI;
// Decls
@@ -80,6 +80,10 @@ namespace clang {
namespace Builtin { class Context; }
+ namespace comments {
+ class FullComment;
+ }
+
/// ASTContext - This class holds long-lived AST nodes (such as types and
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext : public RefCountedBase<ASTContext> {
@@ -198,10 +202,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// \brief The typedef for the __uint128_t type.
mutable TypedefDecl *UInt128Decl;
- /// BuiltinVaListType - built-in va list type.
- /// This is initially null and set by Sema::LazilyCreateBuiltin when
- /// a builtin that takes a valist is encountered.
- QualType BuiltinVaListType;
+ /// \brief The typedef for the target specific predefined
+ /// __builtin_va_list type.
+ mutable TypedefDecl *BuiltinVaListDecl;
/// \brief The typedef for the predefined 'id' type.
mutable TypedefDecl *ObjCIdDecl;
@@ -392,6 +395,11 @@ public:
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
+
+ llvm::BumpPtrAllocator &getAllocator() const {
+ return BumpAlloc;
+ }
+
void *Allocate(unsigned Size, unsigned Align = 8) const {
return BumpAlloc.Allocate(Size, Align);
}
@@ -419,6 +427,85 @@ public:
return FullSourceLoc(Loc,SourceMgr);
}
+ /// \brief All comments in this translation unit.
+ RawCommentList Comments;
+
+ /// \brief True if comments are already loaded from ExternalASTSource.
+ mutable bool CommentsLoaded;
+
+ class RawCommentAndCacheFlags {
+ public:
+ enum Kind {
+ /// We searched for a comment attached to the particular declaration, but
+ /// didn't find any.
+ ///
+ /// getRaw() == 0.
+ NoCommentInDecl = 0,
+
+ /// We have found a comment attached to this particular declaration.
+ ///
+ /// getRaw() != 0.
+ FromDecl,
+
+ /// This declaration does not have an attached comment, and we have
+ /// searched the redeclaration chain.
+ ///
+ /// If getRaw() == 0, the whole redeclaration chain does not have any
+ /// comments.
+ ///
+ /// If getRaw() != 0, it is a comment propagated from other
+ /// redeclaration.
+ FromRedecl
+ };
+
+ Kind getKind() const LLVM_READONLY {
+ return Data.getInt();
+ }
+
+ void setKind(Kind K) {
+ Data.setInt(K);
+ }
+
+ const RawComment *getRaw() const LLVM_READONLY {
+ return Data.getPointer();
+ }
+
+ void setRaw(const RawComment *RC) {
+ Data.setPointer(RC);
+ }
+
+ private:
+ llvm::PointerIntPair<const RawComment *, 2, Kind> Data;
+ };
+
+ /// \brief Mapping from declarations to comments attached to any
+ /// redeclaration.
+ ///
+ /// Raw comments are owned by Comments list. This mapping is populated
+ /// lazily.
+ mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments;
+
+ /// \brief Return the documentation comment attached to a given declaration,
+ /// without looking into cache.
+ RawComment *getRawCommentForDeclNoCache(const Decl *D) const;
+
+public:
+ RawCommentList &getRawCommentList() {
+ return Comments;
+ }
+
+ void addComment(const RawComment &RC) {
+ Comments.addComment(RC, BumpAlloc);
+ }
+
+ /// \brief Return the documentation comment attached to a given declaration.
+ /// Returns NULL if no comment is attached.
+ const RawComment *getRawCommentForAnyRedecl(const Decl *D) const;
+
+ /// Return parsed documentation comment attached to a given declaration.
+ /// Returns NULL if no comment is attached.
+ comments::FullComment *getCommentForDecl(const Decl *D) const;
+
/// \brief Retrieve the attributes for the given declaration.
AttrVec& getDeclAttrs(const Decl *D);
@@ -557,6 +644,7 @@ public:
CanQualType BoolTy;
CanQualType CharTy;
CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
+ CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions.
CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
@@ -575,6 +663,10 @@ public:
mutable QualType AutoDeductTy; // Deduction against 'auto'.
mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'.
+ // Type used to help define __builtin_va_list for some targets.
+ // The type is built when constructing 'BuiltinVaListDecl'.
+ mutable QualType VaListTagTy;
+
ASTContext(LangOptions& LOpts, SourceManager &SM, const TargetInfo *t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
@@ -929,6 +1021,10 @@ public:
/// Used when in C++, as a GCC extension.
QualType getUnsignedWCharType() const;
+ /// getWIntType - In C99, this returns a type compatible with the type
+ /// defined in <stddef.h> as defined by the target.
+ QualType getWIntType() const { return WIntTy; }
+
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType getPointerDiffType() const;
@@ -1148,8 +1244,19 @@ public:
return getObjCInterfaceType(getObjCProtocolDecl());
}
- void setBuiltinVaListType(QualType T);
- QualType getBuiltinVaListType() const { return BuiltinVaListType; }
+ /// \brief Retrieve the C type declaration corresponding to the predefined
+ /// __builtin_va_list type.
+ TypedefDecl *getBuiltinVaListDecl() const;
+
+ /// \brief Retrieve the type of the __builtin_va_list type.
+ QualType getBuiltinVaListType() const {
+ return getTypeDeclType(getBuiltinVaListDecl());
+ }
+
+ /// \brief Retrieve the C type declaration corresponding to the predefined
+ /// __va_list_tag type used to help define the __builtin_va_list type for
+ /// some targets.
+ QualType getVaListTagType() const;
/// getCVRQualifiedType - Returns a type with additional const,
/// volatile, or restrict qualifiers.
@@ -1210,10 +1317,10 @@ public:
const TemplateArgument &ArgPack) const;
enum GetBuiltinTypeError {
- GE_None, //< No error
- GE_Missing_stdio, //< Missing a type from <stdio.h>
- GE_Missing_setjmp, //< Missing a type from <setjmp.h>
- GE_Missing_ucontext //< Missing a type from <ucontext.h>
+ GE_None, ///< No error
+ GE_Missing_stdio, ///< Missing a type from <stdio.h>
+ GE_Missing_setjmp, ///< Missing a type from <setjmp.h>
+ GE_Missing_ucontext ///< Missing a type from <ucontext.h>
};
/// GetBuiltinType - Return the type for the specified builtin. If
@@ -1440,15 +1547,11 @@ public:
/// \brief Retrieves the default calling convention to use for
/// C++ instance methods.
- CallingConv getDefaultMethodCallConv();
+ CallingConv getDefaultCXXMethodCallConv(bool isVariadic);
/// \brief Retrieves the canonical representation of the given
/// calling convention.
- CallingConv getCanonicalCallConv(CallingConv CC) const {
- if (!LangOpts.MRTD && CC == CC_C)
- return CC_Default;
- return CC;
- }
+ CallingConv getCanonicalCallConv(CallingConv CC) const;
/// \brief Determines whether two calling conventions name the same
/// calling convention.
@@ -1463,7 +1566,7 @@ public:
/// be used to refer to a given template. For most templates, this
/// expression is just the template declaration itself. For example,
/// the template std::vector can be referred to via a variety of
- /// names---std::vector, ::std::vector, vector (if vector is in
+ /// names---std::vector, \::std::vector, vector (if vector is in
/// scope), etc.---but all of these names map down to the same
/// TemplateDecl, which is used to form the canonical template name.
///
@@ -1523,12 +1626,12 @@ public:
/// This routine adjusts the given parameter type @p T to the actual
/// parameter type used by semantic analysis (C99 6.7.5.3p[7,8],
/// C++ [dcl.fct]p3). The adjusted parameter type is returned.
- QualType getAdjustedParameterType(QualType T);
+ QualType getAdjustedParameterType(QualType T) const;
/// \brief Retrieve the parameter type as adjusted for use in the signature
/// of a function, decaying array and function types and removing top-level
/// cv-qualifiers.
- QualType getSignatureParameterType(QualType T);
+ QualType getSignatureParameterType(QualType T) const;
/// getArrayDecayedType - Return the properly qualified result of decaying the
/// specified array type to a pointer. This operation is non-trivial when
@@ -1700,7 +1803,7 @@ public:
/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
- /// \brief returns true if there is at lease one @implementation in TU.
+ /// \brief returns true if there is at least one \@implementation in TU.
bool AnyObjCImplementation() {
return !ObjCImpls.empty();
}
@@ -1716,15 +1819,12 @@ public:
/// interface, or null if non exists.
const ObjCMethodDecl *getObjCMethodRedeclaration(
const ObjCMethodDecl *MD) const {
- llvm::DenseMap<const ObjCMethodDecl*, const ObjCMethodDecl*>::const_iterator
- I = ObjCMethodRedecls.find(MD);
- if (I == ObjCMethodRedecls.end())
- return 0;
- return I->second;
+ return ObjCMethodRedecls.lookup(MD);
}
void setObjCMethodRedeclaration(const ObjCMethodDecl *MD,
const ObjCMethodDecl *Redecl) {
+ assert(!getObjCMethodRedeclaration(MD) && "MD already has a redeclaration");
ObjCMethodRedecls[MD] = Redecl;
}
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 7157efe5b3f2..46a9881039c7 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -271,7 +271,8 @@ namespace clang {
/// \brief Determine whether the given types are structurally
/// equivalent.
- bool IsStructurallyEquivalent(QualType From, QualType To);
+ bool IsStructurallyEquivalent(QualType From, QualType To,
+ bool Complain = true);
};
}
diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h
index 217dfade525f..4ff5ea37b882 100644
--- a/include/clang/AST/ASTVector.h
+++ b/include/clang/AST/ASTVector.h
@@ -374,7 +374,7 @@ void ASTVector<T>::grow(ASTContext &C, size_t MinSize) {
NewCapacity = MinSize;
// Allocate the memory from the ASTContext.
- T *NewElts = new (C) T[NewCapacity];
+ T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity];
// Copy the elements over.
if (llvm::is_class<T>::value) {
@@ -387,7 +387,7 @@ void ASTVector<T>::grow(ASTContext &C, size_t MinSize) {
memcpy(NewElts, Begin, CurSize * sizeof(T));
}
- C.Deallocate(Begin);
+ // ASTContext never frees any memory.
Begin = NewElts;
End = NewElts+CurSize;
Capacity = Begin+NewCapacity;
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index ef1aa256626c..27b44d4bd97b 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -1,4 +1,4 @@
-//===--- Attr.h - Classes for representing expressions ----------*- C++ -*-===//
+//===--- Attr.h - Classes for representing attributes ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -147,14 +147,12 @@ public:
typedef SmallVector<Attr*, 2> AttrVec;
typedef SmallVector<const Attr*, 2> ConstAttrVec;
-/// DestroyAttrs - Destroy the contents of an AttrVec.
-inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
-}
-
/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
/// providing attributes that are of a specifc type.
-template <typename SpecificAttr>
+template <typename SpecificAttr, typename Container = AttrVec>
class specific_attr_iterator {
+ typedef typename Container::const_iterator 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
@@ -162,14 +160,14 @@ class specific_attr_iterator {
/// 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;
+ mutable Iterator Current;
void AdvanceToNext() const {
while (!isa<SpecificAttr>(*Current))
++Current;
}
- void AdvanceToNext(AttrVec::const_iterator I) const {
+ void AdvanceToNext(Iterator I) const {
while (Current != I && !isa<SpecificAttr>(*Current))
++Current;
}
@@ -182,7 +180,7 @@ public:
typedef std::ptrdiff_t difference_type;
specific_attr_iterator() : Current() { }
- explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
+ explicit specific_attr_iterator(Iterator i) : Current(i) { }
reference operator*() const {
AdvanceToNext();
@@ -217,23 +215,27 @@ public:
}
};
-template <typename T>
-inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
- return specific_attr_iterator<T>(vec.begin());
+template <typename SpecificAttr, typename Container>
+inline specific_attr_iterator<SpecificAttr, Container>
+ specific_attr_begin(const Container& container) {
+ return specific_attr_iterator<SpecificAttr, Container>(container.begin());
}
-template <typename T>
-inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
- return specific_attr_iterator<T>(vec.end());
+template <typename SpecificAttr, typename Container>
+inline specific_attr_iterator<SpecificAttr, Container>
+ specific_attr_end(const Container& container) {
+ return specific_attr_iterator<SpecificAttr, Container>(container.end());
}
-template <typename T>
-inline bool hasSpecificAttr(const AttrVec& vec) {
- return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
+template <typename SpecificAttr, typename Container>
+inline bool hasSpecificAttr(const Container& container) {
+ return specific_attr_begin<SpecificAttr>(container) !=
+ specific_attr_end<SpecificAttr>(container);
}
-template <typename T>
-inline T *getSpecificAttr(const AttrVec& vec) {
- specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
- if (i != specific_attr_end<T>(vec))
+template <typename SpecificAttr, typename Container>
+inline SpecificAttr *getSpecificAttr(const Container& container) {
+ specific_attr_iterator<SpecificAttr, Container> i =
+ specific_attr_begin<SpecificAttr>(container);
+ if (i != specific_attr_end<SpecificAttr>(container))
return *i;
else
return 0;
diff --git a/include/clang/AST/BaseSubobject.h b/include/clang/AST/BaseSubobject.h
index 6a036bb62cf4..da538e3566a7 100644
--- a/include/clang/AST/BaseSubobject.h
+++ b/include/clang/AST/BaseSubobject.h
@@ -66,9 +66,9 @@ template<> struct DenseMapInfo<clang::BaseSubobject> {
}
static unsigned getHashValue(const clang::BaseSubobject &Base) {
- return
- DenseMapInfo<const clang::CXXRecordDecl *>::getHashValue(Base.getBase()) ^
- DenseMapInfo<int64_t>::getHashValue(Base.getBaseOffset().getQuantity());
+ typedef std::pair<const clang::CXXRecordDecl *, clang::CharUnits> PairTy;
+ return DenseMapInfo<PairTy>::getHashValue(PairTy(Base.getBase(),
+ Base.getBaseOffset()));
}
static bool isEqual(const clang::BaseSubobject &LHS,
diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt
index c10cda84fb83..d7458aa7900e 100644
--- a/include/clang/AST/CMakeLists.txt
+++ b/include/clang/AST/CMakeLists.txt
@@ -15,3 +15,8 @@ clang_tablegen(StmtNodes.inc -gen-clang-stmt-nodes
clang_tablegen(DeclNodes.inc -gen-clang-decl-nodes
SOURCE ../Basic/DeclNodes.td
TARGET ClangDeclNodes)
+
+clang_tablegen(CommentNodes.inc -gen-clang-comment-nodes
+ SOURCE ../Basic/CommentNodes.td
+ TARGET ClangCommentNodes)
+
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 44c554b606c4..ee6eba78e415 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -128,8 +128,7 @@ class CXXBasePaths {
/// while the element contains the number of non-virtual base
/// class subobjects for that class type. The key of the map is
/// the cv-unqualified canonical type of the base class subobject.
- std::map<QualType, std::pair<bool, unsigned>, QualTypeOrdering>
- ClassSubobjects;
+ llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects;
/// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
/// ambiguous paths while it is looking for a path from a derived
diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
new file mode 100644
index 000000000000..01aaac3f77ad
--- /dev/null
+++ b/include/clang/AST/Comment.h
@@ -0,0 +1,1059 @@
+//===--- Comment.h - Comment AST nodes --------------------------*- 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 comment AST nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_COMMENT_H
+#define LLVM_CLANG_AST_COMMENT_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+class Decl;
+class ParmVarDecl;
+class TemplateParameterList;
+
+namespace comments {
+
+/// Any part of the comment.
+/// Abstract class.
+class Comment {
+protected:
+ /// Preferred location to show caret.
+ SourceLocation Loc;
+
+ /// Source range of this AST node.
+ SourceRange Range;
+
+ class CommentBitfields {
+ friend class Comment;
+
+ /// Type of this AST node.
+ unsigned Kind : 8;
+ };
+ enum { NumCommentBits = 8 };
+
+ class InlineContentCommentBitfields {
+ friend class InlineContentComment;
+
+ unsigned : NumCommentBits;
+
+ /// True if there is a newline after this inline content node.
+ /// (There is no separate AST node for a newline.)
+ unsigned HasTrailingNewline : 1;
+ };
+ enum { NumInlineContentCommentBits = NumCommentBits + 1 };
+
+ class TextCommentBitfields {
+ friend class TextComment;
+
+ unsigned : NumInlineContentCommentBits;
+
+ /// True if \c IsWhitespace field contains a valid value.
+ mutable unsigned IsWhitespaceValid : 1;
+
+ /// True if this comment AST node contains only whitespace.
+ mutable unsigned IsWhitespace : 1;
+ };
+ enum { NumTextCommentBits = NumInlineContentCommentBits + 2 };
+
+ class InlineCommandCommentBitfields {
+ friend class InlineCommandComment;
+
+ unsigned : NumInlineContentCommentBits;
+
+ unsigned RenderKind : 2;
+ };
+ enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 1 };
+
+ class HTMLStartTagCommentBitfields {
+ friend class HTMLStartTagComment;
+
+ unsigned : NumInlineContentCommentBits;
+
+ /// True if this tag is self-closing (e. g., <br />). This is based on tag
+ /// spelling in comment (plain <br> would not set this flag).
+ unsigned IsSelfClosing : 1;
+ };
+ enum { NumHTMLStartTagCommentBits = NumInlineContentCommentBits + 1 };
+
+ class ParagraphCommentBitfields {
+ friend class ParagraphComment;
+
+ unsigned : NumCommentBits;
+
+ /// True if \c IsWhitespace field contains a valid value.
+ mutable unsigned IsWhitespaceValid : 1;
+
+ /// True if this comment AST node contains only whitespace.
+ mutable unsigned IsWhitespace : 1;
+ };
+ enum { NumParagraphCommentBits = NumCommentBits + 2 };
+
+ class ParamCommandCommentBitfields {
+ friend class ParamCommandComment;
+
+ unsigned : NumCommentBits;
+
+ /// Parameter passing direction, see ParamCommandComment::PassDirection.
+ unsigned Direction : 2;
+
+ /// True if direction was specified explicitly in the comment.
+ unsigned IsDirectionExplicit : 1;
+ };
+ enum { NumParamCommandCommentBits = 11 };
+
+ union {
+ CommentBitfields CommentBits;
+ InlineContentCommentBitfields InlineContentCommentBits;
+ TextCommentBitfields TextCommentBits;
+ InlineCommandCommentBitfields InlineCommandCommentBits;
+ HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
+ ParagraphCommentBitfields ParagraphCommentBits;
+ ParamCommandCommentBitfields ParamCommandCommentBits;
+ };
+
+ void setSourceRange(SourceRange SR) {
+ Range = SR;
+ }
+
+ void setLocation(SourceLocation L) {
+ Loc = L;
+ }
+
+public:
+ enum CommentKind {
+ NoCommentKind = 0,
+#define COMMENT(CLASS, PARENT) CLASS##Kind,
+#define COMMENT_RANGE(BASE, FIRST, LAST) \
+ First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind,
+#define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \
+ First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind
+#define ABSTRACT_COMMENT(COMMENT)
+#include "clang/AST/CommentNodes.inc"
+ };
+
+ Comment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd) :
+ Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) {
+ CommentBits.Kind = K;
+ }
+
+ CommentKind getCommentKind() const {
+ return static_cast<CommentKind>(CommentBits.Kind);
+ }
+
+ const char *getCommentKindName() const;
+
+ LLVM_ATTRIBUTE_USED void dump() const;
+ LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const;
+ void dump(llvm::raw_ostream &OS, SourceManager *SM) const;
+
+ static bool classof(const Comment *) { return true; }
+
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return Range.getBegin();
+ }
+
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return Range.getEnd();
+ }
+
+ SourceLocation getLocation() const LLVM_READONLY { return Loc; }
+
+ typedef Comment * const *child_iterator;
+
+ child_iterator child_begin() const;
+ child_iterator child_end() const;
+
+ // TODO: const child iterator
+
+ unsigned child_count() const {
+ return child_end() - child_begin();
+ }
+};
+
+/// Inline content (contained within a block).
+/// Abstract class.
+class InlineContentComment : public Comment {
+protected:
+ InlineContentComment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd) :
+ Comment(K, LocBegin, LocEnd) {
+ InlineContentCommentBits.HasTrailingNewline = 0;
+ }
+
+public:
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() >= FirstInlineContentCommentConstant &&
+ C->getCommentKind() <= LastInlineContentCommentConstant;
+ }
+
+ static bool classof(const InlineContentComment *) { return true; }
+
+ void addTrailingNewline() {
+ InlineContentCommentBits.HasTrailingNewline = 1;
+ }
+
+ bool hasTrailingNewline() const {
+ return InlineContentCommentBits.HasTrailingNewline;
+ }
+};
+
+/// Plain text.
+class TextComment : public InlineContentComment {
+ StringRef Text;
+
+public:
+ TextComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Text) :
+ InlineContentComment(TextCommentKind, LocBegin, LocEnd),
+ Text(Text) {
+ TextCommentBits.IsWhitespaceValid = false;
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == TextCommentKind;
+ }
+
+ static bool classof(const TextComment *) { return true; }
+
+ child_iterator child_begin() const { return NULL; }
+
+ child_iterator child_end() const { return NULL; }
+
+ StringRef getText() const LLVM_READONLY { return Text; }
+
+ bool isWhitespace() const {
+ if (TextCommentBits.IsWhitespaceValid)
+ return TextCommentBits.IsWhitespace;
+
+ TextCommentBits.IsWhitespace = isWhitespaceNoCache();
+ TextCommentBits.IsWhitespaceValid = true;
+ return TextCommentBits.IsWhitespace;
+ }
+
+private:
+ bool isWhitespaceNoCache() const;
+};
+
+/// A command with word-like arguments that is considered inline content.
+class InlineCommandComment : public InlineContentComment {
+public:
+ struct Argument {
+ SourceRange Range;
+ StringRef Text;
+
+ Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
+ };
+
+ /// The most appropriate rendering mode for this command, chosen on command
+ /// semantics in Doxygen.
+ enum RenderKind {
+ RenderNormal,
+ RenderBold,
+ RenderMonospaced,
+ RenderEmphasized
+ };
+
+protected:
+ /// Command name.
+ StringRef Name;
+
+ /// Command arguments.
+ llvm::ArrayRef<Argument> Args;
+
+public:
+ InlineCommandComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name,
+ RenderKind RK,
+ llvm::ArrayRef<Argument> Args) :
+ InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
+ Name(Name), Args(Args) {
+ InlineCommandCommentBits.RenderKind = RK;
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == InlineCommandCommentKind;
+ }
+
+ static bool classof(const InlineCommandComment *) { return true; }
+
+ child_iterator child_begin() const { return NULL; }
+
+ child_iterator child_end() const { return NULL; }
+
+ StringRef getCommandName() const {
+ return Name;
+ }
+
+ SourceRange getCommandNameRange() const {
+ return SourceRange(getLocStart().getLocWithOffset(-1),
+ getLocEnd());
+ }
+
+ RenderKind getRenderKind() const {
+ return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
+ }
+
+ unsigned getNumArgs() const {
+ return Args.size();
+ }
+
+ StringRef getArgText(unsigned Idx) const {
+ return Args[Idx].Text;
+ }
+
+ SourceRange getArgRange(unsigned Idx) const {
+ return Args[Idx].Range;
+ }
+};
+
+/// Abstract class for opening and closing HTML tags. HTML tags are always
+/// treated as inline content (regardless HTML semantics); opening and closing
+/// tags are not matched.
+class HTMLTagComment : public InlineContentComment {
+protected:
+ StringRef TagName;
+ SourceRange TagNameRange;
+
+ HTMLTagComment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef TagName,
+ SourceLocation TagNameBegin,
+ SourceLocation TagNameEnd) :
+ InlineContentComment(K, LocBegin, LocEnd),
+ TagName(TagName),
+ TagNameRange(TagNameBegin, TagNameEnd) {
+ setLocation(TagNameBegin);
+ }
+
+public:
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
+ C->getCommentKind() <= LastHTMLTagCommentConstant;
+ }
+
+ static bool classof(const HTMLTagComment *) { return true; }
+
+ StringRef getTagName() const LLVM_READONLY { return TagName; }
+
+ SourceRange getTagNameSourceRange() const LLVM_READONLY {
+ SourceLocation L = getLocation();
+ return SourceRange(L.getLocWithOffset(1),
+ L.getLocWithOffset(1 + TagName.size()));
+ }
+};
+
+/// An opening HTML tag with attributes.
+class HTMLStartTagComment : public HTMLTagComment {
+public:
+ class Attribute {
+ public:
+ SourceLocation NameLocBegin;
+ StringRef Name;
+
+ SourceLocation EqualsLoc;
+
+ SourceRange ValueRange;
+ StringRef Value;
+
+ Attribute() { }
+
+ Attribute(SourceLocation NameLocBegin, StringRef Name) :
+ NameLocBegin(NameLocBegin), Name(Name),
+ EqualsLoc(SourceLocation()),
+ ValueRange(SourceRange()), Value(StringRef())
+ { }
+
+ Attribute(SourceLocation NameLocBegin, StringRef Name,
+ SourceLocation EqualsLoc,
+ SourceRange ValueRange, StringRef Value) :
+ NameLocBegin(NameLocBegin), Name(Name),
+ EqualsLoc(EqualsLoc),
+ ValueRange(ValueRange), Value(Value)
+ { }
+
+ SourceLocation getNameLocEnd() const {
+ return NameLocBegin.getLocWithOffset(Name.size());
+ }
+
+ SourceRange getNameRange() const {
+ return SourceRange(NameLocBegin, getNameLocEnd());
+ }
+ };
+
+private:
+ ArrayRef<Attribute> Attributes;
+
+public:
+ HTMLStartTagComment(SourceLocation LocBegin,
+ StringRef TagName) :
+ HTMLTagComment(HTMLStartTagCommentKind,
+ LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
+ TagName,
+ LocBegin.getLocWithOffset(1),
+ LocBegin.getLocWithOffset(1 + TagName.size())) {
+ HTMLStartTagCommentBits.IsSelfClosing = false;
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == HTMLStartTagCommentKind;
+ }
+
+ static bool classof(const HTMLStartTagComment *) { return true; }
+
+ child_iterator child_begin() const { return NULL; }
+
+ child_iterator child_end() const { return NULL; }
+
+ unsigned getNumAttrs() const {
+ return Attributes.size();
+ }
+
+ const Attribute &getAttr(unsigned Idx) const {
+ return Attributes[Idx];
+ }
+
+ void setAttrs(ArrayRef<Attribute> Attrs) {
+ Attributes = Attrs;
+ if (!Attrs.empty()) {
+ const Attribute &Attr = Attrs.back();
+ SourceLocation L = Attr.ValueRange.getEnd();
+ if (L.isValid())
+ Range.setEnd(L);
+ else {
+ Range.setEnd(Attr.getNameLocEnd());
+ }
+ }
+ }
+
+ void setGreaterLoc(SourceLocation GreaterLoc) {
+ Range.setEnd(GreaterLoc);
+ }
+
+ bool isSelfClosing() const {
+ return HTMLStartTagCommentBits.IsSelfClosing;
+ }
+
+ void setSelfClosing() {
+ HTMLStartTagCommentBits.IsSelfClosing = true;
+ }
+};
+
+/// A closing HTML tag.
+class HTMLEndTagComment : public HTMLTagComment {
+public:
+ HTMLEndTagComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef TagName) :
+ HTMLTagComment(HTMLEndTagCommentKind,
+ LocBegin, LocEnd,
+ TagName,
+ LocBegin.getLocWithOffset(2),
+ LocBegin.getLocWithOffset(2 + TagName.size()))
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == HTMLEndTagCommentKind;
+ }
+
+ static bool classof(const HTMLEndTagComment *) { return true; }
+
+ child_iterator child_begin() const { return NULL; }
+
+ child_iterator child_end() const { return NULL; }
+};
+
+/// Block content (contains inline content).
+/// Abstract class.
+class BlockContentComment : public Comment {
+protected:
+ BlockContentComment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd) :
+ Comment(K, LocBegin, LocEnd)
+ { }
+
+public:
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() >= FirstBlockContentCommentConstant &&
+ C->getCommentKind() <= LastBlockContentCommentConstant;
+ }
+
+ static bool classof(const BlockContentComment *) { return true; }
+};
+
+/// A single paragraph that contains inline content.
+class ParagraphComment : public BlockContentComment {
+ llvm::ArrayRef<InlineContentComment *> Content;
+
+public:
+ ParagraphComment(llvm::ArrayRef<InlineContentComment *> Content) :
+ BlockContentComment(ParagraphCommentKind,
+ SourceLocation(),
+ SourceLocation()),
+ Content(Content) {
+ if (Content.empty()) {
+ ParagraphCommentBits.IsWhitespace = true;
+ ParagraphCommentBits.IsWhitespaceValid = true;
+ return;
+ }
+
+ ParagraphCommentBits.IsWhitespaceValid = false;
+
+ setSourceRange(SourceRange(Content.front()->getLocStart(),
+ Content.back()->getLocEnd()));
+ setLocation(Content.front()->getLocStart());
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == ParagraphCommentKind;
+ }
+
+ static bool classof(const ParagraphComment *) { return true; }
+
+ child_iterator child_begin() const {
+ return reinterpret_cast<child_iterator>(Content.begin());
+ }
+
+ child_iterator child_end() const {
+ return reinterpret_cast<child_iterator>(Content.end());
+ }
+
+ bool isWhitespace() const {
+ if (ParagraphCommentBits.IsWhitespaceValid)
+ return ParagraphCommentBits.IsWhitespace;
+
+ ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
+ ParagraphCommentBits.IsWhitespaceValid = true;
+ return ParagraphCommentBits.IsWhitespace;
+ }
+
+private:
+ bool isWhitespaceNoCache() const;
+};
+
+/// A command that has zero or more word-like arguments (number of word-like
+/// arguments depends on command name) and a paragraph as an argument
+/// (e. g., \\brief).
+class BlockCommandComment : public BlockContentComment {
+public:
+ struct Argument {
+ SourceRange Range;
+ StringRef Text;
+
+ Argument() { }
+ Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
+ };
+
+protected:
+ /// Command name.
+ StringRef Name;
+
+ /// Word-like arguments.
+ llvm::ArrayRef<Argument> Args;
+
+ /// Paragraph argument.
+ ParagraphComment *Paragraph;
+
+ BlockCommandComment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name) :
+ BlockContentComment(K, LocBegin, LocEnd),
+ Name(Name),
+ Paragraph(NULL) {
+ setLocation(getCommandNameRange().getBegin());
+ }
+
+public:
+ BlockCommandComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name) :
+ BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
+ Name(Name),
+ Paragraph(NULL) {
+ setLocation(getCommandNameRange().getBegin());
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
+ C->getCommentKind() <= LastBlockCommandCommentConstant;
+ }
+
+ static bool classof(const BlockCommandComment *) { return true; }
+
+ child_iterator child_begin() const {
+ return reinterpret_cast<child_iterator>(&Paragraph);
+ }
+
+ child_iterator child_end() const {
+ return reinterpret_cast<child_iterator>(&Paragraph + 1);
+ }
+
+ StringRef getCommandName() const {
+ return Name;
+ }
+
+ SourceRange getCommandNameRange() const {
+ return SourceRange(getLocStart().getLocWithOffset(1),
+ getLocStart().getLocWithOffset(1 + Name.size()));
+ }
+
+ unsigned getNumArgs() const {
+ return Args.size();
+ }
+
+ StringRef getArgText(unsigned Idx) const {
+ return Args[Idx].Text;
+ }
+
+ SourceRange getArgRange(unsigned Idx) const {
+ return Args[Idx].Range;
+ }
+
+ void setArgs(llvm::ArrayRef<Argument> A) {
+ Args = A;
+ if (Args.size() > 0) {
+ SourceLocation NewLocEnd = Args.back().Range.getEnd();
+ if (NewLocEnd.isValid())
+ setSourceRange(SourceRange(getLocStart(), NewLocEnd));
+ }
+ }
+
+ ParagraphComment *getParagraph() const LLVM_READONLY {
+ return Paragraph;
+ }
+
+ bool hasNonWhitespaceParagraph() const {
+ return Paragraph && !Paragraph->isWhitespace();
+ }
+
+ void setParagraph(ParagraphComment *PC) {
+ Paragraph = PC;
+ SourceLocation NewLocEnd = PC->getLocEnd();
+ if (NewLocEnd.isValid())
+ setSourceRange(SourceRange(getLocStart(), NewLocEnd));
+ }
+};
+
+/// Doxygen \\param command.
+class ParamCommandComment : public BlockCommandComment {
+private:
+ /// Parameter index in the function declaration.
+ unsigned ParamIndex;
+
+public:
+ enum { InvalidParamIndex = ~0U };
+
+ ParamCommandComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name) :
+ BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, Name),
+ ParamIndex(InvalidParamIndex) {
+ ParamCommandCommentBits.Direction = In;
+ ParamCommandCommentBits.IsDirectionExplicit = false;
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == ParamCommandCommentKind;
+ }
+
+ static bool classof(const ParamCommandComment *) { return true; }
+
+ enum PassDirection {
+ In,
+ Out,
+ InOut
+ };
+
+ static const char *getDirectionAsString(PassDirection D);
+
+ PassDirection getDirection() const LLVM_READONLY {
+ return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
+ }
+
+ bool isDirectionExplicit() const LLVM_READONLY {
+ return ParamCommandCommentBits.IsDirectionExplicit;
+ }
+
+ void setDirection(PassDirection Direction, bool Explicit) {
+ ParamCommandCommentBits.Direction = Direction;
+ ParamCommandCommentBits.IsDirectionExplicit = Explicit;
+ }
+
+ bool hasParamName() const {
+ return getNumArgs() > 0;
+ }
+
+ StringRef getParamName() const {
+ return Args[0].Text;
+ }
+
+ SourceRange getParamNameRange() const {
+ return Args[0].Range;
+ }
+
+ bool isParamIndexValid() const LLVM_READONLY {
+ return ParamIndex != InvalidParamIndex;
+ }
+
+ unsigned getParamIndex() const LLVM_READONLY {
+ assert(isParamIndexValid());
+ return ParamIndex;
+ }
+
+ void setParamIndex(unsigned Index) {
+ ParamIndex = Index;
+ assert(isParamIndexValid());
+ }
+};
+
+/// Doxygen \\tparam command, describes a template parameter.
+class TParamCommandComment : public BlockCommandComment {
+private:
+ /// If this template parameter name was resolved (found in template parameter
+ /// list), then this stores a list of position indexes in all template
+ /// parameter lists.
+ ///
+ /// For example:
+ /// \verbatim
+ /// template<typename C, template<typename T> class TT>
+ /// void test(TT<int> aaa);
+ /// \endverbatim
+ /// For C: Position = { 0 }
+ /// For TT: Position = { 1 }
+ /// For T: Position = { 1, 0 }
+ llvm::ArrayRef<unsigned> Position;
+
+public:
+ TParamCommandComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name) :
+ BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, Name)
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == TParamCommandCommentKind;
+ }
+
+ static bool classof(const TParamCommandComment *) { return true; }
+
+ bool hasParamName() const {
+ return getNumArgs() > 0;
+ }
+
+ StringRef getParamName() const {
+ return Args[0].Text;
+ }
+
+ SourceRange getParamNameRange() const {
+ return Args[0].Range;
+ }
+
+ bool isPositionValid() const LLVM_READONLY {
+ return !Position.empty();
+ }
+
+ unsigned getDepth() const {
+ assert(isPositionValid());
+ return Position.size();
+ }
+
+ unsigned getIndex(unsigned Depth) const {
+ assert(isPositionValid());
+ return Position[Depth];
+ }
+
+ void setPosition(ArrayRef<unsigned> NewPosition) {
+ Position = NewPosition;
+ assert(isPositionValid());
+ }
+};
+
+/// A line of text contained in a verbatim block.
+class VerbatimBlockLineComment : public Comment {
+ StringRef Text;
+
+public:
+ VerbatimBlockLineComment(SourceLocation LocBegin,
+ StringRef Text) :
+ Comment(VerbatimBlockLineCommentKind,
+ LocBegin,
+ LocBegin.getLocWithOffset(Text.size())),
+ Text(Text)
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == VerbatimBlockLineCommentKind;
+ }
+
+ static bool classof(const VerbatimBlockLineComment *) { return true; }
+
+ child_iterator child_begin() const { return NULL; }
+
+ child_iterator child_end() const { return NULL; }
+
+ StringRef getText() const LLVM_READONLY {
+ return Text;
+ }
+};
+
+/// A verbatim block command (e. g., preformatted code). Verbatim block has an
+/// opening and a closing command and contains multiple lines of text
+/// (VerbatimBlockLineComment nodes).
+class VerbatimBlockComment : public BlockCommandComment {
+protected:
+ StringRef CloseName;
+ SourceLocation CloseNameLocBegin;
+ llvm::ArrayRef<VerbatimBlockLineComment *> Lines;
+
+public:
+ VerbatimBlockComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name) :
+ BlockCommandComment(VerbatimBlockCommentKind,
+ LocBegin, LocEnd, Name)
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == VerbatimBlockCommentKind;
+ }
+
+ static bool classof(const VerbatimBlockComment *) { return true; }
+
+ child_iterator child_begin() const {
+ return reinterpret_cast<child_iterator>(Lines.begin());
+ }
+
+ child_iterator child_end() const {
+ return reinterpret_cast<child_iterator>(Lines.end());
+ }
+
+ void setCloseName(StringRef Name, SourceLocation LocBegin) {
+ CloseName = Name;
+ CloseNameLocBegin = LocBegin;
+ }
+
+ void setLines(llvm::ArrayRef<VerbatimBlockLineComment *> L) {
+ Lines = L;
+ }
+
+ StringRef getCloseName() const {
+ return CloseName;
+ }
+
+ unsigned getNumLines() const {
+ return Lines.size();
+ }
+
+ StringRef getText(unsigned LineIdx) const {
+ return Lines[LineIdx]->getText();
+ }
+};
+
+/// A verbatim line command. Verbatim line has an opening command, a single
+/// line of text (up to the newline after the opening command) and has no
+/// closing command.
+class VerbatimLineComment : public BlockCommandComment {
+protected:
+ StringRef Text;
+ SourceLocation TextBegin;
+
+public:
+ VerbatimLineComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name,
+ SourceLocation TextBegin,
+ StringRef Text) :
+ BlockCommandComment(VerbatimLineCommentKind,
+ LocBegin, LocEnd,
+ Name),
+ Text(Text),
+ TextBegin(TextBegin)
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == VerbatimLineCommentKind;
+ }
+
+ static bool classof(const VerbatimLineComment *) { return true; }
+
+ child_iterator child_begin() const { return NULL; }
+
+ child_iterator child_end() const { return NULL; }
+
+ StringRef getText() const {
+ return Text;
+ }
+
+ SourceRange getTextRange() const {
+ return SourceRange(TextBegin, getLocEnd());
+ }
+};
+
+/// Information about the declaration, useful to clients of FullComment.
+struct DeclInfo {
+ /// Declaration the comment is attached to. Should not be NULL.
+ const Decl *ThisDecl;
+
+ /// Parameters that can be referenced by \\param if \c ThisDecl is something
+ /// that we consider a "function".
+ ArrayRef<const ParmVarDecl *> ParamVars;
+
+ /// Function result type if \c ThisDecl is something that we consider
+ /// a "function".
+ QualType ResultType;
+
+ /// Template parameters that can be referenced by \\tparam if \c ThisDecl is
+ /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
+ /// true).
+ const TemplateParameterList *TemplateParameters;
+
+ /// A simplified description of \c ThisDecl kind that should be good enough
+ /// for documentation rendering purposes.
+ enum DeclKind {
+ /// Everything else not explicitly mentioned below.
+ OtherKind,
+
+ /// Something that we consider a "function":
+ /// \li function,
+ /// \li function template,
+ /// \li function template specialization,
+ /// \li member function,
+ /// \li member function template,
+ /// \li member function template specialization,
+ /// \li ObjC method.
+ FunctionKind,
+
+ /// Something that we consider a "class":
+ /// \li class/struct,
+ /// \li class template,
+ /// \li class template (partial) specialization.
+ ClassKind,
+
+ /// Something that we consider a "variable":
+ /// \li namespace scope variables;
+ /// \li static and non-static class data members;
+ /// \li enumerators.
+ VariableKind,
+
+ /// A C++ namespace.
+ NamespaceKind,
+
+ /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration),
+ /// see \c TypedefNameDecl.
+ TypedefKind,
+
+ /// An enumeration or scoped enumeration.
+ EnumKind
+ };
+
+ /// What kind of template specialization \c ThisDecl is.
+ enum TemplateDeclKind {
+ NotTemplate,
+ Template,
+ TemplateSpecialization,
+ TemplatePartialSpecialization
+ };
+
+ /// If false, only \c ThisDecl is valid.
+ unsigned IsFilled : 1;
+
+ /// Simplified kind of \c ThisDecl, see\c DeclKind enum.
+ unsigned Kind : 3;
+
+ /// Is \c ThisDecl a template declaration.
+ unsigned TemplateKind : 2;
+
+ /// Is \c ThisDecl an ObjCMethodDecl.
+ unsigned IsObjCMethod : 1;
+
+ /// Is \c ThisDecl a non-static member function of C++ class or
+ /// instance method of ObjC class.
+ /// Can be true only if \c IsFunctionDecl is true.
+ unsigned IsInstanceMethod : 1;
+
+ /// Is \c ThisDecl a static member function of C++ class or
+ /// class method of ObjC class.
+ /// Can be true only if \c IsFunctionDecl is true.
+ unsigned IsClassMethod : 1;
+
+ void fill();
+
+ DeclKind getKind() const LLVM_READONLY {
+ return static_cast<DeclKind>(Kind);
+ }
+
+ TemplateDeclKind getTemplateKind() const LLVM_READONLY {
+ return static_cast<TemplateDeclKind>(TemplateKind);
+ }
+};
+
+/// A full comment attached to a declaration, contains block content.
+class FullComment : public Comment {
+ llvm::ArrayRef<BlockContentComment *> Blocks;
+
+ DeclInfo *ThisDeclInfo;
+
+public:
+ FullComment(llvm::ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
+ Comment(FullCommentKind, SourceLocation(), SourceLocation()),
+ Blocks(Blocks), ThisDeclInfo(D) {
+ if (Blocks.empty())
+ return;
+
+ setSourceRange(SourceRange(Blocks.front()->getLocStart(),
+ Blocks.back()->getLocEnd()));
+ setLocation(Blocks.front()->getLocStart());
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == FullCommentKind;
+ }
+
+ static bool classof(const FullComment *) { return true; }
+
+ child_iterator child_begin() const {
+ return reinterpret_cast<child_iterator>(Blocks.begin());
+ }
+
+ child_iterator child_end() const {
+ return reinterpret_cast<child_iterator>(Blocks.end());
+ }
+
+ const Decl *getDecl() const LLVM_READONLY {
+ return ThisDeclInfo->ThisDecl;
+ }
+
+ const DeclInfo *getDeclInfo() const LLVM_READONLY {
+ if (!ThisDeclInfo->IsFilled)
+ ThisDeclInfo->fill();
+ return ThisDeclInfo;
+ }
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h
new file mode 100644
index 000000000000..003c33727e35
--- /dev/null
+++ b/include/clang/AST/CommentBriefParser.h
@@ -0,0 +1,56 @@
+//===--- CommentBriefParser.h - Dumb comment parser -------------*- 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 a very simple Doxygen comment parser.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H
+#define LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H
+
+#include "clang/AST/CommentLexer.h"
+
+namespace clang {
+namespace comments {
+
+/// A very simple comment parser that extracts "a brief description".
+///
+/// Due to a variety of comment styles, it considers the following as "a brief
+/// description", in order of priority:
+/// \li a \\brief or \\short command,
+/// \li the first paragraph,
+/// \li a \\result or \\return or \\returns paragraph.
+class BriefParser {
+ Lexer &L;
+
+ const CommandTraits &Traits;
+
+ /// Current lookahead token.
+ Token Tok;
+
+ SourceLocation ConsumeToken() {
+ SourceLocation Loc = Tok.getLocation();
+ L.lex(Tok);
+ return Loc;
+ }
+
+public:
+ BriefParser(Lexer &L, const CommandTraits &Traits);
+
+ /// Return \\brief paragraph, if it exists; otherwise return the first
+ /// paragraph.
+ std::string Parse();
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h
new file mode 100644
index 000000000000..f1883755e520
--- /dev/null
+++ b/include/clang/AST/CommentCommandTraits.h
@@ -0,0 +1,156 @@
+//===--- CommentCommandTraits.h - Comment command properties ----*- 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 class that provides information about comment
+// commands.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
+#define LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace clang {
+namespace comments {
+
+/// This class provides informaiton about commands that can be used
+/// in comments.
+class CommandTraits {
+public:
+ CommandTraits() { }
+
+ /// \brief Check if a given command is a verbatim-like block command.
+ ///
+ /// A verbatim-like block command eats every character (except line starting
+ /// decorations) until matching end command is seen or comment end is hit.
+ ///
+ /// \param BeginName name of the command that starts the verbatim block.
+ /// \param [out] EndName name of the command that ends the verbatim block.
+ ///
+ /// \returns true if a given command is a verbatim block command.
+ bool isVerbatimBlockCommand(StringRef StartName, StringRef &EndName) const;
+
+ /// \brief Register a new verbatim block command.
+ void addVerbatimBlockCommand(StringRef BeginName, StringRef EndName);
+
+ /// \brief Check if a given command is a verbatim line command.
+ ///
+ /// A verbatim-like line command eats everything until a newline is seen or
+ /// comment end is hit.
+ bool isVerbatimLineCommand(StringRef Name) const;
+
+ /// \brief Check if a given command is a command that contains a declaration
+ /// for the entity being documented.
+ ///
+ /// For example:
+ /// \code
+ /// \fn void f(int a);
+ /// \endcode
+ bool isDeclarationCommand(StringRef Name) const;
+
+ /// \brief Register a new verbatim line command.
+ void addVerbatimLineCommand(StringRef Name);
+
+ /// \brief Check if a given command is a block command (of any kind).
+ bool isBlockCommand(StringRef Name) const;
+
+ /// \brief Check if a given command is introducing documentation for
+ /// a function parameter (\\param or an alias).
+ bool isParamCommand(StringRef Name) const;
+
+ /// \brief Check if a given command is introducing documentation for
+ /// a template parameter (\\tparam or an alias).
+ bool isTParamCommand(StringRef Name) const;
+
+ /// \brief Check if a given command is introducing a brief documentation
+ /// paragraph (\\brief or an alias).
+ bool isBriefCommand(StringRef Name) const;
+
+ /// \brief Check if a given command is \\brief or an alias.
+ bool isReturnsCommand(StringRef Name) const;
+
+ /// \returns the number of word-like arguments for a given block command,
+ /// except for \\param and \\tparam commands -- these have special argument
+ /// parsers.
+ unsigned getBlockCommandNumArgs(StringRef Name) const;
+
+ /// \brief Check if a given command is a inline command (of any kind).
+ bool isInlineCommand(StringRef Name) const;
+
+private:
+ struct VerbatimBlockCommand {
+ StringRef BeginName;
+ StringRef EndName;
+ };
+
+ typedef SmallVector<VerbatimBlockCommand, 4> VerbatimBlockCommandVector;
+
+ /// Registered additional verbatim-like block commands.
+ VerbatimBlockCommandVector VerbatimBlockCommands;
+
+ struct VerbatimLineCommand {
+ StringRef Name;
+ };
+
+ typedef SmallVector<VerbatimLineCommand, 4> VerbatimLineCommandVector;
+
+ /// Registered verbatim-like line commands.
+ VerbatimLineCommandVector VerbatimLineCommands;
+};
+
+inline bool CommandTraits::isBlockCommand(StringRef Name) const {
+ return isBriefCommand(Name) || isReturnsCommand(Name) ||
+ isParamCommand(Name) || isTParamCommand(Name) ||
+ llvm::StringSwitch<bool>(Name)
+ .Case("author", true)
+ .Case("authors", true)
+ .Case("pre", true)
+ .Case("post", true)
+ .Default(false);
+}
+
+inline bool CommandTraits::isParamCommand(StringRef Name) const {
+ return Name == "param";
+}
+
+inline bool CommandTraits::isTParamCommand(StringRef Name) const {
+ return Name == "tparam" || // Doxygen
+ Name == "templatefield"; // HeaderDoc
+}
+
+inline bool CommandTraits::isBriefCommand(StringRef Name) const {
+ return Name == "brief" || Name == "short";
+}
+
+inline bool CommandTraits::isReturnsCommand(StringRef Name) const {
+ return Name == "returns" || Name == "return" || Name == "result";
+}
+
+inline unsigned CommandTraits::getBlockCommandNumArgs(StringRef Name) const {
+ return 0;
+}
+
+inline bool CommandTraits::isInlineCommand(StringRef Name) const {
+ return llvm::StringSwitch<bool>(Name)
+ .Case("b", true)
+ .Cases("c", "p", true)
+ .Cases("a", "e", "em", true)
+ .Default(false);
+}
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h
new file mode 100644
index 000000000000..6e8941057994
--- /dev/null
+++ b/include/clang/AST/CommentDiagnostic.h
@@ -0,0 +1,29 @@
+//===--- CommentDiagnostic.h - Diagnostics for the AST library --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_COMMENTDIAGNOSTIC_H
+#define LLVM_CLANG_COMMENTDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+#define COMMENTSTART
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_COMMENT_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
+
diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h
new file mode 100644
index 000000000000..7a24b1163178
--- /dev/null
+++ b/include/clang/AST/CommentLexer.h
@@ -0,0 +1,353 @@
+//===--- CommentLexer.h - Lexer for structured comments ---------*- 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 lexer for structured comments and supporting token class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_COMMENT_LEXER_H
+#define LLVM_CLANG_AST_COMMENT_LEXER_H
+
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace comments {
+
+class Lexer;
+class TextTokenRetokenizer;
+class CommandTraits;
+
+namespace tok {
+enum TokenKind {
+ eof,
+ newline,
+ text,
+ command,
+ verbatim_block_begin,
+ verbatim_block_line,
+ verbatim_block_end,
+ verbatim_line_name,
+ verbatim_line_text,
+ html_start_tag, // <tag
+ html_ident, // attr
+ html_equals, // =
+ html_quoted_string, // "blah\"blah" or 'blah\'blah'
+ html_greater, // >
+ html_slash_greater, // />
+ html_end_tag // </tag
+};
+} // end namespace tok
+
+class CommentOptions {
+public:
+ bool Markdown;
+};
+
+/// \brief Comment token.
+class Token {
+ friend class Lexer;
+ friend class TextTokenRetokenizer;
+
+ /// The location of the token.
+ SourceLocation Loc;
+
+ /// The actual kind of the token.
+ tok::TokenKind Kind;
+
+ /// Length of the token spelling in comment. Can be 0 for synthenized
+ /// tokens.
+ unsigned Length;
+
+ /// Contains text value associated with a token.
+ const char *TextPtr1;
+ unsigned TextLen1;
+
+public:
+ SourceLocation getLocation() const LLVM_READONLY { return Loc; }
+ void setLocation(SourceLocation SL) { Loc = SL; }
+
+ SourceLocation getEndLocation() const LLVM_READONLY {
+ if (Length == 0 || Length == 1)
+ return Loc;
+ return Loc.getLocWithOffset(Length - 1);
+ }
+
+ tok::TokenKind getKind() const LLVM_READONLY { return Kind; }
+ void setKind(tok::TokenKind K) { Kind = K; }
+
+ bool is(tok::TokenKind K) const LLVM_READONLY { return Kind == K; }
+ bool isNot(tok::TokenKind K) const LLVM_READONLY { return Kind != K; }
+
+ unsigned getLength() const LLVM_READONLY { return Length; }
+ void setLength(unsigned L) { Length = L; }
+
+ StringRef getText() const LLVM_READONLY {
+ assert(is(tok::text));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setText(StringRef Text) {
+ assert(is(tok::text));
+ TextPtr1 = Text.data();
+ TextLen1 = Text.size();
+ }
+
+ StringRef getCommandName() const LLVM_READONLY {
+ assert(is(tok::command));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setCommandName(StringRef Name) {
+ assert(is(tok::command));
+ TextPtr1 = Name.data();
+ TextLen1 = Name.size();
+ }
+
+ StringRef getVerbatimBlockName() const LLVM_READONLY {
+ assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setVerbatimBlockName(StringRef Name) {
+ assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
+ TextPtr1 = Name.data();
+ TextLen1 = Name.size();
+ }
+
+ StringRef getVerbatimBlockText() const LLVM_READONLY {
+ assert(is(tok::verbatim_block_line));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setVerbatimBlockText(StringRef Text) {
+ assert(is(tok::verbatim_block_line));
+ TextPtr1 = Text.data();
+ TextLen1 = Text.size();
+ }
+
+ /// Returns the name of verbatim line command.
+ StringRef getVerbatimLineName() const LLVM_READONLY {
+ assert(is(tok::verbatim_line_name));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setVerbatimLineName(StringRef Name) {
+ assert(is(tok::verbatim_line_name));
+ TextPtr1 = Name.data();
+ TextLen1 = Name.size();
+ }
+
+ StringRef getVerbatimLineText() const LLVM_READONLY {
+ assert(is(tok::verbatim_line_text));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setVerbatimLineText(StringRef Text) {
+ assert(is(tok::verbatim_line_text));
+ TextPtr1 = Text.data();
+ TextLen1 = Text.size();
+ }
+
+ StringRef getHTMLTagStartName() const LLVM_READONLY {
+ assert(is(tok::html_start_tag));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setHTMLTagStartName(StringRef Name) {
+ assert(is(tok::html_start_tag));
+ TextPtr1 = Name.data();
+ TextLen1 = Name.size();
+ }
+
+ StringRef getHTMLIdent() const LLVM_READONLY {
+ assert(is(tok::html_ident));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setHTMLIdent(StringRef Name) {
+ assert(is(tok::html_ident));
+ TextPtr1 = Name.data();
+ TextLen1 = Name.size();
+ }
+
+ StringRef getHTMLQuotedString() const LLVM_READONLY {
+ assert(is(tok::html_quoted_string));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setHTMLQuotedString(StringRef Str) {
+ assert(is(tok::html_quoted_string));
+ TextPtr1 = Str.data();
+ TextLen1 = Str.size();
+ }
+
+ StringRef getHTMLTagEndName() const LLVM_READONLY {
+ assert(is(tok::html_end_tag));
+ return StringRef(TextPtr1, TextLen1);
+ }
+
+ void setHTMLTagEndName(StringRef Name) {
+ assert(is(tok::html_end_tag));
+ TextPtr1 = Name.data();
+ TextLen1 = Name.size();
+ }
+
+ void dump(const Lexer &L, const SourceManager &SM) const;
+};
+
+/// \brief Comment lexer.
+class Lexer {
+private:
+ Lexer(const Lexer&); // DO NOT IMPLEMENT
+ void operator=(const Lexer&); // DO NOT IMPLEMENT
+
+ /// Allocator for strings that are semantic values of tokens and have to be
+ /// computed (for example, resolved decimal character references).
+ llvm::BumpPtrAllocator &Allocator;
+
+ const CommandTraits &Traits;
+
+ const char *const BufferStart;
+ const char *const BufferEnd;
+ SourceLocation FileLoc;
+ CommentOptions CommOpts;
+
+ const char *BufferPtr;
+
+ /// One past end pointer for the current comment. For BCPL comments points
+ /// to newline or BufferEnd, for C comments points to star in '*/'.
+ const char *CommentEnd;
+
+ enum LexerCommentState {
+ LCS_BeforeComment,
+ LCS_InsideBCPLComment,
+ LCS_InsideCComment,
+ LCS_BetweenComments
+ };
+
+ /// Low-level lexer state, track if we are inside or outside of comment.
+ LexerCommentState CommentState;
+
+ enum LexerState {
+ /// Lexing normal comment text
+ LS_Normal,
+
+ /// Finished lexing verbatim block beginning command, will lex first body
+ /// line.
+ LS_VerbatimBlockFirstLine,
+
+ /// Lexing verbatim block body line-by-line, skipping line-starting
+ /// decorations.
+ LS_VerbatimBlockBody,
+
+ /// Finished lexing verbatim line beginning command, will lex text (one
+ /// line).
+ LS_VerbatimLineText,
+
+ /// Finished lexing \verbatim <TAG \endverbatim part, lexing tag attributes.
+ LS_HTMLStartTag,
+
+ /// Finished lexing \verbatim </TAG \endverbatim part, lexing '>'.
+ LS_HTMLEndTag
+ };
+
+ /// Current lexing mode.
+ LexerState State;
+
+ /// If State is LS_VerbatimBlock, contains the name of verbatim end
+ /// command, including command marker.
+ SmallString<16> VerbatimBlockEndCommandName;
+
+ /// Given a character reference name (e.g., "lt"), return the character that
+ /// it stands for (e.g., "<").
+ StringRef resolveHTMLNamedCharacterReference(StringRef Name) const;
+
+ /// Given a Unicode codepoint as base-10 integer, return the character.
+ StringRef resolveHTMLDecimalCharacterReference(StringRef Name) const;
+
+ /// Given a Unicode codepoint as base-16 integer, return the character.
+ StringRef resolveHTMLHexCharacterReference(StringRef Name) const;
+
+ void formTokenWithChars(Token &Result, const char *TokEnd,
+ tok::TokenKind Kind) {
+ const unsigned TokLen = TokEnd - BufferPtr;
+ Result.setLocation(getSourceLocation(BufferPtr));
+ Result.setKind(Kind);
+ Result.setLength(TokLen);
+#ifndef NDEBUG
+ Result.TextPtr1 = "<UNSET>";
+ Result.TextLen1 = 7;
+#endif
+ BufferPtr = TokEnd;
+ }
+
+ void formTextToken(Token &Result, const char *TokEnd) {
+ StringRef Text(BufferPtr, TokEnd - BufferPtr);
+ formTokenWithChars(Result, TokEnd, tok::text);
+ Result.setText(Text);
+ }
+
+ SourceLocation getSourceLocation(const char *Loc) const {
+ assert(Loc >= BufferStart && Loc <= BufferEnd &&
+ "Location out of range for this buffer!");
+
+ const unsigned CharNo = Loc - BufferStart;
+ return FileLoc.getLocWithOffset(CharNo);
+ }
+
+ /// Eat string matching regexp \code \s*\* \endcode.
+ void skipLineStartingDecorations();
+
+ /// Lex stuff inside comments. CommentEnd should be set correctly.
+ void lexCommentText(Token &T);
+
+ void setupAndLexVerbatimBlock(Token &T,
+ const char *TextBegin,
+ char Marker, StringRef EndName);
+
+ void lexVerbatimBlockFirstLine(Token &T);
+
+ void lexVerbatimBlockBody(Token &T);
+
+ void setupAndLexVerbatimLine(Token &T, const char *TextBegin);
+
+ void lexVerbatimLineText(Token &T);
+
+ void lexHTMLCharacterReference(Token &T);
+
+ void setupAndLexHTMLStartTag(Token &T);
+
+ void lexHTMLStartTag(Token &T);
+
+ void setupAndLexHTMLEndTag(Token &T);
+
+ void lexHTMLEndTag(Token &T);
+
+public:
+ Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits,
+ SourceLocation FileLoc, const CommentOptions &CommOpts,
+ const char *BufferStart, const char *BufferEnd);
+
+ void lex(Token &T);
+
+ StringRef getSpelling(const Token &Tok,
+ const SourceManager &SourceMgr,
+ bool *Invalid = NULL) const;
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h
new file mode 100644
index 000000000000..039079931c58
--- /dev/null
+++ b/include/clang/AST/CommentParser.h
@@ -0,0 +1,124 @@
+//===--- CommentParser.h - Doxygen comment parser ---------------*- 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 Doxygen comment parser.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_COMMENT_PARSER_H
+#define LLVM_CLANG_AST_COMMENT_PARSER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/AST/CommentLexer.h"
+#include "clang/AST/Comment.h"
+#include "clang/AST/CommentSema.h"
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+class SourceManager;
+
+namespace comments {
+class CommandTraits;
+
+/// Doxygen comment parser.
+class Parser {
+ Parser(const Parser&); // DO NOT IMPLEMENT
+ void operator=(const Parser&); // DO NOT IMPLEMENT
+
+ friend class TextTokenRetokenizer;
+
+ Lexer &L;
+
+ Sema &S;
+
+ /// Allocator for anything that goes into AST nodes.
+ llvm::BumpPtrAllocator &Allocator;
+
+ /// Source manager for the comment being parsed.
+ const SourceManager &SourceMgr;
+
+ DiagnosticsEngine &Diags;
+
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags.Report(Loc, DiagID);
+ }
+
+ const CommandTraits &Traits;
+
+ /// Current lookahead token. We can safely assume that all tokens are from
+ /// a single source file.
+ Token Tok;
+
+ /// A stack of additional lookahead tokens.
+ SmallVector<Token, 8> MoreLATokens;
+
+ void consumeToken() {
+ if (MoreLATokens.empty())
+ L.lex(Tok);
+ else {
+ Tok = MoreLATokens.back();
+ MoreLATokens.pop_back();
+ }
+ }
+
+ void putBack(const Token &OldTok) {
+ MoreLATokens.push_back(Tok);
+ Tok = OldTok;
+ }
+
+ void putBack(ArrayRef<Token> Toks) {
+ if (Toks.empty())
+ return;
+
+ MoreLATokens.push_back(Tok);
+ for (const Token *I = &Toks.back(),
+ *B = &Toks.front();
+ I != B; --I) {
+ MoreLATokens.push_back(*I);
+ }
+
+ Tok = Toks[0];
+ }
+
+public:
+ Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator,
+ const SourceManager &SourceMgr, DiagnosticsEngine &Diags,
+ const CommandTraits &Traits);
+
+ /// Parse arguments for \\param command.
+ void parseParamCommandArgs(ParamCommandComment *PC,
+ TextTokenRetokenizer &Retokenizer);
+
+ /// Parse arguments for \\tparam command.
+ void parseTParamCommandArgs(TParamCommandComment *TPC,
+ TextTokenRetokenizer &Retokenizer);
+
+ void parseBlockCommandArgs(BlockCommandComment *BC,
+ TextTokenRetokenizer &Retokenizer,
+ unsigned NumArgs);
+
+ BlockCommandComment *parseBlockCommand();
+ InlineCommandComment *parseInlineCommand();
+
+ HTMLStartTagComment *parseHTMLStartTag();
+ HTMLEndTagComment *parseHTMLEndTag();
+
+ BlockContentComment *parseParagraphOrBlockCommand();
+
+ VerbatimBlockComment *parseVerbatimBlock();
+ VerbatimLineComment *parseVerbatimLine();
+ BlockContentComment *parseBlockContent();
+ FullComment *parseFullComment();
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
new file mode 100644
index 000000000000..e1756ca3e2f1
--- /dev/null
+++ b/include/clang/AST/CommentSema.h
@@ -0,0 +1,230 @@
+//===--- CommentSema.h - Doxygen comment semantic analysis ------*- 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 semantic analysis class for Doxygen comments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_COMMENT_SEMA_H
+#define LLVM_CLANG_AST_COMMENT_SEMA_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/AST/Comment.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+class Decl;
+class SourceMgr;
+
+namespace comments {
+class CommandTraits;
+
+class Sema {
+ Sema(const Sema&); // DO NOT IMPLEMENT
+ void operator=(const Sema&); // DO NOT IMPLEMENT
+
+ /// Allocator for AST nodes.
+ llvm::BumpPtrAllocator &Allocator;
+
+ /// Source manager for the comment being parsed.
+ const SourceManager &SourceMgr;
+
+ DiagnosticsEngine &Diags;
+
+ const CommandTraits &Traits;
+
+ /// Information about the declaration this comment is attached to.
+ DeclInfo *ThisDeclInfo;
+
+ /// Comment AST nodes that correspond to \c ParamVars for which we have
+ /// found a \\param command or NULL if no documentation was found so far.
+ ///
+ /// Has correct size and contains valid values if \c DeclInfo->IsFilled is
+ /// true.
+ llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs;
+
+ /// Comment AST nodes that correspond to parameter names in
+ /// \c TemplateParameters.
+ ///
+ /// Contains a valid value if \c DeclInfo->IsFilled is true.
+ llvm::StringMap<TParamCommandComment *> TemplateParameterDocs;
+
+ /// AST node for the \\brief command and its aliases.
+ const BlockCommandComment *BriefCommand;
+
+ /// AST node for the \\returns command and its aliases.
+ const BlockCommandComment *ReturnsCommand;
+
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags.Report(Loc, DiagID);
+ }
+
+ /// A stack of HTML tags that are currently open (not matched with closing
+ /// tags).
+ SmallVector<HTMLStartTagComment *, 8> HTMLOpenTags;
+
+public:
+ Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
+ DiagnosticsEngine &Diags, const CommandTraits &Traits);
+
+ void setDecl(const Decl *D);
+
+ /// Returns a copy of array, owned by Sema's allocator.
+ template<typename T>
+ ArrayRef<T> copyArray(ArrayRef<T> Source) {
+ size_t Size = Source.size();
+ if (Size != 0) {
+ T *Mem = Allocator.Allocate<T>(Size);
+ std::uninitialized_copy(Source.begin(), Source.end(), Mem);
+ return llvm::makeArrayRef(Mem, Size);
+ } else
+ return llvm::makeArrayRef(static_cast<T *>(NULL), 0);
+ }
+
+ ParagraphComment *actOnParagraphComment(
+ ArrayRef<InlineContentComment *> Content);
+
+ BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name);
+
+ void actOnBlockCommandArgs(BlockCommandComment *Command,
+ ArrayRef<BlockCommandComment::Argument> Args);
+
+ void actOnBlockCommandFinish(BlockCommandComment *Command,
+ ParagraphComment *Paragraph);
+
+ ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name);
+
+ void actOnParamCommandDirectionArg(ParamCommandComment *Command,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg);
+
+ void actOnParamCommandParamNameArg(ParamCommandComment *Command,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg);
+
+ void actOnParamCommandFinish(ParamCommandComment *Command,
+ ParagraphComment *Paragraph);
+
+ TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name);
+
+ void actOnTParamCommandParamNameArg(TParamCommandComment *Command,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg);
+
+ void actOnTParamCommandFinish(TParamCommandComment *Command,
+ ParagraphComment *Paragraph);
+
+ InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
+ SourceLocation CommandLocEnd,
+ StringRef CommandName);
+
+ InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
+ SourceLocation CommandLocEnd,
+ StringRef CommandName,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg);
+
+ InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name);
+
+ TextComment *actOnText(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Text);
+
+ VerbatimBlockComment *actOnVerbatimBlockStart(SourceLocation Loc,
+ StringRef Name);
+
+ VerbatimBlockLineComment *actOnVerbatimBlockLine(SourceLocation Loc,
+ StringRef Text);
+
+ void actOnVerbatimBlockFinish(VerbatimBlockComment *Block,
+ SourceLocation CloseNameLocBegin,
+ StringRef CloseName,
+ ArrayRef<VerbatimBlockLineComment *> Lines);
+
+ VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin,
+ StringRef Name,
+ SourceLocation TextBegin,
+ StringRef Text);
+
+ HTMLStartTagComment *actOnHTMLStartTagStart(SourceLocation LocBegin,
+ StringRef TagName);
+
+ void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag,
+ ArrayRef<HTMLStartTagComment::Attribute> Attrs,
+ SourceLocation GreaterLoc,
+ bool IsSelfClosing);
+
+ HTMLEndTagComment *actOnHTMLEndTag(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef TagName);
+
+ FullComment *actOnFullComment(ArrayRef<BlockContentComment *> Blocks);
+
+ void checkBlockCommandEmptyParagraph(BlockCommandComment *Command);
+
+ void checkReturnsCommand(const BlockCommandComment *Command);
+
+ /// Emit diagnostics about duplicate block commands that should be
+ /// used only once per comment, e.g., \\brief and \\returns.
+ void checkBlockCommandDuplicate(const BlockCommandComment *Command);
+
+ bool isFunctionDecl();
+ bool isTemplateOrSpecialization();
+
+ ArrayRef<const ParmVarDecl *> getParamVars();
+
+ /// Extract all important semantic information from
+ /// \c ThisDeclInfo->ThisDecl into \c ThisDeclInfo members.
+ void inspectThisDecl();
+
+ /// Returns index of a function parameter with a given name.
+ unsigned resolveParmVarReference(StringRef Name,
+ ArrayRef<const ParmVarDecl *> ParamVars);
+
+ /// Returns index of a function parameter with the name closest to a given
+ /// typo.
+ unsigned correctTypoInParmVarReference(StringRef Typo,
+ ArrayRef<const ParmVarDecl *> ParamVars);
+
+ bool resolveTParamReference(StringRef Name,
+ const TemplateParameterList *TemplateParameters,
+ SmallVectorImpl<unsigned> *Position);
+
+ StringRef correctTypoInTParamReference(
+ StringRef Typo,
+ const TemplateParameterList *TemplateParameters);
+
+ InlineCommandComment::RenderKind
+ getInlineCommandRenderKind(StringRef Name) const;
+
+ bool isHTMLEndTagOptional(StringRef Name);
+ bool isHTMLEndTagForbidden(StringRef Name);
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/include/clang/AST/CommentVisitor.h b/include/clang/AST/CommentVisitor.h
new file mode 100644
index 000000000000..47867a634fcc
--- /dev/null
+++ b/include/clang/AST/CommentVisitor.h
@@ -0,0 +1,66 @@
+//===--- CommentVisitor.h - Visitor for Comment subclasses ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Comment.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+namespace comments {
+
+template <typename T> struct make_ptr { typedef T *type; };
+template <typename T> struct make_const_ptr { typedef const T *type; };
+
+template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
+class CommentVisitorBase {
+public:
+#define PTR(CLASS) typename Ptr<CLASS>::type
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass*>(this)->visit ## NAME(static_cast<PTR(CLASS)>(C))
+
+ RetTy visit(PTR(Comment) C) {
+ if (!C)
+ return RetTy();
+
+ switch (C->getCommentKind()) {
+ default: llvm_unreachable("Unknown comment kind!");
+#define ABSTRACT_COMMENT(COMMENT)
+#define COMMENT(CLASS, PARENT) \
+ case Comment::CLASS##Kind: DISPATCH(CLASS, CLASS);
+#include "clang/AST/CommentNodes.inc"
+#undef ABSTRACT_COMMENT
+#undef COMMENT
+ }
+ }
+
+ // If the derived class does not implement a certain Visit* method, fall back
+ // on Visit* method for the superclass.
+#define ABSTRACT_COMMENT(COMMENT) COMMENT
+#define COMMENT(CLASS, PARENT) \
+ RetTy visit ## CLASS(PTR(CLASS) C) { DISPATCH(PARENT, PARENT); }
+#include "clang/AST/CommentNodes.inc"
+#undef ABSTRACT_COMMENT
+#undef COMMENT
+
+ RetTy visitComment(PTR(Comment) C) { return RetTy(); }
+
+#undef PTR
+#undef DISPATCH
+};
+
+template<typename ImplClass, typename RetTy=void>
+class CommentVisitor :
+ public CommentVisitorBase<make_ptr, ImplClass, RetTy> {};
+
+template<typename ImplClass, typename RetTy=void>
+class ConstCommentVisitor :
+ public CommentVisitorBase<make_const_ptr, ImplClass, RetTy> {};
+
+} // end namespace comments
+} // end namespace clang
+
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 0c47f2e486f3..e9f25b368aad 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -99,7 +99,7 @@ public:
};
/// NamedDecl - This represents a decl with a name. Many decls have names such
-/// as ObjCMethodDecl, but not @class, etc.
+/// as ObjCMethodDecl, but not \@class, etc.
class NamedDecl : public Decl {
virtual void anchor();
/// Name - The name of this declaration, which is typically a normal
@@ -218,6 +218,7 @@ public:
Visibility visibility_;
bool explicit_;
+ void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
public:
LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
explicit_(false) {}
@@ -242,8 +243,6 @@ public:
bool visibilityExplicit() const { return explicit_; }
void setLinkage(Linkage L) { linkage_ = L; }
- void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
-
void mergeLinkage(Linkage L) {
setLinkage(minLinkage(linkage(), L));
}
@@ -256,15 +255,15 @@ public:
// down to one of its members. If the member has no explicit visibility,
// the class visibility wins.
void mergeVisibility(Visibility V, bool E = false) {
- // If one has explicit visibility and the other doesn't, keep the
- // explicit one.
- if (visibilityExplicit() && !E)
+ // Never increase the visibility
+ if (visibility() < V)
return;
- if (!visibilityExplicit() && E)
- setVisibility(V, E);
- // If both are explicit or both are implicit, keep the minimum.
- setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E);
+ // If we have an explicit visibility, keep it
+ if (visibilityExplicit())
+ return;
+
+ setVisibility(V, E);
}
// Merge the visibility V, keeping the most restrictive one.
// This is used for cases like merging the visibility of a template
@@ -275,9 +274,16 @@ public:
if (visibility() < V)
return;
+ // FIXME: this
// If this visibility is explicit, keep it.
if (visibilityExplicit() && !E)
return;
+
+ // should be replaced with this
+ // Don't lose the explicit bit for nothing
+ // if (visibility() == V && visibilityExplicit())
+ // return;
+
setVisibility(V, E);
}
void mergeVisibility(LinkageInfo Other) {
@@ -295,11 +301,6 @@ public:
mergeLinkage(Other);
mergeVisibilityWithMin(Other);
}
-
- friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) {
- L.merge(R);
- return L;
- }
};
/// \brief Determine what kind of linkage this entity has.
@@ -1151,7 +1152,7 @@ public:
}
/// \brief Determine whether this variable is the exception variable in a
- /// C++ catch statememt or an Objective-C @catch statement.
+ /// C++ catch statememt or an Objective-C \@catch statement.
bool isExceptionVariable() const {
return VarDeclBits.ExceptionVar;
}
@@ -1182,7 +1183,7 @@ public:
bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; }
void setARCPseudoStrong(bool ps) { VarDeclBits.ARCPseudoStrong = ps; }
- /// Whether this variable is (C++0x) constexpr.
+ /// Whether this variable is (C++11) constexpr.
bool isConstexpr() const { return VarDeclBits.IsConstexpr; }
void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; }
@@ -1735,9 +1736,9 @@ public:
bool hasInheritedPrototype() const { return HasInheritedPrototype; }
void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; }
- /// Whether this is a (C++0x) constexpr function or constexpr constructor.
+ /// Whether this is a (C++11) constexpr function or constexpr constructor.
bool isConstexpr() const { return IsConstexpr; }
- void setConstexpr(bool IC) { IsConstexpr = IC; }
+ void setConstexpr(bool IC);
/// \brief Whether this function has been deleted.
///
@@ -2092,25 +2093,26 @@ class FieldDecl : public DeclaratorDecl {
bool Mutable : 1;
mutable unsigned CachedFieldIndex : 31;
- /// \brief A pointer to either the in-class initializer for this field (if
- /// the boolean value is false), or the bit width expression for this bit
- /// field (if the boolean value is true).
+ /// \brief An InClassInitStyle value, and either a bit width expression (if
+ /// the InClassInitStyle value is ICIS_NoInit), or a pointer to the in-class
+ /// initializer for this field (otherwise).
///
/// We can safely combine these two because in-class initializers are not
/// permitted for bit-fields.
///
- /// If the boolean is false and the initializer is null, then this field has
- /// an in-class initializer which has not yet been parsed and attached.
- llvm::PointerIntPair<Expr *, 1, bool> InitializerOrBitWidth;
+ /// If the InClassInitStyle is not ICIS_NoInit and the initializer is null,
+ /// then this field has an in-class initializer which has not yet been parsed
+ /// and attached.
+ llvm::PointerIntPair<Expr *, 2, unsigned> InitializerOrBitWidth;
protected:
FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
- bool HasInit)
+ InClassInitStyle InitStyle)
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
Mutable(Mutable), CachedFieldIndex(0),
- InitializerOrBitWidth(BW, !HasInit) {
- assert(!(BW && HasInit) && "got initializer for bitfield");
+ InitializerOrBitWidth(BW, InitStyle) {
+ assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield");
}
public:
@@ -2118,7 +2120,7 @@ public:
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
- bool HasInit);
+ InClassInitStyle InitStyle);
static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -2129,12 +2131,10 @@ public:
/// isMutable - Determines whether this field is mutable (C++ only).
bool isMutable() const { return Mutable; }
- /// \brief Set whether this field is mutable (C++ only).
- void setMutable(bool M) { Mutable = M; }
-
/// isBitfield - Determines whether this field is a bitfield.
bool isBitField() const {
- return InitializerOrBitWidth.getInt() && InitializerOrBitWidth.getPointer();
+ return getInClassInitStyle() == ICIS_NoInit &&
+ InitializerOrBitWidth.getPointer();
}
/// @brief Determines whether this is an unnamed bitfield.
@@ -2150,39 +2150,44 @@ public:
return isBitField() ? InitializerOrBitWidth.getPointer() : 0;
}
unsigned getBitWidthValue(const ASTContext &Ctx) const;
- void setBitWidth(Expr *BW) {
- assert(!InitializerOrBitWidth.getPointer() &&
- "bit width or initializer already set");
- InitializerOrBitWidth.setPointer(BW);
- InitializerOrBitWidth.setInt(1);
- }
- /// removeBitWidth - Remove the bitfield width from this member.
+
+ /// setBitWidth - Set the bit-field width for this member.
+ // Note: used by some clients (i.e., do not remove it).
+ void setBitWidth(Expr *Width);
+ /// removeBitWidth - Remove the bit-field width from this member.
+ // Note: used by some clients (i.e., do not remove it).
void removeBitWidth() {
- assert(isBitField() && "no bit width to remove");
+ assert(isBitField() && "no bitfield width to remove");
InitializerOrBitWidth.setPointer(0);
}
- /// hasInClassInitializer - Determine whether this member has a C++0x in-class
+ /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which
+ /// this field has.
+ InClassInitStyle getInClassInitStyle() const {
+ return static_cast<InClassInitStyle>(InitializerOrBitWidth.getInt());
+ }
+
+ /// hasInClassInitializer - Determine whether this member has a C++11 in-class
/// initializer.
bool hasInClassInitializer() const {
- return !InitializerOrBitWidth.getInt();
+ return getInClassInitStyle() != ICIS_NoInit;
}
- /// getInClassInitializer - Get the C++0x in-class initializer for this
+ /// getInClassInitializer - Get the C++11 in-class initializer for this
/// member, or null if one has not been set. If a valid declaration has an
/// in-class initializer, but this returns null, then we have not parsed and
/// attached it yet.
Expr *getInClassInitializer() const {
return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() : 0;
}
- /// setInClassInitializer - Set the C++0x in-class initializer for this
+ /// setInClassInitializer - Set the C++11 in-class initializer for this
/// member.
void setInClassInitializer(Expr *Init);
- /// removeInClassInitializer - Remove the C++0x in-class initializer from this
+ /// removeInClassInitializer - Remove the C++11 in-class initializer from this
/// member.
void removeInClassInitializer() {
- assert(!InitializerOrBitWidth.getInt() && "no initializer to remove");
+ assert(hasInClassInitializer() && "no initializer to remove");
InitializerOrBitWidth.setPointer(0);
- InitializerOrBitWidth.setInt(1);
+ InitializerOrBitWidth.setInt(ICIS_NoInit);
}
/// getParent - Returns the parent of this field declaration, which
@@ -2201,6 +2206,9 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const FieldDecl *D) { return true; }
static bool classofKind(Kind K) { return K >= firstField && K <= lastField; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// EnumConstantDecl - An instance of this object exists for each enum constant
@@ -2308,7 +2316,10 @@ protected:
: NamedDecl(DK, DC, L, Id), TypeForDecl(0), LocStart(StartL) {}
public:
- // Low-level accessor
+ // Low-level accessor. If you just want the type defined by this node,
+ // check out ASTContext::getTypeDeclType or one of
+ // ASTContext::getTypedefType, ASTContext::getRecordType, etc. if you
+ // already know the specific kind of node this is.
const Type *getTypeForDecl() const { return TypeForDecl; }
void setTypeForDecl(const Type *TD) { TypeForDecl = TD; }
@@ -2602,6 +2613,7 @@ public:
void setCompleteDefinition(bool V) { IsCompleteDefinition = V; }
+ // FIXME: Return StringRef;
const char *getKindName() const {
return TypeWithKeyword::getTagTypeKindName(getTagKind());
}
@@ -3214,8 +3226,8 @@ public:
/// @__experimental_modules_import std.vector;
/// \endcode
///
-/// Import declarations can also be implicitly generated from #include/#import
-/// directives.
+/// Import declarations can also be implicitly generated from
+/// \#include/\#import directives.
class ImportDecl : public Decl {
/// \brief The imported module, along with a bit that indicates whether
/// we have source-location information for each identifier in the module
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 223289123eb7..ac2cc9ec4d27 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECLBASE_H
#include "clang/AST/Attr.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/PointerUnion.h"
@@ -692,17 +693,17 @@ public:
Decl *Starter;
public:
- typedef Decl* value_type;
- typedef Decl* reference;
- typedef Decl* pointer;
+ typedef Decl *value_type;
+ typedef const value_type &reference;
+ typedef const value_type *pointer;
typedef std::forward_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
+ typedef std::ptrdiff_t difference_type;
redecl_iterator() : Current(0) { }
explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { }
reference operator*() const { return Current; }
- pointer operator->() const { return Current; }
+ value_type operator->() const { return Current; }
redecl_iterator& operator++() {
assert(Current && "Advancing while iterator has reached end");
@@ -856,8 +857,11 @@ public:
static void printGroup(Decl** Begin, unsigned NumDecls,
raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
- LLVM_ATTRIBUTE_USED void dump() const;
- LLVM_ATTRIBUTE_USED void dumpXML() const;
+ // Debuggers don't usually respect default arguments.
+ LLVM_ATTRIBUTE_USED void dump() const { dump(llvm::errs()); }
+ void dump(raw_ostream &Out) const;
+ // Debuggers don't usually respect default arguments.
+ LLVM_ATTRIBUTE_USED void dumpXML() const { dumpXML(llvm::errs()); }
void dumpXML(raw_ostream &OS) const;
private:
@@ -1141,7 +1145,7 @@ public:
/// inline, its enclosing namespace, recursively.
bool InEnclosingNamespaceSetOf(const DeclContext *NS) const;
- /// \\brief Collects all of the declaration contexts that are semantically
+ /// \brief Collects all of the declaration contexts that are semantically
/// connected to this declaration context.
///
/// For declaration contexts that have multiple semantically connected but
@@ -1173,9 +1177,9 @@ public:
Decl *Current;
public:
- typedef Decl* value_type;
- typedef Decl* reference;
- typedef Decl* pointer;
+ typedef Decl *value_type;
+ typedef const value_type &reference;
+ typedef const value_type *pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
@@ -1183,7 +1187,8 @@ public:
explicit decl_iterator(Decl *C) : Current(C) { }
reference operator*() const { return Current; }
- pointer operator->() const { return Current; }
+ // This doesn't meet the iterator requirements, but it's convenient
+ value_type operator->() const { return Current; }
decl_iterator& operator++() {
Current = Current->getNextDeclInContext();
@@ -1207,14 +1212,14 @@ public:
/// decls_begin/decls_end - Iterate over the declarations stored in
/// this context.
decl_iterator decls_begin() const;
- decl_iterator decls_end() const;
+ decl_iterator decls_end() const { return decl_iterator(); }
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;
+ decl_iterator noload_decls_end() const { return decl_iterator(); }
/// specific_decl_iterator - Iterates over a subrange of
/// declarations stored in a DeclContext, providing only those that
@@ -1237,9 +1242,11 @@ public:
}
public:
- typedef SpecificDecl* value_type;
- typedef SpecificDecl* reference;
- typedef SpecificDecl* pointer;
+ typedef SpecificDecl *value_type;
+ // TODO: Add reference and pointer typedefs (with some appropriate proxy
+ // type) if we ever have a need for them.
+ typedef void reference;
+ typedef void pointer;
typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
difference_type;
typedef std::forward_iterator_tag iterator_category;
@@ -1258,8 +1265,9 @@ public:
SkipToNextDecl();
}
- reference operator*() const { return cast<SpecificDecl>(*Current); }
- pointer operator->() const { return cast<SpecificDecl>(*Current); }
+ value_type operator*() const { return cast<SpecificDecl>(*Current); }
+ // This doesn't meet the iterator requirements, but it's convenient
+ value_type operator->() const { return **this; }
specific_decl_iterator& operator++() {
++Current;
@@ -1311,16 +1319,18 @@ public:
}
public:
- typedef SpecificDecl* value_type;
- typedef SpecificDecl* reference;
- typedef SpecificDecl* pointer;
+ typedef SpecificDecl *value_type;
+ // TODO: Add reference and pointer typedefs (with some appropriate proxy
+ // type) if we ever have a need for them.
+ typedef void reference;
+ typedef void pointer;
typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
difference_type;
typedef std::forward_iterator_tag iterator_category;
filtered_decl_iterator() : Current() { }
- /// specific_decl_iterator - Construct a new iterator over a
+ /// filtered_decl_iterator - Construct a new iterator over a
/// subset of the declarations the range [C,
/// end-of-declarations). If A is non-NULL, it is a pointer to a
/// member function of SpecificDecl that should return true for
@@ -1332,8 +1342,8 @@ public:
SkipToNextDecl();
}
- reference operator*() const { return cast<SpecificDecl>(*Current); }
- pointer operator->() const { return cast<SpecificDecl>(*Current); }
+ value_type operator*() const { return cast<SpecificDecl>(*Current); }
+ value_type operator->() const { return cast<SpecificDecl>(*Current); }
filtered_decl_iterator& operator++() {
++Current;
@@ -1410,7 +1420,9 @@ public:
/// and enumerator names preceding any tag name. Note that this
/// routine will not look into parent contexts.
lookup_result lookup(DeclarationName Name);
- lookup_const_result lookup(DeclarationName Name) const;
+ lookup_const_result lookup(DeclarationName Name) const {
+ return const_cast<DeclContext*>(this)->lookup(Name);
+ }
/// \brief A simplistic name lookup mechanism that performs name lookup
/// into this declaration context without consulting the external source.
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 7f3ec4c61656..851e3105bc0d 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -41,6 +41,7 @@ class CXXFinalOverriderMap;
class CXXIndirectPrimaryBaseSet;
class FriendDecl;
class LambdaExpr;
+class UsingDecl;
/// \brief Represents any kind of function declaration, whether it is a
/// concrete function or a function template.
@@ -98,7 +99,7 @@ namespace llvm {
namespace clang {
-/// AccessSpecDecl - An access specifier followed by colon ':'.
+/// @brief Represents an access specifier followed by colon ':'.
///
/// An objects of this class represents sugar for the syntactic occurrence
/// of an access specifier followed by a colon in the list of member
@@ -110,7 +111,7 @@ namespace clang {
/// "access declarations" (C++98 11.3 [class.access.dcl]).
class AccessSpecDecl : public Decl {
virtual void anchor();
- /// ColonLoc - The location of the ':'.
+ /// \brief The location of the ':'.
SourceLocation ColonLoc;
AccessSpecDecl(AccessSpecifier AS, DeclContext *DC,
@@ -121,14 +122,14 @@ class AccessSpecDecl : public Decl {
AccessSpecDecl(EmptyShell Empty)
: Decl(AccessSpec, Empty) { }
public:
- /// getAccessSpecifierLoc - The location of the access specifier.
+ /// \brief The location of the access specifier.
SourceLocation getAccessSpecifierLoc() const { return getLocation(); }
- /// setAccessSpecifierLoc - Sets the location of the access specifier.
+ /// \brief Sets the location of the access specifier.
void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); }
- /// getColonLoc - The location of the colon following the access specifier.
+ /// \brief The location of the colon following the access specifier.
SourceLocation getColonLoc() const { return ColonLoc; }
- /// setColonLoc - Sets the location of the colon.
+ /// \brief Sets the location of the colon.
void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; }
SourceRange getSourceRange() const LLVM_READONLY {
@@ -149,7 +150,7 @@ public:
};
-/// CXXBaseSpecifier - A base class of a C++ class.
+/// \brief Represents a base class of a C++ class.
///
/// Each CXXBaseSpecifier represents a single, direct base class (or
/// struct) of a C++ class (or struct). It specifies the type of that
@@ -175,7 +176,7 @@ class CXXBaseSpecifier {
/// expansion.
SourceLocation EllipsisLoc;
- /// Virtual - Whether this is a virtual base class or not.
+ /// \brief Whether this is a virtual base class or not.
bool Virtual : 1;
/// BaseOfClass - Whether this is the base of a class (true) or of a
@@ -357,6 +358,9 @@ class CXXRecordDecl : public RecordDecl {
/// \brief True if there no non-field members declared by the user.
bool HasOnlyCMembers : 1;
+ /// \brief True if any field has an in-class initializer.
+ bool HasInClassInitializer : 1;
+
/// HasTrivialDefaultConstructor - True when, if this class has a default
/// constructor, this default constructor is trivial.
///
@@ -382,26 +386,10 @@ class CXXRecordDecl : public RecordDecl {
/// constructor for this class would be constexpr.
bool DefaultedDefaultConstructorIsConstexpr : 1;
- /// DefaultedCopyConstructorIsConstexpr - True if a defaulted copy
- /// constructor for this class would be constexpr.
- bool DefaultedCopyConstructorIsConstexpr : 1;
-
- /// DefaultedMoveConstructorIsConstexpr - True if a defaulted move
- /// constructor for this class would be constexpr.
- bool DefaultedMoveConstructorIsConstexpr : 1;
-
/// HasConstexprDefaultConstructor - True if this class has a constexpr
/// default constructor (either user-declared or implicitly declared).
bool HasConstexprDefaultConstructor : 1;
- /// HasConstexprCopyConstructor - True if this class has a constexpr copy
- /// constructor (either user-declared or implicitly declared).
- bool HasConstexprCopyConstructor : 1;
-
- /// HasConstexprMoveConstructor - True if this class has a constexpr move
- /// constructor (either user-declared or implicitly declared).
- bool HasConstexprMoveConstructor : 1;
-
/// HasTrivialCopyConstructor - True when this class has a trivial copy
/// constructor.
///
@@ -554,13 +542,21 @@ class CXXRecordDecl : public RecordDecl {
/// \brief Retrieve the set of direct base classes.
CXXBaseSpecifier *getBases() const {
- return Bases.get(Definition->getASTContext().getExternalSource());
+ if (!Bases.isOffset())
+ return Bases.get(0);
+ return getBasesSlowCase();
}
/// \brief Retrieve the set of virtual base classes.
CXXBaseSpecifier *getVBases() const {
- return VBases.get(Definition->getASTContext().getExternalSource());
+ if (!VBases.isOffset())
+ return VBases.get(0);
+ return getVBasesSlowCase();
}
+
+ private:
+ CXXBaseSpecifier *getBasesSlowCase() const;
+ CXXBaseSpecifier *getVBasesSlowCase() const;
} *DefinitionData;
/// \brief Describes a C++ closure type (generated by a lambda expression).
@@ -647,6 +643,9 @@ class CXXRecordDecl : public RecordDecl {
void markedVirtualFunctionPure();
friend void FunctionDecl::setPure(bool);
+ void markedConstructorConstexpr(CXXConstructorDecl *CD);
+ friend void FunctionDecl::setConstexpr(bool);
+
friend class ASTNodeImporter;
protected:
@@ -1040,6 +1039,10 @@ public:
/// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
bool isAggregate() const { return data().Aggregate; }
+ /// hasInClassInitializer - Whether this class has any in-class initializers
+ /// for non-static data members.
+ bool hasInClassInitializer() const { return data().HasInClassInitializer; }
+
/// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
/// that is an aggregate that has no non-static non-POD data members, no
/// reference data members, no user-defined copy assignment operator and no
@@ -1091,19 +1094,8 @@ public:
/// defaultedDefaultConstructorIsConstexpr - Whether a defaulted default
/// constructor for this class would be constexpr.
bool defaultedDefaultConstructorIsConstexpr() const {
- return data().DefaultedDefaultConstructorIsConstexpr;
- }
-
- /// defaultedCopyConstructorIsConstexpr - Whether a defaulted copy
- /// constructor for this class would be constexpr.
- bool defaultedCopyConstructorIsConstexpr() const {
- return data().DefaultedCopyConstructorIsConstexpr;
- }
-
- /// defaultedMoveConstructorIsConstexpr - Whether a defaulted move
- /// constructor for this class would be constexpr.
- bool defaultedMoveConstructorIsConstexpr() const {
- return data().DefaultedMoveConstructorIsConstexpr;
+ return data().DefaultedDefaultConstructorIsConstexpr &&
+ (!isUnion() || hasInClassInitializer());
}
/// hasConstexprDefaultConstructor - Whether this class has a constexpr
@@ -1111,23 +1103,7 @@ public:
bool hasConstexprDefaultConstructor() const {
return data().HasConstexprDefaultConstructor ||
(!data().UserDeclaredConstructor &&
- data().DefaultedDefaultConstructorIsConstexpr && isLiteral());
- }
-
- /// hasConstexprCopyConstructor - Whether this class has a constexpr copy
- /// constructor.
- bool hasConstexprCopyConstructor() const {
- return data().HasConstexprCopyConstructor ||
- (!data().DeclaredCopyConstructor &&
- data().DefaultedCopyConstructorIsConstexpr && isLiteral());
- }
-
- /// hasConstexprMoveConstructor - Whether this class has a constexpr move
- /// constructor.
- bool hasConstexprMoveConstructor() const {
- return data().HasConstexprMoveConstructor ||
- (needsImplicitMoveConstructor() &&
- data().DefaultedMoveConstructorIsConstexpr && isLiteral());
+ defaultedDefaultConstructorIsConstexpr());
}
// hasTrivialCopyConstructor - Whether this class has a trivial copy
@@ -1212,12 +1188,12 @@ public:
/// This routine will return non-NULL for (non-templated) member
/// classes of class templates. For example, given:
///
- /// \code
+ /// @code
/// template<typename T>
/// struct X {
/// struct A { };
/// };
- /// \endcode
+ /// @endcode
///
/// The declaration for X<int>::A is a (non-templated) CXXRecordDecl
/// whose parent is the class template specialization X<int>. For
@@ -1319,7 +1295,7 @@ public:
///
/// \returns true if this class is virtually derived from Base,
/// false otherwise.
- bool isVirtuallyDerivedFrom(CXXRecordDecl *Base) const;
+ bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const;
/// \brief Determine whether this class is provably not derived from
/// the type \p Base.
@@ -1573,6 +1549,9 @@ public:
bool isStatic() const { return getStorageClass() == SC_Static; }
bool isInstance() const { return !isStatic(); }
+ bool isConst() { return getType()->castAs<FunctionType>()->isConst(); }
+ bool isVolatile() { return getType()->castAs<FunctionType>()->isVolatile(); }
+
bool isVirtual() const {
CXXMethodDecl *CD =
cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
@@ -1602,8 +1581,8 @@ public:
return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
}
- /// isUserProvided - True if it is either an implicit constructor or
- /// if it was defaulted or deleted on first declaration.
+ /// isUserProvided - True if this method is user-declared and was not
+ /// deleted or defaulted on its first declaration.
bool isUserProvided() const {
return !(isDeleted() || getCanonicalDecl()->isDefaulted());
}
@@ -1642,13 +1621,13 @@ public:
///
/// In the following example, \c f() has an lvalue ref-qualifier, \c g()
/// has an rvalue ref-qualifier, and \c h() has no ref-qualifier.
- /// \code
+ /// @code
/// struct X {
/// void f() &;
/// void g() &&;
/// void h();
/// };
- /// \endcode
+ /// @endcode
RefQualifierKind getRefQualifier() const {
return getType()->getAs<FunctionProtoType>()->getRefQualifier();
}
@@ -1663,7 +1642,20 @@ public:
/// supplied by IR generation to either forward to the function call operator
/// or clone the function call operator.
bool isLambdaStaticInvoker() const;
-
+
+ /// \brief Find the method in RD that corresponds to this one.
+ ///
+ /// Find if RD or one of the classes it inherits from override this method.
+ /// If so, return it. RD is assumed to be a base class of the class defining
+ /// this method (or be the class itself).
+ CXXMethodDecl *
+ getCorrespondingMethodInClass(const CXXRecordDecl *RD);
+
+ const CXXMethodDecl *
+ getCorrespondingMethodInClass(const CXXRecordDecl *RD) const {
+ return const_cast<CXXMethodDecl*>(this)->getCorrespondingMethodInClass(RD);
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const CXXMethodDecl *D) { return true; }
@@ -2468,7 +2460,9 @@ public:
friend class ASTDeclReader;
};
-/// NamespaceAliasDecl - Represents a C++ namespace alias. For example:
+/// \brief Represents a C++ namespace alias.
+///
+/// For example:
///
/// @code
/// namespace Foo = Bar;
@@ -2555,17 +2549,19 @@ public:
static bool classofKind(Kind K) { return K == NamespaceAlias; }
};
-/// UsingShadowDecl - Represents a shadow declaration introduced into
-/// a scope by a (resolved) using declaration. For example,
+/// \brief Represents a shadow declaration introduced into a scope by a
+/// (resolved) using declaration.
///
+/// For example,
+/// @code
/// namespace A {
/// void foo();
/// }
/// namespace B {
-/// using A::foo(); // <- a UsingDecl
-/// // Also creates a UsingShadowDecl for A::foo in B
+/// using A::foo; // <- a UsingDecl
+/// // Also creates a UsingShadowDecl for A::foo() in B
/// }
-///
+/// @endcode
class UsingShadowDecl : public NamedDecl {
virtual void anchor();
@@ -2627,8 +2623,12 @@ public:
friend class ASTDeclWriter;
};
-/// UsingDecl - Represents a C++ using-declaration. For example:
+/// \brief Represents a C++ using-declaration.
+///
+/// For example:
+/// @code
/// using someNameSpace::someIdentifier;
+/// @endcode
class UsingDecl : public NamedDecl {
virtual void anchor();
@@ -2643,8 +2643,10 @@ class UsingDecl : public NamedDecl {
DeclarationNameLoc DNLoc;
/// \brief The first shadow declaration of the shadow decl chain associated
- /// with this using declaration. The bool member of the pair store whether
- /// this decl has the 'typename' keyword.
+ /// with this using declaration.
+ ///
+ /// The bool member of the pair store whether this decl has the \c typename
+ /// keyword.
llvm::PointerIntPair<UsingShadowDecl *, 1, bool> FirstUsingShadow;
UsingDecl(DeclContext *DC, SourceLocation UL,
@@ -2753,14 +2755,17 @@ public:
friend class ASTDeclWriter;
};
-/// UnresolvedUsingValueDecl - Represents a dependent using
-/// declaration which was not marked with 'typename'. Unlike
-/// non-dependent using declarations, these *only* bring through
+/// \brief Represents a dependent using declaration which was not marked with
+/// \c typename.
+///
+/// Unlike non-dependent using declarations, these *only* bring through
/// non-types; otherwise they would break two-phase lookup.
///
-/// template <class T> class A : public Base<T> {
+/// @code
+/// template \<class T> class A : public Base<T> {
/// using Base<T>::foo;
/// };
+/// @endcode
class UnresolvedUsingValueDecl : public ValueDecl {
virtual void anchor();
@@ -2824,14 +2829,16 @@ public:
friend class ASTDeclWriter;
};
-/// UnresolvedUsingTypenameDecl - Represents a dependent using
-/// declaration which was marked with 'typename'.
+/// @brief Represents a dependent using declaration which was marked with
+/// \c typename.
///
-/// template <class T> class A : public Base<T> {
+/// @code
+/// template \<class T> class A : public Base<T> {
/// using typename Base<T>::foo;
/// };
+/// @endcode
///
-/// The type associated with a unresolved using typename decl is
+/// The type associated with an unresolved using typename decl is
/// currently always a typename type.
class UnresolvedUsingTypenameDecl : public TypeDecl {
virtual void anchor();
@@ -2885,34 +2892,36 @@ public:
static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
};
-/// StaticAssertDecl - Represents a C++0x static_assert declaration.
+/// \brief Represents a C++11 static_assert declaration.
class StaticAssertDecl : public Decl {
virtual void anchor();
- Expr *AssertExpr;
+ llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed;
StringLiteral *Message;
SourceLocation RParenLoc;
StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc,
- Expr *assertexpr, StringLiteral *message,
- SourceLocation RParenLoc)
- : Decl(StaticAssert, DC, StaticAssertLoc), AssertExpr(assertexpr),
- Message(message), RParenLoc(RParenLoc) { }
+ Expr *AssertExpr, StringLiteral *Message,
+ SourceLocation RParenLoc, bool Failed)
+ : Decl(StaticAssert, DC, StaticAssertLoc),
+ AssertExprAndFailed(AssertExpr, Failed), Message(Message),
+ RParenLoc(RParenLoc) { }
public:
static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StaticAssertLoc,
Expr *AssertExpr, StringLiteral *Message,
- SourceLocation RParenLoc);
+ SourceLocation RParenLoc, bool Failed);
static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- Expr *getAssertExpr() { return AssertExpr; }
- const Expr *getAssertExpr() const { return AssertExpr; }
+ Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); }
+ const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); }
StringLiteral *getMessage() { return Message; }
const StringLiteral *getMessage() const { return Message; }
+ bool isFailed() const { return AssertExprAndFailed.getInt(); }
+
SourceLocation getRParenLoc() const { return RParenLoc; }
- void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getLocation(), getRParenLoc());
@@ -2925,7 +2934,7 @@ public:
friend class ASTDeclReader;
};
-/// Insertion operator for diagnostics. This allows sending AccessSpecifier's
+/// Insertion operator for diagnostics. This allows sending an AccessSpecifier
/// into a diagnostic with <<.
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
AccessSpecifier AS);
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index c5f2aa0b848b..39f04c68a3c7 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -17,8 +17,8 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/DeclCXX.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include <algorithm>
@@ -196,7 +196,7 @@ public:
};
class StoredDeclsMap
- : public llvm::DenseMap<DeclarationName, StoredDeclsList> {
+ : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
public:
static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index ba1eb8d729f3..9a64f08dee50 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -71,10 +71,12 @@ private:
: Decl(Decl::Friend, Empty), NextFriend() { }
FriendDecl *getNextFriend() {
- return cast_or_null<FriendDecl>(
- NextFriend.get(getASTContext().getExternalSource()));
+ if (!NextFriend.isOffset())
+ return cast_or_null<FriendDecl>(NextFriend.get(0));
+ return getNextFriendSlowCase();
}
-
+ FriendDecl *getNextFriendSlowCase();
+
public:
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, FriendUnion Friend_,
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 4ae073ec4608..6c39f2c3abe1 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -136,7 +136,7 @@ private:
mutable unsigned HasRedeclaration : 1;
// NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
- /// @required/@optional
+ /// \@required/\@optional
unsigned DeclImplementation : 2;
// NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
@@ -150,6 +150,15 @@ private:
/// "standard" position, a enum SelectorLocationsKind.
unsigned SelLocsKind : 2;
+ /// \brief Whether this method overrides any other in the class hierarchy.
+ ///
+ /// A method is said to override any method in the class's
+ /// base classes, its protocols, or its categories' protocols, that has
+ /// the same selector and is of the same kind (class or instance).
+ /// A method in an implementation is not considered as overriding the same
+ /// method in the interface or its categories.
+ unsigned IsOverriding : 1;
+
// Result type of this method.
QualType MethodDeclType;
@@ -162,7 +171,7 @@ private:
unsigned NumParams;
/// List of attributes for this method declaration.
- SourceLocation EndLoc; // the location of the ';' or '}'.
+ SourceLocation DeclEndLoc; // the location of the ';' or '{'.
// The following are only used for method definitions, null otherwise.
// FIXME: space savings opportunity, consider a sub-class.
@@ -230,10 +239,10 @@ private:
IsDefined(isDefined), IsRedeclaration(0), HasRedeclaration(0),
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
RelatedResultType(HasRelatedResultType),
- SelLocsKind(SelLoc_StandardNoSpace),
+ SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0),
MethodDeclType(T), ResultTInfo(ResultTInfo),
ParamsAndSelLocs(0), NumParams(0),
- EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {
+ DeclEndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {
setImplicit(isImplicitlyDeclared);
}
@@ -281,12 +290,16 @@ public:
bool isRedeclaration() const { return IsRedeclaration; }
void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);
+ /// \brief Returns the location where the declarator ends. It will be
+ /// the location of ';' for a method declaration and the location of '{'
+ /// for a method definition.
+ SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; }
+
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; }
- void setEndLoc(SourceLocation Loc) { EndLoc = Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY;
virtual SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(getLocation(), EndLoc);
+ return SourceRange(getLocation(), getLocEnd());
}
SourceLocation getSelectorStartLoc() const {
@@ -301,7 +314,7 @@ public:
getSelLocsKind() == SelLoc_StandardWithSpace,
llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
NumParams),
- EndLoc);
+ DeclEndLoc);
return getStoredSelLocs()[Index];
}
@@ -396,7 +409,17 @@ public:
bool isDefined() const { return IsDefined; }
void setDefined(bool isDefined) { IsDefined = isDefined; }
- // Related to protocols declared in @protocol
+ /// \brief Whether this method overrides any other in the class hierarchy.
+ ///
+ /// A method is said to override any method in the class's
+ /// base classes, its protocols, or its categories' protocols, that has
+ /// the same selector and is of the same kind (class or instance).
+ /// A method in an implementation is not considered as overriding the same
+ /// method in the interface or its categories.
+ bool isOverriding() const { return IsOverriding; }
+ void setOverriding(bool isOverriding) { IsOverriding = isOverriding; }
+
+ // Related to protocols declared in \@protocol
void setDeclImplementation(ImplementationControl ic) {
DeclImplementation = ic;
}
@@ -528,24 +551,28 @@ public:
}
};
-/// ObjCInterfaceDecl - Represents an ObjC class declaration. For example:
+/// \brief Represents an ObjC class declaration.
+///
+/// For example:
///
+/// \code
/// // MostPrimitive declares no super class (not particularly useful).
-/// @interface MostPrimitive
+/// \@interface MostPrimitive
/// // no instance variables or methods.
-/// @end
+/// \@end
///
/// // NSResponder inherits from NSObject & implements NSCoding (a protocol).
-/// @interface NSResponder : NSObject <NSCoding>
+/// \@interface NSResponder : NSObject \<NSCoding>
/// { // instance variables are represented by ObjCIvarDecl.
/// id nextResponder; // nextResponder instance variable.
/// }
/// - (NSResponder *)nextResponder; // return a pointer to NSResponder.
/// - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer
-/// @end // to an NSEvent.
+/// \@end // to an NSEvent.
+/// \endcode
///
-/// Unlike C/C++, forward class declarations are accomplished with @class.
-/// Unlike C/C++, @class allows for a list of classes to be forward declared.
+/// Unlike C/C++, forward class declarations are accomplished with \@class.
+/// Unlike C/C++, \@class allows for a list of classes to be forward declared.
/// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
/// typically inherit from NSObject (an exception is NSProxy).
///
@@ -566,10 +593,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// Class's super class.
ObjCInterfaceDecl *SuperClass;
- /// Protocols referenced in the @interface declaration
+ /// Protocols referenced in the \@interface declaration
ObjCProtocolList ReferencedProtocols;
- /// Protocols reference in both the @interface and class extensions.
+ /// Protocols reference in both the \@interface and class extensions.
ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
/// \brief List of categories and class extensions defined for this class.
@@ -799,21 +826,21 @@ public:
bool hasDefinition() const { return Data; }
/// \brief Retrieve the definition of this class, or NULL if this class
- /// has been forward-declared (with @class) but not yet defined (with
- /// @interface).
+ /// has been forward-declared (with \@class) but not yet defined (with
+ /// \@interface).
ObjCInterfaceDecl *getDefinition() {
return hasDefinition()? Data->Definition : 0;
}
/// \brief Retrieve the definition of this class, or NULL if this class
- /// has been forward-declared (with @class) but not yet defined (with
- /// @interface).
+ /// has been forward-declared (with \@class) but not yet defined (with
+ /// \@interface).
const ObjCInterfaceDecl *getDefinition() const {
return hasDefinition()? Data->Definition : 0;
}
/// \brief Starts the definition of this Objective-C class, taking it from
- /// a forward declaration (@class) to a definition (@interface).
+ /// a forward declaration (\@class) to a definition (\@interface).
void startDefinition();
ObjCInterfaceDecl *getSuperClass() const {
@@ -879,8 +906,8 @@ public:
}
/// isObjCRequiresPropertyDefs - Checks that a class or one of its super
- /// classes must not be auto-synthesized. Returns class decl. if it must not be;
- /// 0, otherwise.
+ /// classes must not be auto-synthesized. Returns class decl. if it must not
+ /// be; 0, otherwise.
const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const {
const ObjCInterfaceDecl *Class = this;
while (Class) {
@@ -912,8 +939,13 @@ public:
}
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
- // Lookup a method in the classes implementation hierarchy.
- ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true);
+ /// \brief Lookup a method in the classes implementation hierarchy.
+ ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel,
+ bool Instance=true) const;
+
+ ObjCMethodDecl *lookupPrivateClassMethod(const Selector &Sel) {
+ return lookupPrivateMethod(Sel, false);
+ }
SourceLocation getEndOfDefinitionLoc() const {
if (!hasDefinition())
@@ -928,8 +960,8 @@ public:
SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; }
/// isImplicitInterfaceDecl - check that this is an implicitly declared
- /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation
- /// declaration without an @interface declaration.
+ /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
+ /// declaration without an \@interface declaration.
bool isImplicitInterfaceDecl() const {
return hasDefinition() ? Data->Definition->isImplicit() : isImplicit();
}
@@ -972,14 +1004,14 @@ public:
/// instance variables are identical to C. The only exception is Objective-C
/// supports C++ style access control. For example:
///
-/// @interface IvarExample : NSObject
+/// \@interface IvarExample : NSObject
/// {
/// id defaultToProtected;
-/// @public:
+/// \@public:
/// id canBePublic; // same as C++.
-/// @protected:
+/// \@protected:
/// id canBeProtected; // same as C++.
-/// @package:
+/// \@package:
/// id canBePackage; // framework visibility (not available in C++).
/// }
///
@@ -997,7 +1029,7 @@ private:
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
bool synthesized)
: FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
- /*Mutable=*/false, /*HasInit=*/false),
+ /*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
public:
@@ -1046,8 +1078,7 @@ private:
};
-/// ObjCAtDefsFieldDecl - Represents a field declaration created by an
-/// @defs(...).
+/// \brief Represents a field declaration created by an \@defs(...).
class ObjCAtDefsFieldDecl : public FieldDecl {
virtual void anchor();
ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc,
@@ -1055,7 +1086,7 @@ class ObjCAtDefsFieldDecl : public FieldDecl {
QualType T, Expr *BW)
: FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
/*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
- BW, /*Mutable=*/false, /*HasInit=*/false) {}
+ BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {}
public:
static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1071,29 +1102,35 @@ public:
static bool classofKind(Kind K) { return K == ObjCAtDefsField; }
};
-/// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols
-/// declare a pure abstract type (i.e no instance variables are permitted).
-/// Protocols originally drew inspiration from C++ pure virtual functions (a C++
-/// feature with nice semantics and lousy syntax:-). Here is an example:
+/// \brief Represents an Objective-C protocol declaration.
+///
+/// Objective-C protocols declare a pure abstract type (i.e., no instance
+/// variables are permitted). Protocols originally drew inspiration from
+/// C++ pure virtual functions (a C++ feature with nice semantics and lousy
+/// syntax:-). Here is an example:
///
-/// @protocol NSDraggingInfo <refproto1, refproto2>
+/// \code
+/// \@protocol NSDraggingInfo <refproto1, refproto2>
/// - (NSWindow *)draggingDestinationWindow;
/// - (NSImage *)draggedImage;
-/// @end
+/// \@end
+/// \endcode
///
/// This says that NSDraggingInfo requires two methods and requires everything
/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as
/// well.
///
-/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo>
-/// @end
+/// \code
+/// \@interface ImplementsNSDraggingInfo : NSObject \<NSDraggingInfo>
+/// \@end
+/// \endcode
///
/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and
/// protocols are in distinct namespaces. For example, Cocoa defines both
/// an NSObject protocol and class (which isn't allowed in Java). As a result,
/// protocols are referenced using angle brackets as follows:
///
-/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
+/// id \<NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
///
class ObjCProtocolDecl : public ObjCContainerDecl,
public Redeclarable<ObjCProtocolDecl> {
@@ -1255,9 +1292,9 @@ public:
/// you to add instance data. The following example adds "myMethod" to all
/// NSView's within a process:
///
-/// @interface NSView (MyViewMethods)
+/// \@interface NSView (MyViewMethods)
/// - myMethod;
-/// @end
+/// \@end
///
/// Categories also allow you to split the implementation of a class across
/// several files (a feature more naturally supported in C++).
@@ -1279,9 +1316,6 @@ 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 category name in this declaration.
SourceLocation CategoryNameLoc;
@@ -1295,7 +1329,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation())
: ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
- ClassInterface(IDecl), NextClassCategory(0), HasSynthBitfield(false),
+ ClassInterface(IDecl), NextClassCategory(0),
CategoryNameLoc(CategoryNameLoc),
IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
}
@@ -1345,9 +1379,6 @@ public:
bool IsClassExtension() const { return getIdentifier() == 0; }
const ObjCCategoryDecl *getNextClassExtension() const;
- bool hasSynthBitfield() const { return HasSynthBitfield; }
- void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
-
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
ivar_iterator ivar_begin() const {
return ivar_iterator(decls_begin());
@@ -1431,16 +1462,16 @@ public:
};
/// ObjCCategoryImplDecl - An object of this class encapsulates a category
-/// @implementation declaration. If a category class has declaration of a
+/// \@implementation declaration. If a category class has declaration of a
/// property, its implementation must be specified in the category's
-/// @implementation declaration. Example:
-/// @interface I @end
-/// @interface I(CATEGORY)
-/// @property int p1, d1;
-/// @end
-/// @implementation I(CATEGORY)
-/// @dynamic p1,d1;
-/// @end
+/// \@implementation declaration. Example:
+/// \@interface I \@end
+/// \@interface I(CATEGORY)
+/// \@property int p1, d1;
+/// \@end
+/// \@implementation I(CATEGORY)
+/// \@dynamic p1,d1;
+/// \@end
///
/// ObjCCategoryImplDecl
class ObjCCategoryImplDecl : public ObjCImplDecl {
@@ -1493,15 +1524,6 @@ public:
return Id ? Id->getNameStart() : "";
}
- /// getNameAsCString - Get the name of identifier for the class
- /// interface associated with this implementation as a C string
- /// (const char*).
- //
- // FIXME: Deprecated, move clients to getName().
- const char *getNameAsCString() const {
- return Id ? Id->getNameStart() : "";
- }
-
/// @brief Get the name of the class associated with this interface.
//
// FIXME: Deprecated, move clients to getName().
@@ -1523,9 +1545,9 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID);
/// method definitions are specified. For example:
///
/// @code
-/// @implementation MyClass
+/// \@implementation MyClass
/// - (void)myMethod { /* do something */ }
-/// @end
+/// \@end
/// @endcode
///
/// Typically, instance variables are specified in the class interface,
@@ -1537,7 +1559,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
virtual void anchor();
/// Implementation Class's super class.
ObjCInterfaceDecl *SuperClass;
- /// @implementation may have private ivars.
+ /// \@implementation may have private ivars.
SourceLocation IvarLBraceLoc;
SourceLocation IvarRBraceLoc;
@@ -1549,9 +1571,6 @@ class ObjCImplementationDecl : public ObjCImplDecl {
/// true if class has a .cxx_[construct,destruct] method.
bool HasCXXStructors : 1;
- /// true of class extension has at least one bitfield ivar.
- bool HasSynthBitfield : 1;
-
ObjCImplementationDecl(DeclContext *DC,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl,
@@ -1562,7 +1581,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc),
IvarRBraceLoc(IvarRBraceLoc),
IvarInitializers(0), NumIvarInitializers(0),
- HasCXXStructors(false), HasSynthBitfield(false){}
+ HasCXXStructors(false) {}
public:
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
ObjCInterfaceDecl *classInterface,
@@ -1609,9 +1628,6 @@ public:
bool hasCXXStructors() const { return HasCXXStructors; }
void setHasCXXStructors(bool val) { HasCXXStructors = val; }
- bool hasSynthBitfield() const { return HasSynthBitfield; }
- void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
-
/// getIdentifier - Get the identifier that names the class
/// interface associated with this implementation.
IdentifierInfo *getIdentifier() const {
@@ -1628,15 +1644,6 @@ public:
return getIdentifier()->getName();
}
- /// getNameAsCString - Get the name of identifier for the class
- /// interface associated with this implementation as a C string
- /// (const char*).
- //
- // FIXME: Move to StringRef API.
- const char *getNameAsCString() const {
- return getName().data();
- }
-
/// @brief Get the name of the class associated with this interface.
//
// FIXME: Move to StringRef API.
@@ -1679,7 +1686,7 @@ public:
raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID);
/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
-/// declared as @compatibility_alias alias class.
+/// declared as \@compatibility_alias alias class.
class ObjCCompatibleAliasDecl : public NamedDecl {
virtual void anchor();
/// Class that this is an alias of.
@@ -1706,10 +1713,12 @@ public:
};
-/// ObjCPropertyDecl - Represents one property declaration in an interface.
-/// For example:
-/// @property (assign, readwrite) int MyProperty;
+/// \brief Represents one property declaration in an Objective-C interface.
///
+/// For example:
+/// \code{.mm}
+/// \@property (assign, readwrite) int MyProperty;
+/// \endcode
class ObjCPropertyDecl : public NamedDecl {
virtual void anchor();
public:
@@ -1738,12 +1747,12 @@ public:
enum SetterKind { Assign, Retain, Copy, Weak };
enum PropertyControl { None, Required, Optional };
private:
- SourceLocation AtLoc; // location of @property
+ SourceLocation AtLoc; // location of \@property
SourceLocation LParenLoc; // location of '(' starting attribute list or null.
TypeSourceInfo *DeclType;
unsigned PropertyAttributes : NumPropertyAttrsBits;
unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits;
- // @required/@optional
+ // \@required/\@optional
unsigned PropertyImplementation : 2;
Selector GetterName; // getter name of NULL if no getter
@@ -1855,7 +1864,7 @@ public:
ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; }
- // Related to @optional/@required declared in @protocol
+ // Related to \@optional/\@required declared in \@protocol
void setPropertyImplementation(PropertyControl pc) {
PropertyImplementation = pc;
}
@@ -1885,7 +1894,7 @@ public:
/// ObjCPropertyImplDecl - Represents implementation declaration of a property
/// in a class or category implementation block. For example:
-/// @synthesize prop1 = ivar1;
+/// \@synthesize prop1 = ivar1;
///
class ObjCPropertyImplDecl : public Decl {
public:
@@ -1894,26 +1903,27 @@ public:
Dynamic
};
private:
- SourceLocation AtLoc; // location of @synthesize or @dynamic
+ SourceLocation AtLoc; // location of \@synthesize or \@dynamic
- /// \brief For @synthesize, the location of the ivar, if it was written in
+ /// \brief For \@synthesize, the location of the ivar, if it was written in
/// the source code.
///
/// \code
- /// @synthesize int a = b
+ /// \@synthesize int a = b
/// \endcode
SourceLocation IvarLoc;
/// Property declaration being implemented
ObjCPropertyDecl *PropertyDecl;
- /// Null for @dynamic. Required for @synthesize.
+ /// Null for \@dynamic. Required for \@synthesize.
ObjCIvarDecl *PropertyIvarDecl;
- /// Null for @dynamic. Non-null if property must be copy-constructed in getter
+ /// Null for \@dynamic. Non-null if property must be copy-constructed in
+ /// getter.
Expr *GetterCXXConstructor;
- /// Null for @dynamic. Non-null if property has assignment operator to call
+ /// Null for \@dynamic. Non-null if property has assignment operator to call
/// in Setter synthesis.
Expr *SetterCXXAssignment;
@@ -1963,6 +1973,17 @@ public:
this->IvarLoc = IvarLoc;
}
+ /// \brief For \@synthesize, returns true if an ivar name was explicitly
+ /// specified.
+ ///
+ /// \code
+ /// \@synthesize int a = b; // true
+ /// \@synthesize int a; // false
+ /// \endcode
+ bool isIvarNameSpecified() const {
+ return IvarLoc.isValid() && IvarLoc != getLocation();
+ }
+
Expr *getGetterCXXConstructor() const {
return GetterCXXConstructor;
}
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 36549eab38d9..7affc7e15f27 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the C++ template declaration subclasses.
-//
+///
+/// \file
+/// \brief Defines the C++ template declaration subclasses.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H
@@ -38,8 +39,8 @@ class TypeAliasTemplateDecl;
typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
TemplateTemplateParmDecl*> TemplateParameter;
-/// TemplateParameterList - Stores a list of template parameters for a
-/// TemplateDecl and its derived classes.
+/// \brief Stores a list of template parameters for a TemplateDecl and its
+/// derived classes.
class TemplateParameterList {
/// The location of the 'template' keyword.
SourceLocation TemplateLoc;
@@ -64,10 +65,10 @@ public:
unsigned NumParams,
SourceLocation RAngleLoc);
- /// iterator - Iterates through the template parameters in this list.
+ /// \brief Iterates through the template parameters in this list.
typedef NamedDecl** iterator;
- /// const_iterator - Iterates through the template parameters in this list.
+ /// \brief Iterates through the template parameters in this list.
typedef NamedDecl* const* const_iterator;
iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); }
@@ -90,9 +91,10 @@ public:
}
/// \brief Returns the minimum number of arguments needed to form a
- /// template specialization. This may be fewer than the number of
- /// template parameters, if some of the parameters have default
- /// arguments or if there is a parameter pack.
+ /// template specialization.
+ ///
+ /// This may be fewer than the number of template parameters, if some of
+ /// the parameters have default arguments or if there is a parameter pack.
unsigned getMinRequiredArguments() const;
/// \brief Get the depth of this template parameter list in the set of
@@ -111,8 +113,8 @@ public:
}
};
-/// FixedSizeTemplateParameterList - Stores a list of template parameters for a
-/// TemplateDecl and its derived classes. Suitable for creating on the stack.
+/// \brief Stores a list of template parameters for a TemplateDecl and its
+/// derived classes. Suitable for creating on the stack.
template<size_t N>
class FixedSizeTemplateParameterList : public TemplateParameterList {
NamedDecl *Params[N];
@@ -195,10 +197,11 @@ public:
// Kinds of Templates
//===----------------------------------------------------------------------===//
-/// TemplateDecl - The base class of all kinds of template declarations (e.g.,
-/// class, function, etc.). The TemplateDecl class stores the list of template
-/// parameters and a reference to the templated scoped declaration: the
-/// underlying AST node.
+/// \brief The base class of all kinds of template declarations (e.g.,
+/// class, function, etc.).
+///
+/// The TemplateDecl class stores the list of template parameters and a
+/// reference to the templated scoped declaration: the underlying AST node.
class TemplateDecl : public NamedDecl {
virtual void anchor();
protected:
@@ -404,16 +407,19 @@ public:
};
/// \brief Provides information about a dependent function-template
-/// specialization declaration. Since explicit function template
-/// specialization and instantiation declarations can only appear in
-/// namespace scope, and you can only specialize a member of a
-/// fully-specialized class, the only way to get one of these is in
-/// a friend declaration like the following:
+/// specialization declaration.
+///
+/// Since explicit function template specialization and instantiation
+/// declarations can only appear in namespace scope, and you can only
+/// specialize a member of a fully-specialized class, the only way to
+/// get one of these is in a friend declaration like the following:
///
-/// template <class T> void foo(T);
-/// template <class T> class A {
+/// \code
+/// template \<class T> void foo(T);
+/// template \<class T> class A {
/// friend void foo<>(T);
/// };
+/// \endcode
class DependentFunctionTemplateSpecializationInfo {
union {
// Force sizeof to be a multiple of sizeof(void*) so that the
@@ -512,7 +518,8 @@ protected:
typedef _SETraits SETraits;
typedef _DeclType DeclType;
- typedef typename llvm::FoldingSet<EntryType>::iterator SetIteratorType;
+ typedef typename llvm::FoldingSetVector<EntryType>::iterator
+ SetIteratorType;
SetIteratorType SetIter;
@@ -541,13 +548,13 @@ protected:
};
template <typename EntryType>
- SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSet<EntryType> &Specs,
- bool isEnd) {
+ SpecIterator<EntryType>
+ makeSpecIterator(llvm::FoldingSetVector<EntryType> &Specs, bool isEnd) {
return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
}
template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
- findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs,
+ findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
const TemplateArgument *Args, unsigned NumArgs,
void *&InsertPos);
@@ -583,7 +590,7 @@ protected:
public:
template <class decl_type> friend class RedeclarableTemplate;
- /// Retrieves the canonical declaration of this template.
+ /// \brief Retrieves the canonical declaration of this template.
RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDeclaration(); }
const RedeclarableTemplateDecl *getCanonicalDecl() const {
return getFirstDeclaration();
@@ -646,7 +653,7 @@ public:
///
/// which was itself created during the instantiation of \c X<int>. Calling
/// getInstantiatedFromMemberTemplate() on this FunctionTemplateDecl will
- /// retrieve the FunctionTemplateDecl for the original template "f" within
+ /// retrieve the FunctionTemplateDecl for the original template \c f within
/// the class template \c X<T>, i.e.,
///
/// \code
@@ -706,7 +713,7 @@ protected:
/// \brief The function template specializations for this function
/// template, including explicit specializations and instantiations.
- llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
+ llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations;
/// \brief The set of "injected" template arguments used within this
/// function template.
@@ -732,13 +739,14 @@ protected:
/// \brief Retrieve the set of function template specializations of this
/// function template.
- llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
+ llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
+ getSpecializations() {
return getCommonPtr()->Specializations;
}
/// \brief Add a specialization of this function template.
///
- /// \param InsertPos Insert position in the FoldingSet, must have been
+ /// \param InsertPos Insert position in the FoldingSetVector, must have been
/// retrieved by an earlier call to findSpecialization().
void addSpecialization(FunctionTemplateSpecializationInfo* Info,
void *InsertPos);
@@ -830,8 +838,10 @@ public:
// Kinds of Template Parameters
//===----------------------------------------------------------------------===//
-/// The TemplateParmPosition class defines the position of a template parameter
-/// within a template parameter list. Because template parameter can be listed
+/// \brief Defines the position of a template parameter within a template
+/// parameter list.
+///
+/// Because template parameter can be listed
/// sequentially for out-of-line template members, each template parameter is
/// given a Depth - the nesting of template parameter scopes - and a Position -
/// the occurrence within the parameter list.
@@ -866,15 +876,17 @@ public:
unsigned getIndex() const { return Position; }
};
-/// TemplateTypeParmDecl - Declaration of a template type parameter,
-/// e.g., "T" in
-/// @code
+/// \brief Declaration of a template type parameter.
+///
+/// For example, "T" in
+/// \code
/// template<typename T> class vector;
-/// @endcode
+/// \endcode
class TemplateTypeParmDecl : public TypeDecl {
/// \brief Whether this template type parameter was declaration with
- /// the 'typename' keyword. If false, it was declared with the
- /// 'class' keyword.
+ /// the 'typename' keyword.
+ ///
+ /// If false, it was declared with the 'class' keyword.
bool Typename : 1;
/// \brief Whether this template type parameter inherited its
@@ -904,8 +916,9 @@ public:
unsigned ID);
/// \brief Whether this template type parameter was declared with
- /// the 'typename' keyword. If not, it was declared with the 'class'
- /// keyword.
+ /// the 'typename' keyword.
+ ///
+ /// If not, it was declared with the 'class' keyword.
bool wasDeclaredWithTypename() const { return Typename; }
/// \brief Determine whether this template parameter has a default
@@ -1688,11 +1701,11 @@ protected:
/// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations.
- llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
+ llvm::FoldingSetVector<ClassTemplateSpecializationDecl> Specializations;
/// \brief The class template partial specializations for this class
/// template.
- llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>
+ llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>
PartialSpecializations;
/// \brief The injected-class-name type for this class template.
@@ -1710,11 +1723,11 @@ protected:
void LoadLazySpecializations();
/// \brief Retrieve the set of specializations of this class template.
- llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations();
+ llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &getSpecializations();
/// \brief Retrieve the set of partial specializations of this class
/// template.
- llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
+ llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
getPartialSpecializations();
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
@@ -1732,18 +1745,18 @@ protected:
}
public:
- /// Get the underlying class declarations of the template.
+ /// \brief Get the underlying class declarations of the template.
CXXRecordDecl *getTemplatedDecl() const {
return static_cast<CXXRecordDecl *>(TemplatedDecl);
}
- /// Returns whether this template declaration defines the primary
+ /// \brief Returns whether this template declaration defines the primary
/// class pattern.
bool isThisDeclarationADefinition() const {
return getTemplatedDecl()->isThisDeclarationADefinition();
}
- /// Create a class template node.
+ /// \brief Create a class template node.
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
@@ -1751,7 +1764,7 @@ public:
NamedDecl *Decl,
ClassTemplateDecl *PrevDecl);
- /// Create an empty class template node.
+ /// \brief Create an empty class template node.
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
/// \brief Return the specialization with the provided arguments if it exists,
@@ -1880,14 +1893,18 @@ public:
friend class ASTDeclWriter;
};
-/// Declaration of a friend template. For example:
+/// \brief Declaration of a friend template.
///
-/// template <typename T> class A {
+/// For example:
+/// \code
+/// template \<typename T> class A {
/// friend class MyVector<T>; // not a friend template
-/// template <typename U> friend class B; // not a friend template
-/// template <typename U> friend class Foo<T>::Nested; // friend template
+/// template \<typename U> friend class B; // not a friend template
+/// template \<typename U> friend class Foo<T>::Nested; // friend template
/// };
-/// NOTE: This class is not currently in use. All of the above
+/// \endcode
+///
+/// \note This class is not currently in use. All of the above
/// will yield a FriendDecl, not a FriendTemplateDecl.
class FriendTemplateDecl : public Decl {
virtual void anchor();
@@ -1950,7 +1967,7 @@ public:
return Friend.dyn_cast<NamedDecl*>();
}
- /// Retrieves the location of the 'friend' keyword.
+ /// \brief Retrieves the location of the 'friend' keyword.
SourceLocation getFriendLoc() const {
return FriendLoc;
}
@@ -1972,9 +1989,12 @@ public:
friend class ASTDeclReader;
};
-/// Declaration of an alias template. For example:
+/// \brief Declaration of an alias template.
///
-/// template <typename T> using V = std::map<T*, int, MyCompare<T>>;
+/// For example:
+/// \code
+/// template \<typename T> using V = std::map<T*, int, MyCompare<T>>;
+/// \endcode
class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
static void DeallocateCommon(void *Ptr);
@@ -2046,14 +2066,18 @@ public:
friend class ASTDeclWriter;
};
-/// Declaration of a function specialization at template class scope.
+/// \brief Declaration of a function specialization at template class scope.
+///
/// This is a non standard extension needed to support MSVC.
+///
/// For example:
+/// \code
/// template <class T>
/// class A {
/// template <class U> void foo(U a) { }
/// template<> void foo(int a) { }
/// }
+/// \endcode
///
/// "template<> foo(int a)" will be saved in Specialization as a normal
/// CXXMethodDecl. Then during an instantiation of class A, it will be
@@ -2062,23 +2086,33 @@ class ClassScopeFunctionSpecializationDecl : public Decl {
virtual void anchor();
ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc,
- CXXMethodDecl *FD)
+ CXXMethodDecl *FD, bool Args,
+ TemplateArgumentListInfo TemplArgs)
: Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc),
- Specialization(FD) {}
+ Specialization(FD), HasExplicitTemplateArgs(Args),
+ TemplateArgs(TemplArgs) {}
ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
: Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
CXXMethodDecl *Specialization;
+ bool HasExplicitTemplateArgs;
+ TemplateArgumentListInfo TemplateArgs;
public:
CXXMethodDecl *getSpecialization() const { return Specialization; }
+ bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
+ const TemplateArgumentListInfo& templateArgs() const { return TemplateArgs; }
static ClassScopeFunctionSpecializationDecl *Create(ASTContext &C,
DeclContext *DC,
SourceLocation Loc,
- CXXMethodDecl *FD) {
- return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD);
+ CXXMethodDecl *FD,
+ bool HasExplicitTemplateArgs,
+ TemplateArgumentListInfo TemplateArgs) {
+ return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD,
+ HasExplicitTemplateArgs,
+ TemplateArgs);
}
static ClassScopeFunctionSpecializationDecl *
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 6349d9c001fd..614652540679 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -58,11 +58,14 @@ public:
private:
/// StoredNameKind - The kind of name that is actually stored in the
/// upper bits of the Ptr field. This is only used internally.
+ ///
+ /// Note: The entries here are synchronized with the entries in Selector,
+ /// for efficient translation between the two.
enum StoredNameKind {
StoredIdentifier = 0,
- StoredObjCZeroArgSelector,
- StoredObjCOneArgSelector,
- StoredDeclarationNameExtra,
+ StoredObjCZeroArgSelector = 0x01,
+ StoredObjCOneArgSelector = 0x02,
+ StoredDeclarationNameExtra = 0x03,
PtrMask = 0x03
};
@@ -106,8 +109,8 @@ private:
/// CXXSpecialName, returns a pointer to it. Otherwise, returns
/// a NULL pointer.
CXXSpecialName *getAsCXXSpecialName() const {
- if (getNameKind() >= CXXConstructorName &&
- getNameKind() <= CXXConversionFunctionName)
+ NameKind Kind = getNameKind();
+ if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName)
return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
return 0;
}
@@ -153,9 +156,9 @@ private:
friend class DeclarationNameTable;
friend class NamedDecl;
- /// getFETokenInfoAsVoid - Retrieves the front end-specified pointer
- /// for this name as a void pointer.
- void *getFETokenInfoAsVoid() const;
+ /// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer
+ /// for this name as a void pointer if it's not an identifier.
+ void *getFETokenInfoAsVoidSlow() const;
public:
/// DeclarationName - Used to create an empty selector.
@@ -168,7 +171,7 @@ public:
}
// Construct a declaration name from an Objective-C selector.
- DeclarationName(Selector Sel);
+ DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) { }
/// getUsingDirectiveName - Return name for all using-directives.
static DeclarationName getUsingDirectiveName();
@@ -251,14 +254,24 @@ public:
/// getObjCSelector - Get the Objective-C selector stored in this
/// declaration name.
- Selector getObjCSelector() const;
+ Selector getObjCSelector() const {
+ assert((getNameKind() == ObjCZeroArgSelector ||
+ getNameKind() == ObjCOneArgSelector ||
+ getNameKind() == ObjCMultiArgSelector ||
+ Ptr == 0) && "Not a selector!");
+ return Selector(Ptr);
+ }
/// getFETokenInfo/setFETokenInfo - The language front-end is
/// allowed to associate arbitrary metadata with some kinds of
/// declaration names, including normal identifiers and C++
/// constructors, destructors, and conversion functions.
template<typename T>
- T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); }
+ T *getFETokenInfo() const {
+ if (const IdentifierInfo *Info = getAsIdentifierInfo())
+ return Info->getFETokenInfo<T>();
+ return static_cast<T*>(getFETokenInfoAsVoidSlow());
+ }
void setFETokenInfo(void *T);
@@ -564,7 +577,9 @@ struct DenseMapInfo<clang::DeclarationName> {
return clang::DeclarationName::getTombstoneMarker();
}
- static unsigned getHashValue(clang::DeclarationName);
+ static unsigned getHashValue(clang::DeclarationName Name) {
+ return DenseMapInfo<void*>::getHashValue(Name.getAsOpaquePtr());
+ }
static inline bool
isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
index bab1606dcee4..d5e9c8c678fe 100644
--- a/include/clang/AST/EvaluatedExprVisitor.h
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -24,7 +24,7 @@ namespace clang {
class ASTContext;
-/// \begin Given a potentially-evaluated expression, this visitor visits all
+/// \brief Given a potentially-evaluated expression, this visitor visits all
/// of its potentially-evaluated subexpressions, recursively.
template<typename ImplClass>
class EvaluatedExprVisitor : public StmtVisitor<ImplClass> {
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index b0b9b0fd6ffe..89c003c8f664 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_EXPR_H
#include "clang/AST/APValue.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/AST/DeclAccessPair.h"
@@ -179,11 +180,12 @@ public:
SourceLocation getExprLoc() const LLVM_READONLY;
/// isUnusedResultAWarning - Return true if this immediate expression should
- /// be warned about if the result is unused. If so, fill in Loc and Ranges
- /// with location to warn on and the source range[s] to report with the
- /// warning.
- bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
- SourceRange &R2, ASTContext &Ctx) const;
+ /// be warned about if the result is unused. If so, fill in expr, location,
+ /// and ranges with expr to warn on and source locations/ranges appropriate
+ /// for a warning.
+ bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc,
+ SourceRange &R1, SourceRange &R2,
+ ASTContext &Ctx) const;
/// isLValue - True if this expression is an "l-value" according to
/// the rules of the current language. C and C++ give somewhat
@@ -212,7 +214,8 @@ public:
LV_InvalidMessageExpression,
LV_MemberFunction,
LV_SubObjCPropertySetting,
- LV_ClassTemporary
+ LV_ClassTemporary,
+ LV_ArrayTemporary
};
/// Reasons why an expression might not be an l-value.
LValueClassification ClassifyLValue(ASTContext &Ctx) const;
@@ -223,7 +226,7 @@ public:
/// recursively, any member or element of all contained aggregates or unions)
/// with a const-qualified type.
///
- /// \param Loc [in] [out] - A source location which *may* be filled
+ /// \param Loc [in,out] - A source location which *may* be filled
/// in with the location of the expression making this a
/// non-modifiable lvalue, if specified.
enum isModifiableLvalueResult {
@@ -241,7 +244,8 @@ public:
MLV_MemberFunction,
MLV_SubObjCPropertySetting,
MLV_InvalidMessageExpression,
- MLV_ClassTemporary
+ MLV_ClassTemporary,
+ MLV_ArrayTemporary
};
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
SourceLocation *Loc = 0) const;
@@ -260,7 +264,8 @@ public:
CL_DuplicateVectorComponents, // A vector shuffle with dupes.
CL_MemberFunction, // An expression referring to a member function
CL_SubObjCPropertySetting,
- CL_ClassTemporary, // A prvalue of class type
+ CL_ClassTemporary, // A temporary of class type, or subobject thereof.
+ CL_ArrayTemporary, // A temporary of array type.
CL_ObjCMessageRValue, // ObjC message is an rvalue
CL_PRValue // A prvalue for any other reason, of any other type
};
@@ -505,9 +510,8 @@ public:
bool isEvaluatable(const ASTContext &Ctx) const;
/// HasSideEffects - This routine returns true for all those expressions
- /// which must be evaluated each time and must not be optimized away
- /// or evaluated at compile time. Example is a function call, volatile
- /// variable read.
+ /// which have any effect other than producing a value. Example is a function
+ /// call, volatile variable read, or throwing an exception.
bool HasSideEffects(const ASTContext &Ctx) const;
/// \brief Determine whether this expression involves a call to any function
@@ -537,8 +541,15 @@ public:
/// \brief Expression is not a Null pointer constant.
NPCK_NotNull = 0,
- /// \brief Expression is a Null pointer constant built from a zero integer.
- NPCK_ZeroInteger,
+ /// \brief Expression is a Null pointer constant built from a zero integer
+ /// expression that is not a simple, possibly parenthesized, zero literal.
+ /// C++ Core Issue 903 will classify these expressions as "not pointers"
+ /// once it is adopted.
+ /// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
+ NPCK_ZeroExpression,
+
+ /// \brief Expression is a Null pointer constant built from a literal zero.
+ NPCK_ZeroLiteral,
/// \brief Expression is a C++0X nullptr.
NPCK_CXX0X_nullptr,
@@ -591,6 +602,10 @@ public:
return cast<Expr>(Stmt::IgnoreImplicit());
}
+ const Expr *IgnoreImplicit() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->IgnoreImplicit();
+ }
+
/// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
/// its subexpression. If that subexpression is also a ParenExpr,
/// then this method recursively returns its subexpression, and so forth.
@@ -630,6 +645,13 @@ public:
/// ParenExpr or CastExprs, returning their operand.
Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY;
+ /// Ignore parentheses and derived-to-base casts.
+ Expr *ignoreParenBaseCasts() LLVM_READONLY;
+
+ const Expr *ignoreParenBaseCasts() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->ignoreParenBaseCasts();
+ }
+
/// \brief Determine whether this expression is a default function argument.
///
/// Default arguments are implicitly generated in the abstract syntax tree
@@ -661,6 +683,15 @@ public:
static bool hasAnyTypeDependentArguments(llvm::ArrayRef<Expr *> Exprs);
+ /// \brief For an expression of class type or pointer to class type,
+ /// return the most derived class decl the expression is known to refer to.
+ ///
+ /// If this expression is a cast, this method looks through it to find the
+ /// most derived decl that can be inferred from the expression.
+ /// This is valid because derived-to-base conversions have undefined
+ /// behavior if the object isn't dynamically of the derived type.
+ const CXXRecordDecl *getBestDynamicClassType() const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExprConstant &&
T->getStmtClass() <= lastExprConstant;
@@ -1043,6 +1074,7 @@ public:
enum IdentType {
Func,
Function,
+ LFunction, // Same as Function, but as wide string.
PrettyFunction,
/// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
@@ -1142,16 +1174,8 @@ class IntegerLiteral : public Expr, public APIntStorage {
public:
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
// or UnsignedLongLongTy
- IntegerLiteral(ASTContext &C, const llvm::APInt &V,
- QualType type, SourceLocation l)
- : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
- false, false),
- Loc(l) {
- assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
- assert(V.getBitWidth() == C.getIntWidth(type) &&
- "Integer type is not the correct size for constant.");
- setValue(C, V);
- }
+ IntegerLiteral(ASTContext &C, const llvm::APInt &V, QualType type,
+ SourceLocation l);
/// \brief Returns a new integer literal with value 'V' and type 'type'.
/// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy,
@@ -1229,22 +1253,10 @@ class FloatingLiteral : public Expr, private APFloatStorage {
SourceLocation Loc;
FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
- QualType Type, SourceLocation L)
- : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
- false, false), Loc(L) {
- FloatingLiteralBits.IsIEEE =
- &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad;
- FloatingLiteralBits.IsExact = isexact;
- setValue(C, V);
- }
+ QualType Type, SourceLocation L);
/// \brief Construct an empty floating-point literal.
- explicit FloatingLiteral(ASTContext &C, EmptyShell Empty)
- : Expr(FloatingLiteralClass, Empty) {
- FloatingLiteralBits.IsIEEE =
- &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad;
- FloatingLiteralBits.IsExact = false;
- }
+ explicit FloatingLiteral(ASTContext &C, EmptyShell Empty);
public:
static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V,
@@ -1381,8 +1393,8 @@ public:
return StringRef(StrData.asChar, getByteLength());
}
- /// Allow clients that need the byte representation, such as ASTWriterStmt
- /// ::VisitStringLiteral(), access.
+ /// Allow access to clients that need the byte representation, such as
+ /// ASTWriterStmt::VisitStringLiteral().
StringRef getBytes() const {
// FIXME: StringRef may not be the right type to use as a result for this.
if (CharByteWidth == 1)
@@ -1395,6 +1407,8 @@ public:
getByteLength());
}
+ void outputString(raw_ostream &OS);
+
uint32_t getCodeUnit(size_t i) const {
assert(i < Length && "out of bounds access");
if (CharByteWidth == 1)
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index b69693d7c6a3..ecfa9e213637 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_EXPRCXX_H
#define LLVM_CLANG_AST_EXPRCXX_H
+#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/AST/TemplateBase.h"
@@ -50,14 +51,18 @@ class TemplateArgumentListInfo;
class CXXOperatorCallExpr : public CallExpr {
/// \brief The overloaded operator.
OverloadedOperatorKind Operator;
+ SourceRange Range;
+ SourceRange getSourceRangeImpl() const LLVM_READONLY;
public:
CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
Expr **args, unsigned numargs, QualType t,
ExprValueKind VK, SourceLocation operatorloc)
: CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, numargs, t, VK,
operatorloc),
- Operator(Op) {}
+ Operator(Op) {
+ Range = getSourceRangeImpl();
+ }
explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
CallExpr(C, CXXOperatorCallExprClass, Empty) { }
@@ -65,7 +70,6 @@ public:
/// getOperator - Returns the kind of overloaded operator that this
/// expression refers to.
OverloadedOperatorKind getOperator() const { return Operator; }
- void setOperator(OverloadedOperatorKind Kind) { Operator = Kind; }
/// getOperatorLoc - Returns the location of the operator symbol in
/// the expression. When @c getOperator()==OO_Call, this is the
@@ -74,12 +78,15 @@ public:
/// bracket.
SourceLocation getOperatorLoc() const { return getRParenLoc(); }
- SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const { return Range; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXOperatorCallExprClass;
}
static bool classof(const CXXOperatorCallExpr *) { return true; }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// CXXMemberCallExpr - Represents a call to a member function that
@@ -112,7 +119,7 @@ public:
/// declaration as that of the class context of the CXXMethodDecl which this
/// function is calling.
/// FIXME: Returns 0 for member pointer call exprs.
- CXXRecordDecl *getRecordDecl();
+ CXXRecordDecl *getRecordDecl() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXMemberCallExprClass;
@@ -369,10 +376,21 @@ public:
return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral();
}
+ SourceLocation getLocStart() const {
+ if (getLiteralOperatorKind() == LOK_Template)
+ return getRParenLoc();
+ return getArg(0)->getLocStart();
+ }
+ SourceLocation getLocEnd() const { return getRParenLoc(); }
+ SourceRange getSourceRange() const {
+ return SourceRange(getLocStart(), getLocEnd());
+ }
+
+
/// getUDSuffixLoc - Returns the location of a ud-suffix in the expression.
/// For a string literal, there may be multiple identical suffixes. This
/// returns the first.
- SourceLocation getUDSuffixLoc() const { return getRParenLoc(); }
+ SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; }
/// getUDSuffix - Returns the ud-suffix specified for this literal.
const IdentifierInfo *getUDSuffix() const;
@@ -481,6 +499,10 @@ public:
Operand = (TypeSourceInfo*)0;
}
+ /// Determine whether this typeid has a type operand which is potentially
+ /// evaluated, per C++11 [expr.typeid]p3.
+ bool isPotentiallyEvaluated() const;
+
bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }
/// \brief Retrieves the type operand of this typeid() expression after
@@ -859,7 +881,7 @@ public:
child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
};
-/// CXXConstructExpr - Represents a call to a C++ constructor.
+/// \brief Represents a call to a C++ constructor.
class CXXConstructExpr : public Expr {
public:
enum ConstructionKind {
@@ -983,6 +1005,7 @@ public:
SourceRange getSourceRange() const LLVM_READONLY;
SourceRange getParenRange() const { return ParenRange; }
+ void setParenRange(SourceRange Range) { ParenRange = Range; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstructExprClass ||
@@ -998,9 +1021,13 @@ public:
friend class ASTStmtReader;
};
-/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion
-/// that uses "functional" notion (C++ [expr.type.conv]). Example: @c
-/// x = int(0.5);
+/// \brief Represents an explicit C++ type conversion that uses "functional"
+/// notation (C++ [expr.type.conv]).
+///
+/// Example:
+/// @code
+/// x = int(0.5);
+/// @endcode
class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
@@ -1231,7 +1258,8 @@ private:
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace);
+ SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack);
/// \brief Construct an empty lambda expression.
LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars)
@@ -1269,7 +1297,8 @@ public:
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace);
+ SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack);
/// \brief Construct a new lambda expression that will be deserialized from
/// an external source.
@@ -1419,15 +1448,16 @@ public:
child_range children() { return child_range(); }
};
-/// CXXNewExpr - A new expression for memory allocation and constructor calls,
-/// e.g: "new CXXNewExpr(foo)".
+/// @brief Represents a new-expression for memory allocation and constructor
+// calls, e.g: "new CXXNewExpr(foo)".
class CXXNewExpr : public Expr {
// Contains an optional array size expression, an optional initialization
// expression, and any number of optional placement arguments, in that order.
Stmt **SubExprs;
- // Points to the allocation function used.
+ /// \brief Points to the allocation function used.
FunctionDecl *OperatorNew;
- // Points to the deallocation function used in case of error. May be null.
+ /// \brief Points to the deallocation function used in case of error. May be
+ /// null.
FunctionDecl *OperatorDelete;
/// \brief The allocated type-source information, as written in the source.
@@ -1607,8 +1637,8 @@ public:
}
};
-/// CXXDeleteExpr - A delete expression for memory deallocation and destructor
-/// calls, e.g. "delete[] pArray".
+/// \brief Represents a \c delete expression for memory deallocation and
+/// destructor calls, e.g. "delete[] pArray".
class CXXDeleteExpr : public Expr {
// Points to the operator delete overload that is used. Could be a member.
FunctionDecl *OperatorDelete;
@@ -1678,8 +1708,7 @@ public:
friend class ASTStmtReader;
};
-/// \brief Structure used to store the type being destroyed by a
-/// pseudo-destructor expression.
+/// \brief Stores the type being destroyed by a pseudo-destructor expression.
class PseudoDestructorTypeStorage {
/// \brief Either the type source information or the name of the type, if
/// it couldn't be resolved due to type-dependence.
@@ -1866,11 +1895,14 @@ public:
child_range children() { return child_range(&Base, &Base + 1); }
};
-/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
-/// implementation of TR1/C++0x type trait templates.
+/// \brief Represents a GCC or MS unary type trait, as used in the
+/// implementation of TR1/C++11 type trait templates.
+///
/// Example:
-/// __is_pod(int) == true
-/// __is_enum(std::string) == false
+/// @code
+/// __is_pod(int) == true
+/// __is_enum(std::string) == false
+/// @endcode
class UnaryTypeTraitExpr : public Expr {
/// UTT - The trait. A UnaryTypeTrait enum in MSVC compat unsigned.
unsigned UTT : 31;
@@ -1921,10 +1953,13 @@ public:
friend class ASTStmtReader;
};
-/// BinaryTypeTraitExpr - A GCC or MS binary type trait, as used in the
-/// implementation of TR1/C++0x type trait templates.
+/// \brief Represents a GCC or MS binary type trait, as used in the
+/// implementation of TR1/C++11 type trait templates.
+///
/// Example:
-/// __is_base_of(Base, Derived) == true
+/// @code
+/// __is_base_of(Base, Derived) == true
+/// @endcode
class BinaryTypeTraitExpr : public Expr {
/// BTT - The trait. A BinaryTypeTrait enum in MSVC compat unsigned.
unsigned BTT : 8;
@@ -2086,30 +2121,33 @@ public:
};
-/// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the
-/// implementation of __array_rank and __array_extent.
+/// \brief An Embarcadero array type trait, as used in the implementation of
+/// __array_rank and __array_extent.
+///
/// Example:
-/// __array_rank(int[10][20]) == 2
-/// __array_extent(int, 1) == 20
+/// @code
+/// __array_rank(int[10][20]) == 2
+/// __array_extent(int, 1) == 20
+/// @endcode
class ArrayTypeTraitExpr : public Expr {
virtual void anchor();
- /// ATT - The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
+ /// \brief The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
unsigned ATT : 2;
- /// The value of the type trait. Unspecified if dependent.
+ /// \brief The value of the type trait. Unspecified if dependent.
uint64_t Value;
- /// The array dimension being queried, or -1 if not used
+ /// \brief The array dimension being queried, or -1 if not used.
Expr *Dimension;
- /// Loc - The location of the type trait keyword.
+ /// \brief The location of the type trait keyword.
SourceLocation Loc;
- /// RParen - The location of the closing paren.
+ /// \brief The location of the closing paren.
SourceLocation RParen;
- /// The type being queried.
+ /// \brief The type being queried.
TypeSourceInfo *QueriedType;
public:
@@ -2156,22 +2194,26 @@ public:
friend class ASTStmtReader;
};
-/// ExpressionTraitExpr - An expression trait intrinsic
+/// \brief An expression trait intrinsic.
+///
/// Example:
-/// __is_lvalue_expr(std::cout) == true
-/// __is_lvalue_expr(1) == false
+/// @code
+/// __is_lvalue_expr(std::cout) == true
+/// __is_lvalue_expr(1) == false
+/// @endcode
class ExpressionTraitExpr : public Expr {
- /// ET - The trait. A ExpressionTrait enum in MSVC compat unsigned.
+ /// \brief The trait. A ExpressionTrait enum in MSVC compat unsigned.
unsigned ET : 31;
- /// The value of the type trait. Unspecified if dependent.
+ /// \brief The value of the type trait. Unspecified if dependent.
bool Value : 1;
- /// Loc - The location of the type trait keyword.
+ /// \brief The location of the type trait keyword.
SourceLocation Loc;
- /// RParen - The location of the closing paren.
+ /// \brief The location of the closing paren.
SourceLocation RParen;
+ /// \brief The expression being queried.
Expr* QueriedExpression;
public:
ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et,
@@ -2190,7 +2232,9 @@ public:
: Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false),
QueriedExpression() { }
- SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, RParen);}
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(Loc, RParen);
+ }
ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); }
@@ -2211,9 +2255,9 @@ public:
/// \brief A reference to an overloaded function set, either an
-/// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr.
+/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr.
class OverloadExpr : public Expr {
- /// The common name of these declarations.
+ /// \brief The common name of these declarations.
DeclarationNameInfo NameInfo;
/// \brief The nested-name-specifier that qualifies the name, if any.
@@ -2292,7 +2336,7 @@ public:
return Result;
}
- /// Gets the naming class of this lookup, if any.
+ /// \brief Gets the naming class of this lookup, if any.
CXXRecordDecl *getNamingClass() const;
typedef UnresolvedSetImpl::iterator decls_iterator;
@@ -2301,25 +2345,25 @@ public:
return UnresolvedSetIterator(Results + NumResults);
}
- /// Gets the number of declarations in the unresolved set.
+ /// \brief Gets the number of declarations in the unresolved set.
unsigned getNumDecls() const { return NumResults; }
- /// Gets the full name info.
+ /// \brief Gets the full name info.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
- /// Gets the name looked up.
+ /// \brief Gets the name looked up.
DeclarationName getName() const { return NameInfo.getName(); }
- /// Gets the location of the name.
+ /// \brief Gets the location of the name.
SourceLocation getNameLoc() const { return NameInfo.getLoc(); }
- /// Fetches the nested-name qualifier, if one was given.
+ /// \brief Fetches the nested-name qualifier, if one was given.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
- /// Fetches the nested-name qualifier with source-location information, if
- /// one was given.
+ /// \brief Fetches the nested-name qualifier with source-location
+ /// information, if one was given.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
/// \brief Retrieve the location of the template keyword preceding
@@ -2343,10 +2387,10 @@ public:
return getTemplateKWAndArgsInfo()->RAngleLoc;
}
- /// Determines whether the name was preceded by the template keyword.
+ /// \brief Determines whether the name was preceded by the template keyword.
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
- /// Determines whether this expression had explicit template arguments.
+ /// \brief Determines whether this expression had explicit template arguments.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
// Note that, inconsistently with the explicit-template-argument AST
@@ -2370,12 +2414,13 @@ public:
return getExplicitTemplateArgs().NumTemplateArgs;
}
- /// Copies the template arguments into the given structure.
+ /// \brief Copies the template arguments into the given structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
getExplicitTemplateArgs().copyInto(List);
}
/// \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 ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() {
@@ -2394,15 +2439,15 @@ public:
};
/// \brief A reference to a name which we were able to look up during
-/// parsing but could not resolve to a specific declaration. This
-/// arises in several ways:
+/// parsing but could not resolve to a specific declaration.
+///
+/// This arises in several ways:
/// * we might be waiting for argument-dependent lookup
/// * the name might resolve to an overloaded function
/// and eventually:
/// * the lookup might have included a function template
-/// These never include UnresolvedUsingValueDecls, which are always
-/// class members and therefore appear only in
-/// UnresolvedMemberLookupExprs.
+/// These never include UnresolvedUsingValueDecls, which are always class
+/// members and therefore appear only in UnresolvedMemberLookupExprs.
class UnresolvedLookupExpr : public OverloadExpr {
/// True if these lookup results should be extended by
/// argument-dependent lookup if this is the operand of a function
@@ -2483,8 +2528,8 @@ public:
/// argument-dependent lookup.
bool requiresADL() const { return RequiresADL; }
- /// True if namespace ::std should be artificially added to the set of
- /// associated namespaecs for argument-dependent lookup purposes.
+ /// True if namespace \::std should be artificially added to the set of
+ /// associated namespaces for argument-dependent lookup purposes.
bool isStdAssociatedNamespace() const { return StdIsAssociatedNamespace; }
/// True if this lookup is overloaded.
@@ -2744,9 +2789,9 @@ public:
/// type-dependent.
///
/// The explicit type conversions expressed by
-/// CXXUnresolvedConstructExpr have the form \c T(a1, a2, ..., aN),
-/// where \c T is some type and \c a1, a2, ..., aN are values, and
-/// either \C T is a dependent type or one or more of the \c a's is
+/// CXXUnresolvedConstructExpr have the form <tt>T(a1, a2, ..., aN)</tt>,
+/// where \c T is some type and \c a1, \c a2, ..., \c aN are values, and
+/// either \c T is a dependent type or one or more of the <tt>a</tt>'s is
/// type-dependent. For example, this would occur in a template such
/// as:
///
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 4bfd12c06930..93a5ada27915 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -87,43 +87,45 @@ public:
child_range children() { return child_range(); }
};
-/// ObjCNumericLiteral - used for objective-c numeric literals;
-/// as in: @42 or @true (c++/objc++) or @__yes (c/objc)
-class ObjCNumericLiteral : public Expr {
- /// Number - expression AST node for the numeric literal
- Stmt *Number;
- ObjCMethodDecl *ObjCNumericLiteralMethod;
- SourceLocation AtLoc;
+/// ObjCBoxedExpr - used for generalized expression boxing.
+/// as in: @(strdup("hello world")) or @(random())
+/// Also used for boxing non-parenthesized numeric literals;
+/// as in: @42 or \@true (c++/objc++) or \@__yes (c/objc).
+class ObjCBoxedExpr : public Expr {
+ Stmt *SubExpr;
+ ObjCMethodDecl *BoxingMethod;
+ SourceRange Range;
public:
- ObjCNumericLiteral(Stmt *NL, QualType T, ObjCMethodDecl *method,
- SourceLocation L)
- : Expr(ObjCNumericLiteralClass, T, VK_RValue, OK_Ordinary,
- false, false, false, false), Number(NL),
- ObjCNumericLiteralMethod(method), AtLoc(L) {}
- explicit ObjCNumericLiteral(EmptyShell Empty)
- : Expr(ObjCNumericLiteralClass, Empty) {}
+ ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
+ SourceRange R)
+ : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
+ E->isTypeDependent(), E->isValueDependent(),
+ E->isInstantiationDependent(), E->containsUnexpandedParameterPack()),
+ SubExpr(E), BoxingMethod(method), Range(R) {}
+ explicit ObjCBoxedExpr(EmptyShell Empty)
+ : Expr(ObjCBoxedExprClass, Empty) {}
- Expr *getNumber() { return cast<Expr>(Number); }
- const Expr *getNumber() const { return cast<Expr>(Number); }
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
- ObjCMethodDecl *getObjCNumericLiteralMethod() const {
- return ObjCNumericLiteralMethod;
+ ObjCMethodDecl *getBoxingMethod() const {
+ return BoxingMethod;
}
-
- SourceLocation getAtLoc() const { return AtLoc; }
+
+ SourceLocation getAtLoc() const { return Range.getBegin(); }
SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(AtLoc, Number->getSourceRange().getEnd());
+ return Range;
}
-
+
static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCNumericLiteralClass;
+ return T->getStmtClass() == ObjCBoxedExprClass;
}
- static bool classof(const ObjCNumericLiteral *) { return true; }
+ static bool classof(const ObjCBoxedExpr *) { return true; }
// Iterators
- child_range children() { return child_range(&Number, &Number+1); }
-
+ child_range children() { return child_range(&SubExpr, &SubExpr+1); }
+
friend class ASTStmtReader;
};
@@ -332,9 +334,9 @@ public:
};
-/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type
-/// and behavior as StringLiteral except that the string initializer is obtained
-/// from ASTContext with the encoding type as an argument.
+/// ObjCEncodeExpr, used for \@encode in Objective-C. \@encode has the same
+/// type and behavior as StringLiteral except that the string initializer is
+/// obtained from ASTContext with the encoding type as an argument.
class ObjCEncodeExpr : public Expr {
TypeSourceInfo *EncodedType;
SourceLocation AtLoc, RParenLoc;
@@ -376,7 +378,7 @@ public:
child_range children() { return child_range(); }
};
-/// ObjCSelectorExpr used for @selector in Objective-C.
+/// ObjCSelectorExpr used for \@selector in Objective-C.
class ObjCSelectorExpr : public Expr {
Selector SelName;
SourceLocation AtLoc, RParenLoc;
@@ -419,19 +421,20 @@ public:
/// The return type is "Protocol*".
class ObjCProtocolExpr : public Expr {
ObjCProtocolDecl *TheProtocol;
- SourceLocation AtLoc, RParenLoc;
+ SourceLocation AtLoc, ProtoLoc, RParenLoc;
public:
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
- SourceLocation at, SourceLocation rp)
+ SourceLocation at, SourceLocation protoLoc, SourceLocation rp)
: Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
false, false),
- TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {}
+ TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {}
explicit ObjCProtocolExpr(EmptyShell Empty)
: Expr(ObjCProtocolExprClass, Empty) {}
ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
+ SourceLocation getProtocolIdLoc() const { return ProtoLoc; }
SourceLocation getAtLoc() const { return AtLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
@@ -448,6 +451,9 @@ public:
// Iterators
child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
@@ -1019,7 +1025,7 @@ public:
/// a l-value or r-value reference will be an l-value or x-value,
/// respectively.
///
- /// \param LBrac The location of the open square bracket '['.
+ /// \param LBracLoc The location of the open square bracket '['.
///
/// \param SuperLoc The location of the "super" keyword.
///
@@ -1033,8 +1039,6 @@ public:
///
/// \param Args The message send arguments.
///
- /// \param NumArgs The number of arguments.
- ///
/// \param RBracLoc The location of the closing square bracket ']'.
static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
ExprValueKind VK,
@@ -1059,7 +1063,7 @@ public:
/// a l-value or r-value reference will be an l-value or x-value,
/// respectively.
///
- /// \param LBrac The location of the open square bracket '['.
+ /// \param LBracLoc The location of the open square bracket '['.
///
/// \param Receiver The type of the receiver, including
/// source-location information.
@@ -1071,8 +1075,6 @@ public:
///
/// \param Args The message send arguments.
///
- /// \param NumArgs The number of arguments.
- ///
/// \param RBracLoc The location of the closing square bracket ']'.
static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
ExprValueKind VK,
@@ -1095,7 +1097,7 @@ public:
/// a l-value or r-value reference will be an l-value or x-value,
/// respectively.
///
- /// \param LBrac The location of the open square bracket '['.
+ /// \param LBracLoc The location of the open square bracket '['.
///
/// \param Receiver The expression used to produce the object that
/// will receive this message.
@@ -1107,8 +1109,6 @@ public:
///
/// \param Args The message send arguments.
///
- /// \param NumArgs The number of arguments.
- ///
/// \param RBracLoc The location of the closing square bracket ']'.
static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
ExprValueKind VK,
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index e2a60d5cf032..7aedfe2ef600 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -179,6 +179,9 @@ public:
/// \c ObjCInterfaceDecl::setExternallyCompleted().
virtual void CompleteType(ObjCInterfaceDecl *Class) { }
+ /// \brief Loads comment ranges.
+ virtual void ReadComments() { }
+
/// \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.
diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile
index 2854b7f40632..f6dd4ce6e69a 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 AttrImpl.inc StmtNodes.inc DeclNodes.inc
+BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc CommentNodes.inc
TABLEGEN_INC_FILES_COMMON = 1
@@ -27,3 +27,9 @@ $(ObjDir)/DeclNodes.inc.tmp : $(TD_SRC_DIR)/DeclNodes.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang declaration node tables with tblgen"
$(Verb) $(ClangTableGen) -gen-clang-decl-nodes -o $(call SYSPATH, $@) $<
+
+$(ObjDir)/CommentNodes.inc.tmp : $(TD_SRC_DIR)/CommentNodes.td $(CLANG_TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang comment node tables with tblgen"
+ $(Verb) $(ClangTableGen) -gen-clang-comment-nodes -o $(call SYSPATH, $@) $<
+
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index ca22ed6a0d97..a0dffb93088b 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -121,6 +121,7 @@ public:
raw_ostream &) = 0;
void mangleGlobalBlock(const BlockDecl *BD,
+ const NamedDecl *ID,
raw_ostream &Out);
void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
const BlockDecl *BD, raw_ostream &Out);
@@ -129,7 +130,8 @@ public:
void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
raw_ostream &Out);
// Do the right thing.
- void mangleBlock(const BlockDecl *BD, raw_ostream &Out);
+ void mangleBlock(const BlockDecl *BD, raw_ostream &Out,
+ const NamedDecl *ID=0);
void mangleObjCMethodName(const ObjCMethodDecl *MD,
raw_ostream &);
diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h
index 40e975906784..51ae1daf14f3 100644
--- a/include/clang/AST/NSAPI.h
+++ b/include/clang/AST/NSAPI.h
@@ -11,11 +11,13 @@
#define LLVM_CLANG_AST_NSAPI_H
#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
namespace clang {
class ASTContext;
class QualType;
+ class Expr;
// \brief Provides info and caches identifiers/selectors for NSFoundation API.
class NSAPI {
@@ -37,15 +39,33 @@ public:
enum NSStringMethodKind {
NSStr_stringWithString,
+ NSStr_stringWithUTF8String,
+ NSStr_stringWithCStringEncoding,
+ NSStr_stringWithCString,
NSStr_initWithString
};
- static const unsigned NumNSStringMethods = 2;
+ static const unsigned NumNSStringMethods = 5;
IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
/// \brief The Objective-C NSString selectors.
Selector getNSStringSelector(NSStringMethodKind MK) const;
+ /// \brief Return NSStringMethodKind if \param Sel is such a selector.
+ llvm::Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const;
+
+ /// \brief Returns true if the expression \param E is a reference of
+ /// "NSUTF8StringEncoding" enum constant.
+ bool isNSUTF8StringEncodingConstant(const Expr *E) const {
+ return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId);
+ }
+
+ /// \brief Returns true if the expression \param E is a reference of
+ /// "NSASCIIStringEncoding" enum constant.
+ bool isNSASCIIStringEncodingConstant(const Expr *E) const {
+ return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId);
+ }
+
/// \brief Enumerates the NSArray methods used to generate literals.
enum NSArrayMethodKind {
NSArr_array,
@@ -88,6 +108,35 @@ public:
llvm::Optional<NSDictionaryMethodKind>
getNSDictionaryMethodKind(Selector Sel);
+ /// \brief Returns selector for "objectForKeyedSubscript:".
+ Selector getObjectForKeyedSubscriptSelector() const {
+ return getOrInitSelector(StringRef("objectForKeyedSubscript"),
+ objectForKeyedSubscriptSel);
+ }
+
+ /// \brief Returns selector for "objectAtIndexedSubscript:".
+ Selector getObjectAtIndexedSubscriptSelector() const {
+ return getOrInitSelector(StringRef("objectAtIndexedSubscript"),
+ objectAtIndexedSubscriptSel);
+ }
+
+ /// \brief Returns selector for "setObject:forKeyedSubscript".
+ Selector getSetObjectForKeyedSubscriptSelector() const {
+ StringRef Ids[] = { "setObject", "forKeyedSubscript" };
+ return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel);
+ }
+
+ /// \brief Returns selector for "setObject:atIndexedSubscript".
+ Selector getSetObjectAtIndexedSubscriptSelector() const {
+ StringRef Ids[] = { "setObject", "atIndexedSubscript" };
+ return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel);
+ }
+
+ /// \brief Returns selector for "isEqual:".
+ Selector getIsEqualSelector() const {
+ return getOrInitSelector(StringRef("isEqual"), isEqualSel);
+ }
+
/// \brief Enumerates the NSNumber methods used to generate literals.
enum NSNumberLiteralMethodKind {
NSNumberWithChar,
@@ -126,10 +175,22 @@ public:
/// \brief Determine the appropriate NSNumber factory method kind for a
/// literal of the given type.
- static llvm::Optional<NSNumberLiteralMethodKind>
- getNSNumberFactoryMethodKind(QualType T);
+ llvm::Optional<NSNumberLiteralMethodKind>
+ getNSNumberFactoryMethodKind(QualType T) const;
+
+ /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
+ bool isObjCBOOLType(QualType T) const;
+ /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
+ bool isObjCNSIntegerType(QualType T) const;
+ /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
+ bool isObjCNSUIntegerType(QualType T) const;
private:
+ bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
+ bool isObjCEnumerator(const Expr *E,
+ StringRef name, IdentifierInfo *&II) const;
+ Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const;
+
ASTContext &Ctx;
mutable IdentifierInfo *ClassIds[NumClassIds];
@@ -145,6 +206,13 @@ private:
/// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];
+
+ mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel,
+ setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel,
+ isEqualSel;
+
+ mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId;
+ mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId;
};
} // end namespace clang
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index b5bd824c6504..a5aec1fdda6b 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -31,7 +31,7 @@ class TypeLoc;
class LangOptions;
/// \brief Represents a C++ nested name specifier, such as
-/// "::std::vector<int>::".
+/// "\::std::vector<int>::".
///
/// C++ nested name specifiers are the prefixes to qualified
/// namespaces. For example, "foo::" in "foo::x" is a nested name
@@ -190,7 +190,7 @@ public:
bool isInstantiationDependent() const;
/// \brief Whether this nested-name-specifier contains an unexpanded
- /// parameter pack (for C++0x variadic templates).
+ /// parameter pack (for C++11 variadic templates).
bool containsUnexpandedParameterPack() const;
/// \brief Print this nested name specifier to the given output
@@ -247,7 +247,7 @@ public:
/// nested-name-specifier.
///
/// For example, if this instance refers to a nested-name-specifier
- /// \c ::std::vector<int>::, the returned source range would cover
+ /// \c \::std::vector<int>::, the returned source range would cover
/// from the initial '::' to the last '::'.
SourceRange getSourceRange() const LLVM_READONLY;
@@ -255,7 +255,7 @@ public:
/// this nested-name-specifier, not including the prefix.
///
/// For example, if this instance refers to a nested-name-specifier
- /// \c ::std::vector<int>::, the returned source range would cover
+ /// \c \::std::vector<int>::, the returned source range would cover
/// from "vector" to the last '::'.
SourceRange getLocalSourceRange() const;
@@ -286,7 +286,7 @@ public:
/// \brief Return the prefix of this nested-name-specifier.
///
/// For example, if this instance refers to a nested-name-specifier
- /// \c ::std::vector<int>::, the prefix is \c ::std::. Note that the
+ /// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the
/// returned prefix may be empty, if this is the first component of
/// the nested-name-specifier.
NestedNameSpecifierLoc getPrefix() const {
@@ -443,8 +443,9 @@ public:
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
/// \brief Retrieve a nested-name-specifier with location
- /// information based on the information in this builder. This loc
- /// will contain references to the builder's internal data and may
+ /// information based on the information in this builder.
+ ///
+ /// This loc will contain references to the builder's internal data and may
/// be invalidated by any change to the builder.
NestedNameSpecifierLoc getTemporary() const {
return NestedNameSpecifierLoc(Representation, Buffer);
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
index 258637d7f9bd..63594141ac66 100644
--- a/include/clang/AST/OperationKinds.h
+++ b/include/clang/AST/OperationKinds.h
@@ -291,7 +291,7 @@ enum CastKind {
CK_CopyAndAutoreleaseBlockObject
};
-#define CK_Invalid ((CastKind) -1)
+static const CastKind CK_Invalid = static_cast<CastKind>(-1);
enum BinaryOperatorKind {
// Operators listed in order of precedence.
diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h
new file mode 100644
index 000000000000..4901d07c3cdc
--- /dev/null
+++ b/include/clang/AST/RawCommentList.h
@@ -0,0 +1,220 @@
+//===--- RawCommentList.h - Classes for processing raw comments -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_RAW_COMMENT_LIST_H
+#define LLVM_CLANG_AST_RAW_COMMENT_LIST_H
+
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace clang {
+
+class ASTContext;
+class ASTReader;
+class Decl;
+
+namespace comments {
+ class FullComment;
+} // end namespace comments
+
+class RawComment {
+public:
+ enum CommentKind {
+ RCK_Invalid, ///< Invalid comment
+ RCK_OrdinaryBCPL, ///< Any normal BCPL comments
+ RCK_OrdinaryC, ///< Any normal C comment
+ RCK_BCPLSlash, ///< \code /// stuff \endcode
+ RCK_BCPLExcl, ///< \code //! stuff \endcode
+ RCK_JavaDoc, ///< \code /** stuff */ \endcode
+ RCK_Qt, ///< \code /*! stuff */ \endcode, also used by HeaderDoc
+ RCK_Merged ///< Two or more documentation comments merged together
+ };
+
+ RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { }
+
+ RawComment(const SourceManager &SourceMgr, SourceRange SR,
+ bool Merged = false);
+
+ CommentKind getKind() const LLVM_READONLY {
+ return (CommentKind) Kind;
+ }
+
+ bool isInvalid() const LLVM_READONLY {
+ return Kind == RCK_Invalid;
+ }
+
+ bool isMerged() const LLVM_READONLY {
+ return Kind == RCK_Merged;
+ }
+
+ /// Is this comment attached to any declaration?
+ bool isAttached() const LLVM_READONLY {
+ return !DeclOrParsedComment.isNull();
+ }
+
+ /// Return the declaration that this comment is attached to.
+ const Decl *getDecl() const;
+
+ /// Set the declaration that this comment is attached to.
+ void setDecl(const Decl *D) {
+ assert(DeclOrParsedComment.isNull());
+ DeclOrParsedComment = D;
+ }
+
+ /// Returns true if it is a comment that should be put after a member:
+ /// \code ///< stuff \endcode
+ /// \code //!< stuff \endcode
+ /// \code /**< stuff */ \endcode
+ /// \code /*!< stuff */ \endcode
+ bool isTrailingComment() const LLVM_READONLY {
+ assert(isDocumentation());
+ return IsTrailingComment;
+ }
+
+ /// Returns true if it is a probable typo:
+ /// \code //< stuff \endcode
+ /// \code /*< stuff */ \endcode
+ bool isAlmostTrailingComment() const LLVM_READONLY {
+ return IsAlmostTrailingComment;
+ }
+
+ /// Returns true if this comment is not a documentation comment.
+ bool isOrdinary() const LLVM_READONLY {
+ return (Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC);
+ }
+
+ /// Returns true if this comment any kind of a documentation comment.
+ bool isDocumentation() const LLVM_READONLY {
+ return !isInvalid() && !isOrdinary();
+ }
+
+ /// Returns raw comment text with comment markers.
+ StringRef getRawText(const SourceManager &SourceMgr) const {
+ if (RawTextValid)
+ return RawText;
+
+ RawText = getRawTextSlow(SourceMgr);
+ RawTextValid = true;
+ return RawText;
+ }
+
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return Range;
+ }
+
+ unsigned getBeginLine(const SourceManager &SM) const;
+ unsigned getEndLine(const SourceManager &SM) const;
+
+ const char *getBriefText(const ASTContext &Context) const {
+ if (BriefTextValid)
+ return BriefText;
+
+ return extractBriefText(Context);
+ }
+
+ /// Returns a \c FullComment AST node, parsing the comment if needed.
+ comments::FullComment *getParsed(const ASTContext &Context) const {
+ if (comments::FullComment *FC =
+ DeclOrParsedComment.dyn_cast<comments::FullComment *>())
+ return FC;
+
+ return parse(Context);
+ }
+
+private:
+ SourceRange Range;
+
+ mutable StringRef RawText;
+ mutable const char *BriefText;
+ mutable llvm::PointerUnion<const Decl *, comments::FullComment *>
+ DeclOrParsedComment;
+
+ mutable bool RawTextValid : 1; ///< True if RawText is valid
+ mutable bool BriefTextValid : 1; ///< True if BriefText is valid
+
+ unsigned Kind : 3;
+
+ bool IsTrailingComment : 1;
+ bool IsAlmostTrailingComment : 1;
+
+ mutable bool BeginLineValid : 1; ///< True if BeginLine is valid
+ mutable bool EndLineValid : 1; ///< True if EndLine is valid
+ mutable unsigned BeginLine; ///< Cached line number
+ mutable unsigned EndLine; ///< Cached line number
+
+ /// \brief Constructor for AST deserialization.
+ RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
+ bool IsAlmostTrailingComment) :
+ Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K),
+ IsTrailingComment(IsTrailingComment),
+ IsAlmostTrailingComment(IsAlmostTrailingComment),
+ BeginLineValid(false), EndLineValid(false)
+ { }
+
+ StringRef getRawTextSlow(const SourceManager &SourceMgr) const;
+
+ const char *extractBriefText(const ASTContext &Context) const;
+
+ comments::FullComment *parse(const ASTContext &Context) const;
+
+ friend class ASTReader;
+};
+
+/// \brief Compare comments' source locations.
+template<>
+class BeforeThanCompare<RawComment> {
+ const SourceManager &SM;
+
+public:
+ explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { }
+
+ bool operator()(const RawComment &LHS, const RawComment &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.getSourceRange().getBegin(),
+ RHS.getSourceRange().getBegin());
+ }
+
+ bool operator()(const RawComment *LHS, const RawComment *RHS) {
+ return operator()(*LHS, *RHS);
+ }
+};
+
+/// \brief This class represents all comments included in the translation unit,
+/// sorted in order of appearance in the translation unit.
+class RawCommentList {
+public:
+ RawCommentList(SourceManager &SourceMgr) :
+ SourceMgr(SourceMgr), OnlyWhitespaceSeen(true) { }
+
+ void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator);
+
+ ArrayRef<RawComment *> getComments() const {
+ return Comments;
+ }
+
+private:
+ SourceManager &SourceMgr;
+ std::vector<RawComment *> Comments;
+ RawComment LastComment;
+ bool OnlyWhitespaceSeen;
+
+ void addCommentsToFront(const std::vector<RawComment *> &C) {
+ size_t OldSize = Comments.size();
+ Comments.resize(C.size() + OldSize);
+ std::copy_backward(Comments.begin(), Comments.begin() + OldSize,
+ Comments.end());
+ std::copy(C.begin(), C.end(), Comments.begin());
+ }
+
+ friend class ASTReader;
+};
+
+} // end namespace clang
+
+#endif
+
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index ec07267d6624..3a870d057bad 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -14,10 +14,9 @@
#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
#define LLVM_CLANG_AST_LAYOUTINFO_H
-#include "llvm/Support/DataTypes.h"
-#include "llvm/ADT/DenseMap.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/DenseMap.h"
namespace clang {
class ASTContext;
@@ -33,18 +32,43 @@ namespace clang {
/// ObjCInterfaceDecl. FIXME - Find appropriate name.
/// These objects are managed by ASTContext.
class ASTRecordLayout {
+public:
+ struct VBaseInfo {
+ /// The offset to this virtual base in the complete-object layout
+ /// of this class.
+ CharUnits VBaseOffset;
+
+ private:
+ /// Whether this virtual base requires a vtordisp field in the
+ /// Microsoft ABI. These fields are required for certain operations
+ /// in constructors and destructors.
+ bool HasVtorDisp;
+
+ public:
+ bool hasVtorDisp() const { return HasVtorDisp; }
+
+ VBaseInfo() : HasVtorDisp(false) {}
+
+ VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) :
+ VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {}
+ };
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>
+ VBaseOffsetsMapTy;
+
+private:
/// Size - Size of record in characters.
CharUnits Size;
/// DataSize - Size of record in characters without tail padding.
CharUnits DataSize;
- /// FieldOffsets - Array of field offsets in bits.
- uint64_t *FieldOffsets;
-
// Alignment - Alignment of record in characters.
CharUnits Alignment;
+ /// FieldOffsets - Array of field offsets in bits.
+ uint64_t *FieldOffsets;
+
// FieldCount - Number of fields.
unsigned FieldCount;
@@ -63,11 +87,13 @@ class ASTRecordLayout {
/// any empty subobjects.
CharUnits SizeOfLargestEmptySubobject;
- /// VFPtrOffset - Virtual function table offset (Microsoft-only).
- CharUnits VFPtrOffset;
-
/// VBPtrOffset - Virtual base table offset (Microsoft-only).
CharUnits VBPtrOffset;
+
+ /// HasOwnVFPtr - Does this class provide a virtual function table
+ /// (vtable in Itanium, vftbl in Microsoft) that is independent from
+ /// its base classes?
+ bool HasOwnVFPtr; // TODO: stash this somewhere more efficient
/// PrimaryBase - The primary base info for this record.
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
@@ -79,7 +105,7 @@ class ASTRecordLayout {
BaseOffsetsMapTy BaseOffsets;
/// VBaseOffsets - Contains a map from vbase classes to their offset.
- BaseOffsetsMapTy VBaseOffsets;
+ VBaseOffsetsMapTy VBaseOffsets;
};
/// CXXInfo - If the record layout is for a C++ record, this will have
@@ -96,7 +122,7 @@ class ASTRecordLayout {
typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
- CharUnits vfptroffset, CharUnits vbptroffset,
+ bool hasOwnVFPtr, CharUnits vbptroffset,
CharUnits datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
CharUnits nonvirtualsize, CharUnits nonvirtualalign,
@@ -104,7 +130,7 @@ class ASTRecordLayout {
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
const BaseOffsetsMapTy& BaseOffsets,
- const BaseOffsetsMapTy& VBaseOffsets);
+ const VBaseOffsetsMapTy& VBaseOffsets);
~ASTRecordLayout() {}
@@ -180,27 +206,7 @@ public:
assert(CXXInfo && "Record layout does not have C++ specific info!");
assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
- return CXXInfo->VBaseOffsets[VBase];
- }
-
- /// getBaseClassOffsetInBits - Get the offset, in bits, for the given
- /// base class.
- uint64_t getBaseClassOffsetInBits(const CXXRecordDecl *Base) const {
- assert(CXXInfo && "Record layout does not have C++ specific info!");
- assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
-
- return getBaseClassOffset(Base).getQuantity() *
- Base->getASTContext().getCharWidth();
- }
-
- /// getVBaseClassOffsetInBits - Get the offset, in bits, for the given
- /// base class.
- uint64_t getVBaseClassOffsetInBits(const CXXRecordDecl *VBase) const {
- assert(CXXInfo && "Record layout does not have C++ specific info!");
- assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
-
- return getVBaseClassOffset(VBase).getQuantity() *
- VBase->getASTContext().getCharWidth();
+ return CXXInfo->VBaseOffsets[VBase].VBaseOffset;
}
CharUnits getSizeOfLargestEmptySubobject() const {
@@ -208,11 +214,16 @@ public:
return CXXInfo->SizeOfLargestEmptySubobject;
}
- /// getVFPtrOffset - Get the offset for virtual function table pointer.
- /// This is only meaningful with the Microsoft ABI.
- CharUnits getVFPtrOffset() const {
+ /// hasOwnVFPtr - Does this class provide its own virtual-function
+ /// table pointer, rather than inheriting one from a primary base
+ /// class? If so, it is at offset zero.
+ ///
+ /// This implies that the ABI has no primary base class, meaning
+ /// that it has no base classes that are suitable under the conditions
+ /// of the ABI.
+ bool hasOwnVFPtr() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
- return CXXInfo->VFPtrOffset;
+ return CXXInfo->HasOwnVFPtr;
}
/// getVBPtrOffset - Get the offset for virtual base table pointer.
@@ -221,6 +232,11 @@ public:
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->VBPtrOffset;
}
+
+ const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->VBaseOffsets;
+ }
};
} // end namespace clang
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index f1b517102137..2e56a486f3d0 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -148,10 +148,15 @@ public:
/// TypeLocs.
bool shouldWalkTypesOfTypeLocs() const { return true; }
+ /// \brief Return whether this visitor should recurse into implicit
+ /// code, e.g., implicit constructors and destructors.
+ bool shouldVisitImplicitCode() const { return false; }
+
/// \brief Return whether \param S should be traversed using data recursion
/// to avoid a stack overflow with extreme cases.
bool shouldUseDataRecursionFor(Stmt *S) const {
- return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) || isa<CaseStmt>(S);
+ return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) ||
+ isa<CaseStmt>(S) || isa<CXXOperatorCallExpr>(S);
}
/// \brief Recursively visit a statement or expression, by
@@ -392,8 +397,8 @@ public:
private:
// These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
- bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern);
- bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ;
+ bool TraverseClassInstantiations(ClassTemplateDecl *D);
+ bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ;
bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
unsigned Count);
bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
@@ -404,18 +409,14 @@ private:
bool TraverseFunctionHelper(FunctionDecl *D);
bool TraverseVarHelper(VarDecl *D);
- bool Walk(Stmt *S);
-
struct EnqueueJob {
Stmt *S;
Stmt::child_iterator StmtIt;
- EnqueueJob(Stmt *S) : S(S), StmtIt() {
- if (Expr *E = dyn_cast_or_null<Expr>(S))
- S = E->IgnoreParens();
- }
+ EnqueueJob(Stmt *S) : S(S), StmtIt() {}
};
bool dataTraverse(Stmt *S);
+ bool dataTraverseNode(Stmt *S, bool &EnqueueChildren);
};
template<typename Derived>
@@ -434,7 +435,12 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
if (getDerived().shouldUseDataRecursionFor(CurrS)) {
if (job.StmtIt == Stmt::child_iterator()) {
- if (!Walk(CurrS)) return false;
+ bool EnqueueChildren = true;
+ if (!dataTraverseNode(CurrS, EnqueueChildren)) return false;
+ if (!EnqueueChildren) {
+ Queue.pop_back();
+ continue;
+ }
job.StmtIt = CurrS->child_begin();
} else {
++job.StmtIt;
@@ -455,10 +461,25 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
}
template<typename Derived>
-bool RecursiveASTVisitor<Derived>::Walk(Stmt *S) {
-
+bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
+ bool &EnqueueChildren) {
+
+// The cast for DISPATCH_WALK is needed for older versions of g++, but causes
+// problems for MSVC. So we'll skip the cast entirely for MSVC.
+#if defined(_MSC_VER)
+ #define GCC_CAST(CLASS)
+#else
+ #define GCC_CAST(CLASS) (bool (RecursiveASTVisitor::*)(CLASS*))
+#endif
+
+ // Dispatch to the corresponding WalkUpFrom* function only if the derived
+ // class didn't override Traverse* (and thus the traversal is trivial).
#define DISPATCH_WALK(NAME, CLASS, VAR) \
- return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR));
+ if (&RecursiveASTVisitor::Traverse##NAME == \
+ GCC_CAST(CLASS)&Derived::Traverse##NAME) \
+ return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR)); \
+ EnqueueChildren = false; \
+ return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR));
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
@@ -495,6 +516,7 @@ bool RecursiveASTVisitor<Derived>::Walk(Stmt *S) {
}
#undef DISPATCH_WALK
+#undef GCC_CAST
return true;
}
@@ -591,10 +613,9 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
if (!D)
return true;
- // As a syntax visitor, we want to ignore declarations for
- // implicitly-defined declarations (ones not typed explicitly by the
- // user).
- if (D->isImplicit())
+ // As a syntax visitor, by default we want to ignore declarations for
+ // implicit declarations (ones not typed explicitly by the user).
+ if (!getDerived().shouldVisitImplicitCode() && D->isImplicit())
return true;
switch (D->getKind()) {
@@ -1231,7 +1252,8 @@ bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \
DEF_TRAVERSE_DECL(AccessSpecDecl, { })
DEF_TRAVERSE_DECL(BlockDecl, {
- TRY_TO(TraverseTypeLoc(D->getSignatureAsWritten()->getTypeLoc()));
+ if (TypeSourceInfo *TInfo = D->getSignatureAsWritten())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
TRY_TO(TraverseStmt(D->getBody()));
// This return statement makes sure the traversal of nodes in
// decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
@@ -1269,7 +1291,13 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, {
})
DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
- TRY_TO(TraverseDecl(D->getSpecialization()));
+ TRY_TO(TraverseDecl(D->getSpecialization()));
+
+ if (D->hasExplicitTemplateArgs()) {
+ const TemplateArgumentListInfo& args = D->templateArgs();
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ args.getArgumentArray(), args.size()));
+ }
})
DEF_TRAVERSE_DECL(LinkageSpecDecl, { })
@@ -1377,35 +1405,20 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
}
// A helper method for traversing the implicit instantiations of a
-// class.
+// class template.
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
- ClassTemplateDecl* D, Decl *Pattern) {
- assert(isa<ClassTemplateDecl>(Pattern) ||
- isa<ClassTemplatePartialSpecializationDecl>(Pattern));
-
+ ClassTemplateDecl *D) {
ClassTemplateDecl::spec_iterator end = D->spec_end();
for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
ClassTemplateSpecializationDecl* SD = *it;
switch (SD->getSpecializationKind()) {
// Visit the implicit instantiations with the requested pattern.
- case TSK_ImplicitInstantiation: {
- llvm::PointerUnion<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *> U
- = SD->getInstantiatedFrom();
-
- bool ShouldVisit;
- if (U.is<ClassTemplateDecl*>())
- ShouldVisit = (U.get<ClassTemplateDecl*>() == Pattern);
- else
- ShouldVisit
- = (U.get<ClassTemplatePartialSpecializationDecl*>() == Pattern);
-
- if (ShouldVisit)
- TRY_TO(TraverseDecl(SD));
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ TRY_TO(TraverseDecl(SD));
break;
- }
// We don't need to do anything on an explicit instantiation
// or explicit specialization because there will be an explicit
@@ -1414,11 +1427,6 @@ bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
case TSK_ExplicitInstantiationDefinition:
case TSK_ExplicitSpecialization:
break;
-
- // We don't need to do anything for an uninstantiated
- // specialization.
- case TSK_Undeclared:
- break;
}
}
@@ -1433,12 +1441,12 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, {
// By default, we do not traverse the instantiations of
// class templates since they do not appear 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));
- }
+ //
+ // We only traverse the class instantiations when we see the canonical
+ // declaration of the template, to ensure we only visit them once.
+ if (getDerived().shouldVisitTemplateInstantiations() &&
+ D == D->getCanonicalDecl())
+ TRY_TO(TraverseClassInstantiations(D));
// Note that getInstantiatedFromMemberTemplate() is just a link
// from a template instantiation back to the template from which
@@ -1449,24 +1457,25 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, {
// function while skipping its specializations.
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
- FunctionTemplateDecl* D) {
+ 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_Undeclared:
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.
+ // FIXME: For now traverse explicit instantiations here. Change that
+ // once they are represented as dedicated nodes in the AST.
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
+ TRY_TO(TraverseDecl(FD));
break;
- case TSK_Undeclared: // Declaration of the template definition.
case TSK_ExplicitSpecialization:
break;
}
@@ -1480,26 +1489,21 @@ DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
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
+ // function templates since they do not appear 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));
- }
- }
+ //
+ // We only traverse the function instantiations when we see the canonical
+ // declaration of the template, to ensure we only visit them once.
+ if (getDerived().shouldVisitTemplateInstantiations() &&
+ D == D->getCanonicalDecl())
+ TRY_TO(TraverseFunctionInstantiations(D));
})
DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
// D is the "T" in something like
// template <template <typename> class T> class container { };
TRY_TO(TraverseDecl(D->getTemplatedDecl()));
- if (D->hasDefaultArgument()) {
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
}
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
@@ -1509,7 +1513,7 @@ DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
// D is the "T" in something like "template<typename T> class vector;"
if (D->getTypeForDecl())
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
- if (D->hasDefaultArgument())
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
})
@@ -1567,7 +1571,7 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
CXXRecordDecl *D) {
if (!TraverseRecordHelper(D))
return false;
- if (D->hasDefinition()) {
+ if (D->isCompleteDefinition()) {
for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
E = D->bases_end();
I != E; ++I) {
@@ -1634,11 +1638,7 @@ DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
// 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));
+ // Instantiations will have been visited with the primary template.
})
DEF_TRAVERSE_DECL(EnumConstantDecl, {
@@ -1714,7 +1714,9 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
// FunctionNoProtoType or FunctionProtoType, or a typedef. This
// also covers the return type and the function parameters,
// including exception specifications.
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ if (clang::TypeSourceInfo *TSI = D->getTypeSourceInfo()) {
+ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+ }
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
// Constructor initializers.
@@ -1767,7 +1769,8 @@ template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
TRY_TO(TraverseDeclaratorHelper(D));
// Default params are taken care of when we traverse the ParmVarDecl.
- if (!isa<ParmVarDecl>(D))
+ if (!isa<ParmVarDecl>(D) &&
+ (!D->isCXXForRangeDecl() || getDerived().shouldVisitImplicitCode()))
TRY_TO(TraverseStmt(D->getInit()));
return true;
}
@@ -1783,7 +1786,8 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, {
DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
// A non-type template parameter, e.g. "S" in template<int S> class Foo ...
TRY_TO(TraverseDeclaratorHelper(D));
- TRY_TO(TraverseStmt(D->getDefaultArgument()));
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ TRY_TO(TraverseStmt(D->getDefaultArgument()));
})
DEF_TRAVERSE_DECL(ParmVarDecl, {
@@ -1837,6 +1841,11 @@ DEF_TRAVERSE_STMT(AsmStmt, {
// children() iterates over inputExpr and outputExpr.
})
+DEF_TRAVERSE_STMT(MSAsmStmt, {
+ // FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once
+ // added this needs to be implemented.
+ })
+
DEF_TRAVERSE_STMT(CXXCatchStmt, {
TRY_TO(TraverseDecl(S->getExceptionDecl()));
// children() iterates over the handler block.
@@ -1879,7 +1888,15 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, { })
-DEF_TRAVERSE_STMT(CXXForRangeStmt, { })
+DEF_TRAVERSE_STMT(CXXForRangeStmt, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO(TraverseStmt(S->getLoopVarStmt()));
+ TRY_TO(TraverseStmt(S->getRangeInit()));
+ TRY_TO(TraverseStmt(S->getBody()));
+ // Visit everything else only if shouldVisitImplicitCode().
+ return true;
+ }
+})
DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
@@ -2146,7 +2163,10 @@ DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
DEF_TRAVERSE_STMT(GNUNullExpr, { })
DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { })
DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, { })
-DEF_TRAVERSE_STMT(ObjCEncodeExpr, { })
+DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
+ if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+})
DEF_TRAVERSE_STMT(ObjCIsaExpr, { })
DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { })
DEF_TRAVERSE_STMT(ObjCMessageExpr, { })
@@ -2209,7 +2229,7 @@ DEF_TRAVERSE_STMT(FloatingLiteral, { })
DEF_TRAVERSE_STMT(ImaginaryLiteral, { })
DEF_TRAVERSE_STMT(StringLiteral, { })
DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
-DEF_TRAVERSE_STMT(ObjCNumericLiteral, { })
+DEF_TRAVERSE_STMT(ObjCBoxedExpr, { })
DEF_TRAVERSE_STMT(ObjCArrayLiteral, { })
DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { })
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index 88abadb26a8f..e3b340a5a1fe 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -25,26 +25,25 @@ template<typename decl_type>
class Redeclarable {
protected:
- // FIXME: PointerIntPair is a value class that should not be inherited from.
- // This should change to using containment.
- struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> {
+ class DeclLink {
+ llvm::PointerIntPair<decl_type *, 1, bool> NextAndIsPrevious;
+ public:
DeclLink(decl_type *D, bool isLatest)
- : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { }
-
- typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type;
+ : NextAndIsPrevious(D, isLatest) { }
- bool NextIsPrevious() const { return base_type::getInt() == false; }
- bool NextIsLatest() const { return base_type::getInt() == true; }
- decl_type *getNext() const { return base_type::getPointer(); }
+ bool NextIsPrevious() const { return !NextAndIsPrevious.getInt(); }
+ bool NextIsLatest() const { return NextAndIsPrevious.getInt(); }
+ decl_type *getNext() const { return NextAndIsPrevious.getPointer(); }
+ void setNext(decl_type *D) { NextAndIsPrevious.setPointer(D); }
};
- struct PreviousDeclLink : public DeclLink {
- PreviousDeclLink(decl_type *D) : DeclLink(D, false) { }
- };
+ static DeclLink PreviousDeclLink(decl_type *D) {
+ return DeclLink(D, false);
+ }
- struct LatestDeclLink : public DeclLink {
- LatestDeclLink(decl_type *D) : DeclLink(D, true) { }
- };
+ static DeclLink LatestDeclLink(decl_type *D) {
+ return DeclLink(D, true);
+ }
/// \brief Points to the next redeclaration in the chain.
///
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 1b0f576e271d..79e1920159cd 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -19,8 +19,8 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/StmtIterator.h"
#include "clang/AST/DeclGroup.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/Lex/Token.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
@@ -37,9 +37,11 @@ namespace clang {
class ParmVarDecl;
class QualType;
class IdentifierInfo;
+ class LabelDecl;
class SourceManager;
class StringLiteral;
class SwitchStmt;
+ class VarDecl;
//===--------------------------------------------------------------------===//
// ExprIterator - Iterators for iterating over Stmt* arrays that contain
@@ -499,6 +501,14 @@ public:
decl_iterator decl_end() { return DG.end(); }
const_decl_iterator decl_begin() const { return DG.begin(); }
const_decl_iterator decl_end() const { return DG.end(); }
+
+ typedef std::reverse_iterator<decl_iterator> reverse_decl_iterator;
+ reverse_decl_iterator decl_rbegin() {
+ return reverse_decl_iterator(decl_end());
+ }
+ reverse_decl_iterator decl_rend() {
+ return reverse_decl_iterator(decl_begin());
+ }
};
/// NullStmt - This is the null statement ";": C99 6.8.3p3.
@@ -545,20 +555,13 @@ class CompoundStmt : public Stmt {
Stmt** Body;
SourceLocation LBracLoc, RBracLoc;
public:
- CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned NumStmts,
- SourceLocation LB, SourceLocation RB)
- : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) {
- CompoundStmtBits.NumStmts = NumStmts;
- assert(CompoundStmtBits.NumStmts == NumStmts &&
- "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
-
- if (NumStmts == 0) {
- Body = 0;
- return;
- }
+ CompoundStmt(ASTContext &C, Stmt **StmtStart, unsigned NumStmts,
+ SourceLocation LB, SourceLocation RB);
- Body = new (C) Stmt*[NumStmts];
- memcpy(Body, StmtStart, NumStmts * sizeof(*Body));
+ // \brief Build an empty compound statment with a location.
+ explicit CompoundStmt(SourceLocation Loc)
+ : Stmt(CompoundStmtClass), Body(0), LBracLoc(Loc), RBracLoc(Loc) {
+ CompoundStmtBits.NumStmts = 0;
}
// \brief Build an empty compound statement.
@@ -803,24 +806,32 @@ public:
class AttributedStmt : public Stmt {
Stmt *SubStmt;
SourceLocation AttrLoc;
- AttrVec Attrs;
- // TODO: It can be done as Attr *Attrs[1]; and variable size array as in
- // StringLiteral
+ unsigned NumAttrs;
+ const Attr *Attrs[1];
friend class ASTStmtReader;
-public:
- AttributedStmt(SourceLocation loc, const AttrVec &attrs, Stmt *substmt)
- : Stmt(AttributedStmtClass), SubStmt(substmt), AttrLoc(loc), Attrs(attrs) {
+ AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
+ : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
+ NumAttrs(Attrs.size()) {
+ memcpy(this->Attrs, Attrs.data(), Attrs.size() * sizeof(Attr*));
}
- // \brief Build an empty attributed statement.
- explicit AttributedStmt(EmptyShell Empty)
- : Stmt(AttributedStmtClass, Empty) {
+ explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
+ : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
+ memset(Attrs, 0, NumAttrs * sizeof(Attr*));
}
+public:
+ static AttributedStmt *Create(ASTContext &C, SourceLocation Loc,
+ ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
+ // \brief Build an empty attributed statement.
+ static AttributedStmt *CreateEmpty(ASTContext &C, unsigned NumAttrs);
+
SourceLocation getAttrLoc() const { return AttrLoc; }
- const AttrVec &getAttrs() const { return Attrs; }
+ ArrayRef<const Attr*> getAttrs() const {
+ return ArrayRef<const Attr*>(Attrs, NumAttrs);
+ }
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
@@ -1606,6 +1617,69 @@ public:
}
};
+/// MSAsmStmt - This represents a MS inline-assembly statement extension.
+///
+class MSAsmStmt : public Stmt {
+ SourceLocation AsmLoc, EndLoc;
+ std::string AsmStr;
+
+ bool IsSimple;
+ bool IsVolatile;
+
+ unsigned NumAsmToks;
+ unsigned NumLineEnds;
+ unsigned NumClobbers;
+
+ Token *AsmToks;
+ unsigned *LineEnds;
+ Stmt **Exprs;
+ StringRef *Clobbers;
+
+public:
+ MSAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
+ bool isvolatile, ArrayRef<Token> asmtoks,
+ ArrayRef<unsigned> lineends, StringRef asmstr,
+ ArrayRef<StringRef> clobbers, SourceLocation endloc);
+
+ SourceLocation getAsmLoc() const { return AsmLoc; }
+ void setAsmLoc(SourceLocation L) { AsmLoc = L; }
+ SourceLocation getEndLoc() const { return EndLoc; }
+ void setEndLoc(SourceLocation L) { EndLoc = L; }
+
+ unsigned getNumAsmToks() { return NumAsmToks; }
+ Token *getAsmToks() { return AsmToks; }
+ unsigned getNumLineEnds() { return NumLineEnds; }
+ unsigned *getLineEnds() { return LineEnds; }
+
+ bool isVolatile() const { return IsVolatile; }
+ void setVolatile(bool V) { IsVolatile = V; }
+ bool isSimple() const { return IsSimple; }
+ void setSimple(bool V) { IsSimple = V; }
+
+ //===--- Asm String Analysis ---===//
+
+ const std::string *getAsmString() const { return &AsmStr; }
+ std::string *getAsmString() { return &AsmStr; }
+ void setAsmString(StringRef &E) { AsmStr = E.str(); }
+
+ //===--- Other ---===//
+
+ unsigned getNumClobbers() const { return NumClobbers; }
+ StringRef getClobber(unsigned i) { return Clobbers[i]; }
+
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(AsmLoc, EndLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MSAsmStmtClass;
+ }
+ static bool classof(const MSAsmStmt *) { return true; }
+
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[0]);
+ }
+};
+
class SEHExceptStmt : public Stmt {
SourceLocation Loc;
Stmt *Children[2];
diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h
index a32104123b15..e7e1232989e3 100644
--- a/include/clang/AST/StmtObjC.h
+++ b/include/clang/AST/StmtObjC.h
@@ -6,10 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Objective-C statement AST node classes.
-//
-//===----------------------------------------------------------------------===//
+
+/// \file
+/// \brief Defines the Objective-C statement AST node classes.
#ifndef LLVM_CLANG_AST_STMTOBJC_H
#define LLVM_CLANG_AST_STMTOBJC_H
@@ -19,9 +18,9 @@
namespace clang {
-/// ObjCForCollectionStmt - This represents Objective-c's collection statement;
-/// represented as 'for (element 'in' collection-expression)' stmt.
+/// \brief Represents Objective-C's collection statement.
///
+/// This is represented as 'for (element 'in' collection-expression)' stmt.
class ObjCForCollectionStmt : public Stmt {
enum { ELEM, COLLECTION, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt.
@@ -70,7 +69,7 @@ public:
}
};
-/// ObjCAtCatchStmt - This represents objective-c's @catch statement.
+/// \brief Represents Objective-C's \@catch statement.
class ObjCAtCatchStmt : public Stmt {
private:
VarDecl *ExceptionDecl;
@@ -118,7 +117,7 @@ public:
child_range children() { return child_range(&Body, &Body + 1); }
};
-/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement
+/// \brief Represents Objective-C's \@finally statement
class ObjCAtFinallyStmt : public Stmt {
Stmt *AtFinallyStmt;
SourceLocation AtFinallyLoc;
@@ -151,24 +150,23 @@ public:
}
};
-/// ObjCAtTryStmt - This represent objective-c's over-all
-/// @try ... @catch ... @finally statement.
+/// \brief Represents Objective-C's \@try ... \@catch ... \@finally statement.
class ObjCAtTryStmt : public Stmt {
private:
- // The location of the
+ // The location of the @ in the \@try.
SourceLocation AtTryLoc;
// The number of catch blocks in this statement.
unsigned NumCatchStmts : 16;
- // Whether this statement has a @finally statement.
+ // Whether this statement has a \@finally statement.
bool HasFinally : 1;
- /// \brief Retrieve the statements that are stored after this @try statement.
+ /// \brief Retrieve the statements that are stored after this \@try statement.
///
/// The order of the statements in memory follows the order in the source,
- /// with the @try body first, followed by the @catch statements (if any) and,
- /// finally, the @finally (if it exists).
+ /// with the \@try body first, followed by the \@catch statements (if any)
+ /// and, finally, the \@finally (if it exists).
Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); }
const Stmt* const *getStmts() const {
return reinterpret_cast<const Stmt * const*> (this + 1);
@@ -192,26 +190,26 @@ public:
unsigned NumCatchStmts,
bool HasFinally);
- /// \brief Retrieve the location of the @ in the @try.
+ /// \brief Retrieve the location of the @ in the \@try.
SourceLocation getAtTryLoc() const { return AtTryLoc; }
void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; }
- /// \brief Retrieve the @try body.
+ /// \brief Retrieve the \@try body.
const Stmt *getTryBody() const { return getStmts()[0]; }
Stmt *getTryBody() { return getStmts()[0]; }
void setTryBody(Stmt *S) { getStmts()[0] = S; }
- /// \brief Retrieve the number of @catch statements in this try-catch-finally
+ /// \brief Retrieve the number of \@catch statements in this try-catch-finally
/// block.
unsigned getNumCatchStmts() const { return NumCatchStmts; }
- /// \brief Retrieve a @catch statement.
+ /// \brief Retrieve a \@catch statement.
const ObjCAtCatchStmt *getCatchStmt(unsigned I) const {
assert(I < NumCatchStmts && "Out-of-bounds @catch index");
return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
}
- /// \brief Retrieve a @catch statement.
+ /// \brief Retrieve a \@catch statement.
ObjCAtCatchStmt *getCatchStmt(unsigned I) {
assert(I < NumCatchStmts && "Out-of-bounds @catch index");
return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
@@ -223,7 +221,7 @@ public:
getStmts()[I + 1] = S;
}
- /// Retrieve the @finally statement, if any.
+ /// \brief Retrieve the \@finally statement, if any.
const ObjCAtFinallyStmt *getFinallyStmt() const {
if (!HasFinally)
return 0;
@@ -254,11 +252,14 @@ public:
}
};
-/// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement.
-/// Example: @synchronized (sem) {
-/// do-something;
-/// }
+/// \brief Represents Objective-C's \@synchronized statement.
///
+/// Example:
+/// \code
+/// @synchronized (sem) {
+/// do-something;
+/// }
+/// \endcode
class ObjCAtSynchronizedStmt : public Stmt {
private:
enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
@@ -309,7 +310,7 @@ public:
}
};
-/// ObjCAtThrowStmt - This represents objective-c's @throw statement.
+/// \brief Represents Objective-C's \@throw statement.
class ObjCAtThrowStmt : public Stmt {
Stmt *Throw;
SourceLocation AtThrowLoc;
@@ -343,8 +344,7 @@ public:
child_range children() { return child_range(&Throw, &Throw+1); }
};
-/// ObjCAutoreleasePoolStmt - This represent objective-c's
-/// @autoreleasepool Statement
+/// \brief Represents Objective-C's \@autoreleasepool Statement
class ObjCAutoreleasePoolStmt : public Stmt {
Stmt *SubStmt;
SourceLocation AtLoc;
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 65f54600c009..54c9f2c534d2 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -73,7 +73,15 @@ private:
union {
uintptr_t TypeOrValue;
struct {
- char Value[sizeof(llvm::APSInt)];
+ // We store a decomposed APSInt with the data allocated by ASTContext if
+ // BitWidth > 64. The memory may be shared between multiple
+ // TemplateArgument instances.
+ union {
+ uint64_t VAL; ///< Used to store the <= 64 bits integer value.
+ const uint64_t *pVal; ///< Used to store the >64 bits integer value.
+ };
+ unsigned BitWidth : 31;
+ unsigned IsUnsigned : 1;
void *Type;
} Integer;
struct {
@@ -104,11 +112,15 @@ public:
TypeOrValue = reinterpret_cast<uintptr_t>(D);
}
- /// \brief Construct an integral constant template argument.
- TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
- // FIXME: Large integral values will get leaked. Do something
- // similar to what we did with IntegerLiteral.
- new (Integer.Value) llvm::APSInt(Value);
+ /// \brief Construct an integral constant template argument. The memory to
+ /// store the value is allocated with Ctx.
+ TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
+
+ /// \brief Construct an integral constant template argument with the same
+ /// value as Other but a different type.
+ TemplateArgument(const TemplateArgument &Other, QualType Type)
+ : Kind(Integral) {
+ Integer = Other.Integer;
Integer.Type = Type.getAsOpaquePtr();
}
@@ -165,62 +177,6 @@ public:
this->Args.NumArgs = NumArgs;
}
- /// \brief Copy constructor for a template argument.
- TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
- // FIXME: Large integral values will get leaked. Do something
- // similar to what we did with IntegerLiteral.
- if (Kind == Integral) {
- new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else if (Kind == Pack) {
- Args.NumArgs = Other.Args.NumArgs;
- Args.Args = Other.Args.Args;
- } else if (Kind == Template || Kind == TemplateExpansion) {
- TemplateArg.Name = Other.TemplateArg.Name;
- TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
- } else
- TypeOrValue = Other.TypeOrValue;
- }
-
- TemplateArgument& operator=(const TemplateArgument& Other) {
- using llvm::APSInt;
-
- if (Kind == Other.Kind && Kind == Integral) {
- // Copy integral values.
- *this->getAsIntegral() = *Other.getAsIntegral();
- Integer.Type = Other.Integer.Type;
- return *this;
- }
-
- // Destroy the current integral value, if that's what we're holding.
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
-
- Kind = Other.Kind;
-
- if (Other.Kind == Integral) {
- new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else if (Other.Kind == Pack) {
- Args.NumArgs = Other.Args.NumArgs;
- Args.Args = Other.Args.Args;
- } else if (Kind == Template || Kind == TemplateExpansion) {
- TemplateArg.Name = Other.TemplateArg.Name;
- TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
- } else {
- TypeOrValue = Other.TypeOrValue;
- }
-
- return *this;
- }
-
- ~TemplateArgument() {
- using llvm::APSInt;
-
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
- }
-
/// \brief Create a new template argument pack by copying the given set of
/// template arguments.
static TemplateArgument CreatePackCopy(ASTContext &Context,
@@ -286,14 +242,15 @@ public:
llvm::Optional<unsigned> getNumTemplateExpansions() const;
/// \brief Retrieve the template argument as an integral value.
- llvm::APSInt *getAsIntegral() {
- if (Kind != Integral)
- return 0;
- return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
- }
+ // FIXME: Provide a way to read the integral data without copying the value.
+ llvm::APSInt getAsIntegral() const {
+ using namespace llvm;
+ if (Integer.BitWidth <= 64)
+ return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
- const llvm::APSInt *getAsIntegral() const {
- return const_cast<TemplateArgument*>(this)->getAsIntegral();
+ unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
+ return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
+ Integer.IsUnsigned);
}
/// \brief Retrieve the type of the integral value.
@@ -342,14 +299,12 @@ public:
return Args.NumArgs;
}
- /// Determines whether two template arguments are superficially the
+ /// \brief Determines whether two template arguments are superficially the
/// same.
bool structurallyEquals(const TemplateArgument &Other) const;
- /// \brief When the template argument is a pack expansion, returns
+ /// \brief When the template argument is a pack expansion, returns
/// the pattern of the pack expansion.
- ///
- /// \param Ellipsis Will be set to the location of the ellipsis.
TemplateArgument getPackExpansionPattern() const;
/// \brief Print this template argument to the given output stream.
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 7b615c19dcc4..6564b66548a4 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -29,6 +29,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/Twine.h"
#include "clang/Basic/LLVM.h"
namespace clang {
@@ -377,8 +378,6 @@ public:
return hasConst();
}
- bool isSupersetOf(Qualifiers Other) const;
-
/// \brief Determine whether this set of qualifiers is a strict superset of
/// another set of qualifiers, not considering qualifier compatibility.
bool isStrictSupersetOf(Qualifiers Other) const;
@@ -412,12 +411,11 @@ public:
}
std::string getAsString() const;
- std::string getAsString(const PrintingPolicy &Policy) const {
- std::string Buffer;
- getAsStringInternal(Buffer, Policy);
- return Buffer;
- }
- void getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const;
+ std::string getAsString(const PrintingPolicy &Policy) const;
+
+ bool isEmptyWhenPrinted(const PrintingPolicy &Policy) const;
+ void print(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool appendSpaceIfNonEmpty = false) const;
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger(Mask);
@@ -522,8 +520,6 @@ public:
void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
/// Retrieves a pointer to the underlying (unqualified) type.
- /// This should really return a const Type, but it's not worth
- /// changing all the users right now.
///
/// This function requires that the type not be NULL. If the type might be
/// NULL, use the (slightly less efficient) \c getTypePtrOrNull().
@@ -634,6 +630,11 @@ public:
/// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
bool isPODType(ASTContext &Context) const;
+ /// isCXX98PODType() - Return true if this is a POD type according to the
+ /// rules of the C++98 standard, regardless of the current compilation's
+ /// language.
+ bool isCXX98PODType(ASTContext &Context) const;
+
/// isCXX11PODType() - Return true if this is a POD type according to the
/// more relaxed rules of the C++11 standard, regardless of the current
/// compilation's language.
@@ -824,11 +825,20 @@ public:
}
static std::string getAsString(const Type *ty, Qualifiers qs);
- std::string getAsString(const PrintingPolicy &Policy) const {
- std::string S;
- getAsStringInternal(S, Policy);
- return S;
+ std::string getAsString(const PrintingPolicy &Policy) const;
+
+ void print(raw_ostream &OS, const PrintingPolicy &Policy,
+ const Twine &PlaceHolder = Twine()) const {
+ print(split(), OS, Policy, PlaceHolder);
+ }
+ static void print(SplitQualType split, raw_ostream &OS,
+ const PrintingPolicy &policy, const Twine &PlaceHolder) {
+ return print(split.Ty, split.Quals, OS, policy, PlaceHolder);
}
+ static void print(const Type *ty, Qualifiers qs,
+ raw_ostream &OS, const PrintingPolicy &policy,
+ const Twine &PlaceHolder);
+
void getAsStringInternal(std::string &Str,
const PrintingPolicy &Policy) const {
return getAsStringInternal(split(), Str, Policy);
@@ -841,6 +851,27 @@ public:
std::string &out,
const PrintingPolicy &policy);
+ class StreamedQualTypeHelper {
+ const QualType &T;
+ const PrintingPolicy &Policy;
+ const Twine &PlaceHolder;
+ public:
+ StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy,
+ const Twine &PlaceHolder)
+ : T(T), Policy(Policy), PlaceHolder(PlaceHolder) { }
+
+ friend raw_ostream &operator<<(raw_ostream &OS,
+ const StreamedQualTypeHelper &SQT) {
+ SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder);
+ return OS;
+ }
+ };
+
+ StreamedQualTypeHelper stream(const PrintingPolicy &Policy,
+ const Twine &PlaceHolder = Twine()) const {
+ return StreamedQualTypeHelper(*this, Policy, PlaceHolder);
+ }
+
void dump(const char *s) const;
void dump() const;
@@ -1107,8 +1138,6 @@ private:
unsigned TC : 8;
/// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
- /// Note that this should stay at the end of the ivars for Type so that
- /// subclasses can pack their bitfields into the same word.
unsigned Dependent : 1;
/// \brief Whether this type somehow involves a template parameter, even
@@ -1614,7 +1643,7 @@ public:
AutoType *getContainedAutoType() const;
/// Member-template getAs<specific type>'. Look through sugar for
- /// an instance of <specific type>. This scheme will eventually
+ /// an instance of \<specific type>. This scheme will eventually
/// replace the specific getAsXXXX methods above.
///
/// There are some specializations of this member template listed
@@ -1626,7 +1655,7 @@ public:
const ArrayType *getAsArrayTypeUnsafe() const;
/// Member-template castAs<specific type>. Look through sugar for
- /// the underlying instance of <specific type>.
+ /// the underlying instance of \<specific type>.
///
/// This method has the same relationship to getAs<T> as cast<T> has
/// to dyn_cast<T>; which is to say, the underlying type *must*
@@ -1715,9 +1744,9 @@ public:
friend class ASTWriter;
};
-template <> inline const TypedefType *Type::getAs() const {
- return dyn_cast<TypedefType>(this);
-}
+/// \brief This will check for a TypedefType by removing any existing sugar
+/// until it reaches a TypedefType or a non-sugared type.
+template <> const TypedefType *Type::getAs() const;
// We can do canonical leaf types faster, because we don't have to
// worry about preserving child type decoration.
@@ -1752,7 +1781,13 @@ public:
}
Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); }
- const char *getName(const PrintingPolicy &Policy) const;
+ StringRef getName(const PrintingPolicy &Policy) const;
+ const char *getNameAsCString(const PrintingPolicy &Policy) const {
+ // The StringRef is null-terminated.
+ StringRef str = getName(Policy);
+ assert(!str.empty() && str.data()[str.size()] == '\0');
+ return str.data();
+ }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2641,6 +2676,9 @@ public:
bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); }
CallingConv getCallConv() const { return getExtInfo().getCC(); }
ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
+ bool isConst() const { return getTypeQuals() & Qualifiers::Const; }
+ bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; }
+ bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; }
/// \brief Determine the type of an expression that calls a function of
/// this type.
@@ -2808,6 +2846,8 @@ public:
} else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
EPI.ExceptionSpecDecl = getExceptionSpecDecl();
EPI.ExceptionSpecTemplate = getExceptionSpecTemplate();
+ } else if (EPI.ExceptionSpecType == EST_Unevaluated) {
+ EPI.ExceptionSpecDecl = getExceptionSpecDecl();
}
if (hasAnyConsumedArgs())
EPI.ConsumedArguments = getConsumedArgsBuffer();
@@ -2851,11 +2891,13 @@ public:
// NoexceptExpr sits where the arguments end.
return *reinterpret_cast<Expr *const *>(arg_type_end());
}
- /// \brief If this function type has an uninstantiated exception
- /// specification, this is the function whose exception specification
- /// is represented by this type.
+ /// \brief If this function type has an exception specification which hasn't
+ /// been determined yet (either because it has not been evaluated or because
+ /// it has not been instantiated), this is the function whose exception
+ /// specification is represented by this type.
FunctionDecl *getExceptionSpecDecl() const {
- if (getExceptionSpecType() != EST_Uninstantiated)
+ if (getExceptionSpecType() != EST_Uninstantiated &&
+ getExceptionSpecType() != EST_Unevaluated)
return 0;
return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[0];
}
@@ -2870,7 +2912,7 @@ public:
}
bool isNothrow(ASTContext &Ctx) const {
ExceptionSpecificationType EST = getExceptionSpecType();
- assert(EST != EST_Delayed && EST != EST_Uninstantiated);
+ assert(EST != EST_Unevaluated && EST != EST_Uninstantiated);
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
return true;
if (EST != EST_ComputedNoexcept)
@@ -2928,8 +2970,11 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
+ // FIXME: Remove the string version.
void printExceptionSpecification(std::string &S,
PrintingPolicy Policy) const;
+ void printExceptionSpecification(raw_ostream &OS,
+ PrintingPolicy Policy) const;
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionProto;
@@ -3582,6 +3627,7 @@ public:
/// \brief Print a template argument list, including the '<' and '>'
/// enclosing the template arguments.
+ // FIXME: remove the string ones.
static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
unsigned NumArgs,
const PrintingPolicy &Policy,
@@ -3594,6 +3640,23 @@ public:
static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &,
const PrintingPolicy &Policy);
+ /// \brief Print a template argument list, including the '<' and '>'
+ /// enclosing the template arguments.
+ static void PrintTemplateArgumentList(raw_ostream &OS,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy,
+ bool SkipBrackets = false);
+
+ static void PrintTemplateArgumentList(raw_ostream &OS,
+ const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy);
+
+ static void PrintTemplateArgumentList(raw_ostream &OS,
+ const TemplateArgumentListInfo &,
+ const PrintingPolicy &Policy);
+
/// True if this template specialization type matches a current
/// instantiation in the context in which it is found.
bool isCurrentInstantiation() const {
@@ -3641,7 +3704,7 @@ public:
unsigned getNumArgs() const { return NumArgs; }
/// \brief Retrieve a specific template argument as a type.
- /// \precondition @c isArgType(Arg)
+ /// \pre @c isArgType(Arg)
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
bool isSugared() const {
@@ -4045,7 +4108,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
PackExpansionType(QualType Pattern, QualType Canon,
llvm::Optional<unsigned> NumExpansions)
- : Type(PackExpansion, Canon, /*Dependent=*/true,
+ : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(),
/*InstantiationDependent=*/true,
/*VariableModified=*/Pattern->isVariablyModifiedType(),
/*ContainsUnexpandedParameterPack=*/false),
@@ -4097,8 +4160,10 @@ public:
/// list of protocols.
///
/// Given the following declarations:
-/// @class C;
-/// @protocol P;
+/// \code
+/// \@class C;
+/// \@protocol P;
+/// \endcode
///
/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType
/// with base C and no protocols.
@@ -4312,11 +4377,13 @@ public:
/// This method is equivalent to getPointeeType() except that
/// it discards any typedefs (or other sugar) between this
/// type and the "outermost" object type. So for:
- /// @class A; @protocol P; @protocol Q;
+ /// \code
+ /// \@class A; \@protocol P; \@protocol Q;
/// typedef A<P> AP;
/// typedef A A1;
/// typedef A1<P> A1P;
/// typedef A1P<Q> A1PQ;
+ /// \endcode
/// For 'A*', getObjectType() will return 'A'.
/// For 'A<P>*', getObjectType() will return 'A<P>'.
/// For 'AP*', getObjectType() will return 'A<P>'.
@@ -4333,7 +4400,7 @@ public:
}
/// getInterfaceType - If this pointer points to an Objective C
- /// @interface type, gets the type for that interface. Any protocol
+ /// \@interface type, gets the type for that interface. Any protocol
/// qualifiers on the interface are ignored.
///
/// \return null if the base type for this pointer is 'id' or 'Class'
@@ -4341,7 +4408,7 @@ public:
return getObjectType()->getBaseType()->getAs<ObjCInterfaceType>();
}
- /// getInterfaceDecl - If this pointer points to an Objective @interface
+ /// getInterfaceDecl - If this pointer points to an Objective \@interface
/// type, gets the declaration for that interface.
///
/// \return null if the base type for this pointer is 'id' or 'Class'
@@ -4970,7 +5037,7 @@ struct ArrayType_cannot_be_used_with_getAs { };
template<typename T>
struct ArrayType_cannot_be_used_with_getAs<T, true>;
-/// Member-template getAs<specific type>'.
+// Member-template getAs<specific type>'.
template <typename T> const T *Type::getAs() const {
ArrayType_cannot_be_used_with_getAs<T> at;
(void)at;
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index aab87be7c48f..1d1c1d172573 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -831,6 +831,7 @@ public:
struct ObjCInterfaceLocInfo {
SourceLocation NameLoc;
+ SourceLocation NameEndLoc;
};
/// \brief Wrapper for source info for ObjC interfaces.
@@ -850,9 +851,17 @@ public:
void setNameLoc(SourceLocation Loc) {
getLocalData()->NameLoc = Loc;
}
-
+
SourceRange getLocalSourceRange() const {
- return SourceRange(getNameLoc());
+ return SourceRange(getNameLoc(), getNameEndLoc());
+ }
+
+ SourceLocation getNameEndLoc() const {
+ return getLocalData()->NameEndLoc;
+ }
+
+ void setNameEndLoc(SourceLocation Loc) {
+ getLocalData()->NameEndLoc = Loc;
}
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
new file mode 100644
index 000000000000..dd237eece3e4
--- /dev/null
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -0,0 +1,141 @@
+//===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides a way to construct an ASTConsumer that runs given matchers
+// over the AST and invokes a given callback on every match.
+//
+// The general idea is to construct a matcher expression that describes a
+// subtree match on the AST. Next, a callback that is executed every time the
+// expression matches is registered, and the matcher is run over the AST of
+// some code. Matched subexpressions can be bound to string IDs and easily
+// be accessed from the registered callback. The callback can than use the
+// AST nodes that the subexpressions matched on to output information about
+// the match or construct changes that can be applied to the code.
+//
+// Example:
+// class HandleMatch : public MatchFinder::MatchCallback {
+// public:
+// virtual void Run(const MatchFinder::MatchResult &Result) {
+// const CXXRecordDecl *Class =
+// Result.Nodes.GetDeclAs<CXXRecordDecl>("id");
+// ...
+// }
+// };
+//
+// int main(int argc, char **argv) {
+// ClangTool Tool(argc, argv);
+// MatchFinder finder;
+// finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))),
+// new HandleMatch);
+// return Tool.Run(newFrontendActionFactory(&finder));
+// }
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+namespace clang {
+
+namespace ast_matchers {
+
+/// \brief A class to allow finding matches over the Clang AST.
+///
+/// After creation, you can add multiple matchers to the MatchFinder via
+/// calls to addMatcher(...).
+///
+/// Once all matchers are added, newASTConsumer() returns an ASTConsumer
+/// that will trigger the callbacks specified via addMatcher(...) when a match
+/// is found.
+///
+/// See ASTMatchers.h for more information about how to create matchers.
+///
+/// Not intended to be subclassed.
+class MatchFinder {
+public:
+ /// \brief Contains all information for a given match.
+ ///
+ /// Every time a match is found, the MatchFinder will invoke the registered
+ /// MatchCallback with a MatchResult containing information about the match.
+ struct MatchResult {
+ MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
+
+ /// \brief Contains the nodes bound on the current match.
+ ///
+ /// This allows user code to easily extract matched AST nodes.
+ const BoundNodes Nodes;
+
+ /// \brief Utilities for interpreting the matched AST structures.
+ /// @{
+ clang::ASTContext * const Context;
+ clang::SourceManager * const SourceManager;
+ /// @}
+ };
+
+ /// \brief Called when the Match registered for it was successfully found
+ /// in the AST.
+ class MatchCallback {
+ public:
+ virtual ~MatchCallback();
+ virtual void run(const MatchResult &Result) = 0;
+ };
+
+ /// \brief Called when parsing is finished. Intended for testing only.
+ class ParsingDoneTestCallback {
+ public:
+ virtual ~ParsingDoneTestCallback();
+ virtual void run() = 0;
+ };
+
+ MatchFinder();
+ ~MatchFinder();
+
+ /// \brief Adds a matcher to execute when running over the AST.
+ ///
+ /// Calls 'Action' with the BoundNodes on every match.
+ /// Adding more than one 'NodeMatch' allows finding different matches in a
+ /// single pass over the AST.
+ ///
+ /// Does not take ownership of 'Action'.
+ /// @{
+ void addMatcher(const DeclarationMatcher &NodeMatch,
+ MatchCallback *Action);
+ void addMatcher(const TypeMatcher &NodeMatch,
+ MatchCallback *Action);
+ void addMatcher(const StatementMatcher &NodeMatch,
+ MatchCallback *Action);
+ /// @}
+
+ /// \brief Creates a clang ASTConsumer that finds all matches.
+ clang::ASTConsumer *newASTConsumer();
+
+ /// \brief Registers a callback to notify the end of parsing.
+ ///
+ /// The provided closure is called after parsing is done, before the AST is
+ /// traversed. Useful for benchmarking.
+ /// Each call to FindAll(...) will call the closure once.
+ void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
+
+private:
+ /// \brief The MatchCallback*'s will be called every time the
+ /// UntypedBaseMatcher matches on the AST.
+ std::vector< std::pair<
+ const internal::UntypedBaseMatcher*,
+ MatchCallback*> > Triggers;
+
+ /// \brief Called when parsing is done.
+ ParsingDoneTestCallback *ParsingDone;
+};
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
new file mode 100644
index 000000000000..37e82e8318dd
--- /dev/null
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -0,0 +1,1799 @@
+//===--- ASTMatchers.h - Structural query framework -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements matchers to be used together with the MatchFinder to
+// match AST nodes.
+//
+// Matchers are created by generator functions, which can be combined in
+// a functional in-language DSL to express queries over the C++ AST.
+//
+// For example, to match a class with a certain name, one would call:
+// record(hasName("MyClass"))
+// which returns a matcher that can be used to find all AST nodes that declare
+// a class named 'MyClass'.
+//
+// For more complicated match expressions we're often interested in accessing
+// multiple parts of the matched AST nodes once a match is found. In that case,
+// use the id(...) matcher around the match expressions that match the nodes
+// you want to access.
+//
+// For example, when we're interested in child classes of a certain class, we
+// would write:
+// record(hasName("MyClass"), hasChild(id("child", record())))
+// When the match is found via the MatchFinder, a user provided callback will
+// be called with a BoundNodes instance that contains a mapping from the
+// strings that we provided for the id(...) calls to the nodes that were
+// matched.
+// In the given example, each time our matcher finds a match we get a callback
+// where "child" is bound to the CXXRecordDecl node of the matching child
+// class declaration.
+//
+// See ASTMatchersInternal.h for a more in-depth explanation of the
+// implementation details of the matcher framework.
+//
+// See ASTMatchFinder.h for how to use the generated matchers to run over
+// an AST.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+
+#include "clang/AST/DeclTemplate.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "clang/ASTMatchers/ASTMatchersMacros.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace ast_matchers {
+
+/// \brief Maps string IDs to AST nodes matched by parts of a matcher.
+///
+/// The bound nodes are generated by adding id(...) matchers into the
+/// match expression around the matchers for the nodes we want to access later.
+///
+/// The instances of BoundNodes are created by MatchFinder when the user's
+/// callbacks are executed every time a match is found.
+class BoundNodes {
+public:
+ /// \brief Returns the AST node bound to 'ID'.
+ /// Returns NULL if there was no node bound to 'ID' or if there is a node but
+ /// it cannot be converted to the specified type.
+ /// FIXME: We'll need one of those for every base type.
+ /// @{
+ template <typename T>
+ const T *getDeclAs(StringRef ID) const {
+ return getNodeAs<T>(DeclBindings, ID);
+ }
+ template <typename T>
+ const T *getStmtAs(StringRef ID) const {
+ return getNodeAs<T>(StmtBindings, ID);
+ }
+ /// @}
+
+private:
+ /// \brief Create BoundNodes from a pre-filled map of bindings.
+ BoundNodes(const std::map<std::string, const Decl*> &DeclBindings,
+ const std::map<std::string, const Stmt*> &StmtBindings)
+ : DeclBindings(DeclBindings), StmtBindings(StmtBindings) {}
+
+ template <typename T, typename MapT>
+ const T *getNodeAs(const MapT &Bindings, StringRef ID) const {
+ typename MapT::const_iterator It = Bindings.find(ID);
+ if (It == Bindings.end()) {
+ return NULL;
+ }
+ return llvm::dyn_cast<T>(It->second);
+ }
+
+ std::map<std::string, const Decl*> DeclBindings;
+ std::map<std::string, const Stmt*> StmtBindings;
+
+ friend class internal::BoundNodesTree;
+};
+
+/// \brief If the provided matcher matches a node, binds the node to 'ID'.
+///
+/// FIXME: Add example for accessing it.
+template <typename T>
+internal::Matcher<T> id(const std::string &ID,
+ const internal::BindableMatcher<T> &InnerMatcher) {
+ return InnerMatcher.bind(ID);
+}
+
+/// \brief Types of matchers for the top-level classes in the AST class
+/// hierarchy.
+/// @{
+typedef internal::Matcher<Decl> DeclarationMatcher;
+typedef internal::Matcher<QualType> TypeMatcher;
+typedef internal::Matcher<Stmt> StatementMatcher;
+/// @}
+
+/// \brief Matches any node.
+///
+/// Useful when another matcher requires a child matcher, but there's no
+/// additional constraint. This will often be used with an explicit conversion
+/// to a internal::Matcher<> type such as TypeMatcher.
+///
+/// Example: DeclarationMatcher(anything()) matches all declarations, e.g.,
+/// "int* p" and "void f()" in
+/// int* p;
+/// void f();
+inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher> anything() {
+ return internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>();
+}
+
+/// \brief Matches declarations.
+///
+/// Examples matches \c X, \c C, and the friend declaration inside \c C;
+/// \code
+/// void X();
+/// class C {
+/// friend X;
+/// };
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, Decl> decl;
+
+/// \brief Matches a declaration of anything that could have a name.
+///
+/// Example matches X, S, the anonymous union type, i, and U;
+/// typedef int X;
+/// struct S {
+/// union {
+/// int i;
+/// } U;
+/// };
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ NamedDecl> nameableDeclaration;
+
+/// \brief Matches C++ class declarations.
+///
+/// Example matches X, Z
+/// class X;
+/// template<class T> class Z {};
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ CXXRecordDecl> record;
+
+/// \brief Matches C++ class template specializations.
+///
+/// Given
+/// template<typename T> class A {};
+/// template<> class A<double> {};
+/// A<int> a;
+/// classTemplateSpecialization()
+/// matches the specializations \c A<int> and \c A<double>
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ClassTemplateSpecializationDecl> classTemplateSpecialization;
+
+/// \brief Matches classTemplateSpecializations that have at least one
+/// TemplateArgument matching the given Matcher.
+///
+/// Given
+/// template<typename T> class A {};
+/// template<> class A<double> {};
+/// A<int> a;
+/// classTemplateSpecialization(hasAnyTemplateArgument(
+/// refersToType(asString("int"))))
+/// matches the specialization \c A<int>
+AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument,
+ internal::Matcher<TemplateArgument>, Matcher) {
+ const TemplateArgumentList &List = Node.getTemplateArgs();
+ for (unsigned i = 0; i < List.size(); ++i) {
+ if (Matcher.matches(List.get(i), Finder, Builder))
+ return true;
+ }
+ return false;
+}
+
+/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument
+/// matches the given Matcher.
+///
+/// Given
+/// template<typename T, typename U> class A {};
+/// A<bool, int> b;
+/// A<int, bool> c;
+/// classTemplateSpecialization(hasTemplateArgument(
+/// 1, refersToType(asString("int"))))
+/// matches the specialization \c A<bool, int>
+AST_MATCHER_P2(ClassTemplateSpecializationDecl, hasTemplateArgument,
+ unsigned, N, internal::Matcher<TemplateArgument>, Matcher) {
+ const TemplateArgumentList &List = Node.getTemplateArgs();
+ if (List.size() <= N)
+ return false;
+ return Matcher.matches(List.get(N), Finder, Builder);
+}
+
+/// \brief Matches a TemplateArgument that refers to a certain type.
+///
+/// Given
+/// struct X {};
+/// template<typename T> struct A {};
+/// A<X> a;
+/// classTemplateSpecialization(hasAnyTemplateArgument(
+/// refersToType(class(hasName("X")))))
+/// matches the specialization \c A<X>
+AST_MATCHER_P(TemplateArgument, refersToType,
+ internal::Matcher<QualType>, Matcher) {
+ if (Node.getKind() != TemplateArgument::Type)
+ return false;
+ return Matcher.matches(Node.getAsType(), Finder, Builder);
+}
+
+/// \brief Matches a TemplateArgument that refers to a certain declaration.
+///
+/// Given
+/// template<typename T> struct A {};
+/// struct B { B* next; };
+/// A<&B::next> a;
+/// classTemplateSpecialization(hasAnyTemplateArgument(
+/// refersToDeclaration(field(hasName("next"))))
+/// matches the specialization \c A<&B::next> with \c field(...) matching
+/// \c B::next
+AST_MATCHER_P(TemplateArgument, refersToDeclaration,
+ internal::Matcher<Decl>, Matcher) {
+ if (const Decl *Declaration = Node.getAsDecl())
+ return Matcher.matches(*Declaration, Finder, Builder);
+ return false;
+}
+
+/// \brief Matches C++ constructor declarations.
+///
+/// Example matches Foo::Foo() and Foo::Foo(int)
+/// class Foo {
+/// public:
+/// Foo();
+/// Foo(int);
+/// int DoSomething();
+/// };
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ CXXConstructorDecl> constructor;
+
+/// \brief Matches explicit C++ destructor declarations.
+///
+/// Example matches Foo::~Foo()
+/// class Foo {
+/// public:
+/// virtual ~Foo();
+/// };
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> destructor;
+
+/// \brief Matches enum declarations.
+///
+/// Example matches X
+/// enum X {
+/// A, B, C
+/// };
+const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
+
+/// \brief Matches enum constants.
+///
+/// Example matches A, B, C
+/// enum X {
+/// A, B, C
+/// };
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ EnumConstantDecl> enumConstant;
+
+/// \brief Matches method declarations.
+///
+/// Example matches y
+/// class X { void y() };
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> method;
+
+/// \brief Matches variable declarations.
+///
+/// Note: this does not match declarations of member variables, which are
+/// "field" declarations in Clang parlance.
+///
+/// Example matches a
+/// int a;
+const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> variable;
+
+/// \brief Matches field declarations.
+///
+/// Given
+/// class X { int m; };
+/// field()
+/// matches 'm'.
+const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> field;
+
+/// \brief Matches function declarations.
+///
+/// Example matches f
+/// void f();
+const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> function;
+
+
+/// \brief Matches statements.
+///
+/// Given
+/// { ++a; }
+/// statement()
+/// matches both the compound statement '{ ++a; }' and '++a'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, Stmt> statement;
+
+/// \brief Matches declaration statements.
+///
+/// Given
+/// int a;
+/// declarationStatement()
+/// matches 'int a'.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ DeclStmt> declarationStatement;
+
+/// \brief Matches member expressions.
+///
+/// Given
+/// class Y {
+/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; }
+/// int a; static int b;
+/// };
+/// memberExpression()
+/// matches this->x, x, y.x, a, this->b
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ MemberExpr> memberExpression;
+
+/// \brief Matches call expressions.
+///
+/// Example matches x.y() and y()
+/// X x;
+/// x.y();
+/// y();
+const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> call;
+
+/// \brief Matches member call expressions.
+///
+/// Example matches x.y()
+/// X x;
+/// x.y();
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr> memberCall;
+
+/// \brief Matches init list expressions.
+///
+/// Given
+/// int a[] = { 1, 2 };
+/// struct B { int x, y; };
+/// B b = { 5, 6 };
+/// initList()
+/// matches "{ 1, 2 }" and "{ 5, 6 }"
+const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
+
+/// \brief Matches using declarations.
+///
+/// Given
+/// namespace X { int x; }
+/// using X::x;
+/// usingDecl()
+/// matches \code using X::x \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
+
+/// \brief Matches constructor call expressions (including implicit ones).
+///
+/// Example matches string(ptr, n) and ptr within arguments of f
+/// (matcher = constructorCall())
+/// void f(const string &a, const string &b);
+/// char *ptr;
+/// int n;
+/// f(string(ptr, n), ptr);
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXConstructExpr> constructorCall;
+
+/// \brief Matches nodes where temporaries are created.
+///
+/// Example matches FunctionTakesString(GetStringByValue())
+/// (matcher = bindTemporaryExpression())
+/// FunctionTakesString(GetStringByValue());
+/// FunctionTakesStringByPointer(GetStringPointer());
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXBindTemporaryExpr> bindTemporaryExpression;
+
+/// \brief Matches new expressions.
+///
+/// Given
+/// new X;
+/// newExpression()
+/// matches 'new X'.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXNewExpr> newExpression;
+
+/// \brief Matches delete expressions.
+///
+/// Given
+/// delete X;
+/// deleteExpression()
+/// matches 'delete X'.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXDeleteExpr> deleteExpression;
+
+/// \brief Matches array subscript expressions.
+///
+/// Given
+/// int i = a[1];
+/// arraySubscriptExpr()
+/// matches "a[1]"
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ArraySubscriptExpr> arraySubscriptExpr;
+
+/// \brief Matches the value of a default argument at the call site.
+///
+/// Example matches the CXXDefaultArgExpr placeholder inserted for the
+/// default value of the second parameter in the call expression f(42)
+/// (matcher = defaultArgument())
+/// void f(int x, int y = 0);
+/// f(42);
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXDefaultArgExpr> defaultArgument;
+
+/// \brief Matches overloaded operator calls.
+///
+/// Note that if an operator isn't overloaded, it won't match. Instead, use
+/// binaryOperator matcher.
+/// Currently it does not match operators such as new delete.
+/// FIXME: figure out why these do not match?
+///
+/// Example matches both operator<<((o << b), c) and operator<<(o, b)
+/// (matcher = overloadedOperatorCall())
+/// ostream &operator<< (ostream &out, int i) { };
+/// ostream &o; int b = 1, c = 1;
+/// o << b << c;
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXOperatorCallExpr> overloadedOperatorCall;
+
+/// \brief Matches expressions.
+///
+/// Example matches x()
+/// void f() { x(); }
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ Expr> expression;
+
+/// \brief Matches expressions that refer to declarations.
+///
+/// Example matches x in if (x)
+/// bool x;
+/// if (x) {}
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ DeclRefExpr> declarationReference;
+
+/// \brief Matches if statements.
+///
+/// Example matches 'if (x) {}'
+/// if (x) {}
+const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
+
+/// \brief Matches for statements.
+///
+/// Example matches 'for (;;) {}'
+/// for (;;) {}
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt, ForStmt> forStmt;
+
+/// \brief Matches the increment statement of a for loop.
+///
+/// Example:
+/// forStmt(hasIncrement(unaryOperator(hasOperatorName("++"))))
+/// matches '++x' in
+/// for (x; x < N; ++x) { }
+AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>,
+ InnerMatcher) {
+ const Stmt *const Increment = Node.getInc();
+ return (Increment != NULL &&
+ InnerMatcher.matches(*Increment, Finder, Builder));
+}
+
+/// \brief Matches the initialization statement of a for loop.
+///
+/// Example:
+/// forStmt(hasLoopInit(declarationStatement()))
+/// matches 'int x = 0' in
+/// for (int x = 0; x < N; ++x) { }
+AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
+ InnerMatcher) {
+ const Stmt *const Init = Node.getInit();
+ return (Init != NULL && InnerMatcher.matches(*Init, Finder, Builder));
+}
+
+/// \brief Matches while statements.
+///
+/// Given
+/// while (true) {}
+/// whileStmt()
+/// matches 'while (true) {}'.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ WhileStmt> whileStmt;
+
+/// \brief Matches do statements.
+///
+/// Given
+/// do {} while (true);
+/// doStmt()
+/// matches 'do {} while(true)'
+const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
+
+/// \brief Matches case and default statements inside switch statements.
+///
+/// Given
+/// switch(a) { case 42: break; default: break; }
+/// switchCase()
+/// matches 'case 42: break;' and 'default: break;'.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ SwitchCase> switchCase;
+
+/// \brief Matches compound statements.
+///
+/// Example matches '{}' and '{{}}'in 'for (;;) {{}}'
+/// for (;;) {{}}
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CompoundStmt> compoundStatement;
+
+/// \brief Matches bool literals.
+///
+/// Example matches true
+/// true
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ CXXBoolLiteralExpr> boolLiteral;
+
+/// \brief Matches string literals (also matches wide string literals).
+///
+/// Example matches "abcd", L"abcd"
+/// char *s = "abcd"; wchar_t *ws = L"abcd"
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ StringLiteral> stringLiteral;
+
+/// \brief Matches character literals (also matches wchar_t).
+///
+/// Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral),
+/// though.
+///
+/// Example matches 'a', L'a'
+/// char ch = 'a'; wchar_t chw = L'a';
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ CharacterLiteral> characterLiteral;
+
+/// \brief Matches integer literals of all sizes / encodings.
+///
+/// Not matching character-encoded integers such as L'a'.
+///
+/// Example matches 1, 1L, 0x1, 1U
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ IntegerLiteral> integerLiteral;
+
+/// \brief Matches binary operator expressions.
+///
+/// Example matches a || b
+/// !(a || b)
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ BinaryOperator> binaryOperator;
+
+/// \brief Matches unary operator expressions.
+///
+/// Example matches !a
+/// !a || b
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ UnaryOperator> unaryOperator;
+
+/// \brief Matches conditional operator expressions.
+///
+/// Example matches a ? b : c
+/// (a ? b : c) + 42
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ConditionalOperator> conditionalOperator;
+
+/// \brief Matches a reinterpret_cast expression.
+///
+/// Either the source expression or the destination type can be matched
+/// using has(), but hasDestinationType() is more specific and can be
+/// more readable.
+///
+/// Example matches reinterpret_cast<char*>(&p) in
+/// void* p = reinterpret_cast<char*>(&p);
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ CXXReinterpretCastExpr> reinterpretCast;
+
+/// \brief Matches a C++ static_cast expression.
+///
+/// \see hasDestinationType
+/// \see reinterpretCast
+///
+/// Example:
+/// staticCast()
+/// matches
+/// static_cast<long>(8)
+/// in
+/// long eight(static_cast<long>(8));
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ CXXStaticCastExpr> staticCast;
+
+/// \brief Matches a dynamic_cast expression.
+///
+/// Example:
+/// dynamicCast()
+/// matches
+/// dynamic_cast<D*>(&b);
+/// in
+/// struct B { virtual ~B() {} }; struct D : B {};
+/// B b;
+/// D* p = dynamic_cast<D*>(&b);
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ CXXDynamicCastExpr> dynamicCast;
+
+/// \brief Matches a const_cast expression.
+///
+/// Example: Matches const_cast<int*>(&r) in
+/// int n = 42;
+/// const int& r(n);
+/// int* p = const_cast<int*>(&r);
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ CXXConstCastExpr> constCast;
+
+/// \brief Matches explicit cast expressions.
+///
+/// Matches any cast expression written in user code, whether it be a
+/// C-style cast, a functional-style cast, or a keyword cast.
+///
+/// Does not match implicit conversions.
+///
+/// Note: the name "explicitCast" is chosen to match Clang's terminology, as
+/// Clang uses the term "cast" to apply to implicit conversions as well as to
+/// actual cast expressions.
+///
+/// \see hasDestinationType.
+///
+/// Example: matches all five of the casts in
+/// int((int)(reinterpret_cast<int>(static_cast<int>(const_cast<int>(42)))))
+/// but does not match the implicit conversion in
+/// long ell = 42;
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ ExplicitCastExpr> explicitCast;
+
+/// \brief Matches the implicit cast nodes of Clang's AST.
+///
+/// This matches many different places, including function call return value
+/// eliding, as well as any type conversions.
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ ImplicitCastExpr> implicitCast;
+
+/// \brief Matches functional cast expressions
+///
+/// Example: Matches Foo(bar);
+/// Foo f = bar;
+/// Foo g = (Foo) bar;
+/// Foo h = Foo(bar);
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ CXXFunctionalCastExpr> functionalCast;
+
+/// \brief Various overloads for the anyOf matcher.
+/// @{
+template<typename C1, typename C2>
+internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, C2>
+anyOf(const C1 &P1, const C2 &P2) {
+ return internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
+ C1, C2 >(P1, P2);
+}
+template<typename C1, typename C2, typename C3>
+internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1,
+ internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2, C3> >
+anyOf(const C1 &P1, const C2 &P2, const C3 &P3) {
+ return anyOf(P1, anyOf(P2, P3));
+}
+template<typename C1, typename C2, typename C3, typename C4>
+internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1,
+ internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2,
+ internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
+ C3, C4> > >
+anyOf(const C1 &P1, const C2 &P2, const C3 &P3, const C4 &P4) {
+ return anyOf(P1, anyOf(P2, anyOf(P3, P4)));
+}
+template<typename C1, typename C2, typename C3, typename C4, typename C5>
+internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1,
+ internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2,
+ internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C3,
+ internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
+ C4, C5> > > >
+anyOf(const C1& P1, const C2& P2, const C3& P3, const C4& P4, const C5& P5) {
+ return anyOf(P1, anyOf(P2, anyOf(P3, anyOf(P4, P5))));
+}
+/// @}
+
+/// \brief Various overloads for the allOf matcher.
+/// @{
+template<typename C1, typename C2>
+internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C1, C2>
+allOf(const C1 &P1, const C2 &P2) {
+ return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher,
+ C1, C2>(P1, P2);
+}
+template<typename C1, typename C2, typename C3>
+internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C1,
+ internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C2, C3> >
+allOf(const C1& P1, const C2& P2, const C3& P3) {
+ return allOf(P1, allOf(P2, P3));
+}
+/// @}
+
+/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
+///
+/// Given
+/// Foo x = bar;
+/// int y = sizeof(x) + alignof(x);
+/// unaryExprOrTypeTraitExpr()
+/// matches \c sizeof(x) and \c alignof(x)
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ UnaryExprOrTypeTraitExpr> unaryExprOrTypeTraitExpr;
+
+/// \brief Matches unary expressions that have a specific type of argument.
+///
+/// Given
+/// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c);
+/// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int"))
+/// matches \c sizeof(a) and \c alignof(c)
+AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType,
+ internal::Matcher<QualType>, Matcher) {
+ const QualType ArgumentType = Node.getTypeOfArgument();
+ return Matcher.matches(ArgumentType, Finder, Builder);
+}
+
+/// \brief Matches unary expressions of a certain kind.
+///
+/// Given
+/// int x;
+/// int s = sizeof(x) + alignof(x)
+/// unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf))
+/// matches \c sizeof(x)
+AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) {
+ return Node.getKind() == Kind;
+}
+
+/// \brief Same as unaryExprOrTypeTraitExpr, but only matching
+/// alignof.
+inline internal::Matcher<Stmt> alignOfExpr(
+ const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) {
+ return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf(
+ ofKind(UETT_AlignOf), Matcher)));
+}
+
+/// \brief Same as unaryExprOrTypeTraitExpr, but only matching
+/// sizeof.
+inline internal::Matcher<Stmt> sizeOfExpr(
+ const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) {
+ return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf(
+ ofKind(UETT_SizeOf), Matcher)));
+}
+
+/// \brief Matches NamedDecl nodes that have the specified name.
+///
+/// Supports specifying enclosing namespaces or classes by prefixing the name
+/// with '<enclosing>::'.
+/// Does not match typedefs of an underlying type with the given name.
+///
+/// Example matches X (Name == "X")
+/// class X;
+///
+/// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X")
+/// namespace a { namespace b { class X; } }
+AST_MATCHER_P(NamedDecl, hasName, std::string, Name) {
+ assert(!Name.empty());
+ const std::string FullNameString = "::" + Node.getQualifiedNameAsString();
+ const llvm::StringRef FullName = FullNameString;
+ const llvm::StringRef Pattern = Name;
+ if (Pattern.startswith("::")) {
+ return FullName == Pattern;
+ } else {
+ return FullName.endswith(("::" + Pattern).str());
+ }
+}
+
+/// \brief Matches NamedDecl nodes whose full names partially match the
+/// given RegExp.
+///
+/// Supports specifying enclosing namespaces or classes by
+/// prefixing the name with '<enclosing>::'. Does not match typedefs
+/// of an underlying type with the given name.
+///
+/// Example matches X (regexp == "::X")
+/// class X;
+///
+/// Example matches X (regexp is one of "::X", "^foo::.*X", among others)
+/// namespace foo { namespace bar { class X; } }
+AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
+ assert(!RegExp.empty());
+ std::string FullNameString = "::" + Node.getQualifiedNameAsString();
+ llvm::Regex RE(RegExp);
+ return RE.match(FullNameString);
+}
+
+/// \brief Matches overloaded operator names.
+///
+/// Matches overloaded operator names specified in strings without the
+/// "operator" prefix, such as "<<", for OverloadedOperatorCall's.
+///
+/// Example matches a << b
+/// (matcher == overloadedOperatorCall(hasOverloadedOperatorName("<<")))
+/// a << b;
+/// c && d; // assuming both operator<<
+/// // and operator&& are overloaded somewhere.
+AST_MATCHER_P(CXXOperatorCallExpr,
+ hasOverloadedOperatorName, std::string, Name) {
+ return getOperatorSpelling(Node.getOperator()) == Name;
+}
+
+/// \brief Matches C++ classes that are directly or indirectly derived from
+/// a class matching \c Base.
+///
+/// Note that a class is considered to be also derived from itself.
+///
+/// Example matches X, Y, Z, C (Base == hasName("X"))
+/// class X; // A class is considered to be derived from itself
+/// class Y : public X {}; // directly derived
+/// class Z : public Y {}; // indirectly derived
+/// typedef X A;
+/// typedef A B;
+/// class C : public B {}; // derived from a typedef of X
+///
+/// In the following example, Bar matches isDerivedFrom(hasName("X")):
+/// class Foo;
+/// typedef Foo X;
+/// class Bar : public Foo {}; // derived from a type that X is a typedef of
+AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
+ internal::Matcher<NamedDecl>, Base) {
+ return Finder->classIsDerivedFrom(&Node, Base, Builder);
+}
+
+/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
+inline internal::Matcher<CXXRecordDecl> isDerivedFrom(StringRef BaseName) {
+ assert(!BaseName.empty());
+ return isDerivedFrom(hasName(BaseName));
+}
+
+/// \brief Matches AST nodes that have child AST nodes that match the
+/// provided matcher.
+///
+/// Example matches X, Y (matcher = record(has(record(hasName("X")))
+/// class X {}; // Matches X, because X::X is a class of name X inside X.
+/// class Y { class X {}; };
+/// class Z { class Y { class X {}; }; }; // Does not match Z.
+///
+/// ChildT must be an AST base type.
+template <typename ChildT>
+internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has(
+ const internal::Matcher<ChildT> &ChildMatcher) {
+ return internal::ArgumentAdaptingMatcher<internal::HasMatcher,
+ ChildT>(ChildMatcher);
+}
+
+/// \brief Matches AST nodes that have descendant AST nodes that match the
+/// provided matcher.
+///
+/// Example matches X, Y, Z
+/// (matcher = record(hasDescendant(record(hasName("X")))))
+/// class X {}; // Matches X, because X::X is a class of name X inside X.
+/// class Y { class X {}; };
+/// class Z { class Y { class X {}; }; };
+///
+/// DescendantT must be an AST base type.
+template <typename DescendantT>
+internal::ArgumentAdaptingMatcher<internal::HasDescendantMatcher, DescendantT>
+hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) {
+ return internal::ArgumentAdaptingMatcher<
+ internal::HasDescendantMatcher,
+ DescendantT>(DescendantMatcher);
+}
+
+
+/// \brief Matches AST nodes that have child AST nodes that match the
+/// provided matcher.
+///
+/// Example matches X, Y (matcher = record(forEach(record(hasName("X")))
+/// class X {}; // Matches X, because X::X is a class of name X inside X.
+/// class Y { class X {}; };
+/// class Z { class Y { class X {}; }; }; // Does not match Z.
+///
+/// ChildT must be an AST base type.
+///
+/// As opposed to 'has', 'forEach' will cause a match for each result that
+/// matches instead of only on the first one.
+template <typename ChildT>
+internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach(
+ const internal::Matcher<ChildT>& ChildMatcher) {
+ return internal::ArgumentAdaptingMatcher<
+ internal::ForEachMatcher,
+ ChildT>(ChildMatcher);
+}
+
+/// \brief Matches AST nodes that have descendant AST nodes that match the
+/// provided matcher.
+///
+/// Example matches X, A, B, C
+/// (matcher = record(forEachDescendant(record(hasName("X")))))
+/// class X {}; // Matches X, because X::X is a class of name X inside X.
+/// class A { class X {}; };
+/// class B { class C { class X {}; }; };
+///
+/// DescendantT must be an AST base type.
+///
+/// As opposed to 'hasDescendant', 'forEachDescendant' will cause a match for
+/// each result that matches instead of only on the first one.
+///
+/// Note: Recursively combined ForEachDescendant can cause many matches:
+/// record(forEachDescendant(record(forEachDescendant(record()))))
+/// will match 10 times (plus injected class name matches) on:
+/// class A { class B { class C { class D { class E {}; }; }; }; };
+template <typename DescendantT>
+internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, DescendantT>
+forEachDescendant(
+ const internal::Matcher<DescendantT>& DescendantMatcher) {
+ return internal::ArgumentAdaptingMatcher<
+ internal::ForEachDescendantMatcher,
+ DescendantT>(DescendantMatcher);
+}
+
+/// \brief Matches if the provided matcher does not match.
+///
+/// Example matches Y (matcher = record(unless(hasName("X"))))
+/// class X {};
+/// class Y {};
+template <typename M>
+internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M> unless(const M &InnerMatcher) {
+ return internal::PolymorphicMatcherWithParam1<
+ internal::NotMatcher, M>(InnerMatcher);
+}
+
+/// \brief Matches a type if the declaration of the type matches the given
+/// matcher.
+///
+/// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>
+inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher,
+ internal::Matcher<Decl> >
+ hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
+ return internal::PolymorphicMatcherWithParam1<
+ internal::HasDeclarationMatcher,
+ internal::Matcher<Decl> >(InnerMatcher);
+}
+
+/// \brief Matches on the implicit object argument of a member call expression.
+///
+/// Example matches y.x() (matcher = call(on(hasType(record(hasName("Y"))))))
+/// class Y { public: void x(); };
+/// void z() { Y y; y.x(); }",
+///
+/// FIXME: Overload to allow directly matching types?
+AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
+ InnerMatcher) {
+ const Expr *ExprNode = const_cast<CXXMemberCallExpr&>(Node)
+ .getImplicitObjectArgument()
+ ->IgnoreParenImpCasts();
+ return (ExprNode != NULL &&
+ InnerMatcher.matches(*ExprNode, Finder, Builder));
+}
+
+/// \brief Matches if the call expression's callee expression matches.
+///
+/// Given
+/// class Y { void x() { this->x(); x(); Y y; y.x(); } };
+/// void f() { f(); }
+/// call(callee(expression()))
+/// matches this->x(), x(), y.x(), f()
+/// with callee(...)
+/// matching this->x, x, y.x, f respectively
+///
+/// Note: Callee cannot take the more general internal::Matcher<Expr>
+/// because this introduces ambiguous overloads with calls to Callee taking a
+/// internal::Matcher<Decl>, as the matcher hierarchy is purely
+/// implemented in terms of implicit casts.
+AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
+ InnerMatcher) {
+ const Expr *ExprNode = Node.getCallee();
+ return (ExprNode != NULL &&
+ InnerMatcher.matches(*ExprNode, Finder, Builder));
+}
+
+/// \brief Matches if the call expression's callee's declaration matches the
+/// given matcher.
+///
+/// Example matches y.x() (matcher = call(callee(method(hasName("x")))))
+/// class Y { public: void x(); };
+/// void z() { Y y; y.x();
+inline internal::Matcher<CallExpr> callee(
+ const internal::Matcher<Decl> &InnerMatcher) {
+ return internal::Matcher<CallExpr>(hasDeclaration(InnerMatcher));
+}
+
+/// \brief Matches if the expression's or declaration's type matches a type
+/// matcher.
+///
+/// Example matches x (matcher = expression(hasType(
+/// hasDeclaration(record(hasName("X"))))))
+/// and z (matcher = variable(hasType(
+/// hasDeclaration(record(hasName("X"))))))
+/// class X {};
+/// void y(X &x) { x; X z; }
+AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>,
+ InnerMatcher) {
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<Expr, NodeType>::value ||
+ llvm::is_base_of<ValueDecl, NodeType>::value),
+ instantiated_with_wrong_types);
+ return InnerMatcher.matches(Node.getType(), Finder, Builder);
+}
+
+/// \brief Overloaded to match the declaration of the expression's or value
+/// declaration's type.
+///
+/// In case of a value declaration (for example a variable declaration),
+/// this resolves one layer of indirection. For example, in the value
+/// declaration "X x;", record(hasName("X")) matches the declaration of X,
+/// while variable(hasType(record(hasName("X")))) matches the declaration
+/// of x."
+///
+/// Example matches x (matcher = expression(hasType(record(hasName("X")))))
+/// and z (matcher = variable(hasType(record(hasName("X")))))
+/// class X {};
+/// void y(X &x) { x; X z; }
+///
+/// Usable as: Matcher<Expr>, Matcher<ValueDecl>
+inline internal::PolymorphicMatcherWithParam1<
+ internal::matcher_hasTypeMatcher,
+ internal::Matcher<QualType> >
+hasType(const internal::Matcher<Decl> &InnerMatcher) {
+ return hasType(internal::Matcher<QualType>(
+ hasDeclaration(InnerMatcher)));
+}
+
+/// \brief Matches if the matched type is represented by the given string.
+///
+/// Given
+/// class Y { public: void x(); };
+/// void z() { Y* y; y->x(); }
+/// call(on(hasType(asString("class Y *"))))
+/// matches y->x()
+AST_MATCHER_P(QualType, asString, std::string, Name) {
+ return Name == Node.getAsString();
+}
+
+/// \brief Matches if the matched type is a pointer type and the pointee type
+/// matches the specified matcher.
+///
+/// Example matches y->x()
+/// (matcher = call(on(hasType(pointsTo(record(hasName("Y")))))))
+/// class Y { public: void x(); };
+/// void z() { Y *y; y->x(); }
+AST_MATCHER_P(
+ QualType, pointsTo, internal::Matcher<QualType>,
+ InnerMatcher) {
+ return (!Node.isNull() && Node->isPointerType() &&
+ InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
+}
+
+/// \brief Overloaded to match the pointee type's declaration.
+inline internal::Matcher<QualType> pointsTo(
+ const internal::Matcher<Decl> &InnerMatcher) {
+ return pointsTo(internal::Matcher<QualType>(
+ hasDeclaration(InnerMatcher)));
+}
+
+/// \brief Matches if the matched type is a reference type and the referenced
+/// type matches the specified matcher.
+///
+/// Example matches X &x and const X &y
+/// (matcher = variable(hasType(references(record(hasName("X"))))))
+/// class X {
+/// void a(X b) {
+/// X &x = b;
+/// const X &y = b;
+/// };
+AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
+ InnerMatcher) {
+ return (!Node.isNull() && Node->isReferenceType() &&
+ InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
+}
+
+/// \brief Overloaded to match the referenced type's declaration.
+inline internal::Matcher<QualType> references(
+ const internal::Matcher<Decl> &InnerMatcher) {
+ return references(internal::Matcher<QualType>(
+ hasDeclaration(InnerMatcher)));
+}
+
+AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *ExprNode =
+ const_cast<CXXMemberCallExpr&>(Node).getImplicitObjectArgument();
+ return (ExprNode != NULL &&
+ InnerMatcher.matches(*ExprNode, Finder, Builder));
+}
+
+/// \brief Matches if the expression's type either matches the specified
+/// matcher, or is a pointer to a type that matches the InnerMatcher.
+inline internal::Matcher<CXXMemberCallExpr> thisPointerType(
+ const internal::Matcher<QualType> &InnerMatcher) {
+ return onImplicitObjectArgument(
+ anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
+}
+
+/// \brief Overloaded to match the type's declaration.
+inline internal::Matcher<CXXMemberCallExpr> thisPointerType(
+ const internal::Matcher<Decl> &InnerMatcher) {
+ return onImplicitObjectArgument(
+ anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
+}
+
+/// \brief Matches a DeclRefExpr that refers to a declaration that matches the
+/// specified matcher.
+///
+/// Example matches x in if(x)
+/// (matcher = declarationReference(to(variable(hasName("x")))))
+/// bool x;
+/// if (x) {}
+AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
+ InnerMatcher) {
+ const Decl *DeclNode = Node.getDecl();
+ return (DeclNode != NULL &&
+ InnerMatcher.matches(*DeclNode, Finder, Builder));
+}
+
+/// \brief Matches a \c DeclRefExpr that refers to a declaration through a
+/// specific using shadow declaration.
+///
+/// FIXME: This currently only works for functions. Fix.
+///
+/// Given
+/// namespace a { void f() {} }
+/// using a::f;
+/// void g() {
+/// f(); // Matches this ..
+/// a::f(); // .. but not this.
+/// }
+/// declarationReference(throughUsingDeclaration(anything()))
+/// matches \c f()
+AST_MATCHER_P(DeclRefExpr, throughUsingDecl,
+ internal::Matcher<UsingShadowDecl>, Matcher) {
+ const NamedDecl *FoundDecl = Node.getFoundDecl();
+ if (const UsingShadowDecl *UsingDecl =
+ llvm::dyn_cast<UsingShadowDecl>(FoundDecl))
+ return Matcher.matches(*UsingDecl, Finder, Builder);
+ return false;
+}
+
+/// \brief Matches a variable declaration that has an initializer expression
+/// that matches the given matcher.
+///
+/// Example matches x (matcher = variable(hasInitializer(call())))
+/// bool y() { return true; }
+/// bool x = y();
+AST_MATCHER_P(
+ VarDecl, hasInitializer, internal::Matcher<Expr>,
+ InnerMatcher) {
+ const Expr *Initializer = Node.getAnyInitializer();
+ return (Initializer != NULL &&
+ InnerMatcher.matches(*Initializer, Finder, Builder));
+}
+
+/// \brief Checks that a call expression or a constructor call expression has
+/// a specific number of arguments (including absent default arguments).
+///
+/// Example matches f(0, 0) (matcher = call(argumentCountIs(2)))
+/// void f(int x, int y);
+/// f(0, 0);
+AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
+ llvm::is_base_of<CXXConstructExpr,
+ NodeType>::value),
+ instantiated_with_wrong_types);
+ return Node.getNumArgs() == N;
+}
+
+/// \brief Matches the n'th argument of a call expression or a constructor
+/// call expression.
+///
+/// Example matches y in x(y)
+/// (matcher = call(hasArgument(0, declarationReference())))
+/// void x(int) { int y; x(y); }
+AST_POLYMORPHIC_MATCHER_P2(
+ hasArgument, unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
+ llvm::is_base_of<CXXConstructExpr,
+ NodeType>::value),
+ instantiated_with_wrong_types);
+ return (N < Node.getNumArgs() &&
+ InnerMatcher.matches(
+ *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
+}
+
+/// \brief Matches a constructor initializer.
+///
+/// Given
+/// struct Foo {
+/// Foo() : foo_(1) { }
+/// int foo_;
+/// };
+/// record(has(constructor(hasAnyConstructorInitializer(anything()))))
+/// record matches Foo, hasAnyConstructorInitializer matches foo_(1)
+AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
+ internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
+ for (CXXConstructorDecl::init_const_iterator I = Node.init_begin();
+ I != Node.init_end(); ++I) {
+ if (InnerMatcher.matches(**I, Finder, Builder)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/// \brief Matches the field declaration of a constructor initializer.
+///
+/// Given
+/// struct Foo {
+/// Foo() : foo_(1) { }
+/// int foo_;
+/// };
+/// record(has(constructor(hasAnyConstructorInitializer(
+/// forField(hasName("foo_"))))))
+/// matches Foo
+/// with forField matching foo_
+AST_MATCHER_P(CXXCtorInitializer, forField,
+ internal::Matcher<FieldDecl>, InnerMatcher) {
+ const FieldDecl *NodeAsDecl = Node.getMember();
+ return (NodeAsDecl != NULL &&
+ InnerMatcher.matches(*NodeAsDecl, Finder, Builder));
+}
+
+/// \brief Matches the initializer expression of a constructor initializer.
+///
+/// Given
+/// struct Foo {
+/// Foo() : foo_(1) { }
+/// int foo_;
+/// };
+/// record(has(constructor(hasAnyConstructorInitializer(
+/// withInitializer(integerLiteral(equals(1)))))))
+/// matches Foo
+/// with withInitializer matching (1)
+AST_MATCHER_P(CXXCtorInitializer, withInitializer,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr* NodeAsExpr = Node.getInit();
+ return (NodeAsExpr != NULL &&
+ InnerMatcher.matches(*NodeAsExpr, Finder, Builder));
+}
+
+/// \brief Matches a contructor initializer if it is explicitly written in
+/// code (as opposed to implicitly added by the compiler).
+///
+/// Given
+/// struct Foo {
+/// Foo() { }
+/// Foo(int) : foo_("A") { }
+/// string foo_;
+/// };
+/// constructor(hasAnyConstructorInitializer(isWritten()))
+/// will match Foo(int), but not Foo()
+AST_MATCHER(CXXCtorInitializer, isWritten) {
+ return Node.isWritten();
+}
+
+/// \brief Matches a constructor declaration that has been implicitly added
+/// by the compiler (eg. implicit default/copy constructors).
+AST_MATCHER(CXXConstructorDecl, isImplicit) {
+ return Node.isImplicit();
+}
+
+/// \brief Matches any argument of a call expression or a constructor call
+/// expression.
+///
+/// Given
+/// void x(int, int, int) { int y; x(1, y, 42); }
+/// call(hasAnyArgument(declarationReference()))
+/// matches x(1, y, 42)
+/// with hasAnyArgument(...)
+/// matching y
+AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher<Expr>,
+ InnerMatcher) {
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
+ llvm::is_base_of<CXXConstructExpr,
+ NodeType>::value),
+ instantiated_with_wrong_types);
+ for (unsigned I = 0; I < Node.getNumArgs(); ++I) {
+ if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(),
+ Finder, Builder)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/// \brief Matches the n'th parameter of a function declaration.
+///
+/// Given
+/// class X { void f(int x) {} };
+/// method(hasParameter(0, hasType(variable())))
+/// matches f(int x) {}
+/// with hasParameter(...)
+/// matching int x
+AST_MATCHER_P2(FunctionDecl, hasParameter,
+ unsigned, N, internal::Matcher<ParmVarDecl>,
+ InnerMatcher) {
+ return (N < Node.getNumParams() &&
+ InnerMatcher.matches(
+ *Node.getParamDecl(N), Finder, Builder));
+}
+
+/// \brief Matches any parameter of a function declaration.
+///
+/// Does not match the 'this' parameter of a method.
+///
+/// Given
+/// class X { void f(int x, int y, int z) {} };
+/// method(hasAnyParameter(hasName("y")))
+/// matches f(int x, int y, int z) {}
+/// with hasAnyParameter(...)
+/// matching int y
+AST_MATCHER_P(FunctionDecl, hasAnyParameter,
+ internal::Matcher<ParmVarDecl>, InnerMatcher) {
+ for (unsigned I = 0; I < Node.getNumParams(); ++I) {
+ if (InnerMatcher.matches(*Node.getParamDecl(I), Finder, Builder)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/// \brief Matches the return type of a function declaration.
+///
+/// Given:
+/// class X { int f() { return 1; } };
+/// method(returns(asString("int")))
+/// matches int f() { return 1; }
+AST_MATCHER_P(FunctionDecl, returns, internal::Matcher<QualType>, Matcher) {
+ return Matcher.matches(Node.getResultType(), Finder, Builder);
+}
+
+/// \brief Matches the condition expression of an if statement, for loop,
+/// or conditional operator.
+///
+/// Example matches true (matcher = hasCondition(boolLiteral(equals(true))))
+/// if (true) {}
+AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>,
+ InnerMatcher) {
+ TOOLING_COMPILE_ASSERT(
+ (llvm::is_base_of<IfStmt, NodeType>::value) ||
+ (llvm::is_base_of<ForStmt, NodeType>::value) ||
+ (llvm::is_base_of<WhileStmt, NodeType>::value) ||
+ (llvm::is_base_of<DoStmt, NodeType>::value) ||
+ (llvm::is_base_of<ConditionalOperator, NodeType>::value),
+ has_condition_requires_if_statement_conditional_operator_or_loop);
+ const Expr *const Condition = Node.getCond();
+ return (Condition != NULL &&
+ InnerMatcher.matches(*Condition, Finder, Builder));
+}
+
+/// \brief Matches the condition variable statement in an if statement.
+///
+/// Given
+/// if (A* a = GetAPointer()) {}
+/// hasConditionVariableStatment(...)
+/// matches 'A* a = GetAPointer()'.
+AST_MATCHER_P(IfStmt, hasConditionVariableStatement,
+ internal::Matcher<DeclStmt>, InnerMatcher) {
+ const DeclStmt* const DeclarationStatement =
+ Node.getConditionVariableDeclStmt();
+ return DeclarationStatement != NULL &&
+ InnerMatcher.matches(*DeclarationStatement, Finder, Builder);
+}
+
+/// \brief Matches the index expression of an array subscript expression.
+///
+/// Given
+/// int i[5];
+/// void f() { i[1] = 42; }
+/// arraySubscriptExpression(hasIndex(integerLiteral()))
+/// matches \c i[1] with the \c integerLiteral() matching \c 1
+AST_MATCHER_P(ArraySubscriptExpr, hasIndex,
+ internal::Matcher<Expr>, matcher) {
+ if (const Expr* Expression = Node.getIdx())
+ return matcher.matches(*Expression, Finder, Builder);
+ return false;
+}
+
+/// \brief Matches the base expression of an array subscript expression.
+///
+/// Given
+/// int i[5];
+/// void f() { i[1] = 42; }
+/// arraySubscriptExpression(hasBase(implicitCast(
+/// hasSourceExpression(declarationReference()))))
+/// matches \c i[1] with the \c declarationReference() matching \c i
+AST_MATCHER_P(ArraySubscriptExpr, hasBase,
+ internal::Matcher<Expr>, matcher) {
+ if (const Expr* Expression = Node.getBase())
+ return matcher.matches(*Expression, Finder, Builder);
+ return false;
+}
+
+/// \brief Matches a 'for', 'while', or 'do while' statement that has
+/// a given body.
+///
+/// Given
+/// for (;;) {}
+/// hasBody(compoundStatement())
+/// matches 'for (;;) {}'
+/// with compoundStatement()
+/// matching '{}'
+AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>,
+ InnerMatcher) {
+ TOOLING_COMPILE_ASSERT(
+ (llvm::is_base_of<DoStmt, NodeType>::value) ||
+ (llvm::is_base_of<ForStmt, NodeType>::value) ||
+ (llvm::is_base_of<WhileStmt, NodeType>::value),
+ has_body_requires_for_while_or_do_statement);
+ const Stmt *const Statement = Node.getBody();
+ return (Statement != NULL &&
+ InnerMatcher.matches(*Statement, Finder, Builder));
+}
+
+/// \brief Matches compound statements where at least one substatement matches
+/// a given matcher.
+///
+/// Given
+/// { {}; 1+2; }
+/// hasAnySubstatement(compoundStatement())
+/// matches '{ {}; 1+2; }'
+/// with compoundStatement()
+/// matching '{}'
+AST_MATCHER_P(CompoundStmt, hasAnySubstatement,
+ internal::Matcher<Stmt>, InnerMatcher) {
+ for (CompoundStmt::const_body_iterator It = Node.body_begin();
+ It != Node.body_end();
+ ++It) {
+ if (InnerMatcher.matches(**It, Finder, Builder)) return true;
+ }
+ return false;
+}
+
+/// \brief Checks that a compound statement contains a specific number of
+/// child statements.
+///
+/// Example: Given
+/// { for (;;) {} }
+/// compoundStatement(statementCountIs(0)))
+/// matches '{}'
+/// but does not match the outer compound statement.
+AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) {
+ return Node.size() == N;
+}
+
+/// \brief Matches literals that are equal to the given value.
+///
+/// Example matches true (matcher = boolLiteral(equals(true)))
+/// true
+///
+/// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>,
+/// Matcher<FloatingLiteral>, Matcher<IntegerLiteral>
+template <typename ValueT>
+internal::PolymorphicMatcherWithParam1<internal::ValueEqualsMatcher, ValueT>
+equals(const ValueT &Value) {
+ return internal::PolymorphicMatcherWithParam1<
+ internal::ValueEqualsMatcher,
+ ValueT>(Value);
+}
+
+/// \brief Matches the operator Name of operator expressions (binary or
+/// unary).
+///
+/// Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
+/// !(a || b)
+AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) {
+ TOOLING_COMPILE_ASSERT(
+ (llvm::is_base_of<BinaryOperator, NodeType>::value) ||
+ (llvm::is_base_of<UnaryOperator, NodeType>::value),
+ has_condition_requires_if_statement_or_conditional_operator);
+ return Name == Node.getOpcodeStr(Node.getOpcode());
+}
+
+/// \brief Matches the left hand side of binary operator expressions.
+///
+/// Example matches a (matcher = binaryOperator(hasLHS()))
+/// a || b
+AST_MATCHER_P(BinaryOperator, hasLHS,
+ internal::Matcher<Expr>, InnerMatcher) {
+ Expr *LeftHandSide = Node.getLHS();
+ return (LeftHandSide != NULL &&
+ InnerMatcher.matches(*LeftHandSide, Finder, Builder));
+}
+
+/// \brief Matches the right hand side of binary operator expressions.
+///
+/// Example matches b (matcher = binaryOperator(hasRHS()))
+/// a || b
+AST_MATCHER_P(BinaryOperator, hasRHS,
+ internal::Matcher<Expr>, InnerMatcher) {
+ Expr *RightHandSide = Node.getRHS();
+ return (RightHandSide != NULL &&
+ InnerMatcher.matches(*RightHandSide, Finder, Builder));
+}
+
+/// \brief Matches if either the left hand side or the right hand side of a
+/// binary operator matches.
+inline internal::Matcher<BinaryOperator> hasEitherOperand(
+ const internal::Matcher<Expr> &InnerMatcher) {
+ return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher));
+}
+
+/// \brief Matches if the operand of a unary operator matches.
+///
+/// Example matches true (matcher = hasOperand(boolLiteral(equals(true))))
+/// !true
+AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr * const Operand = Node.getSubExpr();
+ return (Operand != NULL &&
+ InnerMatcher.matches(*Operand, Finder, Builder));
+}
+
+/// \brief Matches if the cast's source expression matches the given matcher.
+///
+/// Example: matches "a string" (matcher =
+/// hasSourceExpression(constructorCall()))
+///
+/// class URL { URL(string); };
+/// URL url = "a string";
+AST_MATCHER_P(CastExpr, hasSourceExpression,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr* const SubExpression = Node.getSubExpr();
+ return (SubExpression != NULL &&
+ InnerMatcher.matches(*SubExpression, Finder, Builder));
+}
+
+/// \brief Matches casts whose destination type matches a given matcher.
+///
+/// (Note: Clang's AST refers to other conversions as "casts" too, and calls
+/// actual casts "explicit" casts.)
+AST_MATCHER_P(ExplicitCastExpr, hasDestinationType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ const QualType NodeType = Node.getTypeAsWritten();
+ return InnerMatcher.matches(NodeType, Finder, Builder);
+}
+
+/// \brief Matches implicit casts whose destination type matches a given
+/// matcher.
+///
+/// FIXME: Unit test this matcher
+AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ return InnerMatcher.matches(Node.getType(), Finder, Builder);
+}
+
+/// \brief Matches the true branch expression of a conditional operator.
+///
+/// Example matches a
+/// condition ? a : b
+AST_MATCHER_P(ConditionalOperator, hasTrueExpression,
+ internal::Matcher<Expr>, InnerMatcher) {
+ Expr *Expression = Node.getTrueExpr();
+ return (Expression != NULL &&
+ InnerMatcher.matches(*Expression, Finder, Builder));
+}
+
+/// \brief Matches the false branch expression of a conditional operator.
+///
+/// Example matches b
+/// condition ? a : b
+AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
+ internal::Matcher<Expr>, InnerMatcher) {
+ Expr *Expression = Node.getFalseExpr();
+ return (Expression != NULL &&
+ InnerMatcher.matches(*Expression, Finder, Builder));
+}
+
+/// \brief Matches if a declaration has a body attached.
+///
+/// Example matches A, va, fa
+/// class A {};
+/// class B; // Doesn't match, as it has no body.
+/// int va;
+/// extern int vb; // Doesn't match, as it doesn't define the variable.
+/// void fa() {}
+/// void fb(); // Doesn't match, as it has no body.
+///
+/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
+inline internal::PolymorphicMatcherWithParam0<internal::IsDefinitionMatcher>
+isDefinition() {
+ return internal::PolymorphicMatcherWithParam0<
+ internal::IsDefinitionMatcher>();
+}
+
+/// \brief Matches the class declaration that the given method declaration
+/// belongs to.
+///
+/// FIXME: Generalize this for other kinds of declarations.
+/// FIXME: What other kind of declarations would we need to generalize
+/// this to?
+///
+/// Example matches A() in the last line
+/// (matcher = constructorCall(hasDeclaration(method(
+/// ofClass(hasName("A"))))))
+/// class A {
+/// public:
+/// A();
+/// };
+/// A a = A();
+AST_MATCHER_P(CXXMethodDecl, ofClass,
+ internal::Matcher<CXXRecordDecl>, InnerMatcher) {
+ const CXXRecordDecl *Parent = Node.getParent();
+ return (Parent != NULL &&
+ InnerMatcher.matches(*Parent, Finder, Builder));
+}
+
+/// \brief Matches member expressions that are called with '->' as opposed
+/// to '.'.
+///
+/// Member calls on the implicit this pointer match as called with '->'.
+///
+/// Given
+/// class Y {
+/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; }
+/// int a;
+/// static int b;
+/// };
+/// memberExpression(isArrow())
+/// matches this->x, x, y.x, a, this->b
+inline internal::Matcher<MemberExpr> isArrow() {
+ return makeMatcher(new internal::IsArrowMatcher());
+}
+
+/// \brief Matches QualType nodes that are of integer type.
+///
+/// Given
+/// void a(int);
+/// void b(long);
+/// void c(double);
+/// function(hasAnyParameter(hasType(isInteger())))
+/// matches "a(int)", "b(long)", but not "c(double)".
+AST_MATCHER(QualType, isInteger) {
+ return Node->isIntegerType();
+}
+
+/// \brief Matches QualType nodes that are const-qualified, i.e., that
+/// include "top-level" const.
+///
+/// Given
+/// void a(int);
+/// void b(int const);
+/// void c(const int);
+/// void d(const int*);
+/// void e(int const) {};
+/// function(hasAnyParameter(hasType(isConstQualified())))
+/// matches "void b(int const)", "void c(const int)" and
+/// "void e(int const) {}". It does not match d as there
+/// is no top-level const on the parameter type "const int *".
+inline internal::Matcher<QualType> isConstQualified() {
+ return makeMatcher(new internal::IsConstQualifiedMatcher());
+}
+
+/// \brief Matches a member expression where the member is matched by a
+/// given matcher.
+///
+/// Given
+/// struct { int first, second; } first, second;
+/// int i(second.first);
+/// int j(first.second);
+/// memberExpression(member(hasName("first")))
+/// matches second.first
+/// but not first.second (because the member name there is "second").
+AST_MATCHER_P(MemberExpr, member,
+ internal::Matcher<ValueDecl>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
+}
+
+/// \brief Matches a member expression where the object expression is
+/// matched by a given matcher.
+///
+/// Given
+/// struct X { int m; };
+/// void f(X x) { x.m; m; }
+/// memberExpression(hasObjectExpression(hasType(record(hasName("X")))))))
+/// matches "x.m" and "m"
+/// with hasObjectExpression(...)
+/// matching "x" and the implicit object expression of "m" which has type X*.
+AST_MATCHER_P(MemberExpr, hasObjectExpression,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.getBase(), Finder, Builder);
+}
+
+/// \brief Matches any using shadow declaration.
+///
+/// Given
+/// namespace X { void b(); }
+/// using X::b;
+/// usingDecl(hasAnyUsingShadowDecl(hasName("b"))))
+/// matches \code using X::b \endcode
+AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl,
+ internal::Matcher<UsingShadowDecl>, Matcher) {
+ for (UsingDecl::shadow_iterator II = Node.shadow_begin();
+ II != Node.shadow_end(); ++II) {
+ if (Matcher.matches(**II, Finder, Builder))
+ return true;
+ }
+ return false;
+}
+
+/// \brief Matches a using shadow declaration where the target declaration is
+/// matched by the given matcher.
+///
+/// Given
+/// namespace X { int a; void b(); }
+/// using X::a;
+/// using X::b;
+/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(function())))
+/// matches \code using X::b \endcode
+/// but not \code using X::a \endcode
+AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
+ internal::Matcher<NamedDecl>, Matcher) {
+ return Matcher.matches(*Node.getTargetDecl(), Finder, Builder);
+}
+
+/// \brief Matches template instantiations of function, class, or static
+/// member variable template instantiations.
+///
+/// Given
+/// template <typename T> class X {}; class A {}; X<A> x;
+/// or
+/// template <typename T> class X {}; class A {}; template class X<A>;
+/// record(hasName("::X"), isTemplateInstantiation())
+/// matches the template instantiation of X<A>.
+///
+/// But given
+/// template <typename T> class X {}; class A {};
+/// template <> class X<A> {}; X<A> x;
+/// record(hasName("::X"), isTemplateInstantiation())
+/// does not match, as X<A> is an explicit template specialization.
+///
+/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
+inline internal::PolymorphicMatcherWithParam0<
+ internal::IsTemplateInstantiationMatcher>
+isTemplateInstantiation() {
+ return internal::PolymorphicMatcherWithParam0<
+ internal::IsTemplateInstantiationMatcher>();
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
new file mode 100644
index 000000000000..3f5568521c0e
--- /dev/null
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -0,0 +1,901 @@
+//===--- ASTMatchersInternal.h - Structural query framework -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements the base layer of the matcher framework.
+//
+// Matchers are methods that return a Matcher<T> which provides a method
+// Matches(...) which is a predicate on an AST node. The Matches method's
+// parameters define the context of the match, which allows matchers to recurse
+// or store the current node as bound to a specific string, so that it can be
+// retrieved later.
+//
+// In general, matchers have two parts:
+// 1. A function Matcher<T> MatcherName(<arguments>) which returns a Matcher<T>
+// based on the arguments and optionally on template type deduction based
+// on the arguments. Matcher<T>s form an implicit reverse hierarchy
+// to clang's AST class hierarchy, meaning that you can use a Matcher<Base>
+// everywhere a Matcher<Derived> is required.
+// 2. An implementation of a class derived from MatcherInterface<T>.
+//
+// The matcher functions are defined in ASTMatchers.h. To make it possible
+// to implement both the matcher function and the implementation of the matcher
+// interface in one place, ASTMatcherMacros.h defines macros that allow
+// implementing a matcher in a single place.
+//
+// This file contains the base classes needed to construct the actual matchers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
+#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Stmt.h"
+#include "llvm/ADT/VariadicFunction.h"
+#include <map>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace ast_matchers {
+
+/// FIXME: Move into the llvm support library.
+template <bool> struct CompileAssert {};
+#define TOOLING_COMPILE_ASSERT(Expr, Msg) \
+ typedef CompileAssert<(bool(Expr))> Msg[bool(Expr) ? 1 : -1]
+
+class BoundNodes;
+
+namespace internal {
+
+class BoundNodesTreeBuilder;
+
+/// \brief A tree of bound nodes in match results.
+///
+/// If a match can contain multiple matches on the same node with different
+/// matching subexpressions, BoundNodesTree contains a branch for each of
+/// those matching subexpressions.
+///
+/// BoundNodesTree's are created during the matching process; when a match
+/// is found, we iterate over the tree and create a BoundNodes object containing
+/// the union of all bound nodes on the path from the root to a each leaf.
+class BoundNodesTree {
+public:
+ /// \brief A visitor interface to visit all BoundNodes results for a
+ /// BoundNodesTree.
+ class Visitor {
+ public:
+ virtual ~Visitor() {}
+
+ /// \brief Called multiple times during a single call to VisitMatches(...).
+ ///
+ /// 'BoundNodesView' contains the bound nodes for a single match.
+ virtual void visitMatch(const BoundNodes& BoundNodesView) = 0;
+ };
+
+ BoundNodesTree();
+
+ /// \brief Create a BoundNodesTree from pre-filled maps of bindings.
+ BoundNodesTree(const std::map<std::string, const Decl*>& DeclBindings,
+ const std::map<std::string, const Stmt*>& StmtBindings,
+ const std::vector<BoundNodesTree> RecursiveBindings);
+
+ /// \brief Adds all bound nodes to bound_nodes_builder.
+ void copyTo(BoundNodesTreeBuilder* Builder) const;
+
+ /// \brief Visits all matches that this BoundNodesTree represents.
+ ///
+ /// The ownership of 'ResultVisitor' remains at the caller.
+ void visitMatches(Visitor* ResultVisitor);
+
+private:
+ void visitMatchesRecursively(
+ Visitor* ResultVistior,
+ std::map<std::string, const Decl*> DeclBindings,
+ std::map<std::string, const Stmt*> StmtBindings);
+
+ template <typename T>
+ void copyBindingsTo(const T& bindings, BoundNodesTreeBuilder* Builder) const;
+
+ // FIXME: Find out whether we want to use different data structures here -
+ // first benchmarks indicate that it doesn't matter though.
+
+ std::map<std::string, const Decl*> DeclBindings;
+ std::map<std::string, const Stmt*> StmtBindings;
+
+ std::vector<BoundNodesTree> RecursiveBindings;
+};
+
+/// \brief Creates BoundNodesTree objects.
+///
+/// The tree builder is used during the matching process to insert the bound
+/// nodes from the Id matcher.
+class BoundNodesTreeBuilder {
+public:
+ BoundNodesTreeBuilder();
+
+ /// \brief Add a binding from an id to a node.
+ ///
+ /// FIXME: Add overloads for all AST base types.
+ /// @{
+ void setBinding(const std::string &Id, const Decl *Node);
+ void setBinding(const std::string &Id, const Stmt *Node);
+ /// @}
+
+ /// \brief Adds a branch in the tree.
+ void addMatch(const BoundNodesTree& Bindings);
+
+ /// \brief Returns a BoundNodes object containing all current bindings.
+ BoundNodesTree build() const;
+
+private:
+ BoundNodesTreeBuilder(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT
+ void operator=(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT
+
+ std::map<std::string, const Decl*> DeclBindings;
+ std::map<std::string, const Stmt*> StmtBindings;
+
+ std::vector<BoundNodesTree> RecursiveBindings;
+};
+
+class ASTMatchFinder;
+
+/// \brief Generic interface for matchers on an AST node of type T.
+///
+/// Implement this if your matcher may need to inspect the children or
+/// descendants of the node or bind matched nodes to names. If you are
+/// writing a simple matcher that only inspects properties of the
+/// current node and doesn't care about its children or descendants,
+/// implement SingleNodeMatcherInterface instead.
+template <typename T>
+class MatcherInterface : public llvm::RefCountedBaseVPTR {
+public:
+ virtual ~MatcherInterface() {}
+
+ /// \brief Returns true if 'Node' can be matched.
+ ///
+ /// May bind 'Node' to an ID via 'Builder', or recurse into
+ /// the AST via 'Finder'.
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const = 0;
+};
+
+/// \brief Interface for matchers that only evaluate properties on a single node.
+template <typename T>
+class SingleNodeMatcherInterface : public MatcherInterface<T> {
+public:
+ /// \brief Returns true if the matcher matches the provided node.
+ ///
+ /// A subclass must implement this instead of Matches().
+ virtual bool matchesNode(const T &Node) const = 0;
+
+private:
+ /// Implements MatcherInterface::Matches.
+ virtual bool matches(const T &Node,
+ ASTMatchFinder * /* Finder */,
+ BoundNodesTreeBuilder * /* Builder */) const {
+ return matchesNode(Node);
+ }
+};
+
+/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
+///
+/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
+/// required. This establishes an is-a relationship which is reverse
+/// to the AST hierarchy. In other words, Matcher<T> is contravariant
+/// with respect to T. The relationship is built via a type conversion
+/// operator rather than a type hierarchy to be able to templatize the
+/// type hierarchy instead of spelling it out.
+template <typename T>
+class Matcher {
+public:
+ /// \brief Takes ownership of the provided implementation pointer.
+ explicit Matcher(MatcherInterface<T> *Implementation)
+ : Implementation(Implementation) {}
+
+ /// \brief Forwards the call to the underlying MatcherInterface<T> pointer.
+ bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return Implementation->matches(Node, Finder, Builder);
+ }
+
+ /// \brief Implicitly converts this object to a Matcher<Derived>.
+ ///
+ /// Requires Derived to be derived from T.
+ template <typename Derived>
+ operator Matcher<Derived>() const {
+ return Matcher<Derived>(new ImplicitCastMatcher<Derived>(*this));
+ }
+
+ /// \brief Returns an ID that uniquely identifies the matcher.
+ uint64_t getID() const {
+ /// FIXME: Document the requirements this imposes on matcher
+ /// implementations (no new() implementation_ during a Matches()).
+ return reinterpret_cast<uint64_t>(Implementation.getPtr());
+ }
+
+private:
+ /// \brief Allows conversion from Matcher<T> to Matcher<Derived> if Derived
+ /// is derived from T.
+ template <typename Derived>
+ class ImplicitCastMatcher : public MatcherInterface<Derived> {
+ public:
+ explicit ImplicitCastMatcher(const Matcher<T> &From)
+ : From(From) {}
+
+ virtual bool matches(const Derived &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return From.matches(Node, Finder, Builder);
+ }
+
+ private:
+ const Matcher<T> From;
+ };
+
+ llvm::IntrusiveRefCntPtr< MatcherInterface<T> > Implementation;
+}; // class Matcher
+
+/// \brief A convenient helper for creating a Matcher<T> without specifying
+/// the template type argument.
+template <typename T>
+inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
+ return Matcher<T>(Implementation);
+}
+
+/// \brief Matches declarations for QualType and CallExpr.
+///
+/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
+/// not actually used.
+template <typename T, typename DeclMatcherT>
+class HasDeclarationMatcher : public MatcherInterface<T> {
+ TOOLING_COMPILE_ASSERT((llvm::is_same< DeclMatcherT,
+ Matcher<Decl> >::value),
+ instantiated_with_wrong_types);
+public:
+ explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
+
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return matchesSpecialized(Node, Finder, Builder);
+ }
+
+private:
+ /// \brief Extracts the CXXRecordDecl of a QualType and returns whether the
+ /// inner matcher matches on it.
+ bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ /// FIXME: Add other ways to convert...
+ if (Node.isNull())
+ return false;
+ CXXRecordDecl *NodeAsRecordDecl = Node->getAsCXXRecordDecl();
+ return NodeAsRecordDecl != NULL &&
+ InnerMatcher.matches(*NodeAsRecordDecl, Finder, Builder);
+ }
+
+ /// \brief Extracts the Decl of the callee of a CallExpr and returns whether
+ /// the inner matcher matches on it.
+ bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ const Decl *NodeAsDecl = Node.getCalleeDecl();
+ return NodeAsDecl != NULL &&
+ InnerMatcher.matches(*NodeAsDecl, Finder, Builder);
+ }
+
+ /// \brief Extracts the Decl of the constructor call and returns whether the
+ /// inner matcher matches on it.
+ bool matchesSpecialized(const CXXConstructExpr &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ const Decl *NodeAsDecl = Node.getConstructor();
+ return NodeAsDecl != NULL &&
+ InnerMatcher.matches(*NodeAsDecl, Finder, Builder);
+ }
+
+ const Matcher<Decl> InnerMatcher;
+};
+
+/// \brief IsBaseType<T>::value is true if T is a "base" type in the AST
+/// node class hierarchies (i.e. if T is Decl, Stmt, or QualType).
+template <typename T>
+struct IsBaseType {
+ static const bool value =
+ (llvm::is_same<T, Decl>::value ||
+ llvm::is_same<T, Stmt>::value ||
+ llvm::is_same<T, QualType>::value ||
+ llvm::is_same<T, CXXCtorInitializer>::value);
+};
+template <typename T>
+const bool IsBaseType<T>::value;
+
+/// \brief Interface that can match any AST base node type and contains default
+/// implementations returning false.
+class UntypedBaseMatcher : public llvm::RefCountedBaseVPTR {
+public:
+ virtual ~UntypedBaseMatcher() {}
+
+ virtual bool matches(const Decl &DeclNode, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return false;
+ }
+ virtual bool matches(const QualType &TypeNode, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return false;
+ }
+ virtual bool matches(const Stmt &StmtNode, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return false;
+ }
+ virtual bool matches(const CXXCtorInitializer &CtorInitNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return false;
+ }
+
+ /// \brief Returns a unique ID for the matcher.
+ virtual uint64_t getID() const = 0;
+};
+
+/// \brief An UntypedBaseMatcher that overwrites the Matches(...) method for
+/// node type T. T must be an AST base type.
+template <typename T>
+class TypedBaseMatcher : public UntypedBaseMatcher {
+ TOOLING_COMPILE_ASSERT(IsBaseType<T>::value,
+ typed_base_matcher_can_only_be_used_with_base_type);
+public:
+ explicit TypedBaseMatcher(const Matcher<T> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
+
+ using UntypedBaseMatcher::matches;
+ /// \brief Implements UntypedBaseMatcher::Matches.
+ ///
+ /// Since T is guaranteed to be a "base" AST node type, this method is
+ /// guaranteed to override one of the matches() methods from
+ /// UntypedBaseMatcher.
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return InnerMatcher.matches(Node, Finder, Builder);
+ }
+
+ /// \brief Implements UntypedBaseMatcher::getID.
+ virtual uint64_t getID() const {
+ return InnerMatcher.getID();
+ }
+
+private:
+ Matcher<T> InnerMatcher;
+};
+
+/// \brief Interface that allows matchers to traverse the AST.
+/// FIXME: Find a better name.
+///
+/// This provides two entry methods for each base node type in the AST:
+/// - matchesChildOf:
+/// Matches a matcher on every child node of the given node. Returns true
+/// if at least one child node could be matched.
+/// - matchesDescendantOf:
+/// Matches a matcher on all descendant nodes of the given node. Returns true
+/// if at least one descendant matched.
+class ASTMatchFinder {
+public:
+ /// \brief Defines how we descend a level in the AST when we pass
+ /// through expressions.
+ enum TraversalKind {
+ /// Will traverse any child nodes.
+ TK_AsIs,
+ /// Will not traverse implicit casts and parentheses.
+ TK_IgnoreImplicitCastsAndParentheses
+ };
+
+ /// \brief Defines how bindings are processed on recursive matches.
+ enum BindKind {
+ /// Stop at the first match and only bind the first match.
+ BK_First,
+ /// Create results for all combinations of bindings that match.
+ BK_All
+ };
+
+ virtual ~ASTMatchFinder() {}
+
+ /// \brief Returns true if the given class is directly or indirectly derived
+ /// from a base type matching \c base.
+ ///
+ /// A class is considered to be also derived from itself.
+ virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
+ const Matcher<NamedDecl> &Base,
+ BoundNodesTreeBuilder *Builder) = 0;
+
+ // FIXME: Implement for other base nodes.
+ virtual bool matchesChildOf(const Decl &DeclNode,
+ const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesTreeBuilder *Builder,
+ TraversalKind Traverse,
+ BindKind Bind) = 0;
+ virtual bool matchesChildOf(const Stmt &StmtNode,
+ const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesTreeBuilder *Builder,
+ TraversalKind Traverse,
+ BindKind Bind) = 0;
+
+ virtual bool matchesDescendantOf(const Decl &DeclNode,
+ const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesTreeBuilder *Builder,
+ BindKind Bind) = 0;
+ virtual bool matchesDescendantOf(const Stmt &StmtNode,
+ const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesTreeBuilder *Builder,
+ BindKind Bind) = 0;
+};
+
+/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
+/// "adapting" a \c To into a \c T.
+///
+/// The \c ArgumentAdapterT argument specifies how the adaptation is done.
+///
+/// For example:
+/// \c ArgumentAdaptingMatcher<HasMatcher, T>(InnerMatcher);
+/// Given that \c InnerMatcher is of type \c Matcher<T>, this returns a matcher
+/// that is convertible into any matcher of type \c To by constructing
+/// \c HasMatcher<To, T>(InnerMatcher).
+///
+/// If a matcher does not need knowledge about the inner type, prefer to use
+/// PolymorphicMatcherWithParam1.
+template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
+ typename T>
+class ArgumentAdaptingMatcher {
+public:
+ explicit ArgumentAdaptingMatcher(const Matcher<T> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
+
+ template <typename To>
+ operator Matcher<To>() const {
+ return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
+ }
+
+private:
+ const Matcher<T> InnerMatcher;
+};
+
+/// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
+/// created from N parameters p1, ..., pN (of type P1, ..., PN) and
+/// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN)
+/// can be constructed.
+///
+/// For example:
+/// - PolymorphicMatcherWithParam0<IsDefinitionMatcher>()
+/// creates an object that can be used as a Matcher<T> for any type T
+/// where an IsDefinitionMatcher<T>() can be constructed.
+/// - PolymorphicMatcherWithParam1<ValueEqualsMatcher, int>(42)
+/// creates an object that can be used as a Matcher<T> for any type T
+/// where a ValueEqualsMatcher<T, int>(42) can be constructed.
+template <template <typename T> class MatcherT>
+class PolymorphicMatcherWithParam0 {
+public:
+ template <typename T>
+ operator Matcher<T>() const {
+ return Matcher<T>(new MatcherT<T>());
+ }
+};
+
+template <template <typename T, typename P1> class MatcherT,
+ typename P1>
+class PolymorphicMatcherWithParam1 {
+public:
+ explicit PolymorphicMatcherWithParam1(const P1 &Param1)
+ : Param1(Param1) {}
+
+ template <typename T>
+ operator Matcher<T>() const {
+ return Matcher<T>(new MatcherT<T, P1>(Param1));
+ }
+
+private:
+ const P1 Param1;
+};
+
+template <template <typename T, typename P1, typename P2> class MatcherT,
+ typename P1, typename P2>
+class PolymorphicMatcherWithParam2 {
+public:
+ PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2)
+ : Param1(Param1), Param2(Param2) {}
+
+ template <typename T>
+ operator Matcher<T>() const {
+ return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2));
+ }
+
+private:
+ const P1 Param1;
+ const P2 Param2;
+};
+
+/// \brief Matches any instance of the given NodeType.
+///
+/// This is useful when a matcher syntactically requires a child matcher,
+/// but the context doesn't care. See for example: anything().
+///
+/// FIXME: Alternatively we could also create a IsAMatcher or something
+/// that checks that a dyn_cast is possible. This is purely needed for the
+/// difference between calling for example:
+/// record()
+/// and
+/// record(SomeMatcher)
+/// In the second case we need the correct type we were dyn_cast'ed to in order
+/// to get the right type for the inner matcher. In the first case we don't need
+/// that, but we use the type conversion anyway and insert a TrueMatcher.
+template <typename T>
+class TrueMatcher : public SingleNodeMatcherInterface<T> {
+public:
+ virtual bool matchesNode(const T &Node) const {
+ return true;
+ }
+};
+
+/// \brief Provides a MatcherInterface<T> for a Matcher<To> that matches if T is
+/// dyn_cast'able into To and the given Matcher<To> matches on the dyn_cast'ed
+/// node.
+template <typename T, typename To>
+class DynCastMatcher : public MatcherInterface<T> {
+public:
+ explicit DynCastMatcher(const Matcher<To> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
+
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ const To *InnerMatchValue = llvm::dyn_cast<To>(&Node);
+ return InnerMatchValue != NULL &&
+ InnerMatcher.matches(*InnerMatchValue, Finder, Builder);
+ }
+
+private:
+ const Matcher<To> InnerMatcher;
+};
+
+/// \brief Matcher<T> that wraps an inner Matcher<T> and binds the matched node
+/// to an ID if the inner matcher matches on the node.
+template <typename T>
+class IdMatcher : public MatcherInterface<T> {
+public:
+ /// \brief Creates an IdMatcher that binds to 'ID' if 'InnerMatcher' matches
+ /// the node.
+ IdMatcher(StringRef ID, const Matcher<T> &InnerMatcher)
+ : ID(ID), InnerMatcher(InnerMatcher) {}
+
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ bool Result = InnerMatcher.matches(Node, Finder, Builder);
+ if (Result) {
+ Builder->setBinding(ID, &Node);
+ }
+ return Result;
+ }
+
+private:
+ const std::string ID;
+ const Matcher<T> InnerMatcher;
+};
+
+/// \brief A Matcher that allows binding the node it matches to an id.
+///
+/// BindableMatcher provides a \a bind() method that allows binding the
+/// matched node to an id if the match was successful.
+template <typename T>
+class BindableMatcher : public Matcher<T> {
+public:
+ BindableMatcher(MatcherInterface<T> *Implementation)
+ : Matcher<T>(Implementation) {}
+
+ /// \brief Returns a matcher that will bind the matched node on a match.
+ ///
+ /// The returned matcher is equivalent to this matcher, but will
+ /// bind the matched node on a match.
+ Matcher<T> bind(StringRef ID) const {
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<Stmt, T>::value ||
+ llvm::is_base_of<Decl, T>::value),
+ trying_to_bind_unsupported_node_type__only_decl_and_stmt_supported);
+ return Matcher<T>(new IdMatcher<T>(ID, *this));
+ }
+};
+
+/// \brief Matches nodes of type T that have child nodes of type ChildT for
+/// which a specified child matcher matches.
+///
+/// ChildT must be an AST base type.
+template <typename T, typename ChildT>
+class HasMatcher : public MatcherInterface<T> {
+ TOOLING_COMPILE_ASSERT(IsBaseType<ChildT>::value,
+ has_only_accepts_base_type_matcher);
+public:
+ explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
+ : ChildMatcher(ChildMatcher) {}
+
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return Finder->matchesChildOf(
+ Node, ChildMatcher, Builder,
+ ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
+ ASTMatchFinder::BK_First);
+ }
+
+ private:
+ const TypedBaseMatcher<ChildT> ChildMatcher;
+};
+
+/// \brief Matches nodes of type T that have child nodes of type ChildT for
+/// which a specified child matcher matches. ChildT must be an AST base
+/// type.
+/// As opposed to the HasMatcher, the ForEachMatcher will produce a match
+/// for each child that matches.
+template <typename T, typename ChildT>
+class ForEachMatcher : public MatcherInterface<T> {
+ TOOLING_COMPILE_ASSERT(IsBaseType<ChildT>::value,
+ for_each_only_accepts_base_type_matcher);
+ public:
+ explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
+ : ChildMatcher(ChildMatcher) {}
+
+ virtual bool matches(const T& Node,
+ ASTMatchFinder* Finder,
+ BoundNodesTreeBuilder* Builder) const {
+ return Finder->matchesChildOf(
+ Node, ChildMatcher, Builder,
+ ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
+ ASTMatchFinder::BK_All);
+ }
+
+private:
+ const TypedBaseMatcher<ChildT> ChildMatcher;
+};
+
+/// \brief Matches nodes of type T if the given Matcher<T> does not match.
+///
+/// Type argument MatcherT is required by PolymorphicMatcherWithParam1
+/// but not actually used. It will always be instantiated with a type
+/// convertible to Matcher<T>.
+template <typename T, typename MatcherT>
+class NotMatcher : public MatcherInterface<T> {
+public:
+ explicit NotMatcher(const Matcher<T> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
+
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return !InnerMatcher.matches(Node, Finder, Builder);
+ }
+
+private:
+ const Matcher<T> InnerMatcher;
+};
+
+/// \brief Matches nodes of type T for which both provided matchers match.
+///
+/// Type arguments MatcherT1 and MatcherT2 are required by
+/// PolymorphicMatcherWithParam2 but not actually used. They will
+/// always be instantiated with types convertible to Matcher<T>.
+template <typename T, typename MatcherT1, typename MatcherT2>
+class AllOfMatcher : public MatcherInterface<T> {
+public:
+ AllOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2)
+ : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {}
+
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return InnerMatcher1.matches(Node, Finder, Builder) &&
+ InnerMatcher2.matches(Node, Finder, Builder);
+ }
+
+private:
+ const Matcher<T> InnerMatcher1;
+ const Matcher<T> InnerMatcher2;
+};
+
+/// \brief Matches nodes of type T for which at least one of the two provided
+/// matchers matches.
+///
+/// Type arguments MatcherT1 and MatcherT2 are
+/// required by PolymorphicMatcherWithParam2 but not actually
+/// used. They will always be instantiated with types convertible to
+/// Matcher<T>.
+template <typename T, typename MatcherT1, typename MatcherT2>
+class AnyOfMatcher : public MatcherInterface<T> {
+public:
+ AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2)
+ : InnerMatcher1(InnerMatcher1), InnertMatcher2(InnerMatcher2) {}
+
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return InnerMatcher1.matches(Node, Finder, Builder) ||
+ InnertMatcher2.matches(Node, Finder, Builder);
+ }
+
+private:
+ const Matcher<T> InnerMatcher1;
+ const Matcher<T> InnertMatcher2;
+};
+
+/// \brief Creates a Matcher<T> that matches if
+/// T is dyn_cast'able into InnerT and all inner matchers match.
+///
+/// Returns BindableMatcher, as matchers that use dyn_cast have
+/// the same object both to match on and to run submatchers on,
+/// so there is no ambiguity with what gets bound.
+template<typename T, typename InnerT>
+BindableMatcher<T> makeDynCastAllOfComposite(
+ ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
+ if (InnerMatchers.empty()) {
+ Matcher<InnerT> InnerMatcher = makeMatcher(new TrueMatcher<InnerT>);
+ return BindableMatcher<T>(new DynCastMatcher<T, InnerT>(InnerMatcher));
+ }
+ Matcher<InnerT> InnerMatcher = *InnerMatchers.back();
+ for (int i = InnerMatchers.size() - 2; i >= 0; --i) {
+ InnerMatcher = makeMatcher(
+ new AllOfMatcher<InnerT, Matcher<InnerT>, Matcher<InnerT> >(
+ *InnerMatchers[i], InnerMatcher));
+ }
+ return BindableMatcher<T>(new DynCastMatcher<T, InnerT>(InnerMatcher));
+}
+
+/// \brief Matches nodes of type T that have at least one descendant node of
+/// type DescendantT for which the given inner matcher matches.
+///
+/// DescendantT must be an AST base type.
+template <typename T, typename DescendantT>
+class HasDescendantMatcher : public MatcherInterface<T> {
+ TOOLING_COMPILE_ASSERT(IsBaseType<DescendantT>::value,
+ has_descendant_only_accepts_base_type_matcher);
+public:
+ explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
+ : DescendantMatcher(DescendantMatcher) {}
+
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return Finder->matchesDescendantOf(
+ Node, DescendantMatcher, Builder, ASTMatchFinder::BK_First);
+ }
+
+ private:
+ const TypedBaseMatcher<DescendantT> DescendantMatcher;
+};
+
+/// \brief Matches nodes of type T that have at least one descendant node of
+/// type DescendantT for which the given inner matcher matches.
+///
+/// DescendantT must be an AST base type.
+/// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will match
+/// for each descendant node that matches instead of only for the first.
+template <typename T, typename DescendantT>
+class ForEachDescendantMatcher : public MatcherInterface<T> {
+ TOOLING_COMPILE_ASSERT(IsBaseType<DescendantT>::value,
+ for_each_descendant_only_accepts_base_type_matcher);
+ public:
+ explicit ForEachDescendantMatcher(
+ const Matcher<DescendantT>& DescendantMatcher)
+ : DescendantMatcher(DescendantMatcher) {}
+
+ virtual bool matches(const T& Node,
+ ASTMatchFinder* Finder,
+ BoundNodesTreeBuilder* Builder) const {
+ return Finder->matchesDescendantOf(Node, DescendantMatcher, Builder,
+ ASTMatchFinder::BK_All);
+ }
+
+private:
+ const TypedBaseMatcher<DescendantT> DescendantMatcher;
+};
+
+/// \brief Matches on nodes that have a getValue() method if getValue() equals
+/// the value the ValueEqualsMatcher was constructed with.
+template <typename T, typename ValueT>
+class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> {
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<CharacterLiteral, T>::value ||
+ llvm::is_base_of<CXXBoolLiteralExpr,
+ T>::value ||
+ llvm::is_base_of<FloatingLiteral, T>::value ||
+ llvm::is_base_of<IntegerLiteral, T>::value),
+ the_node_must_have_a_getValue_method);
+public:
+ explicit ValueEqualsMatcher(const ValueT &ExpectedValue)
+ : ExpectedValue(ExpectedValue) {}
+
+ virtual bool matchesNode(const T &Node) const {
+ return Node.getValue() == ExpectedValue;
+ }
+
+private:
+ const ValueT ExpectedValue;
+};
+
+template <typename T>
+class IsDefinitionMatcher : public SingleNodeMatcherInterface<T> {
+ TOOLING_COMPILE_ASSERT(
+ (llvm::is_base_of<TagDecl, T>::value) ||
+ (llvm::is_base_of<VarDecl, T>::value) ||
+ (llvm::is_base_of<FunctionDecl, T>::value),
+ is_definition_requires_isThisDeclarationADefinition_method);
+public:
+ virtual bool matchesNode(const T &Node) const {
+ return Node.isThisDeclarationADefinition();
+ }
+};
+
+/// \brief Matches on template instantiations for FunctionDecl, VarDecl or
+/// CXXRecordDecl nodes.
+template <typename T>
+class IsTemplateInstantiationMatcher : public MatcherInterface<T> {
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, T>::value) ||
+ (llvm::is_base_of<VarDecl, T>::value) ||
+ (llvm::is_base_of<CXXRecordDecl, T>::value),
+ requires_getTemplateSpecializationKind_method);
+ public:
+ virtual bool matches(const T& Node,
+ ASTMatchFinder* Finder,
+ BoundNodesTreeBuilder* Builder) const {
+ return (Node.getTemplateSpecializationKind() ==
+ TSK_ImplicitInstantiation ||
+ Node.getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition);
+ }
+};
+
+class IsArrowMatcher : public SingleNodeMatcherInterface<MemberExpr> {
+public:
+ virtual bool matchesNode(const MemberExpr &Node) const {
+ return Node.isArrow();
+ }
+};
+
+class IsConstQualifiedMatcher
+ : public SingleNodeMatcherInterface<QualType> {
+ public:
+ virtual bool matchesNode(const QualType& Node) const {
+ return Node.isConstQualified();
+ }
+};
+
+/// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
+/// variadic functor that takes a number of Matcher<TargetT> and returns a
+/// Matcher<SourceT> that matches TargetT nodes that are matched by all of the
+/// given matchers, if SourceT can be dynamically casted into TargetT.
+///
+/// For example:
+/// const VariadicDynCastAllOfMatcher<
+/// Decl, CXXRecordDecl> record;
+/// Creates a functor record(...) that creates a Matcher<Decl> given
+/// a variable number of arguments of type Matcher<CXXRecordDecl>.
+/// The returned matcher matches if the given Decl can by dynamically
+/// casted to CXXRecordDecl and all given matchers match.
+template <typename SourceT, typename TargetT>
+class VariadicDynCastAllOfMatcher
+ : public llvm::VariadicFunction<
+ BindableMatcher<SourceT>, Matcher<TargetT>,
+ makeDynCastAllOfComposite<SourceT, TargetT> > {
+public:
+ VariadicDynCastAllOfMatcher() {}
+};
+
+} // end namespace internal
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h
new file mode 100644
index 000000000000..c68534acae35
--- /dev/null
+++ b/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -0,0 +1,224 @@
+//===--- ASTMatchersMacros.h - Structural query framework -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines macros that enable us to define new matchers in a single place.
+// Since a matcher is a function which returns a Matcher<T> object, where
+// T is the type of the actual implementation of the matcher, the macros allow
+// us to write matchers like functions and take care of the definition of the
+// class boilerplate.
+//
+// Note that when you define a matcher with an AST_MATCHER* macro, only the
+// function which creates the matcher goes into the current namespace - the
+// class that implements the actual matcher, which gets returned by the
+// generator function, is put into the 'internal' namespace. This allows us
+// to only have the functions (which is all the user cares about) in the
+// 'ast_matchers' namespace and hide the boilerplate.
+//
+// To define a matcher in user code, always put it into the clang::ast_matchers
+// namespace and refer to the internal types via the 'internal::':
+//
+// namespace clang {
+// namespace ast_matchers {
+// AST_MATCHER_P(MemberExpr, Member,
+// internal::Matcher<ValueDecl>, InnerMatcher) {
+// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
+// }
+// } // end namespace ast_matchers
+// } // end namespace clang
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+
+/// \brief AST_MATCHER(Type, DefineMatcher) { ... }
+/// defines a zero parameter function named DefineMatcher() that returns a
+/// Matcher<Type> object.
+///
+/// The code between the curly braces has access to the following variables:
+///
+/// Node: the AST node being matched; its type is Type.
+/// Finder: an ASTMatchFinder*.
+/// Builder: a BoundNodesTreeBuilder*.
+///
+/// The code should return true if 'Node' matches.
+#define AST_MATCHER(Type, DefineMatcher) \
+ namespace internal { \
+ class matcher_##DefineMatcher##Matcher \
+ : public MatcherInterface<Type> { \
+ public: \
+ explicit matcher_##DefineMatcher##Matcher() {} \
+ virtual bool matches( \
+ const Type &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const; \
+ }; \
+ } \
+ inline internal::Matcher<Type> DefineMatcher() { \
+ return internal::makeMatcher( \
+ new internal::matcher_##DefineMatcher##Matcher()); \
+ } \
+ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
+ const Type &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const
+
+/// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... }
+/// defines a single-parameter function named DefineMatcher() that returns a
+/// Matcher<Type> object.
+///
+/// The code between the curly braces has access to the following variables:
+///
+/// Node: the AST node being matched; its type is Type.
+/// Param: the parameter passed to the function; its type
+/// is ParamType.
+/// Finder: an ASTMatchFinder*.
+/// Builder: a BoundNodesTreeBuilder*.
+///
+/// The code should return true if 'Node' matches.
+#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \
+ namespace internal { \
+ class matcher_##DefineMatcher##Matcher \
+ : public MatcherInterface<Type> { \
+ public: \
+ explicit matcher_##DefineMatcher##Matcher( \
+ const ParamType &A##Param) : Param(A##Param) {} \
+ virtual bool matches( \
+ const Type &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const; \
+ private: \
+ const ParamType Param; \
+ }; \
+ } \
+ inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) { \
+ return internal::makeMatcher( \
+ new internal::matcher_##DefineMatcher##Matcher(Param)); \
+ } \
+ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
+ const Type &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const
+
+/// \brief AST_MATCHER_P2(
+/// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
+/// defines a two-parameter function named DefineMatcher() that returns a
+/// Matcher<Type> object.
+///
+/// The code between the curly braces has access to the following variables:
+///
+/// Node: the AST node being matched; its type is Type.
+/// Param1, Param2: the parameters passed to the function; their types
+/// are ParamType1 and ParamType2.
+/// Finder: an ASTMatchFinder*.
+/// Builder: a BoundNodesTreeBuilder*.
+///
+/// The code should return true if 'Node' matches.
+#define AST_MATCHER_P2( \
+ Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) \
+ namespace internal { \
+ class matcher_##DefineMatcher##Matcher \
+ : public MatcherInterface<Type> { \
+ public: \
+ matcher_##DefineMatcher##Matcher( \
+ const ParamType1 &A##Param1, const ParamType2 &A##Param2) \
+ : Param1(A##Param1), Param2(A##Param2) {} \
+ virtual bool matches( \
+ const Type &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const; \
+ private: \
+ const ParamType1 Param1; \
+ const ParamType2 Param2; \
+ }; \
+ } \
+ inline internal::Matcher<Type> DefineMatcher( \
+ const ParamType1 &Param1, const ParamType2 &Param2) { \
+ return internal::makeMatcher( \
+ new internal::matcher_##DefineMatcher##Matcher( \
+ Param1, Param2)); \
+ } \
+ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
+ const Type &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const
+
+/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
+/// defines a single-parameter function named DefineMatcher() that is
+/// polymorphic in the return type.
+///
+/// The variables are the same as for
+/// AST_MATCHER_P, with the addition of NodeType, which specifies the node type
+/// of the matcher Matcher<NodeType> returned by the function matcher().
+///
+/// FIXME: Pull out common code with above macro?
+#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \
+ namespace internal { \
+ template <typename NodeType, typename ParamT> \
+ class matcher_##DefineMatcher##Matcher \
+ : public MatcherInterface<NodeType> { \
+ public: \
+ explicit matcher_##DefineMatcher##Matcher( \
+ const ParamType &A##Param) : Param(A##Param) {} \
+ virtual bool matches( \
+ const NodeType &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const; \
+ private: \
+ const ParamType Param; \
+ }; \
+ } \
+ inline internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##Matcher, \
+ ParamType > \
+ DefineMatcher(const ParamType &Param) { \
+ return internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##Matcher, \
+ ParamType >(Param); \
+ } \
+ template <typename NodeType, typename ParamT> \
+ bool internal::matcher_##DefineMatcher##Matcher<NodeType, ParamT>::matches( \
+ const NodeType &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const
+
+/// \brief AST_POLYMORPHIC_MATCHER_P2(
+/// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
+/// defines a two-parameter function named matcher() that is polymorphic in
+/// the return type.
+///
+/// The variables are the same as for AST_MATCHER_P2, with the
+/// addition of NodeType, which specifies the node type of the matcher
+/// Matcher<NodeType> returned by the function DefineMatcher().
+#define AST_POLYMORPHIC_MATCHER_P2( \
+ DefineMatcher, ParamType1, Param1, ParamType2, Param2) \
+ namespace internal { \
+ template <typename NodeType, typename ParamT1, typename ParamT2> \
+ class matcher_##DefineMatcher##Matcher \
+ : public MatcherInterface<NodeType> { \
+ public: \
+ matcher_##DefineMatcher##Matcher( \
+ const ParamType1 &A##Param1, const ParamType2 &A##Param2) \
+ : Param1(A##Param1), Param2(A##Param2) {} \
+ virtual bool matches( \
+ const NodeType &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const; \
+ private: \
+ const ParamType1 Param1; \
+ const ParamType2 Param2; \
+ }; \
+ } \
+ inline internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##Matcher, \
+ ParamType1, ParamType2 > \
+ DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \
+ return internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##Matcher, \
+ ParamType1, ParamType2 >( \
+ Param1, Param2); \
+ } \
+ template <typename NodeType, typename ParamT1, typename ParamT2> \
+ bool internal::matcher_##DefineMatcher##Matcher< \
+ NodeType, ParamT1, ParamT2>::matches( \
+ const NodeType &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const
+
+#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 9ec27ce91dba..7f50ee392be6 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -175,6 +175,7 @@ public:
switch (kind) {
case PrintErrno:
assert(IsPrintf);
+ return false;
case PercentArg:
return false;
default:
@@ -200,7 +201,7 @@ protected:
Kind kind;
};
-class ArgTypeResult {
+class ArgType {
public:
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
AnyCharTy, CStrTy, WCStrTy, WIntTy };
@@ -208,26 +209,26 @@ private:
const Kind K;
QualType T;
const char *Name;
- ArgTypeResult(bool) : K(InvalidTy), Name(0) {}
+ bool Ptr;
public:
- ArgTypeResult(Kind k = UnknownTy) : K(k), Name(0) {}
- ArgTypeResult(Kind k, const char *n) : K(k), Name(n) {}
- ArgTypeResult(QualType t) : K(SpecificTy), T(t), Name(0) {}
- ArgTypeResult(QualType t, const char *n) : K(SpecificTy), T(t), Name(n) {}
- ArgTypeResult(CanQualType t) : K(SpecificTy), T(t), Name(0) {}
-
- static ArgTypeResult Invalid() { return ArgTypeResult(true); }
+ ArgType(Kind k = UnknownTy, const char *n = 0) : K(k), Name(n), Ptr(false) {}
+ ArgType(QualType t, const char *n = 0)
+ : K(SpecificTy), T(t), Name(n), Ptr(false) {}
+ ArgType(CanQualType t) : K(SpecificTy), T(t), Name(0), Ptr(false) {}
+ static ArgType Invalid() { return ArgType(InvalidTy); }
bool isValid() const { return K != InvalidTy; }
- const QualType *getSpecificType() const {
- return K == SpecificTy ? &T : 0;
+ /// Create an ArgType which corresponds to the type pointer to A.
+ static ArgType PtrTo(const ArgType& A) {
+ assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");
+ ArgType Res = A;
+ Res.Ptr = true;
+ return Res;
}
bool matchesType(ASTContext &C, QualType argTy) const;
- bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; }
-
QualType getRepresentativeType(ASTContext &C) const;
std::string getRepresentativeTypeName(ASTContext &C) const;
@@ -278,7 +279,7 @@ public:
return length + UsesDotPrefix;
}
- ArgTypeResult getArgType(ASTContext &Ctx) const;
+ ArgType getArgType(ASTContext &Ctx) const;
void toString(raw_ostream &os) const;
@@ -354,6 +355,10 @@ public:
bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
bool hasStandardLengthConversionCombination() const;
+
+ /// For a TypedefType QT, if it is a named integer type such as size_t,
+ /// assign the appropriate value to LM and return true.
+ static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);
};
} // end analyze_format_string namespace
@@ -387,7 +392,7 @@ public:
}
};
-using analyze_format_string::ArgTypeResult;
+using analyze_format_string::ArgType;
using analyze_format_string::LengthModifier;
using analyze_format_string::OptionalAmount;
using analyze_format_string::OptionalFlag;
@@ -462,7 +467,7 @@ public:
/// 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, bool IsObjCLiteral) const;
+ ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
const OptionalFlag &hasThousandsGrouping() const {
return HasThousandsGrouping;
@@ -516,35 +521,11 @@ public:
}
};
-using analyze_format_string::ArgTypeResult;
+using analyze_format_string::ArgType;
using analyze_format_string::LengthModifier;
using analyze_format_string::OptionalAmount;
using analyze_format_string::OptionalFlag;
-class ScanfArgTypeResult : public ArgTypeResult {
-public:
- enum Kind { UnknownTy, InvalidTy, CStrTy, WCStrTy, PtrToArgTypeResultTy };
-private:
- Kind K;
- ArgTypeResult A;
- const char *Name;
- QualType getRepresentativeType(ASTContext &C) const;
-public:
- ScanfArgTypeResult(Kind k = UnknownTy, const char* n = 0) : K(k), Name(n) {}
- ScanfArgTypeResult(ArgTypeResult a, const char *n = 0)
- : K(PtrToArgTypeResultTy), A(a), Name(n) {
- assert(A.isValid());
- }
-
- static ScanfArgTypeResult Invalid() { return ScanfArgTypeResult(InvalidTy); }
-
- bool isValid() const { return K != InvalidTy; }
-
- bool matchesType(ASTContext& C, QualType argTy) const;
-
- std::string getRepresentativeTypeName(ASTContext& C) const;
-};
-
class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
OptionalFlag SuppressAssignment; // '*'
public:
@@ -573,7 +554,7 @@ public:
return CS.consumesDataArgument() && !SuppressAssignment;
}
- ScanfArgTypeResult getArgType(ASTContext &Ctx) const;
+ ArgType getArgType(ASTContext &Ctx) const;
bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx);
diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h
index 26e258d64a5f..742cc0434456 100644
--- a/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -60,7 +60,8 @@ enum AccessKind {
enum LockErrorKind {
LEK_LockedSomeLoopIterations,
LEK_LockedSomePredecessors,
- LEK_LockedAtEndOfFunction
+ LEK_LockedAtEndOfFunction,
+ LEK_NotLockedAtEndOfFunction
};
/// Handler class for thread safety warnings.
@@ -123,11 +124,11 @@ public:
/// Warn when a protected operation occurs while the specific mutex protecting
/// the operation is not locked.
- /// \param LockName -- A StringRef name for the lock expression, to be printed
- /// in the error message.
/// \param D -- The decl for the protected variable or function
/// \param POK -- The kind of protected operation (e.g. variable access)
- /// \param AK -- The kind of access (i.e. read or write) that occurred
+ /// \param LockName -- A StringRef name for the lock expression, to be printed
+ /// in the error message.
+ /// \param LK -- The kind of access (i.e. read or write) that occurred
/// \param Loc -- The location of the protected operation.
virtual void handleMutexNotHeld(const NamedDecl *D,
ProtectedOperationKind POK, Name LockName,
diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h
index 4ee66986bef5..45ce4de1f8dd 100644
--- a/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -15,6 +15,8 @@
#ifndef LLVM_CLANG_UNINIT_VALS_H
#define LLVM_CLANG_UNINIT_VALS_H
+#include "llvm/ADT/SmallVector.h"
+
namespace clang {
class AnalysisDeclContext;
@@ -23,15 +25,67 @@ class DeclContext;
class Expr;
class VarDecl;
+/// A use of a variable, which might be uninitialized.
+class UninitUse {
+public:
+ struct Branch {
+ const Stmt *Terminator;
+ unsigned Output;
+ };
+
+private:
+ /// The expression which uses this variable.
+ const Expr *User;
+
+ /// Does this use always see an uninitialized value?
+ bool AlwaysUninit;
+
+ /// This use is always uninitialized if it occurs after any of these branches
+ /// is taken.
+ llvm::SmallVector<Branch, 2> UninitBranches;
+
+public:
+ UninitUse(const Expr *User, bool AlwaysUninit) :
+ User(User), AlwaysUninit(AlwaysUninit) {}
+
+ void addUninitBranch(Branch B) {
+ UninitBranches.push_back(B);
+ }
+
+ /// Get the expression containing the uninitialized use.
+ const Expr *getUser() const { return User; }
+
+ /// The kind of uninitialized use.
+ enum Kind {
+ /// The use might be uninitialized.
+ Maybe,
+ /// The use is uninitialized whenever a certain branch is taken.
+ Sometimes,
+ /// The use is always uninitialized.
+ Always
+ };
+
+ /// Get the kind of uninitialized use.
+ Kind getKind() const {
+ return AlwaysUninit ? Always :
+ !branch_empty() ? Sometimes : Maybe;
+ }
+
+ typedef llvm::SmallVectorImpl<Branch>::const_iterator branch_iterator;
+ /// Branches which inevitably result in the variable being used uninitialized.
+ branch_iterator branch_begin() const { return UninitBranches.begin(); }
+ branch_iterator branch_end() const { return UninitBranches.end(); }
+ bool branch_empty() const { return UninitBranches.empty(); }
+};
+
class UninitVariablesHandler {
public:
UninitVariablesHandler() {}
virtual ~UninitVariablesHandler();
/// Called when the uninitialized variable is used at the given expression.
- virtual void handleUseOfUninitVariable(const Expr *ex,
- const VarDecl *vd,
- bool isAlwaysUninit) {}
+ virtual void handleUseOfUninitVariable(const VarDecl *vd,
+ const UninitUse &use) {}
/// Called when the uninitialized variable analysis detects the
/// idiom 'int x = x'. All other uses of 'x' within the initializer
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 6b6f8ef2cc28..46b4e93bb7d4 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -38,6 +38,7 @@ class PseudoConstantAnalysis;
class ImplicitParamDecl;
class LocationContextManager;
class StackFrameContext;
+class BlockInvocationContext;
class AnalysisDeclContextManager;
class LocationContext;
@@ -73,9 +74,6 @@ class AnalysisDeclContext {
const Decl *D;
- // TranslationUnit is NULL if we don't have multiple translation units.
- idx::TranslationUnit *TU;
-
OwningPtr<CFG> cfg, completeCFG;
OwningPtr<CFGStmtMap> cfgStmtMap;
@@ -98,12 +96,10 @@ class AnalysisDeclContext {
public:
AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
- const Decl *D,
- idx::TranslationUnit *TU);
+ const Decl *D);
AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
const Decl *D,
- idx::TranslationUnit *TU,
const CFG::BuildOptions &BuildOptions);
~AnalysisDeclContext();
@@ -111,8 +107,6 @@ public:
ASTContext &getASTContext() { return D->getASTContext(); }
const Decl *getDecl() const { return D; }
- idx::TranslationUnit *getTranslationUnit() const { return TU; }
-
/// Return the build options used to construct the CFG.
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
@@ -169,6 +163,11 @@ public:
const Stmt *S,
const CFGBlock *Blk,
unsigned Idx);
+
+ const BlockInvocationContext *
+ getBlockInvocationContext(const LocationContext *parent,
+ const BlockDecl *BD,
+ const void *ContextData);
/// Return the specified analysis object, lazily running the analysis if
/// necessary. Return NULL if the analysis could not run.
@@ -212,10 +211,6 @@ public:
AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
- idx::TranslationUnit *getTranslationUnit() const {
- return Ctx->getTranslationUnit();
- }
-
const LocationContext *getParent() const { return Parent; }
bool isParentOf(const LocationContext *LC) const;
@@ -238,8 +233,6 @@ public:
}
const StackFrameContext *getCurrentStackFrame() const;
- const StackFrameContext *
- getStackFrameForDeclContext(const DeclContext *DC) const;
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
@@ -318,27 +311,32 @@ public:
};
class BlockInvocationContext : public LocationContext {
- // FIXME: Add back context-sensivity (we don't want libAnalysis to know
- // about MemRegion).
const BlockDecl *BD;
+
+ // FIXME: Come up with a more type-safe way to model context-sensitivity.
+ const void *ContextData;
friend class LocationContextManager;
BlockInvocationContext(AnalysisDeclContext *ctx,
const LocationContext *parent,
- const BlockDecl *bd)
- : LocationContext(Block, ctx, parent), BD(bd) {}
+ const BlockDecl *bd, const void *contextData)
+ : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
public:
~BlockInvocationContext() {}
const BlockDecl *getBlockDecl() const { return BD; }
+
+ const void *getContextData() const { return ContextData; }
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
- const LocationContext *parent, const BlockDecl *bd) {
+ const LocationContext *parent, const BlockDecl *bd,
+ const void *contextData) {
ProfileCommon(ID, Block, ctx, parent, bd);
+ ID.AddPointer(contextData);
}
static bool classof(const LocationContext *Ctx) {
@@ -359,6 +357,12 @@ public:
const ScopeContext *getScope(AnalysisDeclContext *ctx,
const LocationContext *parent,
const Stmt *s);
+
+ const BlockInvocationContext *
+ getBlockInvocationContext(AnalysisDeclContext *ctx,
+ const LocationContext *parent,
+ const BlockDecl *BD,
+ const void *ContextData);
/// Discard all previously created LocationContext objects.
void clear();
@@ -383,7 +387,7 @@ public:
~AnalysisDeclContextManager();
- AnalysisDeclContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
+ AnalysisDeclContext *getContext(const Decl *D);
bool getUseUnoptimizedCFG() const {
return !cfgBuildOptions.PruneTriviallyFalseEdges;
@@ -402,9 +406,8 @@ public:
}
// Get the top level stack frame.
- const StackFrameContext *getStackFrame(Decl const *D,
- idx::TranslationUnit *TU) {
- return LocContexts.getStackFrame(getContext(D, TU), 0, 0, 0, 0);
+ const StackFrameContext *getStackFrame(const Decl *D) {
+ return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0);
}
// Get a stack frame with parent.
@@ -416,7 +419,6 @@ public:
return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
}
-
/// Discard all previously created AnalysisDeclContexts.
void clear();
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index 27b22b8c622d..4d087e749830 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -21,10 +21,10 @@
#include "llvm/Support/Casting.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/BitVector.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Basic/SourceLocation.h"
+#include <bitset>
#include <cassert>
#include <iterator>
@@ -277,6 +277,7 @@ class CFGBlock {
typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator;
typedef ImplTy::iterator reverse_iterator;
typedef ImplTy::const_iterator const_reverse_iterator;
+ typedef ImplTy::const_reference const_reference;
void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
@@ -284,8 +285,8 @@ class CFGBlock {
return Impl.insert(I, Cnt, E, C);
}
- CFGElement front() const { return Impl.back(); }
- CFGElement back() const { return Impl.front(); }
+ const_reference front() const { return Impl.back(); }
+ const_reference back() const { return Impl.front(); }
iterator begin() { return Impl.rbegin(); }
iterator end() { return Impl.rend(); }
@@ -558,7 +559,7 @@ public:
//===--------------------------------------------------------------------===//
class BuildOptions {
- llvm::BitVector alwaysAddMask;
+ std::bitset<Stmt::lastStmtConstant> alwaysAddMask;
public:
typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs;
ForcedBlkExprs **forcedBlkExprs;
@@ -583,8 +584,7 @@ public:
}
BuildOptions()
- : alwaysAddMask(Stmt::lastStmtConstant, false)
- ,forcedBlkExprs(0), PruneTriviallyFalseEdges(true)
+ : forcedBlkExprs(0), PruneTriviallyFalseEdges(true)
,AddEHEdges(false)
,AddInitializers(false)
,AddImplicitDtors(false) {}
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index 9b6807343c39..509de7bc2178 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -26,7 +26,7 @@
namespace clang {
class CallGraphNode;
-/// \class The AST-based call graph.
+/// \brief The AST-based call graph.
///
/// The call graph extends itself with the given declarations by implementing
/// the recursive AST visitor, which constructs the graph by visiting the given
@@ -102,7 +102,8 @@ public:
void dump() const;
void viewGraph() const;
- /// Part of recursive declaration visitation.
+ /// Part of recursive declaration visitation. We recursively visit all the
+ /// Declarations to collect the root functions.
bool VisitFunctionDecl(FunctionDecl *FD) {
// We skip function template definitions, as their semantics is
// only determined when they are instantiated.
@@ -121,6 +122,11 @@ public:
return true;
}
+ // We are only collecting the declarations, so do not step into the bodies.
+ bool TraverseStmt(Stmt *S) { return true; }
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
private:
/// \brief Add the given declaration to the call graph.
void addNodeForDecl(Decl *D, bool IsGlobal);
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index aa7a33c956e4..5de06cd3a54d 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -40,30 +40,36 @@ public:
BlockEntranceKind,
BlockExitKind,
PreStmtKind,
+ PreStmtPurgeDeadSymbolsKind,
+ PostStmtPurgeDeadSymbolsKind,
PostStmtKind,
PreLoadKind,
PostLoadKind,
PreStoreKind,
PostStoreKind,
- PostPurgeDeadSymbolsKind,
PostConditionKind,
PostLValueKind,
+ MinPostStmtKind = PostStmtKind,
+ MaxPostStmtKind = PostLValueKind,
PostInitializerKind,
CallEnterKind,
- CallExitKind,
- MinPostStmtKind = PostStmtKind,
- MaxPostStmtKind = CallExitKind,
+ CallExitBeginKind,
+ CallExitEndKind,
+ PreImplicitCallKind,
+ PostImplicitCallKind,
+ MinImplicitCallKind = PreImplicitCallKind,
+ MaxImplicitCallKind = PostImplicitCallKind,
EpsilonKind};
private:
- llvm::PointerIntPair<const void *, 2, unsigned> Data1;
+ const void *Data1;
llvm::PointerIntPair<const void *, 2, unsigned> Data2;
// The LocationContext could be NULL to allow ProgramPoint to be used in
// context insensitive analysis.
llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
- const ProgramPointTag *Tag;
+ llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
ProgramPoint();
@@ -72,10 +78,10 @@ protected:
Kind k,
const LocationContext *l,
const ProgramPointTag *tag = 0)
- : Data1(P, ((unsigned) k) & 0x3),
- Data2(0, (((unsigned) k) >> 2) & 0x3),
- L(l, (((unsigned) k) >> 4) & 0x3),
- Tag(tag) {
+ : Data1(P),
+ Data2(0, (((unsigned) k) >> 0) & 0x3),
+ L(l, (((unsigned) k) >> 2) & 0x3),
+ Tag(tag, (((unsigned) k) >> 4) & 0x3) {
assert(getKind() == k);
assert(getLocationContext() == l);
assert(getData1() == P);
@@ -86,13 +92,13 @@ protected:
Kind k,
const LocationContext *l,
const ProgramPointTag *tag = 0)
- : Data1(P1, ((unsigned) k) & 0x3),
- Data2(P2, (((unsigned) k) >> 2) & 0x3),
- L(l, (((unsigned) k) >> 4) & 0x3),
- Tag(tag) {}
+ : Data1(P1),
+ Data2(P2, (((unsigned) k) >> 0) & 0x3),
+ L(l, (((unsigned) k) >> 2) & 0x3),
+ Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
protected:
- const void *getData1() const { return Data1.getPointer(); }
+ const void *getData1() const { return Data1; }
const void *getData2() const { return Data2.getPointer(); }
void setData2(const void *d) { Data2.setPointer(d); }
@@ -105,15 +111,23 @@ public:
}
Kind getKind() const {
- unsigned x = L.getInt();
+ unsigned x = Tag.getInt();
x <<= 2;
- x |= Data2.getInt();
+ x |= L.getInt();
x <<= 2;
- x |= Data1.getInt();
+ x |= Data2.getInt();
return (Kind) x;
}
- const ProgramPointTag *getTag() const { return Tag; }
+ /// \brief Is this a program point corresponding to purge/removal of dead
+ /// symbols and bindings.
+ bool isPurgeKind() {
+ Kind K = getKind();
+ return (K == PostStmtPurgeDeadSymbolsKind ||
+ K == PreStmtPurgeDeadSymbolsKind);
+ }
+
+ const ProgramPointTag *getTag() const { return Tag.getPointer(); }
const LocationContext *getLocationContext() const {
return L.getPointer();
@@ -147,7 +161,7 @@ public:
ID.AddPointer(getData1());
ID.AddPointer(getData2());
ID.AddPointer(getLocationContext());
- ID.AddPointer(Tag);
+ ID.AddPointer(getTag());
}
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
@@ -304,7 +318,7 @@ public:
}
};
-/// \class Represents a program point after a store evaluation.
+/// \brief Represents a program point after a store evaluation.
class PostStore : public PostStmt {
public:
/// Construct the post store point.
@@ -340,14 +354,29 @@ public:
}
};
-class PostPurgeDeadSymbols : public PostStmt {
+/// Represents a point after we ran remove dead bindings BEFORE
+/// processing the given statement.
+class PreStmtPurgeDeadSymbols : public StmtPoint {
public:
- PostPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
+ PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = 0)
- : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {}
+ : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { }
static bool classof(const ProgramPoint* Location) {
- return Location->getKind() == PostPurgeDeadSymbolsKind;
+ return Location->getKind() == PreStmtPurgeDeadSymbolsKind;
+ }
+};
+
+/// Represents a point after we ran remove dead bindings AFTER
+/// processing the given statement.
+class PostStmtPurgeDeadSymbols : public StmtPoint {
+public:
+ PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
+ const ProgramPointTag *tag = 0)
+ : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostStmtPurgeDeadSymbolsKind;
}
};
@@ -383,11 +412,60 @@ public:
}
};
-class CallEnter : public StmtPoint {
+/// Represents an implicit call event.
+///
+/// The nearest statement is provided for diagnostic purposes.
+class ImplicitCallPoint : public ProgramPoint {
+public:
+ ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
+ const LocationContext *L, const ProgramPointTag *Tag)
+ : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
+
+ const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
+ SourceLocation getLocation() const {
+ return SourceLocation::getFromPtrEncoding(getData1());
+ }
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() >= MinImplicitCallKind &&
+ Location->getKind() <= MaxImplicitCallKind;
+ }
+};
+
+/// Represents a program point just before an implicit call event.
+///
+/// Explicit calls will appear as PreStmt program points.
+class PreImplicitCall : public ImplicitCallPoint {
+public:
+ PreImplicitCall(const Decl *D, SourceLocation Loc,
+ const LocationContext *L, const ProgramPointTag *Tag = 0)
+ : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == PreImplicitCallKind;
+ }
+};
+
+/// Represents a program point just after an implicit call event.
+///
+/// Explicit calls will appear as PostStmt program points.
+class PostImplicitCall : public ImplicitCallPoint {
+public:
+ PostImplicitCall(const Decl *D, SourceLocation Loc,
+ const LocationContext *L, const ProgramPointTag *Tag = 0)
+ : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == PostImplicitCallKind;
+ }
+};
+
+/// Represents a point when we begin processing an inlined call.
+class CallEnter : public ProgramPoint {
public:
CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
const LocationContext *callerCtx)
- : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
+ : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
const Stmt *getCallExpr() const {
return static_cast<const Stmt *>(getData1());
@@ -402,14 +480,41 @@ public:
}
};
-class CallExit : public StmtPoint {
+/// Represents a point when we start the call exit sequence (for inlined call).
+///
+/// The call exit is simulated with a sequence of nodes, which occur between
+/// CallExitBegin and CallExitEnd. The following operations occur between the
+/// two program points:
+/// - CallExitBegin
+/// - Bind the return value
+/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
+/// - CallExitEnd
+class CallExitBegin : public ProgramPoint {
+public:
+ // CallExitBegin uses the callee's location context.
+ CallExitBegin(const StackFrameContext *L)
+ : ProgramPoint(0, CallExitBeginKind, L, 0) {}
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == CallExitBeginKind;
+ }
+};
+
+/// Represents a point when we finish the call exit sequence (for inlined call).
+/// \sa CallExitBegin
+class CallExitEnd : public ProgramPoint {
public:
- // CallExit uses the callee's location context.
- CallExit(const Stmt *S, const LocationContext *L)
- : StmtPoint(S, 0, CallExitKind, L, 0) {}
+ // CallExitEnd uses the caller's location context.
+ CallExitEnd(const StackFrameContext *CalleeCtx,
+ const LocationContext *CallerCtx)
+ : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, 0) {}
+
+ const StackFrameContext *getCalleeContext() const {
+ return static_cast<const StackFrameContext *>(getData1());
+ }
static bool classof(const ProgramPoint *Location) {
- return Location->getKind() == CallExitKind;
+ return Location->getKind() == CallExitEndKind;
}
};
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
index 97eb28702736..c510e202f93f 100644
--- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
@@ -69,6 +69,7 @@ public:
DISPATCH_CASE(Field)
DISPATCH_CASE(UsingDirective)
DISPATCH_CASE(Using)
+ DISPATCH_CASE(NamespaceAlias)
default:
llvm_unreachable("Subtype of ScopedDecl not handled.");
}
@@ -90,6 +91,7 @@ public:
DEFAULT_DISPATCH(ObjCCategory)
DEFAULT_DISPATCH(UsingDirective)
DEFAULT_DISPATCH(Using)
+ DEFAULT_DISPATCH(NamespaceAlias)
void VisitCXXRecordDecl(CXXRecordDecl *D) {
static_cast<ImplClass*>(this)->VisitRecordDecl(D);
diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h
index 018f50026541..fecf613a0461 100644
--- a/include/clang/Basic/ABI.h
+++ b/include/clang/Basic/ABI.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// These enums/classes describe ABI related information about constructors,
-// destructors and thunks.
-//
+///
+/// \file
+/// \brief Enums/classes describing ABI related information about constructors,
+/// destructors and thunks.
+///
//===----------------------------------------------------------------------===//
#ifndef CLANG_BASIC_ABI_H
@@ -19,27 +20,27 @@
namespace clang {
-/// CXXCtorType - C++ constructor types
+/// \brief C++ constructor types.
enum CXXCtorType {
- Ctor_Complete, // Complete object ctor
- Ctor_Base, // Base object ctor
- Ctor_CompleteAllocating // Complete object allocating ctor
+ Ctor_Complete, ///< Complete object ctor
+ Ctor_Base, ///< Base object ctor
+ Ctor_CompleteAllocating ///< Complete object allocating ctor
};
-/// CXXDtorType - C++ destructor types
+/// \brief C++ destructor types.
enum CXXDtorType {
- Dtor_Deleting, // Deleting dtor
- Dtor_Complete, // Complete object dtor
- Dtor_Base // Base object dtor
+ Dtor_Deleting, ///< Deleting dtor
+ Dtor_Complete, ///< Complete object dtor
+ Dtor_Base ///< Base object dtor
};
-/// ReturnAdjustment - A return adjustment.
+/// \brief A return adjustment.
struct ReturnAdjustment {
- /// NonVirtual - The non-virtual adjustment from the derived object to its
+ /// \brief The non-virtual adjustment from the derived object to its
/// nearest virtual base.
int64_t NonVirtual;
- /// VBaseOffsetOffset - The offset (in bytes), relative to the address point
+ /// \brief The offset (in bytes), relative to the address point
/// of the virtual base class offset.
int64_t VBaseOffsetOffset;
@@ -63,13 +64,13 @@ struct ReturnAdjustment {
}
};
-/// ThisAdjustment - A 'this' pointer adjustment.
+/// \brief A \c this pointer adjustment.
struct ThisAdjustment {
- /// NonVirtual - The non-virtual adjustment from the derived object to its
+ /// \brief The non-virtual adjustment from the derived object to its
/// nearest virtual base.
int64_t NonVirtual;
- /// VCallOffsetOffset - The offset (in bytes), relative to the address point,
+ /// \brief The offset (in bytes), relative to the address point,
/// of the virtual call offset.
int64_t VCallOffsetOffset;
@@ -93,13 +94,13 @@ struct ThisAdjustment {
}
};
-/// ThunkInfo - The 'this' pointer adjustment as well as an optional return
+/// \brief The \c this pointer adjustment as well as an optional return
/// adjustment for a thunk.
struct ThunkInfo {
- /// This - The 'this' pointer adjustment.
+ /// \brief The \c this pointer adjustment.
ThisAdjustment This;
- /// Return - The return adjustment.
+ /// \brief The return adjustment.
ReturnAdjustment Return;
ThunkInfo() { }
diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h
index d44a9c3b0361..4b1cea50f884 100644
--- a/include/clang/Basic/AddressSpaces.h
+++ b/include/clang/Basic/AddressSpaces.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file provides definitions for the various language-specific address
-// spaces.
-//
+///
+/// \file
+/// \brief Provides definitions for the various language-specific address
+/// spaces.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H
@@ -19,8 +20,9 @@ namespace clang {
namespace LangAS {
-/// This enum defines the set of possible language-specific address spaces.
-/// It uses a high starting offset so as not to conflict with any address
+/// \brief Defines the set of possible language-specific address spaces.
+///
+/// This uses a high starting offset so as not to conflict with any address
/// space used by a target.
enum ID {
Offset = 0xFFFF00,
@@ -29,6 +31,10 @@ enum ID {
opencl_local,
opencl_constant,
+ cuda_device,
+ cuda_constant,
+ cuda_shared,
+
Last,
Count = Last-Offset
};
diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h
index 7e774355488c..7304c8f673e6 100644
--- a/include/clang/Basic/AllDiagnostics.h
+++ b/include/clang/Basic/AllDiagnostics.h
@@ -6,16 +6,17 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file includes all the separate Diagnostic headers & some related
-// helpers.
-//
+///
+/// \file
+/// \brief Includes all the separate Diagnostic headers & some related helpers.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ALL_DIAGNOSTICS_H
#define LLVM_CLANG_ALL_DIAGNOSTICS_H
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/CommentDiagnostic.h"
#include "clang/Analysis/AnalysisDiagnostic.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Frontend/FrontendDiagnostic.h"
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index e8e0f35096f3..99180e450e65 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -80,23 +80,40 @@ class EnumArgument<string name, string type, list<string> values,
list<string> Enums = enums;
}
+// This handles one spelling of an attribute.
+class Spelling<string name, string variety> {
+ string Name = name;
+ string Variety = variety;
+}
+
+class GNU<string name> : Spelling<name, "GNU">;
+class Declspec<string name> : Spelling<name, "Declspec">;
+class CXX11<string namespace, string name> : Spelling<name, "CXX11"> {
+ string Namespace = namespace;
+}
+
class Attr {
// The various ways in which an attribute can be spelled in source
- list<string> Spellings;
+ list<Spelling> Spellings;
// The things to which an attribute can appertain
list<AttrSubject> Subjects;
// The arguments allowed on an attribute
list<Argument> Args = [];
- // The namespaces in which the attribute appears in C++0x attributes.
- // The attribute will not be permitted in C++0x attribute-specifiers if
- // this is empty; the empty string can be used as a namespace.
- list<string> Namespaces = [];
// Set to true for attributes with arguments which require delayed parsing.
bit LateParsed = 0;
+ // Set to false to prevent an attribute from being propagated from a template
+ // to the instantiation.
+ bit Clone = 1;
// Set to true for attributes which must be instantiated within templates
bit TemplateDependent = 0;
+ // Set to true for attributes that have a corresponding AST node.
+ bit ASTNode = 1;
// Set to true for attributes which have handler in Sema.
bit SemaHandler = 1;
+ // Set to true for attributes that are completely ignored.
+ bit Ignored = 0;
+ // Set to true if each of the spellings is a distinct attribute.
+ bit DistinctSpellings = 0;
// Any additional text that should be included verbatim in the class.
code AdditionalMembers = [{}];
}
@@ -112,16 +129,21 @@ class InheritableParamAttr : InheritableAttr;
// Attributes begin here
//
+def AddressSpace : Attr {
+ let Spellings = [GNU<"address_space">];
+ let Args = [IntArgument<"AddressSpace">];
+ let ASTNode = 0;
+}
+
def Alias : InheritableAttr {
- let Spellings = ["alias"];
+ let Spellings = [GNU<"alias">];
let Args = [StringArgument<"Aliasee">];
}
def Aligned : InheritableAttr {
- let Spellings = ["aligned"];
+ let Spellings = [GNU<"aligned">, GNU<"align">];
let Subjects = [NonBitField, NormalVar, Tag];
- let Args = [AlignedArgument<"Alignment">];
- let Namespaces = ["", "std"];
+ let Args = [AlignedArgument<"Alignment">, BoolArgument<"IsMSDeclSpec">];
}
def AlignMac68k : InheritableAttr {
@@ -129,16 +151,27 @@ def AlignMac68k : InheritableAttr {
let SemaHandler = 0;
}
+def AllocSize : Attr {
+ let Spellings = [GNU<"alloc_size">];
+ let Args = [VariadicUnsignedArgument<"Args">];
+}
+
def AlwaysInline : InheritableAttr {
- let Spellings = ["always_inline"];
+ let Spellings = [GNU<"always_inline">];
+}
+
+def TLSModel : InheritableAttr {
+ let Spellings = [GNU<"tls_model">];
+ let Subjects = [Var];
+ let Args = [StringArgument<"Model">];
}
def AnalyzerNoReturn : InheritableAttr {
- let Spellings = ["analyzer_noreturn"];
+ let Spellings = [GNU<"analyzer_noreturn">];
}
def Annotate : InheritableParamAttr {
- let Spellings = ["annotate"];
+ let Spellings = [GNU<"annotate">];
let Args = [StringArgument<"Annotation">];
}
@@ -149,7 +182,7 @@ def AsmLabel : InheritableAttr {
}
def Availability : InheritableAttr {
- let Spellings = ["availability"];
+ let Spellings = [GNU<"availability">];
let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">,
VersionArgument<"deprecated">, VersionArgument<"obsoleted">,
BoolArgument<"unavailable">, StringArgument<"message">];
@@ -163,18 +196,25 @@ def Availability : InheritableAttr {
}
def Blocks : InheritableAttr {
- let Spellings = ["blocks"];
+ let Spellings = [GNU<"blocks">];
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
}
+def Bounded : Attr {
+ let Spellings = [GNU<"bounded">];
+ let ASTNode = 0;
+ let SemaHandler = 0;
+ let Ignored = 1;
+}
+
def CarriesDependency : InheritableParamAttr {
- let Spellings = ["carries_dependency"];
+ let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">,
+ CXX11<"std","carries_dependency">];
let Subjects = [ParmVar, Function];
- let Namespaces = ["", "std"];
}
def CDecl : InheritableAttr {
- let Spellings = ["cdecl", "__cdecl"];
+ let Spellings = [GNU<"cdecl">, GNU<"__cdecl">];
}
// cf_audited_transfer indicates that the given function has been
@@ -182,7 +222,7 @@ def CDecl : InheritableAttr {
// cf_returns_retained attributes. It is generally applied by
// '#pragma clang arc_cf_code_audited' rather than explicitly.
def CFAuditedTransfer : InheritableAttr {
- let Spellings = ["cf_audited_transfer"];
+ let Spellings = [GNU<"cf_audited_transfer">];
let Subjects = [Function];
}
@@ -190,133 +230,151 @@ def CFAuditedTransfer : InheritableAttr {
// It indicates that the function has unknown or unautomatable
// transfer semantics.
def CFUnknownTransfer : InheritableAttr {
- let Spellings = ["cf_unknown_transfer"];
+ let Spellings = [GNU<"cf_unknown_transfer">];
let Subjects = [Function];
}
+def CFReturnsAutoreleased : Attr {
+ let Spellings = [GNU<"cf_returns_autoreleased">];
+ let ASTNode = 0;
+}
+
def CFReturnsRetained : InheritableAttr {
- let Spellings = ["cf_returns_retained"];
+ let Spellings = [GNU<"cf_returns_retained">];
let Subjects = [ObjCMethod, Function];
}
def CFReturnsNotRetained : InheritableAttr {
- let Spellings = ["cf_returns_not_retained"];
+ let Spellings = [GNU<"cf_returns_not_retained">];
let Subjects = [ObjCMethod, Function];
}
def CFConsumed : InheritableParamAttr {
- let Spellings = ["cf_consumed"];
+ let Spellings = [GNU<"cf_consumed">];
let Subjects = [ParmVar];
}
def Cleanup : InheritableAttr {
- let Spellings = ["cleanup"];
+ let Spellings = [GNU<"cleanup">];
let Args = [FunctionArgument<"FunctionDecl">];
}
+def Cold : InheritableAttr {
+ let Spellings = [GNU<"cold">];
+}
+
def Common : InheritableAttr {
- let Spellings = ["common"];
+ let Spellings = [GNU<"common">];
}
def Const : InheritableAttr {
- let Spellings = ["const"];
+ let Spellings = [GNU<"const">, GNU<"__const">];
}
def Constructor : InheritableAttr {
- let Spellings = ["constructor"];
+ let Spellings = [GNU<"constructor">];
let Args = [IntArgument<"Priority">];
}
def CUDAConstant : InheritableAttr {
- let Spellings = ["constant"];
+ let Spellings = [GNU<"constant">];
}
-def CUDADevice : Attr {
- let Spellings = ["device"];
+def CUDADevice : InheritableAttr {
+ let Spellings = [GNU<"device">];
}
def CUDAGlobal : InheritableAttr {
- let Spellings = ["global"];
+ let Spellings = [GNU<"global">];
}
-def CUDAHost : Attr {
- let Spellings = ["host"];
+def CUDAHost : InheritableAttr {
+ let Spellings = [GNU<"host">];
}
def CUDALaunchBounds : InheritableAttr {
- let Spellings = ["launch_bounds"];
+ let Spellings = [GNU<"launch_bounds">];
let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
}
def CUDAShared : InheritableAttr {
- let Spellings = ["shared"];
+ let Spellings = [GNU<"shared">];
}
def OpenCLKernel : Attr {
- let Spellings = ["opencl_kernel_function"];
+ let Spellings = [GNU<"opencl_kernel_function">];
+}
+
+def OpenCLImageAccess : Attr {
+ let Spellings = [GNU<"opencl_image_access">];
+ let Args = [IntArgument<"Access">];
+ let ASTNode = 0;
}
def Deprecated : InheritableAttr {
- let Spellings = ["deprecated"];
+ let Spellings = [GNU<"deprecated">];
let Args = [StringArgument<"Message">];
}
def Destructor : InheritableAttr {
- let Spellings = ["destructor"];
+ let Spellings = [GNU<"destructor">];
let Args = [IntArgument<"Priority">];
}
-def DLLExport : InheritableAttr {
- let Spellings = ["dllexport"];
+def ExtVectorType : Attr {
+ let Spellings = [GNU<"ext_vector_type">];
+ let Args = [ExprArgument<"NumElements">];
+ let ASTNode = 0;
}
-def DLLImport : InheritableAttr {
- let Spellings = ["dllimport"];
+def FallThrough : Attr {
+ let Spellings = [CXX11<"clang","fallthrough">];
+ let Subjects = [NullStmt];
}
def FastCall : InheritableAttr {
- let Spellings = ["fastcall", "__fastcall"];
+ let Spellings = [GNU<"fastcall">, GNU<"__fastcall">];
}
-def Final : InheritableAttr {
+def Final : InheritableAttr {
let Spellings = [];
let SemaHandler = 0;
}
-def MsStruct : InheritableAttr {
- let Spellings = ["__ms_struct__"];
-}
-
def Format : InheritableAttr {
- let Spellings = ["format"];
+ let Spellings = [GNU<"format">];
let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">,
IntArgument<"FirstArg">];
}
def FormatArg : InheritableAttr {
- let Spellings = ["format_arg"];
+ let Spellings = [GNU<"format_arg">];
let Args = [IntArgument<"FormatIdx">];
}
def GNUInline : InheritableAttr {
- let Spellings = ["gnu_inline"];
+ let Spellings = [GNU<"gnu_inline">];
+}
+
+def Hot : InheritableAttr {
+ let Spellings = [GNU<"hot">];
}
def IBAction : InheritableAttr {
- let Spellings = ["ibaction"];
+ let Spellings = [GNU<"ibaction">];
}
def IBOutlet : InheritableAttr {
- let Spellings = ["iboutlet"];
+ let Spellings = [GNU<"iboutlet">];
}
def IBOutletCollection : InheritableAttr {
- let Spellings = ["iboutletcollection"];
+ let Spellings = [GNU<"iboutletcollection">];
let Args = [TypeArgument<"Interface">, SourceLocArgument<"InterfaceLoc">];
}
def Malloc : InheritableAttr {
- let Spellings = ["malloc"];
+ let Spellings = [GNU<"malloc">];
}
def MaxFieldAlignment : InheritableAttr {
@@ -326,7 +384,7 @@ def MaxFieldAlignment : InheritableAttr {
}
def MayAlias : InheritableAttr {
- let Spellings = ["may_alias"];
+ let Spellings = [GNU<"may_alias">];
}
def MSP430Interrupt : InheritableAttr {
@@ -345,28 +403,46 @@ def MBlazeSaveVolatiles : InheritableAttr {
let SemaHandler = 0;
}
+def Mode : Attr {
+ let Spellings = [GNU<"mode">];
+ let Args = [IdentifierArgument<"Mode">];
+ let ASTNode = 0;
+}
+
def Naked : InheritableAttr {
- let Spellings = ["naked"];
+ let Spellings = [GNU<"naked">];
+}
+
+def NeonPolyVectorType : Attr {
+ let Spellings = [GNU<"neon_polyvector_type">];
+ let Args = [IntArgument<"NumElements">];
+ let ASTNode = 0;
+}
+
+def NeonVectorType : Attr {
+ let Spellings = [GNU<"neon_vector_type">];
+ let Args = [IntArgument<"NumElements">];
+ let ASTNode = 0;
}
def ReturnsTwice : InheritableAttr {
- let Spellings = ["returns_twice"];
+ let Spellings = [GNU<"returns_twice">];
}
def NoCommon : InheritableAttr {
- let Spellings = ["nocommon"];
+ let Spellings = [GNU<"nocommon">];
}
def NoDebug : InheritableAttr {
- let Spellings = ["nodebug"];
+ let Spellings = [GNU<"nodebug">];
}
def NoInline : InheritableAttr {
- let Spellings = ["noinline"];
+ let Spellings = [GNU<"noinline">];
}
def NonNull : InheritableAttr {
- let Spellings = ["nonnull"];
+ let Spellings = [GNU<"nonnull">];
let Args = [VariadicUnsignedArgument<"Args">];
let AdditionalMembers =
[{bool isNonNull(unsigned idx) const {
@@ -379,58 +455,58 @@ def NonNull : InheritableAttr {
}
def NoReturn : InheritableAttr {
- let Spellings = ["noreturn"];
+ let Spellings = [GNU<"noreturn">, CXX11<"","noreturn">,
+ CXX11<"std","noreturn">];
// FIXME: Does GCC allow this on the function instead?
let Subjects = [Function];
- let Namespaces = ["", "std"];
}
def NoInstrumentFunction : InheritableAttr {
- let Spellings = ["no_instrument_function"];
+ let Spellings = [GNU<"no_instrument_function">];
let Subjects = [Function];
}
def NoThrow : InheritableAttr {
- let Spellings = ["nothrow"];
+ let Spellings = [GNU<"nothrow">];
}
def NSBridged : InheritableAttr {
- let Spellings = ["ns_bridged"];
+ let Spellings = [GNU<"ns_bridged">];
let Subjects = [Record];
let Args = [IdentifierArgument<"BridgedType">];
}
def NSReturnsRetained : InheritableAttr {
- let Spellings = ["ns_returns_retained"];
+ let Spellings = [GNU<"ns_returns_retained">];
let Subjects = [ObjCMethod, Function];
}
def NSReturnsNotRetained : InheritableAttr {
- let Spellings = ["ns_returns_not_retained"];
+ let Spellings = [GNU<"ns_returns_not_retained">];
let Subjects = [ObjCMethod, Function];
}
def NSReturnsAutoreleased : InheritableAttr {
- let Spellings = ["ns_returns_autoreleased"];
+ let Spellings = [GNU<"ns_returns_autoreleased">];
let Subjects = [ObjCMethod, Function];
}
def NSConsumesSelf : InheritableAttr {
- let Spellings = ["ns_consumes_self"];
+ let Spellings = [GNU<"ns_consumes_self">];
let Subjects = [ObjCMethod];
}
def NSConsumed : InheritableParamAttr {
- let Spellings = ["ns_consumed"];
+ let Spellings = [GNU<"ns_consumed">];
let Subjects = [ParmVar];
}
def ObjCException : InheritableAttr {
- let Spellings = ["objc_exception"];
+ let Spellings = [GNU<"objc_exception">];
}
def ObjCMethodFamily : InheritableAttr {
- let Spellings = ["objc_method_family"];
+ let Spellings = [GNU<"objc_method_family">];
let Subjects = [ObjCMethod];
let Args = [EnumArgument<"Family", "FamilyKind",
["none", "alloc", "copy", "init", "mutableCopy", "new"],
@@ -439,26 +515,26 @@ def ObjCMethodFamily : InheritableAttr {
}
def ObjCNSObject : InheritableAttr {
- let Spellings = ["NSObject"];
+ let Spellings = [GNU<"NSObject">];
}
def ObjCPreciseLifetime : Attr {
- let Spellings = ["objc_precise_lifetime"];
+ let Spellings = [GNU<"objc_precise_lifetime">];
let Subjects = [Var];
}
def ObjCReturnsInnerPointer : Attr {
- let Spellings = ["objc_returns_inner_pointer"];
+ let Spellings = [GNU<"objc_returns_inner_pointer">];
let Subjects = [ObjCMethod];
}
def ObjCRootClass : Attr {
- let Spellings = ["objc_root_class"];
+ let Spellings = [GNU<"objc_root_class">];
let Subjects = [ObjCInterface];
}
def Overloadable : Attr {
- let Spellings = ["overloadable"];
+ let Spellings = [GNU<"overloadable">];
}
def Override : InheritableAttr {
@@ -467,7 +543,9 @@ def Override : InheritableAttr {
}
def Ownership : InheritableAttr {
- let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"];
+ let Spellings = [GNU<"ownership_holds">, GNU<"ownership_returns">,
+ GNU<"ownership_takes">];
+ let DistinctSpellings = 1;
let Args = [EnumArgument<"OwnKind", "OwnershipKind",
["ownership_holds", "ownership_returns", "ownership_takes"],
["Holds", "Returns", "Takes"]>,
@@ -475,118 +553,151 @@ def Ownership : InheritableAttr {
}
def Packed : InheritableAttr {
- let Spellings = ["packed"];
+ let Spellings = [GNU<"packed">];
}
def Pcs : InheritableAttr {
- let Spellings = ["pcs"];
+ let Spellings = [GNU<"pcs">];
let Args = [EnumArgument<"PCS", "PCSType",
["aapcs", "aapcs-vfp"],
["AAPCS", "AAPCS_VFP"]>];
}
def Pure : InheritableAttr {
- let Spellings = ["pure"];
+ let Spellings = [GNU<"pure">];
}
def Regparm : InheritableAttr {
- let Spellings = ["regparm"];
+ let Spellings = [GNU<"regparm">];
let Args = [UnsignedArgument<"NumParams">];
}
def ReqdWorkGroupSize : InheritableAttr {
- let Spellings = ["reqd_work_group_size"];
+ let Spellings = [GNU<"reqd_work_group_size">];
let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
UnsignedArgument<"ZDim">];
}
+def WorkGroupSizeHint : InheritableAttr {
+ let Spellings = [GNU<"work_group_size_hint">];
+ let Args = [UnsignedArgument<"XDim">,
+ UnsignedArgument<"YDim">,
+ UnsignedArgument<"ZDim">];
+}
+
def InitPriority : InheritableAttr {
- let Spellings = ["init_priority"];
+ let Spellings = [GNU<"init_priority">];
let Args = [UnsignedArgument<"Priority">];
}
def Section : InheritableAttr {
- let Spellings = ["section"];
+ let Spellings = [GNU<"section">];
let Args = [StringArgument<"Name">];
}
def Sentinel : InheritableAttr {
- let Spellings = ["sentinel"];
+ let Spellings = [GNU<"sentinel">];
let Args = [DefaultIntArgument<"Sentinel", 0>,
DefaultIntArgument<"NullPos", 0>];
}
def StdCall : InheritableAttr {
- let Spellings = ["stdcall", "__stdcall"];
+ let Spellings = [GNU<"stdcall">, GNU<"__stdcall">];
}
def ThisCall : InheritableAttr {
- let Spellings = ["thiscall", "__thiscall"];
+ let Spellings = [GNU<"thiscall">, GNU<"__thiscall">];
}
def Pascal : InheritableAttr {
- let Spellings = ["pascal", "__pascal"];
+ let Spellings = [GNU<"pascal">];
}
def TransparentUnion : InheritableAttr {
- let Spellings = ["transparent_union"];
+ let Spellings = [GNU<"transparent_union">];
}
def Unavailable : InheritableAttr {
- let Spellings = ["unavailable"];
+ let Spellings = [GNU<"unavailable">];
let Args = [StringArgument<"Message">];
}
def ArcWeakrefUnavailable : InheritableAttr {
- let Spellings = ["objc_arc_weak_reference_unavailable"];
+ let Spellings = [GNU<"objc_arc_weak_reference_unavailable">];
let Subjects = [ObjCInterface];
}
+def ObjCGC : Attr {
+ let Spellings = [GNU<"objc_gc">];
+ let Args = [IdentifierArgument<"Kind">];
+ let ASTNode = 0;
+}
+
+def ObjCOwnership : Attr {
+ let Spellings = [GNU<"objc_ownership">];
+ let Args = [IdentifierArgument<"Kind">];
+ let ASTNode = 0;
+}
+
def ObjCRequiresPropertyDefs : InheritableAttr {
- let Spellings = ["objc_requires_property_definitions"];
+ let Spellings = [GNU<"objc_requires_property_definitions">];
let Subjects = [ObjCInterface];
}
def Unused : InheritableAttr {
- let Spellings = ["unused"];
+ let Spellings = [GNU<"unused">];
}
def Used : InheritableAttr {
- let Spellings = ["used"];
+ let Spellings = [GNU<"used">];
}
def Uuid : InheritableAttr {
- let Spellings = ["uuid"];
+ let Spellings = [GNU<"uuid">];
let Args = [StringArgument<"Guid">];
let Subjects = [CXXRecord];
}
+def VectorSize : Attr {
+ let Spellings = [GNU<"vector_size">];
+ let Args = [ExprArgument<"NumBytes">];
+ let ASTNode = 0;
+}
+
+def VecTypeHint : Attr {
+ let Spellings = [GNU<"vec_type_hint">];
+ let ASTNode = 0;
+ let SemaHandler = 0;
+ let Ignored = 1;
+}
+
def Visibility : InheritableAttr {
- let Spellings = ["visibility"];
+ let Clone = 0;
+ let Spellings = [GNU<"visibility">];
let Args = [EnumArgument<"Visibility", "VisibilityType",
["default", "hidden", "internal", "protected"],
["Default", "Hidden", "Hidden", "Protected"]>];
}
def VecReturn : InheritableAttr {
- let Spellings = ["vecreturn"];
+ let Spellings = [GNU<"vecreturn">];
let Subjects = [CXXRecord];
}
def WarnUnusedResult : InheritableAttr {
- let Spellings = ["warn_unused_result"];
+ let Spellings = [GNU<"warn_unused_result">];
}
def Weak : InheritableAttr {
- let Spellings = ["weak"];
+ let Spellings = [GNU<"weak">];
}
def WeakImport : InheritableAttr {
- let Spellings = ["weak_import"];
+ let Spellings = [GNU<"weak_import">];
}
def WeakRef : InheritableAttr {
- let Spellings = ["weakref"];
+ let Spellings = [GNU<"weakref">];
}
def X86ForceAlignArgPointer : InheritableAttr {
@@ -595,68 +706,68 @@ def X86ForceAlignArgPointer : InheritableAttr {
// AddressSafety attribute (e.g. for AddressSanitizer)
def NoAddressSafetyAnalysis : InheritableAttr {
- let Spellings = ["no_address_safety_analysis"];
+ let Spellings = [GNU<"no_address_safety_analysis">];
}
// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
def GuardedVar : InheritableAttr {
- let Spellings = ["guarded_var"];
+ let Spellings = [GNU<"guarded_var">];
}
def PtGuardedVar : InheritableAttr {
- let Spellings = ["pt_guarded_var"];
+ let Spellings = [GNU<"pt_guarded_var">];
}
def Lockable : InheritableAttr {
- let Spellings = ["lockable"];
+ let Spellings = [GNU<"lockable">];
}
def ScopedLockable : InheritableAttr {
- let Spellings = ["scoped_lockable"];
+ let Spellings = [GNU<"scoped_lockable">];
}
def NoThreadSafetyAnalysis : InheritableAttr {
- let Spellings = ["no_thread_safety_analysis"];
+ let Spellings = [GNU<"no_thread_safety_analysis">];
}
def GuardedBy : InheritableAttr {
- let Spellings = ["guarded_by"];
+ let Spellings = [GNU<"guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def PtGuardedBy : InheritableAttr {
- let Spellings = ["pt_guarded_by"];
+ let Spellings = [GNU<"pt_guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def AcquiredAfter : InheritableAttr {
- let Spellings = ["acquired_after"];
+ let Spellings = [GNU<"acquired_after">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def AcquiredBefore : InheritableAttr {
- let Spellings = ["acquired_before"];
+ let Spellings = [GNU<"acquired_before">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def ExclusiveLockFunction : InheritableAttr {
- let Spellings = ["exclusive_lock_function"];
+ let Spellings = [GNU<"exclusive_lock_function">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def SharedLockFunction : InheritableAttr {
- let Spellings = ["shared_lock_function"];
+ let Spellings = [GNU<"shared_lock_function">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
@@ -665,7 +776,7 @@ def SharedLockFunction : InheritableAttr {
// The first argument is an integer or boolean value specifying the return value
// of a successful lock acquisition.
def ExclusiveTrylockFunction : InheritableAttr {
- let Spellings = ["exclusive_trylock_function"];
+ let Spellings = [GNU<"exclusive_trylock_function">];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
@@ -674,43 +785,85 @@ def ExclusiveTrylockFunction : InheritableAttr {
// The first argument is an integer or boolean value specifying the return value
// of a successful lock acquisition.
def SharedTrylockFunction : InheritableAttr {
- let Spellings = ["shared_trylock_function"];
+ let Spellings = [GNU<"shared_trylock_function">];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def UnlockFunction : InheritableAttr {
- let Spellings = ["unlock_function"];
+ let Spellings = [GNU<"unlock_function">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def LockReturned : InheritableAttr {
- let Spellings = ["lock_returned"];
+ let Spellings = [GNU<"lock_returned">];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def LocksExcluded : InheritableAttr {
- let Spellings = ["locks_excluded"];
+ let Spellings = [GNU<"locks_excluded">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def ExclusiveLocksRequired : InheritableAttr {
- let Spellings = ["exclusive_locks_required"];
+ let Spellings = [GNU<"exclusive_locks_required">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
}
def SharedLocksRequired : InheritableAttr {
- let Spellings = ["shared_locks_required"];
+ let Spellings = [GNU<"shared_locks_required">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
}
+
+// Microsoft-related attributes
+
+def MsStruct : InheritableAttr {
+ let Spellings = [Declspec<"ms_struct">];
+}
+
+def DLLExport : InheritableAttr {
+ let Spellings = [Declspec<"dllexport">];
+}
+
+def DLLImport : InheritableAttr {
+ let Spellings = [Declspec<"dllimport">];
+}
+
+def ForceInline : InheritableAttr {
+ let Spellings = [Declspec<"__forceinline">];
+}
+
+def Win64 : InheritableAttr {
+ let Spellings = [Declspec<"w64">];
+}
+
+def Ptr32 : InheritableAttr {
+ let Spellings = [Declspec<"__ptr32">];
+}
+
+def Ptr64 : InheritableAttr {
+ let Spellings = [Declspec<"__ptr64">];
+}
+
+def SingleInheritance : InheritableAttr {
+ let Spellings = [Declspec<"__single_inheritance">];
+}
+
+def MultipleInheritance : InheritableAttr {
+ let Spellings = [Declspec<"__multiple_inheritance">];
+}
+
+def VirtualInheritance : InheritableAttr {
+ let Spellings = [Declspec<"__virtual_inheritance">];
+}
diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h
index 9d5ae588c50f..150a30e73d3f 100644
--- a/include/clang/Basic/AttrKinds.h
+++ b/include/clang/Basic/AttrKinds.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the attr::Kind enum
-//
+///
+/// \file
+/// \brief Defines the clang::attr::Kind enum.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ATTRKINDS_H
@@ -18,7 +19,7 @@ namespace clang {
namespace attr {
-// Kind - This is a list of all the recognized kinds of attributes.
+// \brief A list of all the recognized kinds of attributes.
enum Kind {
#define ATTR(X) X,
#define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X,
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index d1af218c27be..1b060a509232 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -33,7 +33,8 @@
// H -> SEL
// a -> __builtin_va_list
// A -> "reference" to __builtin_va_list
-// V -> Vector, following num elements and a base type.
+// V -> Vector, followed by the number of elements and the base type.
+// E -> ext_vector, followed by the number of elements and the base type.
// X -> _Complex, followed by the base type.
// Y -> ptrdiff_t
// P -> FILE
@@ -475,6 +476,7 @@ BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
BUILTIN(__builtin_expect, "LiLiLi" , "nc")
BUILTIN(__builtin_prefetch, "vvC*.", "nc")
+BUILTIN(__builtin_readcyclecounter, "ULLi", "n")
BUILTIN(__builtin_trap, "v", "nr")
BUILTIN(__builtin_unreachable, "v", "nr")
BUILTIN(__builtin_shufflevector, "v." , "nc")
@@ -725,6 +727,10 @@ LIBBUILTIN(strndup, "c*cC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(index, "c*cC*i", "f", "strings.h", ALL_LANGUAGES)
LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_LANGUAGES)
LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_LANGUAGES)
+// In some systems str[n]casejmp is a macro that expands to _str[n]icmp.
+// We undefine then here to avoid wrong name.
+#undef strcasecmp
+#undef strncasecmp
LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_LANGUAGES)
LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_LANGUAGES)
// POSIX unistd.h
@@ -804,33 +810,85 @@ LIBBUILTIN(NSLog, "vG.", "fp:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG)
LIBBUILTIN(NSLogv, "vGa", "fP:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG)
// Builtin math library functions
-LIBBUILTIN(pow, "ddd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(powl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(powf, "fff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acos, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acosl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acosf, "ff", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(sqrt, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(sqrtf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asin, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinf, "ff", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(sin, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(sinl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(sinf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atan, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(atan2, "ddd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atan2l, "LdLdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atan2f, "fff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ceil, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ceill, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ceilf, "ff", "fe", "math.h", ALL_LANGUAGES)
LIBBUILTIN(cos, "dd", "fe", "math.h", ALL_LANGUAGES)
LIBBUILTIN(cosl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
LIBBUILTIN(cosf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(exp, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fabs, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fabsl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fabsf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(floor, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(floorl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(floorf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
LIBBUILTIN(fma, "dddd", "fc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(fmal, "LdLdLdLd", "fc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(fmaf, "ffff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmax, "ddd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmaxl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmaxf, "fff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fmin, "ddd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fminl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fminf, "fff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(log, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(pow, "ddd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(powl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(powf, "fff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(round, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(roundl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(roundf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(sin, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(sqrt, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(tan, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
// Blocks runtime Builtin math library functions
LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES)
LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
// Annotation function
-BUILTIN(__builtin_annotation, "UiUicC*", "nc")
+BUILTIN(__builtin_annotation, "v.", "tn")
#undef BUILTIN
#undef LIBBUILTIN
diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index 5afa02010040..257daf10ecee 100644
--- a/include/clang/Basic/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines enum values for all the target-independent builtin
-// functions.
-//
+///
+/// \file
+/// \brief Defines enum values for all the target-independent builtin
+/// functions.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_BUILTINS_H
@@ -56,7 +57,7 @@ struct Info {
bool operator!=(const Info &RHS) const { return !(*this == RHS); }
};
-/// Builtin::Context - This holds information about target-independent and
+/// \brief Holds information about both target-independent and
/// target-specific builtins, allowing easy queries by clients.
class Context {
const Info *TSRecords;
@@ -67,7 +68,7 @@ public:
/// \brief Perform target-specific initialization
void InitializeTarget(const TargetInfo &Target);
- /// InitializeBuiltins - Mark the identifiers for all the builtins with their
+ /// \brief Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void InitializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
@@ -76,39 +77,39 @@ public:
void GetBuiltinNames(SmallVectorImpl<const char *> &Names,
bool NoBuiltins);
- /// Builtin::GetName - Return the identifier name for the specified builtin,
+ /// \brief Return the identifier name for the specified builtin,
/// e.g. "__builtin_abs".
const char *GetName(unsigned ID) const {
return GetRecord(ID).Name;
}
- /// GetTypeString - Get the type descriptor string for the specified builtin.
+ /// \brief Get the type descriptor string for the specified builtin.
const char *GetTypeString(unsigned ID) const {
return GetRecord(ID).Type;
}
- /// isConst - Return true if this function has no side effects and doesn't
+ /// \brief Return true if this function has no side effects and doesn't
/// read memory.
bool isConst(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'c') != 0;
}
- /// isNoThrow - Return true if we know this builtin never throws an exception.
+ /// \brief Return true if we know this builtin never throws an exception.
bool isNoThrow(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'n') != 0;
}
- /// isNoReturn - Return true if we know this builtin never returns.
+ /// \brief Return true if we know this builtin never returns.
bool isNoReturn(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'r') != 0;
}
- /// isReturnsTwice - Return true if we know this builtin can return twice.
+ /// \brief Return true if we know this builtin can return twice.
bool isReturnsTwice(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'j') != 0;
}
- /// isLibFunction - Return true if this is a builtin for a libc/libm function,
+ /// \brief Return true if this is a builtin for a libc/libm function,
/// with a "__builtin_" prefix (e.g. __builtin_abs).
bool isLibFunction(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'F') != 0;
@@ -146,10 +147,10 @@ public:
/// argument and whether this function as a va_list argument.
bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
- /// isConstWithoutErrno - Return true if this function has no side
- /// effects and doesn't read memory, except for possibly errno. Such
- /// functions can be const when the MathErrno lang option is
- /// disabled.
+ /// \brief Return true if this function has no side effects and doesn't
+ /// read memory, except for possibly errno.
+ ///
+ /// Such functions can be const when the MathErrno lang option is disabled.
bool isConstWithoutErrno(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'e') != 0;
}
diff --git a/include/clang/Basic/BuiltinsHexagon.def b/include/clang/Basic/BuiltinsHexagon.def
index 334224f7ca57..c071a464b0ac 100644
--- a/include/clang/Basic/BuiltinsHexagon.def
+++ b/include/clang/Basic/BuiltinsHexagon.def
@@ -1,4 +1,4 @@
-//==--- BuiltinsHexagon.def - Hexagon Builtin function database --*- C++ -*-==//
+//===-- BuiltinsHexagon.def - Hexagon Builtin function database --*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -7,683 +7,872 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the X86-specific builtin function database. Users of
+// This file defines the Hexagon-specific builtin function database. Users of
// this file must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//
-BUILTIN(__builtin_HEXAGON_C2_cmpeq, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpgt, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpgtu, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpeqp, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpgtp, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpgtup, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_C2_bitsset, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_bitsclr, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpeqi, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpgti, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpgtui, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpgei, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpgeui, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmplt, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_cmpltu, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_bitsclri, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_and, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_or, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_xor, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_andn, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_not, "bi", "")
-BUILTIN(__builtin_HEXAGON_C2_orn, "bii", "")
-BUILTIN(__builtin_HEXAGON_C2_pxfer_map, "bi", "")
-BUILTIN(__builtin_HEXAGON_C2_any8, "bi", "")
-BUILTIN(__builtin_HEXAGON_C2_all8, "bi", "")
-BUILTIN(__builtin_HEXAGON_C2_vitpack, "iii", "")
-BUILTIN(__builtin_HEXAGON_C2_mux, "iiii", "")
-BUILTIN(__builtin_HEXAGON_C2_muxii, "iiii", "")
-BUILTIN(__builtin_HEXAGON_C2_muxir, "iiii", "")
-BUILTIN(__builtin_HEXAGON_C2_muxri, "iiii", "")
-BUILTIN(__builtin_HEXAGON_C2_vmux, "LLiiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_C2_mask, "LLii", "")
-BUILTIN(__builtin_HEXAGON_A2_vcmpbeq, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vcmpbgtu, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vcmpheq, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vcmphgt, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vcmphgtu, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vcmpweq, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vcmpwgt, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vcmpwgtu, "bLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_C2_tfrpr, "ii", "")
-BUILTIN(__builtin_HEXAGON_C2_tfrrp, "bi", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s0, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s1, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s0, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s1, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s0, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s1, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s0, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s1, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s0, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s1, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s0, "ULLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s1, "ULLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s0, "ULLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s1, "ULLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s0, "ULLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s1, "ULLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s0, "ULLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s1, "ULLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpysmi, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_macsip, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_macsin, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyss_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyss_acc_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyss_nac_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_s0, "ULLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_acc_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_nac_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpy_up, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_up, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyss_rnd_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyi, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mpyui, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_maci, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_acci, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_accii, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_nacci, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_naccii, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_subacc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_vmac2s_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_vmac2s_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0pack, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1pack, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_vmac2, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vmac2es_s0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vmac2es_s1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vmac2es, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vrmac_s0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vrmpy_s0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s0, "iLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s1, "iLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vdmacs_s0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vdmacs_s1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vdmpys_s0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vdmpys_s1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s0, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmacs_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmacs_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmacsc_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmacsc_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpys_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpys_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpysc_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpysc_s1, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cnacs_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cnacs_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cnacsc_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cnacsc_s1, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpys_acc_s1, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1rp, "iLLii", "")
-BUILTIN(__builtin_HEXAGON_M2_mmacls_s0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmacls_s1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmachs_s0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmachs_s1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyl_s0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyl_s1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyh_s0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyh_s1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmacls_rs0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmacls_rs1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmachs_rs0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmachs_rs1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_hmmpyl_rs1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_hmmpyh_rs1, "iii", "")
-BUILTIN(__builtin_HEXAGON_M2_mmaculs_s0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmaculs_s1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyul_s0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyul_s1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs1, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs1, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0c, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0c, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_cmaci_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmacr_s0, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0c, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0c, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpyi_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_cmpyr_s0, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_i, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_r, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_i, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_r, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_i, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_r, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vcrotate, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_A2_add, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_sub, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addsat, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subsat, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addi, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_l16_ll, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_l16_hl, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_ll, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_hl, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_l16_ll, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_l16_hl, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_ll, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_hl, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_ll, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_lh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_hl, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_hh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_ll, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_lh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hl, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_ll, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_lh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_hl, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_hh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_ll, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_lh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hl, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_aslh, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_asrh, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_addp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_addpsat, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_addsp, "LLiiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_subp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_neg, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_negsat, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_abs, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_abssat, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_vconj, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_negp, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_absp, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_max, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_maxu, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_A2_min, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_minu, "Uiii", "")
-BUILTIN(__builtin_HEXAGON_A2_maxp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_maxup, "ULLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_minp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_minup, "ULLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_tfr, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_tfrsi, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_tfrp, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_tfrpi, "LLii", "")
-BUILTIN(__builtin_HEXAGON_A2_zxtb, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_sxtb, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_zxth, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_sxth, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_combinew, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_A2_combineii, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_A2_combine_hh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_combine_hl, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_combine_lh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_combine_ll, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_tfril, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_tfrih, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_and, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_or, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_xor, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_not, "ii", "")
-BUILTIN(__builtin_HEXAGON_M2_xor_xacc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_A2_subri, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_andir, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_orir, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_andp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_orp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_xorp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_notp, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_sxtw, "LLii", "")
-BUILTIN(__builtin_HEXAGON_A2_sat, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_sath, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_satuh, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_satub, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_satb, "ii", "")
-BUILTIN(__builtin_HEXAGON_A2_vaddub, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vaddubs, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vaddh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vaddhs, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vadduhs, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vaddw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vaddws, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_svavgh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_svavghs, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_svnavgh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_svaddh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_svaddhs, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_svadduhs, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_svsubh, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_svsubhs, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_svsubuhs, "iii", "")
-BUILTIN(__builtin_HEXAGON_A2_vraddub, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vraddub_acc, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vradduh, "iLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vsubub, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vsububs, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vsubh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vsubhs, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vsubuhs, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vsubw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vsubws, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vabsh, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vabshsat, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vabsw, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vabswsat, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vabsdiffw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_M2_vabsdiffh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vrsadub, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vrsadub_acc, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavgub, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavguh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavgh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vnavgh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavgw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vnavgw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavgwr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vnavgwr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavgwcr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vnavgwcr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavghcr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vnavghcr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavguw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavguwr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavgubr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavguhr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vavghr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vnavghr, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vminh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vmaxh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vminub, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vmaxub, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vminuh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vmaxuh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vminw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vmaxw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vminuw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A2_vmaxuw, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_p, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r_acc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_acc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_acc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_acc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p_acc, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p_acc, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_acc, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_acc, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r_nac, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_nac, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_nac, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_nac, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p_nac, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p_nac, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_nac, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_nac, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p_and, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p_and, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_and, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_and, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p_or, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p_or, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_or, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_or, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r_sat, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_sat, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_acc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_acc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_acc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_acc, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_acc, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_acc, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_nac, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_nac, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_nac, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_nac, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_nac, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_nac, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_xacc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_xacc, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_xacc, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_xacc, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_and, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_and, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_and, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_or, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_or, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_or, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_sat, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_addasl_rrri, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_valignib, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_valignrb, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_vspliceib, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_vsplicerb, "LLiLLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_vsplatrh, "LLii", "")
-BUILTIN(__builtin_HEXAGON_S2_vsplatrb, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_insert, "iiiii", "")
-BUILTIN(__builtin_HEXAGON_S2_tableidxb_goodsyntax, "iiiii", "")
-BUILTIN(__builtin_HEXAGON_S2_tableidxh_goodsyntax, "iiiii", "")
-BUILTIN(__builtin_HEXAGON_S2_tableidxw_goodsyntax, "iiiii", "")
-BUILTIN(__builtin_HEXAGON_S2_tableidxd_goodsyntax, "iiiii", "")
-BUILTIN(__builtin_HEXAGON_S2_extractu, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S2_insertp, "LLiLLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_S2_extractup, "LLiLLiii", "")
-BUILTIN(__builtin_HEXAGON_S2_insert_rp, "iiiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_extractu_rp, "iiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_insertp_rp, "LLiLLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_extractup_rp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_tstbit_i, "bii", "")
-BUILTIN(__builtin_HEXAGON_S2_setbit_i, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_togglebit_i, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_clrbit_i, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_tstbit_r, "bii", "")
-BUILTIN(__builtin_HEXAGON_S2_setbit_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_togglebit_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_clrbit_r, "iii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_vh, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_vh, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_vh, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_vh, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_vh, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_vh, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_vh, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_vw, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_svw_trun, "iLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_svw_trun, "iLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_vw, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_vw, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_vw, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_vw, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_vw, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_vw, "LLiLLii", "")
-BUILTIN(__builtin_HEXAGON_S2_vrndpackwh, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vrndpackwhs, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vsxtbh, "LLii", "")
-BUILTIN(__builtin_HEXAGON_S2_vzxtbh, "LLii", "")
-BUILTIN(__builtin_HEXAGON_S2_vsathub, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_svsathub, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_svsathb, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_vsathb, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vtrunohb, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vtrunewh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vtrunowh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vtrunehb, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vsxthw, "LLii", "")
-BUILTIN(__builtin_HEXAGON_S2_vzxthw, "LLii", "")
-BUILTIN(__builtin_HEXAGON_S2_vsatwh, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vsatwuh, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_packhl, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_A2_swiz, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_vsathub_nopack, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vsathb_nopack, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vsatwh_nopack, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_vsatwuh_nopack, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_shuffob, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_shuffeb, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_shuffoh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_shuffeh, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_parityp, "iLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_lfsp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_clbnorm, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_clb, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_cl0, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_cl1, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_clbp, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_cl0p, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_cl1p, "iLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_brev, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_ct0, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_ct1, "ii", "")
-BUILTIN(__builtin_HEXAGON_S2_interleave, "LLiLLi", "")
-BUILTIN(__builtin_HEXAGON_S2_deinterleave, "LLiLLi", "")
+// The format of this database matches clang/Basic/Builtins.def.
-BUILTIN(__builtin_SI_to_SXTHI_asrh, "ii", "")
-
-BUILTIN(__builtin_M2_vrcmpys_s1, "LLiLLii", "")
-BUILTIN(__builtin_M2_vrcmpys_acc_s1, "LLiLLiLLii", "")
-BUILTIN(__builtin_M2_vrcmpys_s1rp, "iLLii", "")
-
-BUILTIN(__builtin_M2_vradduh, "iLLiLLi", "")
-BUILTIN(__builtin_A2_addsp, "LLiiLLi", "")
-BUILTIN(__builtin_A2_addpsat, "LLiLLiLLi", "")
+// The builtins below are not autogenerated from iset.py.
+// Make sure you do not overwrite these.
-BUILTIN(__builtin_A2_maxp, "LLiLLiLLi", "")
-BUILTIN(__builtin_A2_maxup, "LLiLLiLLi", "")
-
-BUILTIN(__builtin_HEXAGON_A4_orn, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_andn, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_ornp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A4_andnp, "LLiLLiLLi", "")
-BUILTIN(__builtin_HEXAGON_A4_combineir, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_A4_combineri, "LLiii", "")
-BUILTIN(__builtin_HEXAGON_C4_cmpneqi, "bii", "")
-BUILTIN(__builtin_HEXAGON_C4_cmpneq, "bii", "")
-BUILTIN(__builtin_HEXAGON_C4_cmpltei, "bii", "")
-BUILTIN(__builtin_HEXAGON_C4_cmplte, "bii", "")
-BUILTIN(__builtin_HEXAGON_C4_cmplteui, "bii", "")
-BUILTIN(__builtin_HEXAGON_C4_cmplteu, "bii", "")
-BUILTIN(__builtin_HEXAGON_A4_rcmpneq, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_rcmpneqi, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_rcmpeq, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_rcmpeqi, "iii", "")
-BUILTIN(__builtin_HEXAGON_C4_fastcorner9, "bii", "")
-BUILTIN(__builtin_HEXAGON_C4_fastcorner9_not, "bii", "")
-BUILTIN(__builtin_HEXAGON_C4_and_andn, "biii", "")
-BUILTIN(__builtin_HEXAGON_C4_and_and, "biii", "")
-BUILTIN(__builtin_HEXAGON_C4_and_orn, "biii", "")
-BUILTIN(__builtin_HEXAGON_C4_and_or, "biii", "")
-BUILTIN(__builtin_HEXAGON_C4_or_andn, "biii", "")
-BUILTIN(__builtin_HEXAGON_C4_or_and, "biii", "")
-BUILTIN(__builtin_HEXAGON_C4_or_orn, "biii", "")
-BUILTIN(__builtin_HEXAGON_C4_or_or, "biii", "")
-BUILTIN(__builtin_HEXAGON_S4_addaddi, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S4_subaddi, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_xor_xacc, "LLiLLiLLiLLi", "")
-
-BUILTIN(__builtin_HEXAGON_M4_and_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_and_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_and_xor, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_and_andn, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_xor_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_xor_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_xor_andn, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_or_and, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_or_or, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_or_xor, "iiii", "")
-BUILTIN(__builtin_HEXAGON_M4_or_andn, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S4_or_andix, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S4_or_andi, "iiii", "")
-BUILTIN(__builtin_HEXAGON_S4_or_ori, "iiii", "")
+BUILTIN(__builtin_SI_to_SXTHI_asrh, "ii", "")
+BUILTIN(__builtin_circ_ldd, "LLi*LLi*LLi*ii", "")
-BUILTIN(__builtin_HEXAGON_A4_modwrapu, "iii", "")
+// The builtins above are not autogenerated from iset.py.
+// Make sure you do not overwrite these.
-BUILTIN(__builtin_HEXAGON_A4_cround_ri, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_cround_rr, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_round_ri, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_round_rr, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_round_ri_sat, "iii", "")
-BUILTIN(__builtin_HEXAGON_A4_round_rr_sat, "iii", "")
+BUILTIN(__builtin_HEXAGON_C2_cmpeq,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgt,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtu,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpeqp,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtp,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtup,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpeqi,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpneqi,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpeq,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpneq,"iii","")
+BUILTIN(__builtin_HEXAGON_C2_bitsset,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_bitsclr,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_nbitsset,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_nbitsclr,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpeqi,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgti,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtui,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgei,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgeui,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmplt,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpltu,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_bitsclri,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_nbitsclri,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmpneqi,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmpltei,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmplteui,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmpneq,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmplte,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmplteu,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_and,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_or,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_xor,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_andn,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_not,"bi","")
+BUILTIN(__builtin_HEXAGON_C2_orn,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_and_and,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_and_or,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_or_and,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_or_or,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_and_andn,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_and_orn,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_or_andn,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_or_orn,"biii","")
+BUILTIN(__builtin_HEXAGON_C2_pxfer_map,"bi","")
+BUILTIN(__builtin_HEXAGON_C2_any8,"bi","")
+BUILTIN(__builtin_HEXAGON_C2_all8,"bi","")
+BUILTIN(__builtin_HEXAGON_C2_vitpack,"iii","")
+BUILTIN(__builtin_HEXAGON_C2_mux,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_muxii,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_muxir,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_muxri,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_vmux,"LLiiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_mask,"LLii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpbeq,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbeqi,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbeq_any,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpbgtu,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbgtui,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbgt,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbgti,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbeq,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbeqi,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgtu,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgtui,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgt,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgti,"bii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpheq,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmphgt,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmphgtu,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpheqi,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmphgti,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmphgtui,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpheq,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgt,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgtu,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpheqi,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgti,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgtui,"bii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpweq,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpwgt,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpwgtu,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpweqi,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpwgti,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpwgtui,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_boundscheck,"biLLi","")
+BUILTIN(__builtin_HEXAGON_A4_tlbmatch,"bLLii","")
+BUILTIN(__builtin_HEXAGON_C2_tfrpr,"ii","")
+BUILTIN(__builtin_HEXAGON_C2_tfrrp,"bi","")
+BUILTIN(__builtin_HEXAGON_C4_fastcorner9,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_fastcorner9_not,"bii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpysmi,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_macsip,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_macsin,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_acc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_nac_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_acc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_nac_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_up,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_up_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_up_s1_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_up,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpysu_up,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_rnd_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M4_mac_up_s1_sat,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_nac_up_s1_sat,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyi,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyui,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_maci,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_acci,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_accii,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_nacci,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_naccii,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_subacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyrr_addr,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyri_addr_u2,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyri_addr,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyri_addi,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyrr_addi,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2s_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2s_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2su_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2su_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0pack,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1pack,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2es_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2es_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2es,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrmac_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrmpy_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s0,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s1,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vrmpybuu,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vrmacbuu,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vrmpybsu,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vrmacbsu,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vmpybuu,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M5_vmpybsu,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M5_vmacbuu,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M5_vmacbsu,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M5_vdmpybsu,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vdmacbsu,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmacs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmacs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmpys_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmpys_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacs_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacs_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacsc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacsc_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpys_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpys_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpysc_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpysc_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacs_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacs_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacsc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacsc_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpys_acc_s1,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1rp,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyl_rs1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyh_rs1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0c,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0c,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_cmaci_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacr_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0c,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0c,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyi_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyr_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyi_wh,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyr_wh,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyi_whc,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyr_whc,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_i,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_r,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_i,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_r,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_i,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_r,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vcrotate,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S4_vrcrotate_acc,"LLiLLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S4_vrcrotate,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_vcnegh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vrcnegh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M4_pmpyw,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M4_vpmpyh,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M4_pmpyw_acc,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M4_vpmpyh_acc,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_A2_add,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_sub,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addsat,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subsat,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addi,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_aslh,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_asrh,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_addp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_addpsat,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_addsp,"LLiiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_subp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_neg,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_negsat,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_abs,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_abssat,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_vconj,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_negp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_absp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_max,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_maxu,"Uiii","")
+BUILTIN(__builtin_HEXAGON_A2_min,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_minu,"Uiii","")
+BUILTIN(__builtin_HEXAGON_A2_maxp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_maxup,"ULLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_minp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_minup,"ULLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_tfr,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_tfrsi,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_tfrp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_tfrpi,"LLii","")
+BUILTIN(__builtin_HEXAGON_A2_zxtb,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_sxtb,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_zxth,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_sxth,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_combinew,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A4_combineri,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A4_combineir,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_combineii,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_combine_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_combine_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_combine_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_combine_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_tfril,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_tfrih,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_and,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_or,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_xor,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_not,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_xor_xacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_xor_xacc,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_andn,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_orn,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_andnp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_ornp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_addaddi,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_subaddi,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_and_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_and_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_and_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_and_xor,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_or_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_or_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_or_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_or_xor,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_or_andix,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_or_andi,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_or_ori,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_xor_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_xor_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_xor_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_subri,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_andir,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_orir,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_andp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_orp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_xorp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_notp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_sxtw,"LLii","")
+BUILTIN(__builtin_HEXAGON_A2_sat,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A2_roundsat,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A2_sath,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_satuh,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_satub,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_satb,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_vaddub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddb_map,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddubs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vadduhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A5_vaddhubs,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddws,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxaddsubw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxsubaddw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxaddsubh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxsubaddh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxaddsubhr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxsubaddhr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_svavgh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svavghs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svnavgh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svaddh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svaddhs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svadduhs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svsubh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svsubhs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svsubuhs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vraddub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vraddub_acc,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vraddh,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vradduh,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubb_map,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsububs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubuhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubws,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabsh,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabshsat,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabsw,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabswsat,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vabsdiffw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vabsdiffh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vrsadub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vrsadub_acc,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgwr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgwr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgwcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgwcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavghcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavghcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguwr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgubr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguhr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavghr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavghr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_round_ri,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_round_rr,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_round_ri_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_round_rr_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_cround_ri,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_cround_rr,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminuh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxuh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminuw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxuw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_vminb,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxb,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminuh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxuh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminuw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxuw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_modwrapu,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_sfadd,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sfsub,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sfmpy,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sffma,"ffff","")
+BUILTIN(__builtin_HEXAGON_F2_sffma_sc,"ffffi","")
+BUILTIN(__builtin_HEXAGON_F2_sffms,"ffff","")
+BUILTIN(__builtin_HEXAGON_F2_sffma_lib,"ffff","")
+BUILTIN(__builtin_HEXAGON_F2_sffms_lib,"ffff","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpeq,"bff","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpgt,"bff","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpge,"bff","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpuo,"bff","")
+BUILTIN(__builtin_HEXAGON_F2_sfmax,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sfmin,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sfclass,"bfi","")
+BUILTIN(__builtin_HEXAGON_F2_sfimm_p,"fi","")
+BUILTIN(__builtin_HEXAGON_F2_sfimm_n,"fi","")
+BUILTIN(__builtin_HEXAGON_F2_sffixupn,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sffixupd,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sffixupr,"ff","")
+BUILTIN(__builtin_HEXAGON_F2_dfadd,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dfsub,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dfmpy,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffma,"dddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffms,"dddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffma_lib,"dddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffms_lib,"dddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffma_sc,"ddddi","")
+BUILTIN(__builtin_HEXAGON_F2_dfmax,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dfmin,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpeq,"bdd","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpgt,"bdd","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpge,"bdd","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpuo,"bdd","")
+BUILTIN(__builtin_HEXAGON_F2_dfclass,"bdi","")
+BUILTIN(__builtin_HEXAGON_F2_dfimm_p,"di","")
+BUILTIN(__builtin_HEXAGON_F2_dfimm_n,"di","")
+BUILTIN(__builtin_HEXAGON_F2_dffixupn,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffixupd,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffixupr,"dd","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2df,"df","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2sf,"fd","")
+BUILTIN(__builtin_HEXAGON_F2_conv_uw2sf,"fi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_uw2df,"di","")
+BUILTIN(__builtin_HEXAGON_F2_conv_w2sf,"fi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_w2df,"di","")
+BUILTIN(__builtin_HEXAGON_F2_conv_ud2sf,"fLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_ud2df,"dLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_d2sf,"fLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_d2df,"dLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2uw,"if","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2w,"if","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2ud,"LLif","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2d,"LLif","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2uw,"id","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2w,"id","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2ud,"LLid","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2d,"LLid","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2uw_chop,"if","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2w_chop,"if","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2ud_chop,"LLif","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2d_chop,"LLif","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2uw_chop,"id","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2w_chop,"id","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2ud_chop,"LLid","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2d_chop,"LLid","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_xacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_xacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_xacc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_xacc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd_goodsyntax,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S4_lsli,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_addasl_rrri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_andi_asl_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_ori_asl_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_addi_asl_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_subi_asl_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_andi_lsr_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_ori_lsr_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_addi_lsr_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_subi_lsr_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_valignib,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_valignrb,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vspliceib,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsplicerb,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsplatrh,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsplatrb,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_insert,"iiiii","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxb_goodsyntax,"iiiii","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxh_goodsyntax,"iiiii","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxw_goodsyntax,"iiiii","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxd_goodsyntax,"iiiii","")
+BUILTIN(__builtin_HEXAGON_A4_bitspliti,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A4_bitsplit,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S4_extract,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_extractu,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_insertp,"LLiLLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S4_extractp,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_extractup,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_insert_rp,"iiiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_extract_rp,"iiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_extractu_rp,"iiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_insertp_rp,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_extractp_rp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_extractup_rp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_tstbit_i,"bii","")
+BUILTIN(__builtin_HEXAGON_S4_ntstbit_i,"bii","")
+BUILTIN(__builtin_HEXAGON_S2_setbit_i,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_togglebit_i,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_clrbit_i,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_tstbit_r,"bii","")
+BUILTIN(__builtin_HEXAGON_S4_ntstbit_r,"bii","")
+BUILTIN(__builtin_HEXAGON_S2_setbit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_togglebit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_clrbit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S5_asrhub_rnd_sat_goodsyntax,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S5_asrhub_sat,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S5_vasrhrnd_goodsyntax,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_svw_trun,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_svw_trun,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vrndpackwh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vrndpackwhs,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsxtbh,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vzxtbh,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsathub,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_svsathub,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_svsathb,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_vsathb,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunohb,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunewh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunowh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunehb,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsxthw,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vzxthw,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwuh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_packhl,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_swiz,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_vsathub_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsathb_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwh_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwuh_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_shuffob,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_shuffeb,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_shuffoh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_shuffeh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S5_popcountp,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S4_parity,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_parityp,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lfsp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_clbnorm,"ii","")
+BUILTIN(__builtin_HEXAGON_S4_clbaddi,"iii","")
+BUILTIN(__builtin_HEXAGON_S4_clbpnorm,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S4_clbpaddi,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S2_clb,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_cl0,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_cl1,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_clbp,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_cl0p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_cl1p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_brev,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_brevp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_ct0,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_ct1,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_ct0p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_ct1p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_interleave,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_deinterleave,"LLiLLi","")
#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsMips.def b/include/clang/Basic/BuiltinsMips.def
new file mode 100644
index 000000000000..d0137155a2d0
--- /dev/null
+++ b/include/clang/Basic/BuiltinsMips.def
@@ -0,0 +1,125 @@
+//===-- BuiltinsMips.def - Mips Builtin function database --------*- 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 MIPS-specific builtin function database. Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+// Add/subtract with optional saturation
+BUILTIN(__builtin_mips_addu_qb, "V4ScV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_addu_s_qb, "V4ScV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_subu_qb, "V4ScV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_subu_s_qb, "V4ScV4ScV4Sc", "n")
+
+BUILTIN(__builtin_mips_addq_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_addq_s_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_subq_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_subq_s_ph, "V2sV2sV2s", "n")
+
+BUILTIN(__builtin_mips_madd, "LLiLLiii", "nc")
+BUILTIN(__builtin_mips_maddu, "LLiLLiUiUi", "nc")
+BUILTIN(__builtin_mips_msub, "LLiLLiii", "nc")
+BUILTIN(__builtin_mips_msubu, "LLiLLiUiUi", "nc")
+
+BUILTIN(__builtin_mips_addq_s_w, "iii", "n")
+BUILTIN(__builtin_mips_subq_s_w, "iii", "n")
+
+BUILTIN(__builtin_mips_addsc, "iii", "n")
+BUILTIN(__builtin_mips_addwc, "iii", "n")
+
+BUILTIN(__builtin_mips_modsub, "iii", "nc")
+
+BUILTIN(__builtin_mips_raddu_w_qb, "iV4Sc", "nc")
+
+BUILTIN(__builtin_mips_absq_s_ph, "V2sV2s", "n")
+BUILTIN(__builtin_mips_absq_s_w, "ii", "n")
+
+BUILTIN(__builtin_mips_precrq_qb_ph, "V4ScV2sV2s", "nc")
+BUILTIN(__builtin_mips_precrqu_s_qb_ph, "V4ScV2sV2s", "n")
+BUILTIN(__builtin_mips_precrq_ph_w, "V2sii", "nc")
+BUILTIN(__builtin_mips_precrq_rs_ph_w, "V2sii", "n")
+BUILTIN(__builtin_mips_preceq_w_phl, "iV2s", "nc")
+BUILTIN(__builtin_mips_preceq_w_phr, "iV2s", "nc")
+BUILTIN(__builtin_mips_precequ_ph_qbl, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_precequ_ph_qbr, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_precequ_ph_qbla, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_precequ_ph_qbra, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_preceu_ph_qbl, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_preceu_ph_qbr, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_preceu_ph_qbla, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_preceu_ph_qbra, "V2sV4Sc", "nc")
+
+BUILTIN(__builtin_mips_shll_qb, "V4ScV4Sci", "n")
+BUILTIN(__builtin_mips_shrl_qb, "V4ScV4Sci", "nc")
+BUILTIN(__builtin_mips_shll_ph, "V2sV2si", "n")
+BUILTIN(__builtin_mips_shll_s_ph, "V2sV2si", "n")
+BUILTIN(__builtin_mips_shra_ph, "V2sV2si", "nc")
+BUILTIN(__builtin_mips_shra_r_ph, "V2sV2si", "nc")
+BUILTIN(__builtin_mips_shll_s_w, "iii", "n")
+BUILTIN(__builtin_mips_shra_r_w, "iii", "nc")
+BUILTIN(__builtin_mips_shilo, "LLiLLii", "nc")
+
+BUILTIN(__builtin_mips_muleu_s_ph_qbl, "V2sV4ScV2s", "n")
+BUILTIN(__builtin_mips_muleu_s_ph_qbr, "V2sV4ScV2s", "n")
+BUILTIN(__builtin_mips_mulq_rs_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_muleq_s_w_phl, "iV2sV2s", "n")
+BUILTIN(__builtin_mips_muleq_s_w_phr, "iV2sV2s", "n")
+BUILTIN(__builtin_mips_mulsaq_s_w_ph, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_maq_s_w_phl, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_maq_s_w_phr, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_maq_sa_w_phl, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_maq_sa_w_phr, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_mult, "LLiii", "nc")
+BUILTIN(__builtin_mips_multu, "LLiUiUi", "nc")
+
+BUILTIN(__builtin_mips_dpau_h_qbl, "LLiLLiV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_dpau_h_qbr, "LLiLLiV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_dpsu_h_qbl, "LLiLLiV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_dpsu_h_qbr, "LLiLLiV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_dpaq_s_w_ph, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_dpsq_s_w_ph, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_dpaq_sa_l_w, "LLiLLiii", "n")
+BUILTIN(__builtin_mips_dpsq_sa_l_w, "LLiLLiii", "n")
+
+BUILTIN(__builtin_mips_cmpu_eq_qb, "vV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpu_lt_qb, "vV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpu_le_qb, "vV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpgu_eq_qb, "iV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpgu_lt_qb, "iV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpgu_le_qb, "iV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmp_eq_ph, "vV2sV2s", "n")
+BUILTIN(__builtin_mips_cmp_lt_ph, "vV2sV2s", "n")
+BUILTIN(__builtin_mips_cmp_le_ph, "vV2sV2s", "n")
+
+BUILTIN(__builtin_mips_extr_s_h, "iLLii", "n")
+BUILTIN(__builtin_mips_extr_w, "iLLii", "n")
+BUILTIN(__builtin_mips_extr_rs_w, "iLLii", "n")
+BUILTIN(__builtin_mips_extr_r_w, "iLLii", "n")
+BUILTIN(__builtin_mips_extp, "iLLii", "n")
+BUILTIN(__builtin_mips_extpdp, "iLLii", "n")
+
+BUILTIN(__builtin_mips_wrdsp, "viIi", "n")
+BUILTIN(__builtin_mips_rddsp, "iIi", "n")
+BUILTIN(__builtin_mips_insv, "iii", "n")
+BUILTIN(__builtin_mips_bitrev, "ii", "nc")
+BUILTIN(__builtin_mips_packrl_ph, "V2sV2sV2s", "nc")
+BUILTIN(__builtin_mips_repl_qb, "V4Sci", "nc")
+BUILTIN(__builtin_mips_repl_ph, "V2si", "nc")
+BUILTIN(__builtin_mips_pick_qb, "V4ScV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_pick_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_mthlip, "LLiLLii", "n")
+BUILTIN(__builtin_mips_bposge32, "i", "n")
+BUILTIN(__builtin_mips_lbux, "iv*i", "n")
+BUILTIN(__builtin_mips_lhx, "iv*i", "n")
+BUILTIN(__builtin_mips_lwx, "iv*i", "n")
+
+#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsPTX.def b/include/clang/Basic/BuiltinsNVPTX.def
index f90a43f7f404..f90a43f7f404 100644
--- a/include/clang/Basic/BuiltinsPTX.def
+++ b/include/clang/Basic/BuiltinsNVPTX.def
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index 4aea980a9d5c..75e60742148d 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -303,8 +303,6 @@ BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "")
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
-BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
-
BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "")
BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "")
BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "")
@@ -354,23 +352,30 @@ BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "")
BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "")
BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","")
-// FIXME: These builtins are horribly broken; reenable when PR11305 is fixed.
-//BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","")
-//BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","")
-//BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","")
-//BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","")
-//BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","")
-//BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","")
-//BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","")
-//BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciic","")
-//BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","")
-//BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","")
+BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","")
+BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","")
+BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","")
+BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","")
+BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","")
+BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","")
+BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","")
+BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","")
+BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","")
+BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","")
BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "")
BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "")
BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "")
BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "")
+// SSE4a
+BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "")
+BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "")
+BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "")
+BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "")
+BUILTIN(__builtin_ia32_movntss, "vf*V4f", "")
+
// AES
BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "")
@@ -379,6 +384,9 @@ BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "")
+// CLMUL
+BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "")
+
// AVX
BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "")
BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "")
@@ -586,6 +594,30 @@ BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "")
BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "")
+// GATHER
+BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2dV2dC*V4iV2dIc", "")
+BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4dV4dC*V4iV4dIc", "")
+BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2dV2dC*V2LLiV2dIc", "")
+BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4dV4dC*V4LLiV4dIc", "")
+BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4fV4fC*V4iV4fIc", "")
+BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8fV8fC*V8iV8fIc", "")
+BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4fV4fC*V2LLiV4fIc", "")
+BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4fV4fC*V4LLiV4fIc", "")
+
+BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiV2LLiC*V4iV2LLiIc", "")
+BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiV4LLiC*V4iV4LLiIc", "")
+BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiV2LLiC*V2LLiV2LLiIc", "")
+BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiV4LLiC*V4LLiV4LLiIc", "")
+BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iV4iC*V4iV4iIc", "")
+BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iV8iC*V8iV8iIc", "")
+BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iV4iC*V2LLiV4iIc", "")
+BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iV4iC*V4LLiV4iIc", "")
+
+// RDRAND
+BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "")
+BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "")
+BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "")
+
// BMI
BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "")
BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "")
@@ -632,4 +664,71 @@ BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "")
BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "")
BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "")
+// XOP
+BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "")
+BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "")
+BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "")
+BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "")
+BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "")
+BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "")
+BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "")
+BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "")
+BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "")
+BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "")
+BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "")
+BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "")
+
+BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "")
+BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "")
+BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "")
+BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "")
+BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "")
+BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "")
+BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "")
+BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "")
+BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "")
+BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "")
+BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "")
+BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "")
+BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "")
+BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "")
+BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "")
+BUILTIN(__builtin_ia32_vpcmov, "V2LLiV2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_vpcmov_256, "V4LLiV4LLiV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "")
+BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "")
+BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "")
+BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "")
+BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "")
+BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "")
+BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "")
+BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "")
+BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "")
+BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "")
+BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "")
+BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "")
+BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "")
+BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "")
+BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "")
+BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "")
+BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "")
+BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "")
+BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "")
+BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "")
+BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "")
+BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "")
+
#undef BUILTIN
diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt
index 3df88c7c4a5e..274b94da8eda 100644
--- a/include/clang/Basic/CMakeLists.txt
+++ b/include/clang/Basic/CMakeLists.txt
@@ -7,6 +7,7 @@ endmacro(clang_diag_gen)
clang_diag_gen(Analysis)
clang_diag_gen(AST)
+clang_diag_gen(Comment)
clang_diag_gen(Common)
clang_diag_gen(Driver)
clang_diag_gen(Frontend)
diff --git a/include/clang/Basic/CommentNodes.td b/include/clang/Basic/CommentNodes.td
new file mode 100644
index 000000000000..7bf32b78b5b6
--- /dev/null
+++ b/include/clang/Basic/CommentNodes.td
@@ -0,0 +1,27 @@
+class Comment<bit abstract = 0> {
+ bit Abstract = abstract;
+}
+
+class DComment<Comment base, bit abstract = 0> : Comment<abstract> {
+ Comment Base = base;
+}
+
+def InlineContentComment : Comment<1>;
+ def TextComment : DComment<InlineContentComment>;
+ def InlineCommandComment : DComment<InlineContentComment>;
+ def HTMLTagComment : DComment<InlineContentComment, 1>;
+ def HTMLStartTagComment : DComment<HTMLTagComment>;
+ def HTMLEndTagComment : DComment<HTMLTagComment>;
+
+def BlockContentComment : Comment<1>;
+ def ParagraphComment : DComment<BlockContentComment>;
+ def BlockCommandComment : DComment<BlockContentComment>;
+ def ParamCommandComment : DComment<BlockCommandComment>;
+ def TParamCommandComment : DComment<BlockCommandComment>;
+ def VerbatimBlockComment : DComment<BlockCommandComment>;
+ def VerbatimLineComment : DComment<BlockCommandComment>;
+
+def VerbatimBlockLineComment : Comment;
+
+def FullComment : Comment;
+
diff --git a/include/clang/Basic/ConvertUTF.h b/include/clang/Basic/ConvertUTF.h
index 7fb587402712..e7cfa8a7677c 100644
--- a/include/clang/Basic/ConvertUTF.h
+++ b/include/clang/Basic/ConvertUTF.h
@@ -110,6 +110,8 @@ typedef unsigned char Boolean; /* 0 or 1 */
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4
+
typedef enum {
conversionOK, /* conversion successful */
sourceExhausted, /* partial character in source, but hit end */
@@ -139,11 +141,13 @@ ConversionResult ConvertUTF8toUTF32 (
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+#endif
ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+#ifdef CLANG_NEEDS_THESE_ONE_DAY
ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
@@ -159,6 +163,37 @@ Boolean isLegalUTF8String(const UTF8 *source, const UTF8 *sourceEnd);
#ifdef __cplusplus
}
+
+/*************************************************************************/
+/* Below are LLVM-specific wrappers of the functions above. */
+
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+/**
+ * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on
+ * WideCharWidth. The converted data is written to ResultPtr, which needs to
+ * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success,
+ * ResultPtr will point one after the end of the copied string.
+ * \return true on success.
+ */
+bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source,
+ char *&ResultPtr);
+
+/**
+ * Convert an Unicode code point to UTF8 sequence.
+ *
+ * \param Source a Unicode code point.
+ * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least
+ * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is
+ * updated one past end of the converted sequence.
+ *
+ * \returns true on success.
+ */
+bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr);
+
+}
#endif
#endif
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index e1571786dd5c..3997fb89ba82 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Diagnostic-related interfaces.
-//
+///
+/// \file
+/// \brief Defines the Diagnostic-related interfaces.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_DIAGNOSTIC_H
@@ -82,7 +83,7 @@ public:
}
/// \brief Create a code modification hint that inserts the given
- /// code from \arg FromRange at a specific location.
+ /// code from \p FromRange at a specific location.
static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc,
CharSourceRange FromRange,
bool BeforePreviousInsertions = false) {
@@ -121,14 +122,15 @@ public:
}
};
-/// DiagnosticsEngine - This concrete class is used by the front-end to report
-/// problems and issues. It massages the diagnostics (e.g. handling things like
-/// "report warnings as errors" and passes them off to the DiagnosticConsumer
-/// for reporting to the user. DiagnosticsEngine is tied to one translation unit
-/// and one SourceManager.
+/// \brief Concrete class used by the front-end to report problems and issues.
+///
+/// This massages the diagnostics (e.g. handling things like "report warnings
+/// as errors" and passes them off to the DiagnosticConsumer for reporting to
+/// the user. DiagnosticsEngine is tied to one translation unit and one
+/// SourceManager.
class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
public:
- /// Level - The level of the diagnostic, after it has been through mapping.
+ /// \brief The level of the diagnostic, after it has been through mapping.
enum Level {
Ignored = DiagnosticIDs::Ignored,
Note = DiagnosticIDs::Note,
@@ -137,34 +139,36 @@ public:
Fatal = DiagnosticIDs::Fatal
};
- /// ExtensionHandling - How do we handle otherwise-unmapped extension? This
- /// is controlled by -pedantic and -pedantic-errors.
+ /// \brief How do we handle otherwise-unmapped extension?
+ ///
+ /// This is controlled by -pedantic and -pedantic-errors.
enum ExtensionHandling {
Ext_Ignore, Ext_Warn, Ext_Error
};
enum ArgumentKind {
- ak_std_string, // std::string
- ak_c_string, // const char *
- ak_sint, // int
- ak_uint, // unsigned
- ak_identifierinfo, // IdentifierInfo
- ak_qualtype, // QualType
- ak_declarationname, // DeclarationName
- ak_nameddecl, // NamedDecl *
- ak_nestednamespec, // NestedNameSpecifier *
- ak_declcontext // DeclContext *
+ ak_std_string, ///< std::string
+ ak_c_string, ///< const char *
+ ak_sint, ///< int
+ ak_uint, ///< unsigned
+ ak_identifierinfo, ///< IdentifierInfo
+ ak_qualtype, ///< QualType
+ ak_declarationname, ///< DeclarationName
+ ak_nameddecl, ///< NamedDecl *
+ ak_nestednamespec, ///< NestedNameSpecifier *
+ ak_declcontext, ///< DeclContext *
+ ak_qualtype_pair ///< pair<QualType, QualType>
};
- /// Specifies which overload candidates to display when overload resolution
- /// fails.
+ /// \brief Specifies which overload candidates to display when overload
+ /// resolution fails.
enum OverloadsShown {
Ovl_All, ///< Show all overloads.
Ovl_Best ///< Show just the "best" overload candidates.
};
- /// ArgumentValue - This typedef represents on argument value, which is a
- /// union discriminated by ArgumentKind, with a value.
+ /// \brief Represents on argument value, which is a union discriminated
+ /// by ArgumentKind, with a value.
typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
private:
@@ -175,6 +179,9 @@ private:
bool ErrorsAsFatal; // Treat errors like fatal errors.
bool SuppressSystemWarnings; // Suppress warnings in system headers.
bool SuppressAllDiagnostics; // Suppress all diagnostics.
+ bool ElideType; // Elide common types of templates.
+ bool PrintTemplateTree; // Print a tree when comparing templates.
+ bool ShowColors; // Color printing is enabled.
OverloadsShown ShowOverloads; // Which overload candidates to show.
unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit.
unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
@@ -187,12 +194,13 @@ private:
bool OwnsDiagClient;
SourceManager *SourceMgr;
- /// \brief Mapping information for diagnostics. Mapping info is
- /// packed into four bits per diagnostic. The low three bits are the mapping
- /// (an instance of diag::Mapping), or zero if unset. The high bit is set
- /// when the mapping was established as a user mapping. If the high bit is
- /// clear, then the low bits are set to the default value, and should be
- /// mapped with -pedantic, -Werror, etc.
+ /// \brief Mapping information for diagnostics.
+ ///
+ /// Mapping info is packed into four bits per diagnostic. The low three
+ /// bits are the mapping (an instance of diag::Mapping), or zero if unset.
+ /// The high bit is set when the mapping was established as a user mapping.
+ /// If the high bit is clear, then the low bits are set to the default
+ /// value, and should be mapped with -pedantic, -Werror, etc.
///
/// A new DiagState is created and kept around when diagnostic pragmas modify
/// the state so that we know what is the diagnostic state at any given
@@ -220,8 +228,10 @@ private:
std::list<DiagState> DiagStates;
/// \brief Represents a point in source where the diagnostic state was
- /// modified because of a pragma. 'Loc' can be null if the point represents
- /// the diagnostic state modifications done through the command-line.
+ /// modified because of a pragma.
+ ///
+ /// 'Loc' can be null if the point represents the diagnostic state
+ /// modifications done through the command-line.
struct DiagStatePoint {
DiagState *State;
FullSourceLoc Loc;
@@ -239,9 +249,11 @@ private:
}
};
- /// \brief A vector of all DiagStatePoints representing changes in diagnostic
- /// state due to diagnostic pragmas. The vector is always sorted according to
- /// the SourceLocation of the DiagStatePoint.
+ /// \brief A sorted vector of all DiagStatePoints representing changes in
+ /// diagnostic state due to diagnostic pragmas.
+ ///
+ /// The vector is always sorted according to the SourceLocation of the
+ /// DiagStatePoint.
typedef std::vector<DiagStatePoint> DiagStatePointsTy;
mutable DiagStatePointsTy DiagStatePoints;
@@ -255,25 +267,24 @@ private:
}
void PushDiagStatePoint(DiagState *State, SourceLocation L) {
- FullSourceLoc Loc(L, *SourceMgr);
+ FullSourceLoc Loc(L, getSourceManager());
// Make sure that DiagStatePoints is always sorted according to Loc.
- assert((Loc.isValid() || DiagStatePoints.empty()) &&
- "Adding invalid loc point after another point");
- assert((Loc.isInvalid() || DiagStatePoints.empty() ||
- DiagStatePoints.back().Loc.isInvalid() ||
+ assert(Loc.isValid() && "Adding invalid loc point");
+ assert(!DiagStatePoints.empty() &&
+ (DiagStatePoints.back().Loc.isInvalid() ||
DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
"Previous point loc comes after or is the same as new one");
- DiagStatePoints.push_back(DiagStatePoint(State,
- FullSourceLoc(Loc, *SourceMgr)));
+ DiagStatePoints.push_back(DiagStatePoint(State, Loc));
}
/// \brief Finds the DiagStatePoint that contains the diagnostic state of
/// the given source location.
DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
- /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
- /// fatal error is emitted, and is sticky.
+ /// \brief Sticky flag set to \c true when an error is emitted.
bool ErrorOccurred;
+
+ /// \brief Sticky flag set to \c true when a fatal error is emitted.
bool FatalErrorOccurred;
/// \brief Indicates that an unrecoverable error has occurred.
@@ -284,18 +295,20 @@ private:
unsigned TrapNumErrorsOccurred;
unsigned TrapNumUnrecoverableErrorsOccurred;
- /// LastDiagLevel - This is the level of the last diagnostic emitted. This is
- /// used to emit continuation diagnostics with the same level as the
+ /// \brief The level of the last diagnostic emitted.
+ ///
+ /// This is used to emit continuation diagnostics with the same level as the
/// diagnostic that they follow.
DiagnosticIDs::Level LastDiagLevel;
- unsigned NumWarnings; // Number of warnings reported
- unsigned NumErrors; // Number of errors reported
- unsigned NumErrorsSuppressed; // Number of errors suppressed
+ unsigned NumWarnings; ///< Number of warnings reported
+ unsigned NumErrors; ///< Number of errors reported
+ unsigned NumErrorsSuppressed; ///< Number of errors suppressed
- /// ArgToStringFn - A function pointer that converts an opaque diagnostic
- /// argument to a strings. This takes the modifiers and argument that was
- /// present in the diagnostic.
+ /// \brief A function pointer that converts an opaque diagnostic
+ /// argument to a strings.
+ ///
+ /// This takes the modifiers and argument that was present in the diagnostic.
///
/// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
/// arguments formatted for this diagnostic. Implementations of this function
@@ -361,14 +374,15 @@ public:
// how diagnostics are emitted.
//
- /// pushMappings - Copies the current DiagMappings and pushes the new copy
+ /// \brief Copies the current DiagMappings and pushes the new copy
/// onto the top of the stack.
void pushMappings(SourceLocation Loc);
- /// popMappings - Pops the current DiagMappings off the top of the stack
- /// causing the new top of the stack to be the active mappings. Returns
- /// true if the pop happens, false if there is only one DiagMapping on the
- /// stack.
+ /// \brief Pops the current DiagMappings off the top of the stack,
+ /// causing the new top of the stack to be the active mappings.
+ ///
+ /// \returns \c true if the pop happens, \c false if there is only one
+ /// DiagMapping on the stack.
bool popMappings(SourceLocation Loc);
/// \brief Set the diagnostic client associated with this diagnostic object.
@@ -377,8 +391,10 @@ public:
/// ownership of \c client.
void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true);
- /// setErrorLimit - Specify a limit for the number of errors we should
- /// emit before giving up. Zero disables the limit.
+ /// \brief Specify a limit for the number of errors we should
+ /// emit before giving up.
+ ///
+ /// Zero disables the limit.
void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
/// \brief Specify the maximum number of template instantiation
@@ -405,29 +421,28 @@ public:
return ConstexprBacktraceLimit;
}
- /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
- /// ignored. If this and WarningsAsErrors are both set, then this one wins.
+ /// \brief When set to true, any unmapped warnings are ignored.
+ ///
+ /// If this and WarningsAsErrors are both set, then this one wins.
void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
- /// setEnableAllWarnings - When set to true, any unmapped ignored warnings
- /// are no longer ignored. If this and IgnoreAllWarnings are both set,
- /// then that one wins.
+ /// \brief When set to true, any unmapped ignored warnings are no longer
+ /// ignored.
+ ///
+ /// If this and IgnoreAllWarnings are both set, then that one wins.
void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; }
bool getEnableAllWarnngs() const { return EnableAllWarnings; }
- /// setWarningsAsErrors - When set to true, any warnings reported are issued
- /// as errors.
+ /// \brief When set to true, any warnings reported are issued as errors.
void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
bool getWarningsAsErrors() const { return WarningsAsErrors; }
- /// setErrorsAsFatal - When set to true, any error reported is made a
- /// fatal error.
+ /// \brief When set to true, any error reported is made a fatal error.
void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
bool getErrorsAsFatal() const { return ErrorsAsFatal; }
- /// setSuppressSystemWarnings - When set to true mask warnings that
- /// come from system headers.
+ /// \brief When set to true mask warnings that come from system headers.
void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
@@ -438,76 +453,105 @@ public:
SuppressAllDiagnostics = Val;
}
bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
-
+
+ /// \brief Set type eliding, to skip outputting same types occurring in
+ /// template types.
+ void setElideType(bool Val = true) { ElideType = Val; }
+ bool getElideType() { return ElideType; }
+
+ /// \brief Set tree printing, to outputting the template difference in a
+ /// tree format.
+ void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; }
+ bool getPrintTemplateTree() { return PrintTemplateTree; }
+
+ /// \brief Set color printing, so the type diffing will inject color markers
+ /// into the output.
+ void setShowColors(bool Val = false) { ShowColors = Val; }
+ bool getShowColors() { return ShowColors; }
+
/// \brief Specify which overload candidates to show when overload resolution
- /// fails. By default, we show all candidates.
+ /// fails.
+ ///
+ /// By default, we show all candidates.
void setShowOverloads(OverloadsShown Val) {
ShowOverloads = Val;
}
OverloadsShown getShowOverloads() const { return ShowOverloads; }
- /// \brief Pretend that the last diagnostic issued was ignored. This can
- /// be used by clients who suppress diagnostics themselves.
+ /// \brief Pretend that the last diagnostic issued was ignored.
+ ///
+ /// This can be used by clients who suppress diagnostics themselves.
void setLastDiagnosticIgnored() {
LastDiagLevel = DiagnosticIDs::Ignored;
}
- /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
- /// extension diagnostics are mapped onto ignore/warning/error. This
- /// corresponds to the GCC -pedantic and -pedantic-errors option.
+ /// \brief Controls whether otherwise-unmapped extension diagnostics are
+ /// mapped onto ignore/warning/error.
+ ///
+ /// This corresponds to the GCC -pedantic and -pedantic-errors option.
void setExtensionHandlingBehavior(ExtensionHandling H) {
ExtBehavior = H;
}
ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; }
- /// AllExtensionsSilenced - This is a counter bumped when an __extension__
- /// block is encountered. When non-zero, all extension diagnostics are
- /// entirely silenced, no matter how they are mapped.
+ /// \brief Counter bumped when an __extension__ block is/ encountered.
+ ///
+ /// When non-zero, all extension diagnostics are entirely silenced, no
+ /// matter how they are mapped.
void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
- /// \brief This allows the client to specify that certain
- /// warnings are ignored. Notes can never be mapped, errors can only be
- /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
+ /// \brief This allows the client to specify that certain warnings are
+ /// ignored.
+ ///
+ /// Notes can never be mapped, errors can only be mapped to fatal, and
+ /// WARNINGs and EXTENSIONs can be mapped arbitrarily.
///
/// \param Loc The source location that this change of diagnostic state should
/// take affect. It can be null if we are setting the latest state.
void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
SourceLocation Loc);
- /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
- /// "unknown-pragmas" to have the specified mapping. This returns true and
- /// ignores the request if "Group" was unknown, false otherwise.
+ /// \brief Change an entire diagnostic group (e.g. "unknown-pragmas") to
+ /// have the specified mapping.
///
- /// 'Loc' is the source location that this change of diagnostic state should
+ /// \returns true (and ignores the request) if "Group" was unknown, false
+ /// otherwise.
+ ///
+ /// \param Loc The source location that this change of diagnostic state should
/// take affect. It can be null if we are setting the state from command-line.
bool setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map,
SourceLocation Loc = SourceLocation());
- /// \brief Set the warning-as-error flag for the given diagnostic. This
- /// function always only operates on the current diagnostic state.
+ /// \brief Set the warning-as-error flag for the given diagnostic.
+ ///
+ /// This function always only operates on the current diagnostic state.
void setDiagnosticWarningAsError(diag::kind Diag, bool Enabled);
- /// \brief Set the warning-as-error flag for the given diagnostic group. This
- /// function always only operates on the current diagnostic state.
+ /// \brief Set the warning-as-error flag for the given diagnostic group.
+ ///
+ /// This function always only operates on the current diagnostic state.
///
/// \returns True if the given group is unknown, false otherwise.
bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);
- /// \brief Set the error-as-fatal flag for the given diagnostic. This function
- /// always only operates on the current diagnostic state.
+ /// \brief Set the error-as-fatal flag for the given diagnostic.
+ ///
+ /// This function always only operates on the current diagnostic state.
void setDiagnosticErrorAsFatal(diag::kind Diag, bool Enabled);
- /// \brief Set the error-as-fatal flag for the given diagnostic group. This
- /// function always only operates on the current diagnostic state.
+ /// \brief Set the error-as-fatal flag for the given diagnostic group.
+ ///
+ /// This function always only operates on the current diagnostic state.
///
/// \returns True if the given group is unknown, false otherwise.
bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
- /// \brief Add the specified mapping to all diagnostics. Mainly to be used
- /// by -Wno-everything to disable all warnings but allow subsequent -W options
- /// to enable specific warnings.
+ /// \brief Add the specified mapping to all diagnostics.
+ ///
+ /// Mainly to be used by -Wno-everything to disable all warnings but allow
+ /// subsequent -W options to enable specific warnings.
void setMappingToAllDiagnostics(diag::Mapping Map,
SourceLocation Loc = SourceLocation());
@@ -525,15 +569,16 @@ public:
this->NumWarnings = NumWarnings;
}
- /// getCustomDiagID - Return an ID for a diagnostic with the specified message
- /// and level. If this is the first request for this diagnosic, it is
- /// registered and created, otherwise the existing ID is returned.
+ /// \brief Return an ID for a diagnostic with the specified message and level.
+ ///
+ /// If this is the first request for this diagnosic, it is registered and
+ /// created, otherwise the existing ID is returned.
unsigned getCustomDiagID(Level L, StringRef Message) {
return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
}
- /// ConvertArgToString - This method converts a diagnostic argument (as an
- /// intptr_t) into the string that represents it.
+ /// \brief Converts a diagnostic argument (as an intptr_t) into the string
+ /// that represents it.
void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
const char *Modifier, unsigned ModLen,
const char *Argument, unsigned ArgLen,
@@ -568,12 +613,15 @@ public:
return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
}
- /// Report - Issue the message to the client. @c DiagID is a member of the
- /// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder
- /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
- /// @c Pos represents the source location associated with the diagnostic,
+ /// \brief Issue the message to the client.
+ ///
+ /// This actually returns an instance of DiagnosticBuilder which emits the
+ /// diagnostics (through @c ProcessDiag) when it is destroyed.
+ ///
+ /// \param DiagID A member of the @c diag::kind enum.
+ /// \param Loc Represents the source location associated with the diagnostic,
/// which can be an invalid location if no position information is available.
- inline DiagnosticBuilder Report(SourceLocation Pos, unsigned DiagID);
+ inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID);
inline DiagnosticBuilder Report(unsigned DiagID);
void Report(const StoredDiagnostic &storedDiag);
@@ -624,55 +672,60 @@ private:
friend class PartialDiagnostic;
friend class DiagnosticErrorTrap;
- /// CurDiagLoc - This is the location of the current diagnostic that is in
- /// flight.
+ /// \brief The location of the current diagnostic that is in flight.
SourceLocation CurDiagLoc;
- /// CurDiagID - This is the ID of the current diagnostic that is in flight.
+ /// \brief The ID of the current diagnostic that is in flight.
+ ///
/// This is set to ~0U when there is no diagnostic in flight.
unsigned CurDiagID;
enum {
- /// MaxArguments - The maximum number of arguments we can hold. We currently
- /// only support up to 10 arguments (%0-%9). A single diagnostic with more
- /// than that almost certainly has to be simplified anyway.
+ /// \brief The maximum number of arguments we can hold.
+ ///
+ /// We currently only support up to 10 arguments (%0-%9). A single
+ /// diagnostic with more than that almost certainly has to be simplified
+ /// anyway.
MaxArguments = 10,
- /// MaxRanges - The maximum number of ranges we can hold.
+ /// \brief The maximum number of ranges we can hold.
MaxRanges = 10,
- /// MaxFixItHints - The maximum number of ranges we can hold.
+ /// \brief The maximum number of ranges we can hold.
MaxFixItHints = 10
};
- /// NumDiagArgs - This contains the number of entries in Arguments.
+ /// \brief The number of entries in Arguments.
signed char NumDiagArgs;
- /// NumDiagRanges - This is the number of ranges in the DiagRanges array.
+ /// \brief The number of ranges in the DiagRanges array.
unsigned char NumDiagRanges;
- /// NumDiagFixItHints - This is the number of hints in the DiagFixItHints
- /// array.
+ /// \brief The number of hints in the DiagFixItHints array.
unsigned char NumDiagFixItHints;
- /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
- /// values, with one for each argument. This specifies whether the argument
- /// is in DiagArgumentsStr or in DiagArguments.
+ /// \brief Specifies whether an argument is in DiagArgumentsStr or
+ /// in DiagArguments.
+ ///
+ /// This is an array of ArgumentKind::ArgumentKind enum values, one for each
+ /// argument.
unsigned char DiagArgumentsKind[MaxArguments];
- /// DiagArgumentsStr - This holds the values of each string argument for the
- /// current diagnostic. This value is only used when the corresponding
- /// ArgumentKind is ak_std_string.
+ /// \brief Holds the values of each string argument for the current
+ /// diagnostic.
+ ///
+ /// This is only used when the corresponding ArgumentKind is ak_std_string.
std::string DiagArgumentsStr[MaxArguments];
- /// DiagArgumentsVal - The values for the various substitution positions. This
- /// is used when the argument is not an std::string. The specific value is
- /// mangled into an intptr_t and the interpretation depends on exactly what
- /// sort of argument kind it is.
+ /// \brief The values for the various substitution positions.
+ ///
+ /// This is used when the argument is not an std::string. The specific
+ /// value is mangled into an intptr_t and the interpretation depends on
+ /// exactly what sort of argument kind it is.
intptr_t DiagArgumentsVal[MaxArguments];
- /// DiagRanges - The list of ranges added to this diagnostic.
+ /// \brief The list of ranges added to this diagnostic.
CharSourceRange DiagRanges[MaxRanges];
- /// FixItHints - If valid, provides a hint with some code to insert, remove,
+ /// \brief If valid, provides a hint with some code to insert, remove,
/// or modify at a particular position.
FixItHint DiagFixItHints[MaxFixItHints];
@@ -691,11 +744,9 @@ private:
return MappingInfo;
}
- /// ProcessDiag - This is the method used to report a diagnostic that is
- /// finally fully formed.
+ /// \brief Used to report a diagnostic that is finally fully formed.
///
- /// \returns true if the diagnostic was emitted, false if it was
- /// suppressed.
+ /// \returns true if the diagnostic was emitted, false if it was suppressed.
bool ProcessDiag() {
return Diags->ProcessDiag(*this);
}
@@ -710,7 +761,9 @@ protected:
friend class Sema;
/// \brief Emit the current diagnostic and clear the diagnostic state.
- bool EmitCurrentDiagnostic();
+ ///
+ /// \param Force Emit the diagnostic regardless of suppression settings.
+ bool EmitCurrentDiagnostic(bool Force = false);
unsigned getCurrentDiagID() const { return CurDiagID; }
@@ -746,7 +799,7 @@ public:
return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
}
- // Set to initial state of "no errors occurred".
+ /// \brief Set to initial state of "no errors occurred".
void reset() {
NumErrors = Diag.TrapNumErrorsOccurred;
NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
@@ -757,11 +810,12 @@ public:
// DiagnosticBuilder
//===----------------------------------------------------------------------===//
-/// DiagnosticBuilder - This is a little helper class used to produce
-/// diagnostics. This is constructed by the DiagnosticsEngine::Report method,
-/// and allows insertion of extra information (arguments and source ranges) into
-/// the currently "in flight" diagnostic. When the temporary for the builder is
-/// destroyed, the diagnostic is issued.
+/// \brief A little helper class used to produce diagnostics.
+///
+/// This is constructed by the DiagnosticsEngine::Report method, and
+/// allows insertion of extra information (arguments and source ranges) into
+/// the currently "in flight" diagnostic. When the temporary for the builder
+/// is destroyed, the diagnostic is issued.
///
/// Note that many of these will be created as temporary objects (many call
/// sites), so we want them to be small and we never want their address taken.
@@ -779,15 +833,25 @@ class DiagnosticBuilder {
// Emit() would end up with if we used that as our status variable.
mutable bool IsActive;
+ /// \brief Flag indicating that this diagnostic is being emitted via a
+ /// call to ForceEmit.
+ mutable bool IsForceEmit;
+
void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
friend class DiagnosticsEngine;
+
+ DiagnosticBuilder()
+ : DiagObj(0), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(false),
+ IsForceEmit(false) { }
+
explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
- : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true) {
+ : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true),
+ IsForceEmit(false) {
assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
}
friend class PartialDiagnostic;
-
+
protected:
void FlushCounts() {
DiagObj->NumDiagArgs = NumArgs;
@@ -799,9 +863,10 @@ protected:
void Clear() const {
DiagObj = 0;
IsActive = false;
+ IsForceEmit = false;
}
- /// isActive - Determine whether this diagnostic is still active.
+ /// \brief Determine whether this diagnostic is still active.
bool isActive() const { return IsActive; }
/// \brief Force the diagnostic builder to emit the diagnostic now.
@@ -821,7 +886,7 @@ protected:
FlushCounts();
// Process the diagnostic.
- bool Result = DiagObj->EmitCurrentDiagnostic();
+ bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit);
// This diagnostic is dead.
Clear();
@@ -835,20 +900,36 @@ public:
DiagnosticBuilder(const DiagnosticBuilder &D) {
DiagObj = D.DiagObj;
IsActive = D.IsActive;
+ IsForceEmit = D.IsForceEmit;
D.Clear();
NumArgs = D.NumArgs;
NumRanges = D.NumRanges;
NumFixits = D.NumFixits;
}
- /// Destructor - The dtor emits the diagnostic.
+ /// \brief Retrieve an empty diagnostic builder.
+ static DiagnosticBuilder getEmpty() {
+ return DiagnosticBuilder();
+ }
+
+ /// \brief Emits the diagnostic.
~DiagnosticBuilder() {
Emit();
}
- /// Operator bool: conversion of DiagnosticBuilder to bool always returns
- /// true. This allows is to be used in boolean error contexts like:
+ /// \brief Forces the diagnostic to be emitted.
+ const DiagnosticBuilder &setForceEmit() const {
+ IsForceEmit = true;
+ return *this;
+ }
+
+ /// \brief Conversion of DiagnosticBuilder to bool always returns \c true.
+ ///
+ /// This allows is to be used in boolean error contexts (where \c true is
+ /// used to indicate that an error has occurred), like:
+ /// \code
/// return Diag(...);
+ /// \endcode
operator bool() const { return true; }
void AddString(StringRef S) const {
@@ -951,9 +1032,6 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
return DB;
}
-/// Report - Issue the message to the client. DiagID is a member of the
-/// diag::kind enum. This actually returns a new instance of DiagnosticBuilder
-/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
unsigned DiagID){
assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
@@ -969,9 +1047,9 @@ inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
// Diagnostic
//===----------------------------------------------------------------------===//
-/// Diagnostic - This is a little helper class (which is basically a smart
-/// pointer that forward info from DiagnosticsEngine) that allows clients to
-/// enquire about the currently in-flight diagnostic.
+/// A little helper class (which is basically a smart pointer that forwards
+/// info from DiagnosticsEngine) that allows clients to enquire about the
+/// currently in-flight diagnostic.
class Diagnostic {
const DiagnosticsEngine *DiagObj;
StringRef StoredDiagMessage;
@@ -988,62 +1066,71 @@ public:
unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
- /// getArgKind - Return the kind of the specified index. Based on the kind
- /// of argument, the accessors below can be used to get the value.
+ /// \brief Return the kind of the specified index.
+ ///
+ /// Based on the kind of argument, the accessors below can be used to get
+ /// the value.
+ ///
+ /// \pre Idx < getNumArgs()
DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
assert(Idx < getNumArgs() && "Argument index out of range!");
return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
}
- /// getArgStdStr - Return the provided argument string specified by Idx.
+ /// \brief Return the provided argument string specified by \p Idx.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string
const std::string &getArgStdStr(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
"invalid argument accessor!");
return DiagObj->DiagArgumentsStr[Idx];
}
- /// getArgCStr - Return the specified C string argument.
+ /// \brief Return the specified C string argument.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string
const char *getArgCStr(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
"invalid argument accessor!");
return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
}
- /// getArgSInt - Return the specified signed integer argument.
+ /// \brief Return the specified signed integer argument.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint
int getArgSInt(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
"invalid argument accessor!");
return (int)DiagObj->DiagArgumentsVal[Idx];
}
- /// getArgUInt - Return the specified unsigned integer argument.
+ /// \brief Return the specified unsigned integer argument.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint
unsigned getArgUInt(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
"invalid argument accessor!");
return (unsigned)DiagObj->DiagArgumentsVal[Idx];
}
- /// getArgIdentifier - Return the specified IdentifierInfo argument.
+ /// \brief Return the specified IdentifierInfo argument.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo
const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
"invalid argument accessor!");
return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
}
- /// getRawArg - Return the specified non-string argument in an opaque form.
+ /// \brief Return the specified non-string argument in an opaque form.
+ /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string
intptr_t getRawArg(unsigned Idx) const {
assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
"invalid argument accessor!");
return DiagObj->DiagArgumentsVal[Idx];
}
-
- /// getNumRanges - Return the number of source ranges associated with this
- /// diagnostic.
+ /// \brief Return the number of source ranges associated with this diagnostic.
unsigned getNumRanges() const {
return DiagObj->NumDiagRanges;
}
+ /// \pre Idx < getNumRanges()
const CharSourceRange &getRange(unsigned Idx) const {
assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
return DiagObj->DiagRanges[Idx];
@@ -1067,13 +1154,14 @@ public:
return getNumFixItHints()? DiagObj->DiagFixItHints : 0;
}
- /// FormatDiagnostic - Format this diagnostic into a string, substituting the
- /// formal arguments into the %0 slots. The result is appended onto the Str
- /// array.
+ /// \brief Format this diagnostic into a string, substituting the
+ /// formal arguments into the %0 slots.
+ ///
+ /// The result is appended onto the \p OutStr array.
void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
- /// FormatDiagnostic - Format the given format-string into the
- /// output buffer using the arguments stored in this diagnostic.
+ /// \brief Format the given format-string into the output buffer using the
+ /// arguments stored in this diagnostic.
void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
SmallVectorImpl<char> &OutStr) const;
};
@@ -1131,12 +1219,12 @@ public:
}
};
-/// DiagnosticConsumer - This is an abstract interface implemented by clients of
-/// the front-end, which formats and prints fully processed diagnostics.
+/// \brief Abstract interface, implemented by clients of the front-end, which
+/// formats and prints fully processed diagnostics.
class DiagnosticConsumer {
protected:
- unsigned NumWarnings; // Number of warnings reported
- unsigned NumErrors; // Number of errors reported
+ unsigned NumWarnings; ///< Number of warnings reported
+ unsigned NumErrors; ///< Number of errors reported
public:
DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { }
@@ -1147,7 +1235,7 @@ public:
virtual ~DiagnosticConsumer();
- /// BeginSourceFile - Callback to inform the diagnostic client that processing
+ /// \brief Callback to inform the diagnostic client that processing
/// of a source file is beginning.
///
/// Note that diagnostics may be emitted outside the processing of a source
@@ -1155,32 +1243,35 @@ public:
/// diagnostics with source range information are required to only be emitted
/// in between BeginSourceFile() and EndSourceFile().
///
- /// \arg LO - The language options for the source file being processed.
- /// \arg PP - The preprocessor object being used for the source; this optional
- /// and may not be present, for example when processing AST source files.
+ /// \param LangOpts The language options for the source file being processed.
+ /// \param PP The preprocessor object being used for the source; this is
+ /// optional, e.g., it may not be present when processing AST source files.
virtual void BeginSourceFile(const LangOptions &LangOpts,
const Preprocessor *PP = 0) {}
- /// EndSourceFile - Callback to inform the diagnostic client that processing
- /// of a source file has ended. The diagnostic client should assume that any
- /// objects made available via \see BeginSourceFile() are inaccessible.
+ /// \brief Callback to inform the diagnostic client that processing
+ /// of a source file has ended.
+ ///
+ /// The diagnostic client should assume that any objects made available via
+ /// BeginSourceFile() are inaccessible.
virtual void EndSourceFile() {}
/// \brief Callback to inform the diagnostic client that processing of all
/// source files has ended.
virtual void finish() {}
- /// IncludeInDiagnosticCounts - This method (whose default implementation
- /// returns true) indicates whether the diagnostics handled by this
+ /// \brief Indicates whether the diagnostics handled by this
/// DiagnosticConsumer should be included in the number of diagnostics
/// reported by DiagnosticsEngine.
+ ///
+ /// The default implementation returns true.
virtual bool IncludeInDiagnosticCounts() const;
- /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+ /// \brief Handle this diagnostic, reporting it to the user or
/// capturing it to a log as needed.
///
- /// Default implementation just keeps track of the total number of warnings
- /// and errors.
+ /// The default implementation just keeps track of the total number of
+ /// warnings and errors.
virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info);
@@ -1189,8 +1280,7 @@ public:
virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const = 0;
};
-/// IgnoringDiagConsumer - This is a diagnostic client that just ignores all
-/// diags.
+/// \brief A diagnostic client that ignores all diagnostics.
class IgnoringDiagConsumer : public DiagnosticConsumer {
virtual void anchor();
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
@@ -1202,6 +1292,22 @@ class IgnoringDiagConsumer : public DiagnosticConsumer {
}
};
+// Struct used for sending info about how a type should be printed.
+struct TemplateDiffTypes {
+ intptr_t FromType;
+ intptr_t ToType;
+ unsigned PrintTree : 1;
+ unsigned PrintFromType : 1;
+ unsigned ElideType : 1;
+ unsigned ShowColors : 1;
+ // The printer sets this variable to true if the template diff was used.
+ unsigned TemplateDiffUsed : 1;
+};
+
+/// Special character that the diagnostic printer will use to toggle the bold
+/// attribute. The character itself will be not be printed.
+const char ToggleHighlight = 127;
+
} // end namespace clang
#endif
diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td
index 109cd0812c68..6dfecdcb7972 100644
--- a/include/clang/Basic/Diagnostic.td
+++ b/include/clang/Basic/Diagnostic.td
@@ -88,6 +88,7 @@ class AccessControl { bit AccessControl = 1; }
// Definitions for Diagnostics.
include "DiagnosticASTKinds.td"
include "DiagnosticAnalysisKinds.td"
+include "DiagnosticCommentKinds.td"
include "DiagnosticCommonKinds.td"
include "DiagnosticDriverKinds.td"
include "DiagnosticFrontendKinds.td"
diff --git a/include/clang/Basic/DiagnosticCommentKinds.td b/include/clang/Basic/DiagnosticCommentKinds.td
new file mode 100644
index 000000000000..235ca79564d3
--- /dev/null
+++ b/include/clang/Basic/DiagnosticCommentKinds.td
@@ -0,0 +1,125 @@
+//==--- DiagnosticCommentKinds.td - diagnostics related to comments -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "Comment" in {
+let CategoryName = "Documentation Issue" in {
+
+// HTML parsing errors. These are under -Wdocumentation to make sure the user
+// knows that we didn't parse something as he might expect.
+
+def warn_doc_html_start_tag_expected_quoted_string : Warning<
+ "expected quoted string after equals sign">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_html_start_tag_expected_ident_or_greater : Warning<
+ "HTML start tag prematurely ended, expected attribute name or '>'">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_html_tag_started_here : Note<
+ "HTML tag started here">;
+
+// HTML semantic errors
+
+def warn_doc_html_end_forbidden : Warning<
+ "HTML end tag '%0' is forbidden">,
+ InGroup<DocumentationHTML>, DefaultIgnore;
+
+def warn_doc_html_end_unbalanced : Warning<
+ "HTML end tag does not match any start tag">,
+ InGroup<DocumentationHTML>, DefaultIgnore;
+
+def warn_doc_html_start_end_mismatch : Warning<
+ "HTML start tag '%0' closed by '%1'">,
+ InGroup<DocumentationHTML>, DefaultIgnore;
+
+def note_doc_html_end_tag : Note<
+ "end tag">;
+
+// Commands
+
+def warn_doc_block_command_empty_paragraph : Warning<
+ "empty paragraph passed to '\\%0' command">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_block_command_duplicate : Warning<
+ "duplicated command '\\%0'">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_block_command_previous : Note<
+ "previous command '\\%0' here">;
+
+def note_doc_block_command_previous_alias : Note<
+ "previous command '\\%0' (an alias of '\\%1') here">;
+
+// \param command
+
+def warn_doc_param_invalid_direction : Warning<
+ "unrecognized parameter passing direction, "
+ "valid directions are '[in]', '[out]' and '[in,out]'">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_param_spaces_in_direction : Warning<
+ "whitespace is not allowed in parameter passing direction">,
+ InGroup<DocumentationPedantic>, DefaultIgnore;
+
+def warn_doc_param_not_attached_to_a_function_decl : Warning<
+ "'\\param' command used in a comment that is not attached to "
+ "a function declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_param_duplicate : Warning<
+ "parameter '%0' is already documented">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_param_previous : Note<
+ "previous documentation">;
+
+def warn_doc_param_not_found : Warning<
+ "parameter '%0' not found in the function declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_param_name_suggestion : Note<
+ "did you mean '%0'?">;
+
+// \tparam command
+
+def warn_doc_tparam_not_attached_to_a_template_decl : Warning<
+ "'\\tparam' command used in a comment that is not attached to "
+ "a template declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_tparam_duplicate : Warning<
+ "template parameter '%0' is already documented">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_tparam_previous : Note<
+ "previous documentation">;
+
+def warn_doc_tparam_not_found : Warning<
+ "template parameter '%0' not found in the template declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_tparam_name_suggestion : Note<
+ "did you mean '%0'?">;
+
+// \returns command
+
+def warn_doc_returns_not_attached_to_a_function_decl : Warning<
+ "'\\%0' command used in a comment that is not attached to "
+ "a function or method declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_returns_attached_to_a_void_function : Warning<
+ "'\\%0' command used in a comment that is attached to a "
+ "%select{function returning void|constructor|destructor|"
+ "method returning void}1">,
+ InGroup<Documentation>, DefaultIgnore;
+
+} // end of documentation issue category
+} // end of AST component
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 103fc00b40f0..f85928740b4c 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -74,6 +74,8 @@ def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
def warn_module_build : Warning<"building module '%0' from source">,
InGroup<ModuleBuild>, DefaultIgnore;
def note_pragma_entered_here : Note<"#pragma entered here">;
+def note_decl_hiding_tag_type : Note<
+ "%1 %0 is hidden by a non-type declaration of %0 here">;
// Sema && Lex
def ext_longlong : Extension<
@@ -106,4 +108,8 @@ def err_file_modified : Error<
"file '%0' modified since it was first processed">, DefaultFatal;
def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but "
"encoding is not supported">, DefaultFatal;
+def err_unable_to_rename_temp : Error<
+ "unable to rename temporary '%0' to output file '%1': '%2'">;
+def err_unable_to_make_temp : Error<
+ "unable to make temporary file: %0">;
}
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index b44315932c6b..583b2345c935 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -33,8 +33,6 @@ def err_drv_use_of_Z_option : Error<
"unsupported use of internal gcc -Z option '%0'">;
def err_drv_output_argument_with_multiple_files : Error<
"cannot specify -o when generating multiple output files">;
-def err_drv_unable_to_make_temp : Error<
- "unable to make temporary file: %0">;
def err_drv_unable_to_remove_file : Error<
"unable to remove file: %0">;
def err_drv_command_failure : Error<
@@ -94,23 +92,32 @@ def err_drv_invalid_arch_for_deployment_target : Error<
def err_drv_objc_gc_arr : Error<
"cannot specify both '-fobjc-arc' and '%0'">;
def err_arc_nonfragile_abi : Error<
- "-fobjc-arc is not supported with fragile abi">;
+ "-fobjc-arc is not supported with legacy abi">;
def err_arc_unsupported : Error<
"-fobjc-arc is not supported on current deployment target">;
def err_drv_mg_requires_m_or_mm : Error<
"option '-MG' requires '-M' or '-MM'">;
+def err_drv_asan_android_requires_pie : Error<
+ "AddressSanitizer on Android requires '-pie'">;
+def err_drv_unknown_objc_runtime : Error<
+ "unknown or ill-formed Objective-C runtime '%0'">;
def warn_c_kext : Warning<
- "ignoring -fapple-kext which is valid for c++ and objective-c++ only">;
+ "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">;
def warn_drv_input_file_unused : Warning<
- "%0: '%1' input unused when '%2' is present">;
+ "%0: '%1' input unused%select{ when '%3' is present|}2">,
+ InGroup<DiagGroup<"unused-command-line-argument">>;
+def warn_drv_input_file_unused_by_cpp : Warning<
+ "%0: '%1' input unused in cpp mode">,
+ InGroup<DiagGroup<"unused-command-line-argument">>;
def warn_drv_preprocessed_input_file_unused : Warning<
- "%0: previously preprocessed input unused when '%1' is present">;
+ "%0: previously preprocessed input%select{ unused when '%2' is present|}1">,
+ InGroup<DiagGroup<"unused-command-line-argument">>;
def warn_drv_unused_argument : Warning<
"argument unused during compilation: '%0'">,
InGroup<DiagGroup<"unused-command-line-argument">>;
def warn_drv_empty_joined_argument : Warning<
- "joined argument expects addition arg: '%0'">,
+ "joined argument expects additional value: '%0'">,
InGroup<DiagGroup<"unused-command-line-argument">>;
def warn_drv_not_using_clang_cpp : Warning<
"not using the clang preprocessor due to user override">;
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 5d6b887feb4b..417a22c96df5 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -48,14 +48,12 @@ def err_fe_unable_to_interface_with_target : Error<
"unable to interface with target machine">;
def err_fe_unable_to_open_output : Error<
"unable to open output file '%0': '%1'">;
-def err_fe_unable_to_rename_temp : Error<
- "unable to rename temporary '%0' to output file '%1': '%2'">;
def err_fe_unable_to_open_logfile : Error<
"unable to open logfile file '%0': '%1'">;
def err_fe_pth_file_has_no_source_header : Error<
"PTH file '%0' does not designate an original source header file for -include-pth">;
def warn_fe_macro_contains_embedded_newline : Warning<
- "macro '%0' contains embedded newline, text after the newline is ignored.">;
+ "macro '%0' contains embedded newline; text after the newline is ignored">;
def warn_fe_cc_print_header_failure : Warning<
"unable to open CC_PRINT_HEADERS file: %0 (using stderr)">;
def warn_fe_cc_log_diagnostics_failure : Warning<
@@ -65,6 +63,10 @@ def warn_fe_serialized_diag_failure : Warning<
"unable to open file %0 for serializing diagnostics (%1)">,
InGroup<DiagGroup<"serialized-diagnostics">>;
+def err_verify_missing_line : Error<
+ "missing or invalid line number following '@' in expected %0">;
+def err_verify_invalid_range : Error<
+ "invalid range following '-' in expected %0">;
def err_verify_missing_start : Error<
"cannot find start ('{{') of expected %0">;
def err_verify_missing_end : Error<
@@ -93,19 +95,19 @@ def warn_unknown_warning_option : Warning<
"unknown warning option '%0'">,
InGroup<DiagGroup<"unknown-warning-option"> >;
def warn_unknown_negative_warning_option : Warning<
- "unknown warning option '%0'?">,
- InGroup<DiagGroup<"unknown-warning-option"> >, DefaultIgnore;
+ "unknown warning option '%0'">,
+ InGroup<DiagGroup<"unknown-warning-option"> >;
def warn_unknown_warning_option_suggest : Warning<
"unknown warning option '%0'; did you mean '%1'?">,
InGroup<DiagGroup<"unknown-warning-option"> >;
def warn_unknown_negative_warning_option_suggest : Warning<
"unknown warning option '%0'; did you mean '%1'?">,
- InGroup<DiagGroup<"unknown-warning-option"> >, DefaultIgnore;
+ InGroup<DiagGroup<"unknown-warning-option"> >;
def warn_unknown_warning_specifier : Warning<
"unknown %0 warning specifier: '%1'">,
InGroup<DiagGroup<"unknown-warning-option"> >;
-def warn_unknown_analyzer_checker : Warning<
+def err_unknown_analyzer_checker : Error<
"no analyzer checkers are associated with '%0'">;
def warn_incompatible_analyzer_plugin_api : Warning<
"checker plugin '%0' is not compatible with this version of the analyzer">,
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index c83985345bce..b95a90bd21c3 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -25,6 +25,7 @@ def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
def : DiagGroup<"attributes">;
def : DiagGroup<"bad-function-cast">;
def Availability : DiagGroup<"availability">;
+def Section : DiagGroup<"section">;
def AutoImport : DiagGroup<"auto-import">;
def ConstantConversion : DiagGroup<"constant-conversion">;
def LiteralConversion : DiagGroup<"literal-conversion">;
@@ -32,6 +33,7 @@ def StringConversion : DiagGroup<"string-conversion">;
def SignConversion : DiagGroup<"sign-conversion">;
def BoolConversion : DiagGroup<"bool-conversion">;
def IntConversion : DiagGroup<"int-conversion">;
+def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">;
def NullConversion : DiagGroup<"null-conversion">;
def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
def CXXCompat: DiagGroup<"c++-compat">;
@@ -56,8 +58,13 @@ def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
def : DiagGroup<"div-by-zero">;
+def DocumentationHTML : DiagGroup<"documentation-html">;
+def DocumentationPedantic : DiagGroup<"documentation-pedantic">;
+def Documentation : DiagGroup<"documentation", [DocumentationHTML]>;
def EmptyBody : DiagGroup<"empty-body">;
def ExtraTokens : DiagGroup<"extra-tokens">;
+def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">;
+def ExtraSemi : DiagGroup<"extra-semi", [CXX11ExtraSemi]>;
def FormatExtraArgs : DiagGroup<"format-extra-args">;
def FormatZeroLength : DiagGroup<"format-zero-length">;
@@ -96,6 +103,7 @@ def CXX11Compat : DiagGroup<"c++11-compat",
def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
def : DiagGroup<"effc++">;
+def DivZero : DiagGroup<"division-by-zero">;
def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
@@ -142,9 +150,13 @@ def : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">;
def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
def : DiagGroup<"overflow">;
+def ForwardClassReceiver : DiagGroup<"receiver-forward-class">;
+def MethodAccess : DiagGroup<"objc-method-access">;
+def ObjCReceiver : DiagGroup<"receiver-expr">;
def OverlengthStrings : DiagGroup<"overlength-strings">;
def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">;
+def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">;
def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">;
def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">;
@@ -162,7 +174,8 @@ def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;
def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;
def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy",
[CXX98CompatBindToTemporaryCopy]>;
-def SelfAssignment : DiagGroup<"self-assign">;
+def SelfAssignmentField : DiagGroup<"self-assign-field">;
+def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentField]>;
def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
def Sentinel : DiagGroup<"sentinel">;
def MissingMethodReturnType : DiagGroup<"missing-method-return-type">;
@@ -206,12 +219,18 @@ def MethodDuplicate : DiagGroup<"duplicate-method-match">;
def CoveredSwitchDefault : DiagGroup<"covered-switch-default">;
def SwitchEnum : DiagGroup<"switch-enum">;
def Switch : DiagGroup<"switch">;
+def ImplicitFallthroughPerFunction :
+ DiagGroup<"implicit-fallthrough-per-function">;
+def ImplicitFallthrough : DiagGroup<"implicit-fallthrough",
+ [ImplicitFallthroughPerFunction]>;
+def InvalidPPToken : DiagGroup<"invalid-pp-token">;
def Trigraphs : DiagGroup<"trigraphs">;
def : DiagGroup<"type-limits">;
def Unicode : DiagGroup<"unicode">;
-def Uninitialized : DiagGroup<"uninitialized">;
def UninitializedMaybe : DiagGroup<"conditional-uninitialized">;
+def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
+def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes]>;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
def UnknownAttributes : DiagGroup<"attributes">;
@@ -223,6 +242,7 @@ def UnusedComparison : DiagGroup<"unused-comparison">;
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">;
def UnneededMemberFunction : DiagGroup<"unneeded-member-function">;
+def UnusedPrivateField : DiagGroup<"unused-private-field">;
def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>;
def UnusedMemberFunction : DiagGroup<"unused-member-function",
[UnneededMemberFunction]>;
@@ -250,7 +270,6 @@ def AutomaticReferenceCounting : DiagGroup<"arc",
ARCRetainCycles,
ARCNonPodMemAccess]>;
def Selector : DiagGroup<"selector">;
-def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
def Protocol : DiagGroup<"protocol">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
@@ -296,7 +315,8 @@ def Conversion : DiagGroup<"conversion",
StringConversion,
SignConversion,
BoolConversion,
- NullConversion,
+ NullConversion, // NULL->non-pointer
+ NonLiteralNullConversion, // (1-1)->pointer (etc)
IntConversion]>,
DiagCategory<"Value Conversion Issue">;
@@ -304,6 +324,7 @@ def Unused : DiagGroup<"unused",
[UnusedArgument, UnusedFunction, UnusedLabel,
// UnusedParameter, (matches GCC's behavior)
// UnusedMemberFunction, (clean-up llvm before enabling)
+ UnusedPrivateField,
UnusedValue, UnusedVariable]>,
DiagCategory<"Unused Entity Issue">;
@@ -354,13 +375,19 @@ def Most : DiagGroup<"most", [
]>;
// Thread Safety warnings
-def ThreadSafety : DiagGroup<"thread-safety">;
+def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">;
+def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">;
+def ThreadSafety : DiagGroup<"thread-safety",
+ [ThreadSafetyAttributes, ThreadSafetyAnalysis]>;
// Note that putting warnings in -Wall will not disable them by default. If a
// warning should be active _only_ when -Wall is passed in, mark it as
// DefaultIgnore in addition to putting it here.
def : DiagGroup<"all", [Most, Parentheses, Switch]>;
+// Warnings enabled by -pedantic. This is magically filled in by TableGen.
+def Pedantic : DiagGroup<"pedantic">;
+
// Aliases.
def : DiagGroup<"", [Extra]>; // -W = -Wextra
def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wendif-tokens
@@ -381,7 +408,7 @@ def NonGCC : DiagGroup<"non-gcc",
// A warning group for warnings about using C++11 features as extensions in
// earlier C++ versions.
-def CXX11 : DiagGroup<"c++11-extensions">;
+def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi]>;
def : DiagGroup<"c++0x-extensions", [CXX11]>;
def DelegatingCtorCycles :
DiagGroup<"delegating-ctor-cycles">;
@@ -413,3 +440,8 @@ def ObjCRedundantAPIUse : DiagGroup<"objc-redundant-api-use", [
def ObjCCocoaAPI : DiagGroup<"objc-cocoa-api", [
ObjCRedundantAPIUse
]>;
+
+def ObjCStringComparison : DiagGroup<"objc-string-compare">;
+def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
+ ObjCStringComparison
+ ]>;
diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h
index a6c22db3e8d0..11552af8f0af 100644
--- a/include/clang/Basic/DiagnosticIDs.h
+++ b/include/clang/Basic/DiagnosticIDs.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Diagnostic IDs-related interfaces.
-//
+///
+/// \file
+/// \brief Defines the Diagnostic IDs-related interfaces.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_DIAGNOSTICIDS_H
@@ -37,14 +38,15 @@ namespace clang {
DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
DIAG_START_PARSE = DIAG_START_LEX + 300,
DIAG_START_AST = DIAG_START_PARSE + 400,
- DIAG_START_SEMA = DIAG_START_AST + 100,
+ DIAG_START_COMMENT = DIAG_START_AST + 100,
+ DIAG_START_SEMA = DIAG_START_COMMENT + 100,
DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
};
class CustomDiagInfo;
- /// diag::kind - All of the diagnostics that can be emitted by the frontend.
+ /// \brief All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;
// Get typedefs for common diagnostics.
@@ -63,10 +65,10 @@ namespace clang {
/// one).
enum Mapping {
// NOTE: 0 means "uncomputed".
- MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
- MAP_WARNING = 2, //< Map this diagnostic to a warning.
- MAP_ERROR = 3, //< Map this diagnostic to an error.
- MAP_FATAL = 4 //< Map this diagnostic to a fatal error.
+ MAP_IGNORE = 1, ///< Map this diagnostic to nothing, ignore it.
+ MAP_WARNING = 2, ///< Map this diagnostic to a warning.
+ MAP_ERROR = 3, ///< Map this diagnostic to an error.
+ MAP_FATAL = 4 ///< Map this diagnostic to a fatal error.
};
}
@@ -111,83 +113,84 @@ public:
/// by multiple Diagnostics for multiple translation units.
class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
public:
- /// Level - The level of the diagnostic, after it has been through mapping.
+ /// Level The level of the diagnostic, after it has been through mapping.
enum Level {
Ignored, Note, Warning, Error, Fatal
};
private:
- /// CustomDiagInfo - Information for uniquing and looking up custom diags.
+ /// \brief Information for uniquing and looking up custom diags.
diag::CustomDiagInfo *CustomDiagInfo;
public:
DiagnosticIDs();
~DiagnosticIDs();
- /// getCustomDiagID - Return an ID for a diagnostic with the specified message
- /// and level. If this is the first request for this diagnosic, it is
- /// registered and created, otherwise the existing ID is returned.
+ /// \brief Return an ID for a diagnostic with the specified message and level.
+ ///
+ /// If this is the first request for this diagnosic, it is registered and
+ /// created, otherwise the existing ID is returned.
unsigned getCustomDiagID(Level L, StringRef Message);
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
//
- /// getDescription - Given a diagnostic ID, return a description of the
- /// issue.
+ /// \brief Given a diagnostic ID, return a description of the issue.
StringRef getDescription(unsigned DiagID) const;
- /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic level
- /// of the specified diagnostic ID is a Warning or Extension. This only works
- /// on builtin diagnostics, not custom ones, and is not legal to call on
- /// NOTEs.
+ /// \brief Return true if the unmapped diagnostic levelof the specified
+ /// diagnostic ID is a Warning or Extension.
+ ///
+ /// This only works on builtin diagnostics, not custom ones, and is not
+ /// legal to call on NOTEs.
static bool isBuiltinWarningOrExtension(unsigned DiagID);
/// \brief Return true if the specified diagnostic is mapped to errors by
/// default.
static bool isDefaultMappingAsError(unsigned DiagID);
- /// \brief Determine whether the given built-in diagnostic ID is a
- /// Note.
+ /// \brief Determine whether the given built-in diagnostic ID is a Note.
static bool isBuiltinNote(unsigned DiagID);
- /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
- /// ID is for an extension of some sort.
- ///
+ /// \brief Determine whether the given built-in diagnostic ID is for an
+ /// extension of some sort.
static bool isBuiltinExtensionDiag(unsigned DiagID) {
bool ignored;
return isBuiltinExtensionDiag(DiagID, ignored);
}
- /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
- /// ID is for an extension of some sort. This also returns EnabledByDefault,
- /// which is set to indicate whether the diagnostic is ignored by default (in
- /// which case -pedantic enables it) or treated as a warning/error by default.
+ /// \brief Determine whether the given built-in diagnostic ID is for an
+ /// extension of some sort, and whether it is enabled by default.
+ ///
+ /// This also returns EnabledByDefault, which is set to indicate whether the
+ /// diagnostic is ignored by default (in which case -pedantic enables it) or
+ /// treated as a warning/error by default.
///
static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
- /// getWarningOptionForDiag - Return the lowest-level warning option that
- /// enables the specified diagnostic. If there is no -Wfoo flag that controls
- /// the diagnostic, this returns null.
+ /// \brief Return the lowest-level warning option that enables the specified
+ /// diagnostic.
+ ///
+ /// If there is no -Wfoo flag that controls the diagnostic, this returns null.
static StringRef getWarningOptionForDiag(unsigned DiagID);
- /// getCategoryNumberForDiag - Return the category number that a specified
- /// DiagID belongs to, or 0 if no category.
+ /// \brief Return the category number that a specified \p DiagID belongs to,
+ /// or 0 if no category.
static unsigned getCategoryNumberForDiag(unsigned DiagID);
- /// getNumberOfCategories - Return the number of categories
+ /// \brief Return the number of diagnostic categories.
static unsigned getNumberOfCategories();
- /// getCategoryNameFromID - Given a category ID, return the name of the
- /// category.
+ /// \brief Given a category ID, return the name of the category.
static StringRef getCategoryNameFromID(unsigned CategoryID);
- /// isARCDiagnostic - Return true if a given diagnostic falls into an
- /// ARC diagnostic category;
+ /// \brief Return true if a given diagnostic falls into an ARC diagnostic
+ /// category.
static bool isARCDiagnostic(unsigned DiagID);
- /// \brief Enumeration describing how the the emission of a diagnostic should
+ /// \brief Enumeration describing how the emission of a diagnostic should
/// be treated when it occurs during C++ template argument deduction.
enum SFINAEResponse {
/// \brief The diagnostic should not be reported, but it should cause
@@ -253,20 +256,23 @@ private:
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
const DiagnosticsEngine &Diag) const;
- /// getDiagnosticLevel - This is an internal implementation helper used when
- /// DiagClass is already known.
+ /// \brief An internal implementation helper used when \p DiagClass is
+ /// already known.
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
unsigned DiagClass,
SourceLocation Loc,
const DiagnosticsEngine &Diag) const;
- /// ProcessDiag - This is the method used to report a diagnostic that is
- /// finally fully formed.
+ /// \brief Used to report a diagnostic that is finally fully formed.
///
- /// \returns true if the diagnostic was emitted, false if it was
+ /// \returns \c true if the diagnostic was emitted, \c false if it was
/// suppressed.
bool ProcessDiag(DiagnosticsEngine &Diag) const;
+ /// \brief Used to emit a diagnostic that is finally fully formed,
+ /// ignoring suppression.
+ void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const;
+
/// \brief Whether the diagnostic may leave the AST in a state where some
/// invariants can break.
bool isUnrecoverable(unsigned DiagID) const;
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 670283ef1a5c..cc958dbdfea2 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -64,9 +64,12 @@ def ext_token_used : Extension<"extension used">,
def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">,
InGroup<CXX11Compat>, DefaultIgnore;
-def warn_unterminated_string : ExtWarn<"missing terminating '\"' character">;
-def warn_unterminated_char : ExtWarn<"missing terminating ' character">;
-def err_empty_character : Error<"empty character constant">;
+def ext_unterminated_string : ExtWarn<"missing terminating '\"' character">,
+ InGroup<InvalidPPToken>;
+def ext_unterminated_char : ExtWarn<"missing terminating ' character">,
+ InGroup<InvalidPPToken>;
+def ext_empty_character : ExtWarn<"empty character constant">,
+ InGroup<InvalidPPToken>;
def err_unterminated_block_comment : Error<"unterminated /* comment">;
def err_invalid_character_to_charify : Error<
"invalid argument to convert to character">;
@@ -177,6 +180,7 @@ def err_bad_character_encoding : Error<
def warn_bad_character_encoding : ExtWarn<
"illegal character encoding in character literal">,
InGroup<DiagGroup<"invalid-source-encoding">>;
+def err_lexing_string : Error<"failure when lexing a string">;
//===----------------------------------------------------------------------===//
@@ -251,7 +255,7 @@ def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
def ext_pp_bad_vaargs_use : Extension<
"__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">;
def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">;
-def ext_variadic_macro : Extension<"variadic macros were introduced in C99">,
+def ext_variadic_macro : Extension<"variadic macros are a C99 feature">,
InGroup<VariadicMacros>;
def warn_cxx98_compat_variadic_macro : Warning<
"variadic macros are incompatible with C++98">,
@@ -264,15 +268,19 @@ def ext_embedded_directive : Extension<
"embedding a directive within macro arguments has undefined behavior">,
InGroup<DiagGroup<"embedded-directive">>;
def ext_missing_varargs_arg : Extension<
- "varargs argument missing, but tolerated as an extension">;
+ "must specify at least one argument for '...' parameter of variadic macro">,
+ InGroup<GNU>;
def ext_empty_fnmacro_arg : Extension<
- "empty macro arguments were standardized in C99">;
+ "empty macro arguments are a C99 feature">, InGroup<C99>;
def warn_cxx98_compat_empty_fnmacro_arg : Warning<
- "empty macro argument list is incompatible with C++98">,
+ "empty macro arguments are incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def note_macro_here : Note<"macro %0 defined here">;
def err_pp_invalid_directive : Error<"invalid preprocessing directive">;
def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal;
+def err_pp_file_not_found_not_fatal : Error<
+ "'%0' file not found with <angled> include; use \"quotes\" instead">;
def err_pp_error_opening_file : Error<
"error opening file '%0': %1">, DefaultFatal;
def err_pp_empty_filename : Error<"empty filename">;
@@ -324,8 +332,7 @@ def err_feature_check_malformed : Error<
"builtin feature check macro requires a parenthesized identifier">;
def err_warning_check_malformed : Error<
- "builtin warning check macro requires a parenthesized string">,
- InGroup<MalformedWarningCheck>;
+ "builtin warning check macro requires a parenthesized string">;
def warn_has_warning_invalid_option :
ExtWarn<"__has_warning expected option name (e.g. \"-Wundef\")">,
InGroup<MalformedWarningCheck>;
@@ -394,7 +401,7 @@ def err_paste_at_start : Error<
"'##' cannot appear at start of macro expansion">;
def err_paste_at_end : Error<"'##' cannot appear at end of macro expansion">;
def ext_paste_comma : Extension<
- "Use of comma pasting extension is non-portable">;
+ "token pasting of ',' and __VA_ARGS__ is a GNU extension">, InGroup<GNU>;
def err_unterm_macro_invoc : Error<
"unterminated function-like macro invocation">;
def err_too_many_args_in_macro_invoc : Error<
@@ -412,6 +419,9 @@ def err_pp_illegal_floating_literal : Error<
"floating point literal in preprocessor expression">;
def err_pp_line_requires_integer : Error<
"#line directive requires a positive integer argument">;
+def ext_pp_line_zero : Extension<
+ "#line directive with zero argument is a GNU extension">,
+ InGroup<GNU>;
def err_pp_line_invalid_filename : Error<
"invalid filename for #line directive">;
def warn_pp_line_decimal : Warning<
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index c183da7a6ac9..8cb82fd4a914 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -20,23 +20,32 @@ def warn_file_asm_volatile : Warning<
let CategoryName = "Parse Issue" in {
-def ext_empty_source_file : Extension<"ISO C forbids an empty source file">;
-def ext_top_level_semi : Extension<
- "extra ';' outside of a function">;
+def ext_empty_translation_unit : Extension<
+ "ISO C requires a translation unit to contain at least one declaration.">,
+ InGroup<DiagGroup<"empty-translation-unit">>;
def warn_cxx98_compat_top_level_semi : Warning<
"extra ';' outside of a function is incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
-def ext_extra_struct_semi : Extension<
- "extra ';' inside a %0">;
-def ext_extra_ivar_semi : Extension<
- "extra ';' inside instance variable list">;
+def ext_extra_semi : Extension<
+ "extra ';' %select{"
+ "outside of a function|"
+ "inside a %1|"
+ "inside instance variable list|"
+ "after member function definition}0">,
+ InGroup<ExtraSemi>;
+def ext_extra_semi_cxx11 : Extension<
+ "extra ';' outside of a function is a C++11 extension">,
+ InGroup<CXX11ExtraSemi>;
+def warn_extra_semi_after_mem_fn_def : Warning<
+ "extra ';' after member function definition">,
+ InGroup<ExtraSemi>, DefaultIgnore;
def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
def ext_integer_complex : Extension<
"complex integer types are an extension">;
-def ext_thread_before : Extension<"'__thread' before 'static'">;
+def ext_thread_before : Extension<"'__thread' before '%0'">;
def ext_empty_struct_union : Extension<
"empty %select{struct|union}0 is a GNU extension">, InGroup<GNU>;
@@ -58,9 +67,12 @@ def ext_c99_compound_literal : Extension<
"compound literals are a C99-specific feature">, InGroup<C99>;
def ext_c99_flexible_array_member : Extension<
"Flexible array members are a C99-specific feature">, InGroup<C99>;
-def ext_enumerator_list_comma : Extension<
- "commas at the end of enumerator lists are a %select{C99|C++11}0-specific "
- "feature">;
+def ext_enumerator_list_comma_c : Extension<
+ "commas at the end of enumerator lists are a C99-specific "
+ "feature">, InGroup<C99>;
+def ext_enumerator_list_comma_cxx : Extension<
+ "commas at the end of enumerator lists are a C++11 extension">,
+ InGroup<CXX11>;
def warn_cxx98_compat_enumerator_list_comma : Warning<
"commas at the end of enumerator lists are incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
@@ -89,8 +101,8 @@ def err_duplicate_default_assoc : Error<
def note_previous_default_assoc : Note<
"previous default generic association is here">;
-def ext_c11_alignas : Extension<
- "_Alignas is a C11-specific feature">, InGroup<C11>;
+def ext_c11_alignment : Extension<
+ "%0 is a C11-specific feature">, InGroup<C11>;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">, InGroup<GNU>;
@@ -311,7 +323,7 @@ def err_templated_using_directive : Error<
def err_templated_using_declaration : Error<
"cannot template a using declaration">;
def err_unexected_colon_in_nested_name_spec : Error<
- "unexpected ':' in nested name specifier">;
+ "unexpected ':' in nested name specifier; did you mean '::'?">;
def err_bool_redeclaration : Error<
"redeclaration of C++ built-in type 'bool'">;
def ext_c11_static_assert : Extension<
@@ -336,6 +348,9 @@ def err_illegal_super_cast : Error<
"cannot cast 'super' (it isn't an expression)">;
def err_nsnumber_nonliteral_unary : Error<
"@%0 must be followed by a number to form an NSNumber object">;
+def warn_cstyle_param : Warning<
+ "use of C-style parameters in Objective-C method declarations"
+ " is deprecated">, InGroup<DeprecatedDeclarations>;
let CategoryName = "ARC Parse Issue" in {
def err_arc_bridge_retain : Error<
@@ -377,6 +392,8 @@ def err_synthesized_property_name : Error<
def warn_semicolon_before_method_body : Warning<
"semicolon before method body is ignored">,
InGroup<DiagGroup<"semicolon-before-method-body">>, DefaultIgnore;
+def note_extra_comma_message_arg : Note<
+ "comma separating Objective-C messaging arguments">;
def err_expected_field_designator : Error<
"expected a field designator, such as '.field = 4'">;
@@ -396,9 +413,8 @@ def err_expected_init_in_condition : Error<
"variable declaration in condition must have an initializer">;
def err_expected_init_in_condition_lparen : Error<
"variable declaration in condition cannot have a parenthesized initializer">;
-def warn_parens_disambiguated_as_function_decl : Warning<
- "parentheses were disambiguated as a function declarator">,
- InGroup<VexingParse>;
+def err_extraneous_rparen_in_condition : Error<
+ "extraneous ')' after condition, expected a statement">;
def warn_dangling_else : Warning<
"add explicit braces to avoid dangling else">,
InGroup<DanglingElse>;
@@ -474,6 +490,10 @@ def err_l_square_l_square_not_attribute : Error<
"introducing an attribute">;
def err_alignas_pack_exp_unsupported : Error<
"pack expansions in alignment specifiers are not supported yet">;
+def err_ms_declspec_type : Error<
+ "__declspec attributes must be an identifier or string literal">;
+def warn_ms_declspec_unknown : Warning<
+ "unknown __declspec attribute %0 ignored">, InGroup<UnknownAttributes>;
/// C++ Templates
def err_expected_template : Error<"expected template">;
@@ -491,9 +511,12 @@ def err_id_after_template_in_nested_name_spec : Error<
"expected template name after 'template' keyword in nested name specifier">;
def err_two_right_angle_brackets_need_space : Error<
"a space is required between consecutive right angle brackets (use '> >')">;
+def err_right_angle_bracket_equal_needs_space : Error<
+ "a space is required between a right angle bracket and an equals sign "
+ "(use '> =')">;
def warn_cxx0x_right_shift_in_template_arg : Warning<
"use of right-shift operator ('>>') in template argument will require "
- "parentheses in C++11">;
+ "parentheses in C++11">, InGroup<CXX11Compat>;
def warn_cxx98_compat_two_right_angle_brackets : Warning<
"consecutive right angle brackets are incompatible with C++98 (use '> >')">,
InGroup<CXX98Compat>, DefaultIgnore;
@@ -648,9 +671,11 @@ def err_availability_unknown_change : Error<
"%0 is not an availability stage; use 'introduced', 'deprecated', or "
"'obsoleted'">;
def err_availability_redundant : Error<
- "redundant %0 availability change; only the last specified change will " "be used">;
+ "redundant %0 availability change; only the last specified change will "
+ "be used">;
def warn_availability_and_unavailable : Warning<
- "'unavailable' availability overrides all other availability information">;
+ "'unavailable' availability overrides all other availability information">,
+ InGroup<Availability>;
// Language specific pragmas
// - Generic warnings
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 0614adee85b8..6d7b52e55f58 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -14,6 +14,19 @@
let Component = "Sema" in {
let CategoryName = "Semantic Issue" in {
+// For loop analysis
+def warn_variables_not_in_loop_body : Warning<
+ "variable%select{s| %1|s %1 and %2|s %1, %2, and %3|s %1, %2, %3, and %4}0 "
+ "used in loop condition not modified in loop body">,
+ InGroup<DiagGroup<"loop-analysis">>, DefaultIgnore;
+
+def warn_identical_enum_values : Warning<
+ "all elements of %0 are initialized with literals to value %1">,
+ InGroup<DiagGroup<"unique-enum">>;
+def note_identical_enum_values : Note<
+ "initialize the last element with the previous element to silence "
+ "this warning">;
+
// Constant expressions
def err_expr_not_ice : Error<
"expression is not an %select{integer|integral}0 constant expression">;
@@ -145,6 +158,11 @@ def warn_redefinition_in_param_list : Warning<
def warn_empty_parens_are_function_decl : Warning<
"empty parentheses interpreted as a function declaration">,
InGroup<VexingParse>;
+def warn_parens_disambiguated_as_function_declaration : Warning<
+ "parentheses were disambiguated as a function declaration">,
+ InGroup<VexingParse>;
+def note_additional_parens_for_variable_declaration : Note<
+ "add a pair of parentheses to declare a variable">;
def note_empty_parens_function_call : Note<
"change this ',' to a ';' to call %0">;
def note_empty_parens_default_ctor : Note<
@@ -160,9 +178,15 @@ def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">,
def warn_unneeded_internal_decl : Warning<
"%select{function|variable}0 %1 is not needed and will not be emitted">,
InGroup<UnneededInternalDecl>, DefaultIgnore;
+def warn_unneeded_static_internal_decl : Warning<
+ "'static' function %0 declared in header file "
+ "should be declared 'static inline'">,
+ InGroup<UnneededInternalDecl>, DefaultIgnore;
def warn_unneeded_member_function : Warning<
"member function %0 is not needed and will not be emitted">,
InGroup<UnneededMemberFunction>, DefaultIgnore;
+def warn_unused_private_field: Warning<"private field %0 is not used">,
+ InGroup<UnusedPrivateField>, DefaultIgnore;
def warn_parameter_size: Warning<
"%0 is a large (%1 bytes) pass-by-value argument; "
@@ -173,6 +197,9 @@ def warn_return_value_size: Warning<
def warn_return_value_udt: Warning<
"%0 has C-linkage specified, but returns user-defined type %1 which is "
"incompatible with C">, InGroup<ReturnTypeCLinkage>;
+def warn_return_value_udt_incomplete: Warning<
+ "%0 has C-linkage specified, but returns incomplete type %1 which could be "
+ "incompatible with C">, InGroup<ReturnTypeCLinkage>;
def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
@@ -325,10 +352,14 @@ def warn_dyn_class_memaccess : Warning<
def note_bad_memaccess_silence : Note<
"explicitly cast the pointer to silence this warning">;
def warn_sizeof_pointer_expr_memaccess : Warning<
- "argument to 'sizeof' in %0 call is the same expression as the "
- "%select{destination|source}1; did you mean to "
- "%select{dereference it|remove the addressof|provide an explicit length}2?">,
+ "'%0' call operates on objects of type %1 while the size is based on a "
+ "different type %2">,
InGroup<DiagGroup<"sizeof-pointer-memaccess">>;
+def warn_sizeof_pointer_expr_memaccess_note : Note<
+ "did you mean to %select{dereference the argument to 'sizeof' (and multiply "
+ "it by the number of elements)|remove the addressof in the argument to "
+ "'sizeof' (and multiply it by the number of elements)|provide an explicit "
+ "length}0?">;
def warn_sizeof_pointer_type_memaccess : Warning<
"argument to 'sizeof' in %0 call is the same pointer type %1 as the "
"%select{destination|source}2; expected %3 or an explicit length">,
@@ -342,9 +373,11 @@ def note_strlcpycat_wrong_size : Note<
def warn_strncat_large_size : Warning<
"the value of the size argument in 'strncat' is too large, might lead to a "
- "buffer overflow">, InGroup<StrncatSize>, DefaultIgnore;
+ "buffer overflow">, InGroup<StrncatSize>;
def warn_strncat_src_size : Warning<"size argument in 'strncat' call appears "
- "to be size of the source">, InGroup<StrncatSize>, DefaultIgnore;
+ "to be size of the source">, InGroup<StrncatSize>;
+def warn_strncat_wrong_size : Warning<
+ "the value of the size argument to 'strncat' is wrong">, InGroup<StrncatSize>;
def note_strncat_wrong_size : Note<
"change the argument to be the free space in the destination buffer minus "
"the terminating null byte">;
@@ -442,6 +475,8 @@ def err_class_extension_after_impl : Error<
"cannot declare class extension for %0 after class implementation">;
def note_implementation_declared : Note<
"class implementation is declared here">;
+def note_while_in_implementation : Note<
+ "detected while default synthesizing properties in class implementation">;
def note_class_declared : Note<
"class is declared here">;
def note_receiver_is_id : Note<
@@ -452,7 +487,7 @@ def err_objc_root_class_subclass : Error<
"objc_root_class attribute may only be specified on a root class declaration">;
def warn_objc_root_class_missing : Warning<
"class %0 defined without specifying a base class">,
- InGroup<ObjCRootClass>, DefaultIgnore;
+ InGroup<ObjCRootClass>;
def note_objc_needs_superclass : Note<
"add a super class to fix this problem">;
def warn_dup_category_def : Warning<
@@ -462,7 +497,7 @@ def err_dup_implementation_class : Error<"reimplementation of class %0">;
def err_dup_implementation_category : Error<
"reimplementation of category %1 for class %0">;
def err_conflicting_ivar_type : Error<
- "instance variable %0 has conflicting type: %1 vs %2">;
+ "instance variable %0 has conflicting type%diff{: $ vs $|}1,2">;
def err_duplicate_ivar_declaration : Error<
"instance variable is already declared">;
def warn_on_superclass_use : Warning<
@@ -481,12 +516,12 @@ def note_required_for_protocol_at :
def warn_conflicting_overriding_ret_types : Warning<
"conflicting return type in "
- "declaration of %0: %1 vs %2">,
+ "declaration of %0%diff{: $ vs $|}1,2">,
InGroup<OverridingMethodMismatch>, DefaultIgnore;
def warn_conflicting_ret_types : Warning<
"conflicting return type in "
- "implementation of %0: %1 vs %2">;
+ "implementation of %0%diff{: $ vs $|}1,2">;
def warn_conflicting_overriding_ret_type_modifiers : Warning<
"conflicting distributed object modifiers on return type "
@@ -510,12 +545,12 @@ def warn_non_covariant_ret_types : Warning<
def warn_conflicting_overriding_param_types : Warning<
"conflicting parameter types in "
- "declaration of %0: %1 vs %2">,
+ "declaration of %0%diff{: $ vs $|}1,2">,
InGroup<OverridingMethodMismatch>, DefaultIgnore;
def warn_conflicting_param_types : Warning<
"conflicting parameter types in "
- "implementation of %0: %1 vs %2">;
+ "implementation of %0%diff{: $ vs $|}1,2">;
def warn_conflicting_param_modifiers : Warning<
"conflicting distributed object modifiers on parameter type "
"in implementation of %0">,
@@ -575,15 +610,17 @@ def err_objc_property_requires_object : Error<
"property with '%0' attribute must be of object type">;
def warn_objc_property_no_assignment_attribute : Warning<
"no 'assign', 'retain', or 'copy' attribute is specified - "
- "'assign' is assumed">;
+ "'assign' is assumed">,
+ InGroup<ObjCPropertyNoAttribute>;
def warn_objc_isa_use : Warning<
"direct access to objective-c's isa is deprecated "
"in favor of object_setClass() and object_getClass()">,
InGroup<DiagGroup<"deprecated-objc-isa-usage">>;
def warn_objc_property_default_assign_on_object : Warning<
- "default property attribute 'assign' not appropriate for non-gc object">;
+ "default property attribute 'assign' not appropriate for non-GC object">,
+ InGroup<ObjCPropertyNoAttribute>;
def warn_property_attr_mismatch : Warning<
- "property attribute in continuation class does not match the primary class">;
+ "property attribute in class extension does not match the primary class">;
def warn_objc_property_copy_missing_on_block : Warning<
"'copy' attribute must be specified for the block property "
"when -fobjc-gc-only is specified">;
@@ -610,9 +647,19 @@ def warn_auto_synthesizing_protocol_property :Warning<
"auto property synthesis will not synthesize property"
" declared in a protocol">,
InGroup<DiagGroup<"objc-protocol-property-synthesis">>;
+def warn_autosynthesis_property_ivar_match :Warning<
+ "autosynthesized property %0 will use %select{|synthesized}1 instance variable "
+ "%2, not existing instance variable %3">,
+ InGroup<DiagGroup<"objc-autosynthesis-property-ivar-name-match">>;
+def warn_missing_explicit_synthesis : Warning <
+ "auto property synthesis is synthesizing property not explicitly synthesized">,
+ InGroup<DiagGroup<"objc-missing-property-synthesis">>, DefaultIgnore;
def warn_property_getter_owning_mismatch : Warning<
"property declared as returning non-retained objects"
"; getter returning retained objects">;
+def error_property_setter_ambiguous_use : Error<
+ "synthesized properties '%0' and '%1' both claim setter %2 -"
+ " use of this setter will cause unexpected behavior">;
def err_ownin_getter_rule : Error<
"property's synthesized getter follows Cocoa naming"
" convention for returning 'owned' objects">;
@@ -621,16 +668,16 @@ def warn_default_atomic_custom_getter_setter : Warning<
"(property should be marked 'atomic' if this is intended)">,
InGroup<CustomAtomic>, DefaultIgnore;
def err_use_continuation_class : Error<
- "illegal redeclaration of property in continuation class %0"
+ "illegal redeclaration of property in class extension %0"
" (attribute must be 'readwrite', while its primary must be 'readonly')">;
def err_type_mismatch_continuation_class : Error<
- "type of property %0 in continuation class does not match "
+ "type of property %0 in class extension does not match "
"property type in primary class">;
def err_use_continuation_class_redeclaration_readwrite : Error<
- "illegal redeclaration of 'readwrite' property in continuation class %0"
+ "illegal redeclaration of 'readwrite' property in class extension %0"
" (perhaps you intended this to be a 'readwrite' redeclaration of a "
"'readonly' public property?)">;
-def err_continuation_class : Error<"continuation class has no primary class">;
+def err_continuation_class : Error<"class extension has no primary class">;
def err_property_type : Error<"property cannot have array or function type %0">;
def error_missing_property_context : Error<
"missing context for property implementation declaration">;
@@ -664,15 +711,16 @@ def warn_arc_perform_selector_leaks : Warning<
def err_gc_weak_property_strong_type : Error<
"weak attribute declared on a __strong type property in GC mode">;
def warn_receiver_is_weak : Warning <
- "weak receiver may be unpredictably null in ARC mode">,
+ "weak %select{receiver|property|implicit property}0 may be "
+ "unpredictably null in ARC mode">,
InGroup<DiagGroup<"receiver-is-weak">>, DefaultIgnore;
-
-def error_synthesized_ivar_yet_not_supported : Error<
- "instance variable synthesis not yet supported"
- " (need to declare %0 explicitly)">;
+def err_incomplete_synthesized_property : Error<
+ "cannot synthesize property %0 with incomplete type %1">;
def error_property_ivar_type : Error<
"type of property %0 (%1) does not match type of ivar %2 (%3)">;
+def error_property_accessor_type : Error<
+ "type of property %0 (%1) does not match type of accessor %2 (%3)">;
def error_ivar_in_superclass_use : Error<
"property %0 attempting to use ivar %1 declared in super class %2">;
def error_weak_property : Error<
@@ -690,6 +738,9 @@ def warn_objc_property_attr_mutually_exclusive : Warning<
def warn_objc_missing_super_dealloc : Warning<
"method possibly missing a [super dealloc] call">,
InGroup<ObjCMissingSuperCalls>;
+def error_dealloc_bad_result_type : Error<
+ "dealloc return type must be correctly specified as 'void' under ARC, "
+ "instead of %0">;
def warn_objc_missing_super_finalize : Warning<
"method possibly missing a [super finalize] call">,
InGroup<ObjCMissingSuperCalls>;
@@ -697,6 +748,12 @@ def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
def warn_implicit_atomic_property : Warning<
"property is assumed atomic by default">, InGroup<ImplicitAtomic>, DefaultIgnore;
+def note_auto_readonly_iboutlet_fixup_suggest : Note<
+ "readonly IBOutlet property should be changed to be readwrite">;
+def warn_auto_readonly_iboutlet_property : Warning<
+ "readonly IBOutlet property when auto-synthesized may "
+ "not work correctly with 'nib' loader">,
+ InGroup<DiagGroup<"readonly-iboutlet-property">>;
def warn_auto_implicit_atomic_property : Warning<
"property is assumed atomic when auto-synthesizing the property">,
InGroup<ImplicitAtomic>, DefaultIgnore;
@@ -823,8 +880,6 @@ def warn_missing_exception_specification : Warning<
"%0 is missing exception specification '%1'">;
def err_noexcept_needs_constant_expression : Error<
"argument to noexcept specifier must be a constant expression">;
-def err_exception_spec_unknown : Error<
- "exception specification is not available until end of class definition">;
// C++ access checking
def err_class_redeclared_with_different_access : Error<
@@ -854,6 +909,9 @@ def err_access_field_ctor : Error<
"field of type %0 has %select{private|protected}2 "
"%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}1constructor">,
AccessControl;
+def err_access_friend_function : Error<
+ "friend function %1 is a %select{private|protected}0 member of %3">,
+ AccessControl;
def err_access_dtor : Error<
"calling a %select{private|protected}1 destructor of class %0">,
@@ -1015,8 +1073,9 @@ def ext_anonymous_struct_union_qualified : Extension<
"anonymous %select{struct|union}0 cannot be '%select{const|volatile|"
"restrict}1'">;
def err_different_return_type_for_overriding_virtual_function : Error<
- "virtual function %0 has a different return type (%1) than the "
- "function it overrides (which has return type %2)">;
+ "virtual function %0 has a different return type "
+ "%diff{($) than the function it overrides (which has return type $)|"
+ "than the function it overrides}1,2">;
def note_overridden_virtual_function : Note<
"overridden virtual function is here">;
@@ -1094,36 +1153,43 @@ def err_destructor_template : Error<
def err_init_conversion_failed : Error<
"cannot initialize %select{a variable|a parameter|return object|an "
"exception object|a member subobject|an array element|a new value|a value|a "
- "base class|a constructor delegation|a vector element}0 of type %1 with an "
- "%select{rvalue|lvalue}2 of type %3"
- "%select{|: different classes (%5 vs %6)"
+ "base class|a constructor delegation|a vector element}0 "
+ "%diff{of type $ with an %select{rvalue|lvalue}2 of type $|"
+ "with an %select{rvalue|lvalue}2 of incompatible type}1,3"
+ "%select{|: different classes%diff{ ($ vs $)|}5,6"
"|: different number of parameters (%5 vs %6)"
- "|: type mismatch at %ordinal5 parameter (%6 vs %7)"
- "|: different return type (%5 vs %6)"
+ "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7"
+ "|: different return type%diff{ ($ vs $)|}5,6"
"|: different qualifiers ("
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}5 vs "
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}6)}4">;
-def err_lvalue_to_rvalue_ref : Error<"rvalue reference to type %0 cannot bind "
- "to lvalue of type %1">;
+def err_lvalue_to_rvalue_ref : Error<"rvalue reference %diff{to type $ cannot "
+ "bind to lvalue of type $|cannot bind to incompatible lvalue}0,1">;
def err_lvalue_reference_bind_to_initlist : Error<
"%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to an "
"initializer list temporary">;
def err_lvalue_reference_bind_to_temporary : Error<
- "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
- "temporary of type %2">;
+ "%select{non-const|volatile}0 lvalue reference %diff{to type $ cannot bind "
+ "to a temporary of type $|cannot bind to incompatible temporary}1,2">;
def err_lvalue_reference_bind_to_unrelated : Error<
- "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
- "value of unrelated type %2">;
+ "%select{non-const|volatile}0 lvalue reference "
+ "%diff{to type $ cannot bind to a value of unrelated type $|"
+ "cannot bind to a value of unrelated type}1,2">;
def err_reference_bind_drops_quals : Error<
- "binding of reference to type %0 to a value of type %1 drops qualifiers">;
+ "binding of reference %diff{to type $ to a value of type $ drops qualifiers|"
+ "drops qualifiers}0,1">;
def err_reference_bind_failed : Error<
- "reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type "
- "%2">;
+ "reference %diff{to type $ could not bind to an %select{rvalue|lvalue}1 of "
+ "type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">;
def err_reference_bind_init_list : Error<
"reference to type %0 cannot bind to an initializer list">;
+def warn_temporary_array_to_pointer_decay : Warning<
+ "pointer is initialized by a temporary array, which will be destroyed at the "
+ "end of the full-expression">,
+ InGroup<DiagGroup<"address-of-array-temporary">>;
def err_init_list_bad_dest_type : Error<
"%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
"list">;
@@ -1154,19 +1220,21 @@ def warn_uninit_self_reference_in_init : Warning<
"variable %0 is uninitialized when used within its own initialization">,
InGroup<Uninitialized>;
def warn_uninit_var : Warning<
- "variable %0 is uninitialized when used here">,
- InGroup<Uninitialized>, DefaultIgnore;
-def warn_maybe_uninit_var :
- Warning<"variable %0 may be uninitialized when used here">,
- InGroup<UninitializedMaybe>, DefaultIgnore;
-def note_uninit_var_def : Note<
- "variable %0 is declared here">;
-def warn_uninit_var_captured_by_block : Warning<
- "variable %0 is uninitialized when captured by block">,
+ "variable %0 is uninitialized when %select{used here|captured by block}1">,
InGroup<Uninitialized>, DefaultIgnore;
-def warn_maybe_uninit_var_captured_by_block : Warning<
- "variable %0 may be uninitialized when captured by block">,
+def warn_sometimes_uninit_var : Warning<
+ "variable %0 is %select{used|captured}1 uninitialized whenever "
+ "%select{'%3' condition is %select{true|false}4|"
+ "'%3' loop %select{is entered|exits because its condition is false}4|"
+ "'%3' loop %select{condition is true|exits because its condition is false}4|"
+ "switch %3 is taken}2">, InGroup<UninitializedSometimes>, DefaultIgnore;
+def warn_maybe_uninit_var : Warning<
+ "variable %0 may be uninitialized when "
+ "%select{used here|captured by block}1">,
InGroup<UninitializedMaybe>, DefaultIgnore;
+def note_uninit_var_def : Note<"variable %0 is declared here">;
+def note_uninit_var_use : Note<
+ "%select{uninitialized use occurs|variable is captured by block}0 here">;
def warn_uninit_byref_blockvar_captured_by_block : Warning<
"block pointer variable %0 is uninitialized when captured by block">,
InGroup<Uninitialized>, DefaultIgnore;
@@ -1174,6 +1242,9 @@ def note_block_var_fixit_add_initialization : Note<
"maybe you meant to use __block %0">;
def note_var_fixit_add_initialization : Note<
"initialize the variable %0 to silence this warning">;
+def note_uninit_fixit_remove_cond : Note<
+ "remove the %select{'%1' if its condition|condition if it}0 "
+ "is always %select{false|true}2">;
def err_init_incomplete_type : Error<"initialization of incomplete type %0">;
def err_temp_copy_no_viable : Error<
@@ -1316,10 +1387,8 @@ def err_delegating_initializer_alone : Error<
def warn_delegating_ctor_cycle : Warning<
"constructor for %0 creates a delegation cycle">, DefaultError,
InGroup<DelegatingCtorCycles>;
-def note_it_delegates_to : Note<
- "it delegates to">, InGroup<DelegatingCtorCycles>;
-def note_which_delegates_to : Note<
- "which delegates to">, InGroup<DelegatingCtorCycles>;
+def note_it_delegates_to : Note<"it delegates to">;
+def note_which_delegates_to : Note<"which delegates to">;
// C++11 range-based for loop
def err_for_range_decl_must_be_var : Error<
@@ -1370,6 +1439,8 @@ def err_constexpr_virtual : Error<"virtual function cannot be constexpr">;
def err_constexpr_virtual_base : Error<
"constexpr %select{member function|constructor}0 not allowed in "
"%select{class|struct}1 with virtual base %plural{1:class|:classes}2">;
+def note_non_literal_incomplete : Note<
+ "incomplete type %0 is not a literal type">;
def note_non_literal_virtual_base : Note<"%select{class|struct}0 with virtual "
"base %plural{1:class|:classes}1 is not a literal type">;
def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
@@ -1427,6 +1498,10 @@ def warn_cxx98_compat_unicode_type : Warning<
// Objective-C++
def err_objc_decls_may_only_appear_in_global_scope : Error<
"Objective-C declarations may only appear in global scope">;
+def warn_auto_var_is_id : Warning<
+ "'auto' deduced as 'id' in declaration of %0">,
+ InGroup<DiagGroup<"auto-var-id">>;
+
// Attributes
def err_nsobject_attribute : Error<
"__attribute ((NSObject)) is for pointer types only">;
@@ -1451,6 +1526,8 @@ def err_attribute_bad_neon_vector_size : Error<
"Neon vector size must be 64 or 128 bits">;
def err_attribute_argument_not_int : Error<
"'%0' attribute requires integer constant">;
+def err_aligned_attribute_argument_not_int : Error<
+ "'aligned' attribute requires integer constant">;
def err_attribute_argument_not_class : Error<
"%0 attribute requires arguments that are class type or point to class type">;
def err_attribute_first_argument_not_int_or_bool : Error<
@@ -1522,17 +1599,19 @@ def err_undeclared_nsnumber : Error<
"NSNumber must be available to use Objective-C literals">;
def err_invalid_nsnumber_type : Error<
"%0 is not a valid literal type for NSNumber">;
+def err_undeclared_nsstring : Error<
+ "cannot box a string value because NSString has not been declared">;
+def err_objc_illegal_boxed_expression_type : Error<
+ "illegal type %0 used in a boxed expression">;
+def err_objc_incomplete_boxed_expression_type : Error<
+ "incomplete type %0 used in a boxed expression">;
def err_undeclared_nsarray : Error<
"NSArray must be available to use Objective-C array literals">;
def err_undeclared_nsdictionary : Error<
"NSDictionary must be available to use Objective-C dictionary "
"literals">;
-def err_undeclared_arraywithobjects : Error<
- "declaration of %0 is missing in NSArray class">;
-def err_undeclared_dictwithobjects : Error<
- "declaration of %0 is missing in NSDictionary class">;
-def err_undeclared_nsnumber_method : Error<
- "declaration of %0 is missing in NSNumber class">;
+def err_undeclared_boxing_method : Error<
+ "declaration of %0 is missing in %1 class">;
def err_objc_literal_method_sig : Error<
"literal construction method %0 has incompatible signature">;
def note_objc_literal_method_param : Note<
@@ -1545,50 +1624,81 @@ def err_invalid_collection_element : Error<
def err_box_literal_collection : Error<
"%select{string|character|boolean|numeric}0 literal must be prefixed by '@' "
"in a collection">;
+def warn_objc_literal_comparison : Warning<
+ "direct comparison of %select{an array literal|a dictionary literal|"
+ "a numeric literal|a boxed expression|}0 has undefined behavior">,
+ InGroup<ObjCLiteralComparison>;
+def warn_objc_string_literal_comparison : Warning<
+ "direct comparison of a string literal has undefined behavior">,
+ InGroup<ObjCStringComparison>;
+def note_objc_literal_comparison_isequal : Note<
+ "use 'isEqual:' instead">;
let CategoryName = "Cocoa API Issue" in {
def warn_objc_redundant_literal_use : Warning<
"using %0 with a literal is redundant">, InGroup<ObjCRedundantLiteralUse>;
}
+def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", "
+ "\"local-dynamic\", \"initial-exec\" or \"local-exec\"">;
+
def err_only_annotate_after_access_spec : Error<
"access specifier can only have annotation attributes">;
+
def err_attribute_section_invalid_for_target : Error<
"argument to 'section' attribute is not valid for this target: %0">;
def err_attribute_section_local_variable : Error<
"'section' attribute is not valid on local variables">;
+def warn_mismatched_section : Warning<
+ "section does not match previous declaration">, InGroup<Section>;
+
def err_attribute_aligned_not_power_of_two : Error<
"requested alignment is not a power of 2">;
+def err_attribute_aligned_greater_than_8192 : Error<
+ "requested alignment must be 8192 bytes or smaller">;
def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
"'%0' redeclared without %1 attribute: previous %1 ignored">;
-def warn_attribute_ignored : Warning<"%0 attribute ignored">;
+def warn_attribute_ignored : Warning<"%0 attribute ignored">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_after_definition_ignored : Warning<
+ "attribute %0 after definition is ignored">,
+ InGroup<IgnoredAttributes>;
def warn_unknown_attribute_ignored : Warning<
"unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
+def warn_unhandled_ms_attribute_ignored : Warning<
+ "__declspec attribute %0 is not supported">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_invalid_on_stmt : Warning<
"attribute %0 cannot be specified on a statement">,
InGroup<IgnoredAttributes>;
def warn_declspec_attribute_ignored : Warning<
"attribute %0 is ignored, place it after \"%select{class|struct|union|enum}1\" to apply attribute to type declaration">, InGroup<IgnoredAttributes>;
def warn_attribute_precede_definition : Warning<
- "attribute declaration must precede definition">;
+ "attribute declaration must precede definition">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_void_function_method : Warning<
"attribute %0 cannot be applied to "
- "%select{functions|Objective-C method}1 without return value">;
+ "%select{functions|Objective-C method}1 without return value">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_weak_on_field : Warning<
- "__weak attribute cannot be specified on a field declaration">;
+ "__weak attribute cannot be specified on a field declaration">,
+ InGroup<IgnoredAttributes>;
def warn_gc_attribute_weak_on_local : Warning<
- "Objective-C GC does not allow weak variables on the stack">;
+ "Objective-C GC does not allow weak variables on the stack">,
+ InGroup<IgnoredAttributes>;
def warn_nsobject_attribute : Warning<
"__attribute ((NSObject)) may be put on a typedef only, "
"attribute is ignored">, InGroup<NSobjectAttribute>;
def warn_attribute_weak_on_local : Warning<
- "__weak attribute cannot be specified on an automatic variable">;
+ "__weak attribute cannot be specified on an automatic variable">,
+ InGroup<IgnoredAttributes>;
def warn_weak_identifier_undeclared : Warning<
"weak identifier %0 never declared">;
def err_attribute_weak_static : Error<
"weak declaration cannot have internal linkage">;
def warn_attribute_weak_import_invalid_on_definition : Warning<
- "'weak_import' attribute cannot be specified on a definition">;
+ "'weak_import' attribute cannot be specified on a definition">,
+ InGroup<IgnoredAttributes>;
def err_attribute_weakref_not_static : Error<
"weakref declaration must have internal linkage">;
def err_attribute_weakref_not_global_context : Error<
@@ -1602,22 +1712,31 @@ def warn_attribute_wrong_decl_type : Warning<
"variables and functions|functions and methods|parameters|"
"functions, methods and blocks|functions, methods, and parameters|"
"classes|variables|methods|variables, functions and labels|"
- "fields and global variables|structs}1">;
+ "fields and global variables|structs|"
+ "variables, functions and tag types|thread-local variables}1">,
+ InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<
"%0 attribute only applies to %select{functions|unions|"
"variables and functions|functions and methods|parameters|"
"functions, methods and blocks|functions, methods, and parameters|"
"classes|variables|methods|variables, functions and labels|"
- "fields and global variables|structs}1">;
+ "fields and global variables|structs|thread-local variables}1">;
def warn_function_attribute_wrong_type : Warning<
- "'%0' only applies to function types; type here is %1">;
+ "'%0' only applies to function types; type here is %1">,
+ InGroup<IgnoredAttributes>;
def warn_pointer_attribute_wrong_type : Warning<
- "'%0' only applies to pointer types; type here is %1">;
+ "'%0' only applies to pointer types; type here is %1">,
+ InGroup<IgnoredAttributes>;
def warn_objc_object_attribute_wrong_type : Warning<
- "'%0' only applies to objective-c object or block pointer types; type here is %1">;
+ "'%0' only applies to Objective-C object or block pointer types; type here is %1">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_requires_functions_or_static_globals : Warning<
+ "%0 only applies to variables with static storage duration and functions">,
+ InGroup<IgnoredAttributes>;
def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
- " attribute ignored">;
+ " attribute ignored">,
+ InGroup<IgnoredAttributes>;
def err_attribute_vecreturn_only_vector_member : Error<
"the vecreturn attribute can only be used on a class or structure with one member, which must be a vector">;
def err_attribute_vecreturn_only_pod_record : Error<
@@ -1649,79 +1768,95 @@ def warn_attribute_not_on_decl : Error<
// Availability attribute
def warn_availability_unknown_platform : Warning<
- "unknown platform %0 in availability macro">;
+ "unknown platform %0 in availability macro">, InGroup<Availability>;
def warn_availability_version_ordering : Warning<
"feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version "
"%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; "
- "attribute ignored">;
-
+ "attribute ignored">, InGroup<Availability>;
+def warn_mismatched_availability: Warning<
+ "availability does not match previous declaration">, InGroup<Availability>;
+
// Thread Safety Attributes
-// Errors when parsing the attributes
+def warn_thread_attribute_ignored : Warning<
+ "ignoring %0 attribute because its argument is invalid">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_argument_not_lockable : Warning<
+ "%0 attribute requires arguments whose type is annotated "
+ "with 'lockable' attribute; type here is '%1'">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_argument_not_class : Warning<
+ "%0 attribute requires arguments that are class type or point to"
+ " class type; type here is '%1'">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_decl_not_lockable : Warning<
+ "%0 attribute can only be applied in a context annotated "
+ "with 'lockable' attribute">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_decl_not_pointer : Warning<
+ "'%0' only applies to pointer types; type here is %1">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_wrong_decl_type : Warning<
+ "%0 attribute only applies to %select{"
+ "fields and global variables|functions and methods|"
+ "classes and structs}1">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
def err_attribute_argument_out_of_range : Error<
"%0 attribute parameter %1 is out of bounds: "
"%plural{0:no parameters to index into|"
"1:can only be 1, since there is one parameter|"
":must be between 1 and %2}2">;
-def warn_attribute_argument_not_lockable : Warning<
- "%0 attribute requires arguments whose type is annotated "
- "with 'lockable' attribute; type here is '%1'">,
- InGroup<ThreadSafety>, DefaultIgnore;
-def warn_attribute_decl_not_lockable : Warning<
- "%0 attribute can only be applied in a context annotated "
- "with 'lockable' attribute">,
- InGroup<ThreadSafety>, DefaultIgnore;
-def warn_attribute_argument_not_class : Warning<
- "%0 attribute requires arguments that are class type or point to"
- " class type; type here is '%1'">,
- InGroup<ThreadSafety>, DefaultIgnore;
+
+// Thread Safety Analysis
def warn_unlock_but_no_lock : Warning<
"unlocking '%0' that was not locked">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_double_lock : Warning<
"locking '%0' that is already locked">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_no_unlock : Warning<
"mutex '%0' is still locked at the end of function">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_expecting_locked : Warning<
+ "expecting mutex '%0' to be locked at the end of function">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
// FIXME: improve the error message about locks not in scope
def warn_lock_some_predecessors : Warning<
"mutex '%0' is not locked on every path through here">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_expecting_lock_held_on_loop : Warning<
"expecting mutex '%0' to be locked at start of each loop">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def note_locked_here : Note<"mutex acquired here">;
def warn_lock_exclusive_and_shared : Warning<
"mutex '%0' is locked exclusively and shared in the same scope">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def note_lock_exclusive_and_shared : Note<
- "the other lock of mutex '%0' is here">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ "the other lock of mutex '%0' is here">;
def warn_variable_requires_lock : Warning<
"%select{reading|writing}2 variable '%0' requires locking "
"%select{'%1'|'%1' exclusively}2">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_var_deref_requires_lock : Warning<
"%select{reading|writing}2 the value pointed to by '%0' requires locking "
"%select{'%1'|'%1' exclusively}2">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_variable_requires_any_lock : Warning<
"%select{reading|writing}1 variable '%0' requires locking "
"%select{any mutex|any mutex exclusively}1">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_var_deref_requires_any_lock : Warning<
"%select{reading|writing}1 the value pointed to by '%0' requires locking "
"%select{any mutex|any mutex exclusively}1">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_fun_requires_lock : Warning<
"calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_fun_excludes_mutex : Warning<
"cannot call function '%0' while mutex '%1' is locked">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_cannot_resolve_lock : Warning<
"cannot resolve lock expression">,
- InGroup<ThreadSafety>, DefaultIgnore;
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_impcast_vector_scalar : Warning<
@@ -1755,8 +1890,7 @@ def warn_impcast_bitfield_precision_constant : Warning<
"implicit truncation from %2 to bitfield changes value from %0 to %1">,
InGroup<ConstantConversion>;
def warn_impcast_literal_float_to_integer : Warning<
- "implicit conversion turns literal floating-point number into integer: "
- "%0 to %1">,
+ "implicit conversion from %0 to %1 changes value from %2 to %3">,
InGroup<LiteralConversion>;
def warn_impcast_string_literal_to_bool : Warning<
"implicit conversion turns string literal into bool: %0 to %1">,
@@ -1767,6 +1901,9 @@ def warn_impcast_different_enum_types : Warning<
def warn_impcast_bool_to_null_pointer : Warning<
"initialization of pointer of type %0 to null from a constant boolean "
"expression">, InGroup<BoolConversion>;
+def warn_non_literal_null_pointer : Warning<
+ "expression which evaluates to zero treated as a null pointer constant of "
+ "type %0">, InGroup<NonLiteralNullConversion>;
def warn_impcast_null_pointer_to_integer : Warning<
"implicit conversion of NULL constant to %0">,
InGroup<NullConversion>;
@@ -1783,28 +1920,37 @@ def warn_cast_align : Warning<
InGroup<CastAlign>, DefaultIgnore;
def warn_attribute_ignored_for_field_of_type : Warning<
- "%0 attribute ignored for field of type %1">;
+ "%0 attribute ignored for field of type %1">,
+ InGroup<IgnoredAttributes>;
def warn_transparent_union_attribute_field_size_align : Warning<
"%select{alignment|size}0 of field %1 (%2 bits) does not match the "
"%select{alignment|size}0 of the first field in transparent union; "
- "transparent_union attribute ignored">;
+ "transparent_union attribute ignored">,
+ InGroup<IgnoredAttributes>;
def note_transparent_union_first_field_size_align : Note<
"%select{alignment|size}0 of first field is %1 bits">;
def warn_transparent_union_attribute_not_definition : Warning<
"transparent_union attribute can only be applied to a union definition; "
- "attribute ignored">;
+ "attribute ignored">,
+ InGroup<IgnoredAttributes>;
def warn_transparent_union_attribute_floating : Warning<
"first field of a transparent union cannot have %select{floating point|"
- "vector}0 type %1; transparent_union attribute ignored">;
+ "vector}0 type %1; transparent_union attribute ignored">,
+ InGroup<IgnoredAttributes>;
def warn_transparent_union_attribute_zero_fields : Warning<
"transparent union definition must contain at least one field; "
- "transparent_union attribute ignored">;
+ "transparent_union attribute ignored">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_type_not_supported : Warning<
- "'%0' attribute argument not supported: %1">;
-def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">;
+ "'%0' attribute argument not supported: %1">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_protected_visibility :
Warning<"target does not support 'protected' visibility; using 'default'">,
InGroup<DiagGroup<"unsupported-visibility">>;
+def err_mismatched_visibility: Error<"visibility does not match previous declaration">;
+def note_previous_attribute : Note<"previous attribute is here">;
def err_unknown_machine_mode : Error<"unknown machine mode %0">;
def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
def err_mode_not_primitive : Error<
@@ -1814,13 +1960,17 @@ def err_mode_wrong_type : Error<
def err_attr_wrong_decl : Error<
"'%0' attribute invalid on this declaration, requires typedef or value">;
def warn_attribute_nonnull_no_pointers : Warning<
- "'nonnull' attribute applied to function with no pointer arguments">;
+ "'nonnull' attribute applied to function with no pointer arguments">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_malloc_pointer_only : Warning<
- "'malloc' attribute only applies to functions returning a pointer type">;
+ "'malloc' attribute only applies to functions returning a pointer type">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_sentinel_named_arguments : Warning<
- "'sentinel' attribute requires named arguments">;
+ "'sentinel' attribute requires named arguments">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_sentinel_not_variadic : Warning<
- "'sentinel' attribute only supported for variadic %select{functions|blocks}0">;
+ "'sentinel' attribute only supported for variadic %select{functions|blocks}0">,
+ InGroup<IgnoredAttributes>;
def err_attribute_sentinel_less_than_zero : Error<
"'sentinel' parameter 1 less than zero">;
def err_attribute_sentinel_not_zero_or_one : Error<
@@ -1832,8 +1982,8 @@ def err_attribute_cleanup_arg_not_function : Error<
def err_attribute_cleanup_func_must_take_one_arg : Error<
"'cleanup' function %0 must take 1 parameter">;
def err_attribute_cleanup_func_arg_incompatible_type : Error<
- "'cleanup' function %0 parameter has type %1 which is incompatible with "
- "type %2">;
+ "'cleanup' function %0 parameter has "
+ "%diff{type $ which is incompatible with type $|incompatible type}1,2">;
def err_attribute_regparm_wrong_platform : Error<
"'regparm' is not valid on this platform">;
def err_attribute_regparm_invalid_number : Error<
@@ -1842,9 +1992,11 @@ def err_attribute_regparm_invalid_number : Error<
// Clang-Specific Attributes
def warn_attribute_iboutlet : Warning<
- "%0 attribute can only be applied to instance variables or properties">;
+ "%0 attribute can only be applied to instance variables or properties">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_ibaction: Warning<
- "ibaction attribute can only be applied to Objective-C instance methods">;
+ "ibaction attribute can only be applied to Objective-C instance methods">,
+ InGroup<IgnoredAttributes>;
def err_iboutletcollection_type : Error<
"invalid type %0 as argument of iboutletcollection attribute">;
def warn_iboutlet_object_type : Warning<
@@ -1862,10 +2014,12 @@ def err_attribute_overloadable_no_prototype : Error<
"'overloadable' function %0 must have a prototype">;
def warn_ns_attribute_wrong_return_type : Warning<
"%0 attribute only applies to %select{functions|methods}1 that "
- "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">;
+ "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">,
+ InGroup<IgnoredAttributes>;
def warn_ns_attribute_wrong_parameter_type : Warning<
"%0 attribute only applies to %select{Objective-C object|pointer}1 "
- "parameters">;
+ "parameters">,
+ InGroup<IgnoredAttributes>;
def err_ns_bridged_not_interface : Error<
"parameter of 'ns_bridged' attribute does not name an Objective-C class">;
@@ -1928,8 +2082,9 @@ def note_default_argument_declared_here : Note<
"default argument declared here">;
def ext_param_promoted_not_compatible_with_prototype : ExtWarn<
- "promoted type %0 of K&R function parameter is not compatible with the "
- "parameter type %1 declared in a previous prototype">,
+ "%diff{promoted type $ of K&R function parameter is not compatible with the "
+ "parameter type $|promoted type of K&R function parameter is not compatible "
+ "with parameter type}0,1 declared in a previous prototype">,
InGroup<KNRPromotedParameter>;
@@ -1964,10 +2119,11 @@ def note_ovl_candidate : Note<"candidate "
"is the implicit copy assignment operator|"
"is the implicit move assignment operator|"
"is an inherited constructor}0%1"
- "%select{| has different class (expected %3 but has %4)"
+ "%select{| has different class%diff{ (expected $ but has $)|}3,4"
"| has different number of parameters (expected %3 but has %4)"
- "| has type mismatch at %ordinal3 parameter (expected %4 but has %5)"
- "| has different return type (%3 expected but has %4)"
+ "| has type mismatch at %ordinal3 parameter"
+ "%diff{ (expected $ but has $)|}4,5"
+ "| has different return type%diff{ ($ expected but has $)|}3,4"
"| has different qualifiers (expected "
"%select{none|const|restrict|const and restrict|volatile|const and volatile"
"|volatile and restrict|const, volatile, and restrict}3 but found "
@@ -1981,7 +2137,7 @@ def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored:
"couldn't infer template argument %0">;
def note_ovl_candidate_inconsistent_deduction : Note<
"candidate template ignored: deduced conflicting %select{types|values|"
- "templates}0 for parameter %1 (%2 vs. %3)">;
+ "templates}0 for parameter %1%diff{ ($ vs. $)|}2,3">;
def note_ovl_candidate_explicit_arg_mismatch_named : Note<
"candidate template ignored: invalid explicitly-specified argument "
"for template parameter %0">;
@@ -1995,7 +2151,9 @@ def note_ovl_candidate_underqualified : Note<
"candidate template ignored: can't deduce a type for %0 which would "
"make %2 equal %1">;
def note_ovl_candidate_substitution_failure : Note<
- "candidate template ignored: substitution failure %0">;
+ "candidate template ignored: substitution failure%0%1">;
+def note_ovl_candidate_disabled_by_enable_if : Note<
+ "candidate template ignored: disabled by %0%1">;
// Note that we don't treat templates differently for this diagnostic.
def note_ovl_candidate_arity : Note<"candidate "
@@ -2009,6 +2167,17 @@ def note_ovl_candidate_arity : Note<"candidate "
"not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 "
"%plural{1:was|:were}4 provided">;
+def note_ovl_candidate_arity_one : Note<"candidate "
+ "%select{function|function|constructor|function|function|constructor|"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0 %select{|template }1not viable: "
+ "%select{requires at least|allows at most single|requires single}2 "
+ "argument %3, but %plural{0:no|:%4}4 arguments were provided">;
+
def note_ovl_candidate_deleted : Note<
"candidate %select{function|function|constructor|"
"function |function |constructor |"
@@ -2035,7 +2204,8 @@ def note_ovl_candidate_bad_conv_incomplete : Note<"candidate "
"function (the implicit copy assignment operator)|"
"function (the implicit move assignment operator)|"
"constructor (inherited)}0%1 "
- "not viable: cannot convert argument of incomplete type %2 to %3">;
+ "not viable: cannot convert argument of incomplete type "
+ "%diff{$ to $|to parameter type}2,3">;
def note_ovl_candidate_bad_list_argument : Note<"candidate "
"%select{function|function|constructor|"
"function |function |constructor |"
@@ -2065,12 +2235,13 @@ def note_ovl_candidate_bad_conv : Note<"candidate "
"function (the implicit copy assignment operator)|"
"function (the implicit move assignment operator)|"
"constructor (inherited)}0%1"
- " not viable: no known conversion from %2 to %3 for "
- "%select{%ordinal5 argument|object argument}4; "
- "%select{|dereference the argument with *|"
- "take the address of the argument with &|"
- "remove *|"
- "remove &}6">;
+ " not viable: no known conversion "
+ "%diff{from $ to $|from argument type to parameter type}2,3 for "
+ "%select{%ordinal5 argument|object argument}4"
+ "%select{|; dereference the argument with *|"
+ "; take the address of the argument with &|"
+ "; remove *|"
+ "; remove &}6">;
def note_ovl_candidate_bad_arc_conv : Note<"candidate "
"%select{function|function|constructor|"
"function |function |constructor |"
@@ -2080,8 +2251,20 @@ def note_ovl_candidate_bad_arc_conv : Note<"candidate "
"function (the implicit copy assignment operator)|"
"function (the implicit move assignment operator)|"
"constructor (inherited)}0%1"
- " not viable: cannot implicitly convert argument of type %2 to %3 for "
+ " not viable: cannot implicitly convert argument "
+ "%diff{of type $ to $|type to parameter type}2,3 for "
"%select{%ordinal5 argument|object argument}4 under ARC">;
+def note_ovl_candidate_bad_lvalue : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0%1"
+ " not viable: expects an l-value for "
+ "%select{%ordinal3 argument|object argument}2">;
def note_ovl_candidate_bad_addrspace : Note<"candidate "
"%select{function|function|constructor|"
"function |function |constructor |"
@@ -2163,7 +2346,7 @@ def note_ovl_candidate_bad_target : Note<
" %select{__device__|__global__|__host__|__host__ __device__}2 function">;
def note_ambiguous_type_conversion: Note<
- "because of ambiguity in conversion of %0 to %1">;
+ "because of ambiguity in conversion %diff{of $ to $|between types}0,1">;
def note_ovl_builtin_binary_candidate : Note<
"built-in candidate %0">;
def note_ovl_builtin_unary_candidate : Note<
@@ -2317,6 +2500,8 @@ def note_template_decl_here : Note<"template is declared here">;
def note_member_of_template_here : Note<"member is declared here">;
def err_template_arg_must_be_type : Error<
"template argument for template type parameter must be a type">;
+def err_template_arg_must_be_type_suggest : Error<
+ "template argument for template type parameter must be a type; did you forget 'typename'?">;
def err_template_arg_must_be_expr : Error<
"template argument for non-type template parameter must be an expression">;
def err_template_arg_nontype_ambig : Error<
@@ -2353,6 +2538,9 @@ def err_template_arg_not_ice : Error<
"expression">;
def err_template_arg_not_address_constant : Error<
"non-type template argument of type %0 is not a constant expression">;
+def warn_cxx98_compat_template_arg_null : Warning<
+ "use of null pointer as non-type template argument is incompatible with "
+ "C++98">, InGroup<CXX98Compat>, DefaultIgnore;
def err_template_arg_untyped_null_constant : Error<
"null non-type template argument must be cast to template parameter type %0">;
def err_template_arg_wrongtype_null_constant : Error<
@@ -2360,7 +2548,7 @@ def err_template_arg_wrongtype_null_constant : Error<
"of type %1">;
def err_deduced_non_type_template_arg_type_mismatch : Error<
"deduced non-type template argument does not have the same type as the "
- "its corresponding template parameter (%0 vs %1)">;
+ "its corresponding template parameter%diff{ ($ vs $)|}0,1">;
def err_template_arg_not_convertible : Error<
"non-type template argument of type %0 cannot be converted to a value "
"of type %1">;
@@ -2371,11 +2559,13 @@ def warn_template_arg_too_large : Warning<
"non-type template argument value '%0' truncated to '%1' for "
"template parameter of type %2">, InGroup<Conversion>, DefaultIgnore;
def err_template_arg_no_ref_bind : Error<
- "non-type template parameter of reference type %0 cannot bind to template "
- "argument of type %1">;
+ "non-type template parameter of reference type "
+ "%diff{$ cannot bind to template argument of type $"
+ "|cannot bind to template of incompatible argument type}0,1">;
def err_template_arg_ref_bind_ignores_quals : Error<
- "reference binding of non-type template parameter of type %0 to template "
- "argument of type %1 ignores qualifiers">;
+ "reference binding of non-type template parameter "
+ "%diff{of type $ to template argument of type $|to template argument}0,1 "
+ "ignores qualifiers">;
def err_template_arg_not_decl_ref : Error<
"non-type template argument does not refer to any declaration">;
def err_template_arg_not_object_or_func_form : Error<
@@ -2701,6 +2891,9 @@ def note_explicit_instantiation_definition_here : Note<
// C++ typename-specifiers
def err_typename_nested_not_found : Error<"no type named %0 in %1">;
+def err_typename_nested_not_found_enable_if : Error<
+ "no type named 'type' in %0; 'enable_if' cannot be used to disable "
+ "this declaration">;
def err_typename_nested_not_type : Error<
"typename specifier refers to non-type member %0 in %1">;
def note_typename_refers_here : Note<
@@ -2768,28 +2961,28 @@ def err_unexpanded_parameter_pack_0 : Error<
"size|static assertion|fixed underlying type|enumerator value|"
"using declaration|friend declaration|qualifier|initializer|default argument|"
"non-type template parameter type|exception type|partial specialization|"
- "__if_exists name|__if_not_exists name}0 "
+ "__if_exists name|__if_not_exists name|lambda|block}0 "
"contains an unexpanded parameter pack">;
def err_unexpanded_parameter_pack_1 : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
"size|static assertion|fixed underlying type|enumerator value|"
"using declaration|friend declaration|qualifier|initializer|default argument|"
"non-type template parameter type|exception type|partial specialization|"
- "__if_exists name|__if_not_exists name}0 "
+ "__if_exists name|__if_not_exists name|lambda|block}0 "
"contains unexpanded parameter pack %1">;
def err_unexpanded_parameter_pack_2 : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
"size|static assertion|fixed underlying type|enumerator value|"
"using declaration|friend declaration|qualifier|initializer|default argument|"
"non-type template parameter type|exception type|partial specialization|"
- "__if_exists name|__if_not_exists name}0 "
+ "__if_exists name|__if_not_exists name|lambda|block}0 "
"contains unexpanded parameter packs %1 and %2">;
def err_unexpanded_parameter_pack_3_or_more : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
"size|static assertion|fixed underlying type|enumerator value|"
"using declaration|friend declaration|qualifier|initializer|default argument|"
"non-type template parameter type|exception type|partial specialization|"
- "__if_exists name|__if_not_exists name}0 "
+ "__if_exists name|__if_not_exists name|lambda|block}0 "
"contains unexpanded parameter packs %1, %2, ...">;
def err_pack_expansion_without_parameter_packs : Error<
@@ -2878,8 +3071,8 @@ def note_deleted_dtor_no_operator_delete : Note<
def note_deleted_special_member_class_subobject : Note<
"%select{default constructor|copy constructor|move constructor|"
"copy assignment operator|move assignment operator|destructor}0 of "
- "%select{||||union }4%1 is implicitly deleted because "
- "%select{base class %3|field %3}2 has "
+ "%1 is implicitly deleted because "
+ "%select{base class %3|%select{||||variant }4field %3}2 has "
"%select{no|a deleted|multiple|an inaccessible|a non-trivial}4 "
"%select{%select{default constructor|copy constructor|move constructor|copy "
"assignment operator|move assignment operator|destructor}0|destructor}5"
@@ -2898,8 +3091,8 @@ def note_deleted_copy_user_declared_move : Note<
"copy %select{constructor|assignment operator}0 is implicitly deleted because"
" %1 has a user-declared move %select{constructor|assignment operator}2">;
def note_deleted_assign_field : Note<
- "%select{copy|move}0 assignment operator of %0 is implicitly deleted "
- "because field %1 is of %select{reference|const-qualified}3 type %2">;
+ "%select{copy|move}0 assignment operator of %1 is implicitly deleted "
+ "because field %2 is of %select{reference|const-qualified}4 type %3">;
// This should eventually be an error.
def warn_undefined_internal : Warning<
@@ -2907,6 +3100,17 @@ def warn_undefined_internal : Warning<
DiagGroup<"undefined-internal">;
def note_used_here : Note<"used here">;
+def warn_internal_in_extern_inline : ExtWarn<
+ "static %select{function|variable}0 %1 is used in an inline function with "
+ "external linkage">, InGroup<DiagGroup<"static-in-inline"> >;
+def ext_internal_in_extern_inline : Extension<
+ "static %select{function|variable}0 %1 is used in an inline function with "
+ "external linkage">, InGroup<DiagGroup<"static-in-inline"> >;
+def note_convert_inline_to_static : Note<
+ "use 'static' to give inline function %0 internal linkage">;
+def note_internal_decl_declared_here : Note<
+ "%0 declared here">;
+
def warn_redefinition_of_typedef : ExtWarn<
"redefinition of typedef %0 is a C11 feature">,
InGroup<DiagGroup<"typedef-redefinition"> >;
@@ -2939,7 +3143,8 @@ def warn_forward_class_redefinition : Warning<
"redefinition of forward class %0 of a typedef name of an object type is ignored">,
InGroup<DiagGroup<"objc-forward-class-redefinition">>;
def err_redefinition_different_typedef : Error<
- "%select{typedef|type alias|type alias template}0 redefinition with different types (%1 vs %2)">;
+ "%select{typedef|type alias|type alias template}0 "
+ "redefinition with different types%diff{ ($ vs $)|}1,2">;
def err_tag_reference_non_tag : Error<
"elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template}0">;
def err_tag_reference_conflict : Error<
@@ -2977,6 +3182,9 @@ def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
def err_duplicate_member : Error<"duplicate member %0">;
def err_misplaced_ivar : Error<
"ivars may not be placed in %select{categories|class extension}0">;
+def warn_ivars_in_interface : Warning<
+ "declaration of ivars in the interface is deprecated">,
+ InGroup<DiagGroup<"objc-interface-ivars">>, DefaultIgnore;
def ext_enum_value_not_int : Extension<
"ISO C restricts enumerator values to range of 'int' (%0 is too "
"%select{small|large}1)">;
@@ -3041,7 +3249,8 @@ def err_local_cant_init : Error<
"'__local' variable cannot have an initializer">;
def err_block_extern_cant_init : Error<
"'extern' variable cannot have an initializer">;
-def warn_extern_init : Warning<"'extern' variable has an initializer">;
+def warn_extern_init : Warning<"'extern' variable has an initializer">,
+ InGroup<DiagGroup<"extern-initializer">>;
def err_variable_object_no_init : Error<
"variable-sized object may not be initialized">;
def err_excess_initializers : Error<
@@ -3070,6 +3279,15 @@ def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
def warn_cxx98_compat_empty_scalar_initializer : Warning<
"scalar initialized from empty initializer list is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_reference_list_init : Warning<
+ "reference initialized from initializer list is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_initializer_list_init : Warning<
+ "initialization of initializer_list object is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_ctor_list_init : Warning<
+ "constructor call from initializer list is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def err_illegal_initializer : Error<
"illegal initializer (only variables can be initialized)">;
def err_illegal_initializer_type : Error<"illegal initializer type %0">;
@@ -3190,7 +3408,7 @@ def note_protected_by___block : Note<
def note_protected_by_objc_ownership : Note<
"jump bypasses initialization of retaining variable">;
def note_enters_block_captures_cxx_obj : Note<
- "jump enters lifetime of block which captures a destructible c++ object">;
+ "jump enters lifetime of block which captures a destructible C++ object">;
def note_enters_block_captures_strong : Note<
"jump enters lifetime of block which strongly captures a variable">;
def note_enters_block_captures_weak : Note<
@@ -3219,7 +3437,7 @@ def note_exits_objc_autoreleasepool : Note<
def note_exits_objc_ownership : Note<
"jump exits scope of retaining variable">;
def note_exits_block_captures_cxx_obj : Note<
- "jump exits lifetime of block which captures a destructible c++ object">;
+ "jump exits lifetime of block which captures a destructible C++ object">;
def note_exits_block_captures_strong : Note<
"jump exits lifetime of block which strongly captures a variable">;
def note_exits_block_captures_weak : Note<
@@ -3329,7 +3547,8 @@ def warn_arc_non_pod_class_with_object_member : Warning<
"to make it ABI-compatible">, InGroup<AutomaticReferenceCountingABI>,
DefaultIgnore;
def warn_arc_retained_assign : Warning<
- "assigning retained object to %select{weak|unsafe_unretained}0 variable"
+ "assigning retained object to %select{weak|unsafe_unretained}0 "
+ "%select{property|variable}1"
"; object will be released after assignment">,
InGroup<ARCUnsafeRetainedAssign>;
def warn_arc_retained_property_assign : Warning<
@@ -3356,8 +3575,7 @@ def err_arc_autoreleasing_capture : Error<
def err_arc_thread_ownership : Error<
"thread-local variable has non-trivial ownership: type is %0">;
def err_arc_indirect_no_ownership : Error<
- "%select{pointer|reference}1 to non-const type %0 with no explicit ownership">,
- InGroup<AutomaticReferenceCounting>;
+ "%select{pointer|reference}1 to non-const type %0 with no explicit ownership">;
def err_arc_array_param_no_ownership : Error<
"must explicitly describe intended ownership of an object array parameter">;
def err_arc_pseudo_dtor_inconstant_quals : Error<
@@ -3378,7 +3596,7 @@ def err_arc_receiver_forward_instance : Error<
"receiver type %0 for instance message is a forward declaration">;
def warn_receiver_forward_instance : Warning<
"receiver type %0 for instance message is a forward declaration">,
- InGroup<DiagGroup<"receiver-forward-class">>, DefaultIgnore;
+ InGroup<ForwardClassReceiver>, DefaultIgnore;
def err_arc_collection_forward : Error<
"collection expression type %0 is a forward declaration">;
def err_arc_multiple_method_decl : Error<
@@ -3454,7 +3672,7 @@ def err_illegal_decl_array_of_functions : Error<
def err_illegal_decl_array_incomplete_type : Error<
"array has incomplete element type %0">;
def err_illegal_message_expr_incomplete_type : Error<
- "objective-c message has incomplete result type %0">;
+ "Objective-C message has incomplete result type %0">;
def err_illegal_decl_array_of_references : Error<
"'%0' declared as array of references of type %1">;
def err_decl_negative_array_size : Error<
@@ -3507,14 +3725,18 @@ def ext_offsetof_extended_field_designator : Extension<
InGroup<DiagGroup<"extended-offsetof">>;
def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
InGroup<InvalidOffsetof>;
+def warn_offsetof_non_standardlayout_type : ExtWarn<
+ "offset of on non-standard-layout type %0">, InGroup<InvalidOffsetof>;
def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">;
def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
-def warn_division_by_zero : Warning<"division by zero is undefined">;
-def warn_remainder_by_zero : Warning<"remainder by zero is undefined">;
+def warn_division_by_zero : Warning<"division by zero is undefined">,
+ InGroup<DivZero>;
+def warn_remainder_by_zero : Warning<"remainder by zero is undefined">,
+ InGroup<DivZero>;
def warn_shift_negative : Warning<"shift count is negative">,
InGroup<DiagGroup<"shift-count-negative">>;
def warn_shift_gt_typewidth : Warning<"shift count >= width of type">,
@@ -3576,17 +3798,17 @@ def warn_sizeof_array_param : Warning<
InGroup<SizeofArrayArgument>;
def err_sizeof_nonfragile_interface : Error<
- "invalid application of '%select{alignof|sizeof}1' to interface %0 in "
- "non-fragile ABI">;
+ "application of '%select{alignof|sizeof}1' to interface %0 is "
+ "not supported on this architecture and platform">;
def err_atdef_nonfragile_interface : Error<
- "invalid application of @defs in non-fragile ABI">;
+ "use of @defs is not supported on this architecture and platform">;
def err_subscript_nonfragile_interface : Error<
- "subscript requires size of interface %0, which is not constant in "
- "non-fragile ABI">;
+ "subscript requires size of interface %0, which is not constant for "
+ "this architecture and platform">;
def err_arithmetic_nonfragile_interface : Error<
- "arithmetic on pointer to interface %0, which is not a constant size in "
- "non-fragile ABI">;
+ "arithmetic on pointer to interface %0, which is not a constant size for "
+ "this architecture and platform">;
def ext_subscript_non_lvalue : Extension<
@@ -3624,6 +3846,8 @@ def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
def err_no_member : Error<"no member named %0 in %1">;
+def err_no_member_overloaded_arrow : Error<
+ "no member named %0 in %1; did you mean to use '->' instead of '.'?">;
def err_member_not_yet_instantiated : Error<
"no member %0 in %1; it has not yet been instantiated">;
@@ -3636,11 +3860,15 @@ def note_enum_specialized_here : Note<
"enum %0 was explicitly specialized here">;
def err_member_redeclared : Error<"class member cannot be redeclared">;
+def err_member_redeclared_in_instantiation : Error<
+ "multiple overloads of %0 instantiate to the same signature %1">;
def err_member_name_of_class : Error<"member %0 has the same name as its class">;
def err_member_def_undefined_record : Error<
"out-of-line definition of %0 from class %1 without definition">;
def err_member_def_does_not_match : Error<
"out-of-line definition of %0 does not match any declaration in %1">;
+def err_friend_decl_does_not_match : Error<
+ "friend declaration of %0 does not match any declaration in %1">;
def err_member_def_does_not_match_suggest : Error<
"out-of-line definition of %0 does not match any declaration in %1; "
"did you mean %2?">;
@@ -3664,8 +3892,8 @@ def note_member_def_close_const_match : Note<
"member declaration does not match because "
"it %select{is|is not}0 const qualified">;
def note_member_def_close_param_match : Note<
- "type of %ordinal0 parameter of member declaration does not match "
- "definition (%1 vs %2)">;
+ "type of %ordinal0 parameter of member declaration does not match definition"
+ "%diff{ ($ vs $)|}1,2">;
def err_typecheck_ivar_variable_size : Error<
"instance variables must have a constant size">;
def err_ivar_reference_type : Error<
@@ -3697,12 +3925,15 @@ def err_array_init_not_init_list : Error<
"array initializer must be an initializer "
"list%select{| or string literal}0">;
def err_array_init_different_type : Error<
- "cannot initialize array of type %0 with array of type %1">;
+ "cannot initialize array %diff{of type $ with array of type $|"
+ "with different type of array}0,1">;
def err_array_init_non_constant_array : Error<
- "cannot initialize array of type %0 with non-constant array of type %1">;
+ "cannot initialize array %diff{of type $ with non-constant array of type $|"
+ "with different type of array}0,1">;
def ext_array_init_copy : Extension<
- "initialization of an array of type %0 from a compound literal of type %1 is "
- "a GNU extension">, InGroup<GNU>;
+ "initialization of an array "
+ "%diff{of type $ from a compound literal of type $|"
+ "from a compound literal}0,1 is a GNU extension">, InGroup<GNU>;
// This is intentionally not disabled by -Wno-gnu.
def ext_array_init_parens : ExtWarn<
"parenthesized initialization of a member array is a GNU extension">,
@@ -3745,7 +3976,7 @@ def note_indirection_through_null : Note<
"consider using __builtin_trap() or qualifying pointer with 'volatile'">;
def warn_pointer_indirection_from_incompatible_type : Warning<
"dereference of type %1 that was reinterpret_cast from type %0 has undefined "
- "behavior.">,
+ "behavior">,
InGroup<DiagGroup<"undefined-reinterpret-cast">>, DefaultIgnore;
def err_objc_object_assignment : Error<
@@ -3753,7 +3984,8 @@ def err_objc_object_assignment : Error<
def err_typecheck_invalid_operands : Error<
"invalid operands to binary expression (%0 and %1)">;
def err_typecheck_sub_ptr_compatible : Error<
- "%0 and %1 are not pointers to compatible types">;
+ "%diff{$ and $ are not pointers to compatible types|"
+ "pointers to incompatible types}0,1">;
def ext_typecheck_ordered_comparison_of_pointer_integer : ExtWarn<
"ordered comparison between pointer and integer (%0 and %1)">;
def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension<
@@ -3769,13 +4001,14 @@ def ext_typecheck_comparison_of_pointer_integer : ExtWarn<
def err_typecheck_comparison_of_pointer_integer : Error<
"comparison between pointer and integer (%0 and %1)">;
def ext_typecheck_comparison_of_distinct_pointers : ExtWarn<
- "comparison of distinct pointer types (%0 and %1)">;
+ "comparison of distinct pointer types%diff{ ($ and $)|}0,1">;
def ext_typecheck_cond_incompatible_operands : ExtWarn<
"incompatible operand types (%0 and %1)">;
def err_cond_voidptr_arc : Error <
- "operands to conditional of types %0 and %1 are incompatible in ARC mode">;
+ "operands to conditional of types%diff{ $ and $|}0,1 are incompatible "
+ "in ARC mode">;
def err_typecheck_comparison_of_distinct_pointers : Error<
- "comparison of distinct pointer types (%0 and %1)">;
+ "comparison of distinct pointer types%diff{ ($ and $)|}0,1">;
def ext_typecheck_comparison_of_distinct_pointers_nonstandard : ExtWarn<
"comparison of distinct pointer types (%0 and %1) uses non-standard "
"composite pointer type %2">;
@@ -3792,7 +4025,8 @@ def warn_runsigned_always_true_comparison : Warning<
"comparison of %0 unsigned%select{| enum}2 expression is always %1">,
InGroup<TautologicalCompare>;
def warn_comparison_of_mixed_enum_types : Warning<
- "comparison of two values with different enumeration types (%0 and %1)">,
+ "comparison of two values with different enumeration types"
+ "%diff{ ($ and $)|}0,1">,
InGroup<DiagGroup<"enum-compare">>;
def warn_null_in_arithmetic_operation : Warning<
"use of NULL in arithmetic operation">,
@@ -3865,8 +4099,8 @@ def err_objc_subscript_key_type : Error<
def err_objc_subscript_dic_object_type : Error<
"method object parameter type %0 is not object type">;
def err_objc_subscript_object_type : Error<
- "cannot assign to this %select{dictionary|array}1 because assigning method's 2nd parameter"
- " of type %0 is not an objective-C pointer type">;
+ "cannot assign to this %select{dictionary|array}1 because assigning method's "
+ "2nd parameter of type %0 is not an Objective-C pointer type">;
def err_objc_subscript_base_type : Error<
"%select{dictionary|array}1 subscript base type %0 is not an Objective-C object">;
def err_objc_multiple_subscript_type_conversion : Error<
@@ -3874,17 +4108,17 @@ def err_objc_multiple_subscript_type_conversion : Error<
"multiple type conversion functions">;
def err_objc_subscript_type_conversion : Error<
"indexing expression is invalid because subscript type %0 is not an integral"
- " or objective-C pointer type">;
+ " or Objective-C pointer type">;
def err_objc_subscript_pointer : Error<
"indexing expression is invalid because subscript type %0 is not an"
- " objective-C pointer">;
+ " Objective-C pointer">;
def err_objc_indexing_method_result_type : Error<
"method for accessing %select{dictionary|array}1 element must have Objective-C"
" object return type instead of %0">;
def err_objc_index_incomplete_class_type : Error<
- "objective-C index expression has incomplete class type %0">;
+ "Objective-C index expression has incomplete class type %0">;
def err_illegal_container_subscripting_op : Error<
- "illegal operation on objective-c container subscripting">;
+ "illegal operation on Objective-C container subscripting">;
def err_property_not_found_forward_class : Error<
"property %0 cannot be found in forward class object %1">;
def err_property_not_as_forward_class : Error<
@@ -3902,7 +4136,7 @@ def ext_gnu_ptr_func_arith : Extension<
"type%select{|s}2 %1%select{| and %3}2 is a GNU extension">,
InGroup<PointerArith>;
def error_readonly_message_assignment : Error<
- "assigning to 'readonly' return result of an objective-c message not allowed">;
+ "assigning to 'readonly' return result of an Objective-C message not allowed">;
def ext_integer_increment_complex : Extension<
"ISO C does not support '++'/'--' on complex integer type %0">;
def ext_integer_complement_complex : Extension<
@@ -3930,13 +4164,17 @@ def err_imaginary_not_supported : Error<"imaginary types are not supported">;
// Obj-c expressions
def warn_root_inst_method_not_found : Warning<
- "instance method %0 is being used on 'Class' which is not in the root class">;
+ "instance method %0 is being used on 'Class' which is not in the root class">,
+ InGroup<MethodAccess>;
def warn_class_method_not_found : Warning<
- "class method %objcclass0 not found (return type defaults to 'id')">;
+ "class method %objcclass0 not found (return type defaults to 'id')">,
+ InGroup<MethodAccess>;
def warn_instance_method_on_class_found : Warning<
- "instance method %0 found instead of class method %1">;
+ "instance method %0 found instead of class method %1">,
+ InGroup<MethodAccess>;
def warn_inst_method_not_found : Warning<
- "instance method %objcinstance0 not found (return type defaults to 'id')">;
+ "instance method %objcinstance0 not found (return type defaults to 'id')">,
+ InGroup<MethodAccess>;
def error_no_super_class_message : Error<
"no @interface declaration found in class messaging of %0">;
def error_root_class_cannot_use_super : Error<
@@ -3951,7 +4189,7 @@ def err_missing_open_square_message_send : Error<
"missing '[' at start of message send expression">;
def warn_bad_receiver_type : Warning<
"receiver type %0 is not 'id' or interface pointer, consider "
- "casting it to 'id'">;
+ "casting it to 'id'">,InGroup<ObjCReceiver>;
def err_bad_receiver_type : Error<"bad receiver type %0">;
def err_unknown_receiver_suggest : Error<
"unknown receiver %0; did you mean %1?">;
@@ -3978,7 +4216,7 @@ def warn_objc_pointer_cxx_catch_fragile : Warning<
"can not catch an exception thrown with @throw in C++ in the non-unified "
"exception model">, InGroup<ObjCNonUnifiedException>;
def err_objc_object_catch : Error<
- "can't catch an Objective C object by value">;
+ "can't catch an Objective-C object by value">;
def err_incomplete_type_objc_at_encode : Error<
"'@encode' of incomplete type %0">;
@@ -4050,7 +4288,7 @@ def err_bad_cxx_cast_member_pointer_size : Error<
def err_bad_reinterpret_cast_reference : Error<
"reinterpret_cast of a %0 to %1 needs its address which is not allowed">;
def warn_undefined_reinterpret_cast : Warning<
- "reinterpret_cast from %0 to %1 has undefined behavior.">,
+ "reinterpret_cast from %0 to %1 has undefined behavior">,
InGroup<DiagGroup<"undefined-reinterpret-cast">>, DefaultIgnore;
// These messages don't adhere to the pattern.
@@ -4191,11 +4429,12 @@ def err_conditional_void_nonvoid : Error<
"%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
"is of type %0">;
def err_conditional_ambiguous : Error<
- "conditional expression is ambiguous; %0 can be converted to %1 "
- "and vice versa">;
+ "conditional expression is ambiguous; "
+ "%diff{$ can be converted to $ and vice versa|"
+ "types can be convert to each other}0,1">;
def err_conditional_ambiguous_ovl : Error<
- "conditional expression is ambiguous; %0 and %1 can be converted to several "
- "common types">;
+ "conditional expression is ambiguous; %diff{$ and $|types}0,1 "
+ "can be converted to several common types">;
def err_throw_incomplete : Error<
"cannot throw object of incomplete type %0">;
@@ -4233,10 +4472,6 @@ let CategoryName = "Lambda Issue" in {
def note_lambda_decl : Note<"lambda expression begins here">;
def err_lambda_unevaluated_operand : Error<
"lambda expression in an unevaluated operand">;
- def ext_lambda_implies_void_return : ExtWarn<
- "C++11 requires lambda with omitted result type to consist of a single "
- "return statement">,
- InGroup<LambdaExtensions>;
def err_lambda_return_init_list : Error<
"cannot deduce lambda return type from initializer list">;
def err_lambda_capture_default_arg : Error<
@@ -4278,8 +4513,10 @@ def ext_pseudo_dtor_on_void : ExtWarn<
"pseudo-destructors on type void are a Microsoft extension">,
InGroup<Microsoft>;
def err_pseudo_dtor_type_mismatch : Error<
- "the type of object expression (%0) does not match the type being destroyed "
- "(%1) in pseudo-destructor expression">;
+ "the type of object expression "
+ "%diff{($) does not match the type being destroyed ($)|"
+ "does not match the type being destroyed}0,1 "
+ "in pseudo-destructor expression">;
def err_pseudo_dtor_call_with_args : Error<
"call to pseudo-destructor cannot have any arguments">;
def err_dtor_expr_without_call : Error<
@@ -4296,11 +4533,12 @@ def err_type_defined_in_condition : Error<
def err_typecheck_bool_condition : Error<
"value of type %0 is not contextually convertible to 'bool'">;
def err_typecheck_ambiguous_condition : Error<
- "conversion from %0 to %1 is ambiguous">;
+ "conversion %diff{from $ to $|between types}0,1 is ambiguous">;
def err_typecheck_nonviable_condition : Error<
- "no viable conversion from %0 to %1">;
+ "no viable conversion%diff{ from $ to $|}0,1">;
def err_typecheck_deleted_function : Error<
- "conversion function from %0 to %1 invokes a deleted function">;
+ "conversion function %diff{from $ to $|between types}0,1 "
+ "invokes a deleted function">;
def err_expected_class_or_namespace : Error<"expected a class or namespace">;
def err_expected_class : Error<"%0 is not a class%select{ or namespace|, "
@@ -4314,6 +4552,9 @@ def err_invalid_declarator_in_function : Error<
def err_not_tag_in_scope : Error<
"no %select{struct|union|class|enum}0 named %1 in %2">;
+def err_no_typeid_with_fno_rtti : Error<
+ "cannot use typeid with -fno-rtti">;
+
def err_cannot_form_pointer_to_member_of_reference_type : Error<
"cannot form a pointer-to-member to member %0 of reference type %1">;
def err_incomplete_object_call : Error<
@@ -4344,42 +4585,66 @@ def note_equality_comparison_silence : Note<
// In most of these diagnostics the %2 is a value from the
// Sema::AssignmentAction enumeration
def err_typecheck_convert_incompatible : Error<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from incompatible type|to parameter of incompatible type|"
- "from a function with incompatible result type|to incompatible type|"
- "with an expression of incompatible type|to parameter of incompatible type|"
- "to incompatible type}2 %1"
+ "%select{%diff{assigning to $ from incompatible type $|"
+ "assigning to type from incompatible type}0,1"
+ "|%diff{passing $ to parameter of incompatible type $|"
+ "passing type to parameter of incompatible type}0,1"
+ "|%diff{returning $ from a function with incompatible result type $|"
+ "returning type from a function with incompatible result type}0,1"
+ "|%diff{converting $ to incompatible type $|"
+ "converting type to incompatible type}0,1"
+ "|%diff{initializing $ with an expression of incompatible type $|"
+ "initializing type with an expression of incompatible type}0,1"
+ "|%diff{sending $ to parameter of incompatible type $|"
+ "sending type to parameter of incompatible type}0,1"
+ "|%diff{casting $ to incompatible type $|"
+ "casting type to incompatible type}0,1}2"
"%select{|; dereference with *|"
"; take the address with &|"
"; remove *|"
"; remove &}3"
- "%select{|: different classes (%5 vs %6)"
+ "%select{|: different classes%diff{ ($ vs $)|}5,6"
"|: different number of parameters (%5 vs %6)"
- "|: type mismatch at %ordinal5 parameter (%6 vs %7)"
- "|: different return type (%5 vs %6)"
+ "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7"
+ "|: different return type%diff{ ($ vs $)|}5,6"
"|: different qualifiers ("
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}5 vs "
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}6)}4">;
def err_typecheck_missing_return_type_incompatible : Error<
- "return type %0 must match previous return type %1 when %select{block "
+ "%diff{return type $ must match previous return type $|"
+ "return type must match previous return type}0,1 when %select{block "
"literal|lambda expression}2 has unspecified explicit return type">;
def warn_incompatible_qualified_id : Warning<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from incompatible type|to parameter of incompatible type|"
- "from a function with incompatible result type|to incompatible type|"
- "with an expression of incompatible type|to parameter of incompatible type|"
- "to incompatible type}2 %1">;
+ "%select{%diff{assigning to $ from incompatible type $|"
+ "assigning to type from incompatible type}0,1"
+ "|%diff{passing $ to parameter of incompatible type $|"
+ "passing type to parameter of incompatible type}0,1"
+ "|%diff{returning $ from a function with incompatible result type $|"
+ "returning type from a function with incompatible result type}0,1"
+ "|%diff{converting $ to incompatible type $|"
+ "converting type to incompatible type}0,1"
+ "|%diff{initializing $ with an expression of incompatible type $|"
+ "initializing type with an expression of incompatible type}0,1"
+ "|%diff{sending $ to parameter of incompatible type $|"
+ "sending type to parameter of incompatible type}0,1"
+ "|%diff{casting $ to incompatible type $|"
+ "casting type to incompatible type}0,1}2">;
def ext_typecheck_convert_pointer_int : ExtWarn<
"incompatible pointer to integer conversion "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1"
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
"%select{|; dereference with *|"
"; take the address with &|"
"; remove *|"
@@ -4387,92 +4652,163 @@ def ext_typecheck_convert_pointer_int : ExtWarn<
InGroup<IntConversion>;
def ext_typecheck_convert_int_pointer : ExtWarn<
"incompatible integer to pointer conversion "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1"
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
"%select{|; dereference with *|"
"; take the address with &|"
"; remove *|"
"; remove &}3">,
InGroup<IntConversion>;
def ext_typecheck_convert_pointer_void_func : Extension<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1 "
- "converts between void pointer and function pointer">;
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " converts between void pointer and function pointer">;
def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1 "
- "converts between pointers to integer types with different sign">,
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " converts between pointers to integer types with different sign">,
InGroup<DiagGroup<"pointer-sign">>;
def ext_typecheck_convert_incompatible_pointer : ExtWarn<
"incompatible pointer types "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1"
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
"%select{|; dereference with *|"
"; take the address with &|"
"; remove *|"
"; remove &}3">,
InGroup<IncompatiblePointerTypes>;
def ext_typecheck_convert_discards_qualifiers : ExtWarn<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1 discards "
- "qualifiers">,
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " discards qualifiers">,
InGroup<IncompatiblePointerTypes>;
def ext_nested_pointer_qualifier_mismatch : ExtWarn<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1 discards "
- "qualifiers in nested pointer types">,
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " discards qualifiers in nested pointer types">,
InGroup<IncompatiblePointerTypes>;
def warn_incompatible_vectors : Warning<
"incompatible vector types "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1">,
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2">,
InGroup<VectorConversion>, DefaultIgnore;
def err_int_to_block_pointer : Error<
"invalid block pointer conversion "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1">;
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2">;
def err_typecheck_convert_incompatible_block_pointer : Error<
"incompatible block pointer types "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1">;
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2">;
def err_typecheck_incompatible_address_space : Error<
- "%select{assigning %1 to %0"
- "|passing %0 to parameter of type %1"
- "|returning %0 from a function with result type %1"
- "|converting %0 to type %1"
- "|initializing %0 with an expression of type %1"
- "|sending %0 to parameter of type %1"
- "|casting %0 to type %1}2"
+ "%select{%diff{assigning $ to $|assigning to different types}1,0"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
" changes address space of pointer">;
def err_typecheck_incompatible_ownership : Error<
- "%select{assigning %1 to %0"
- "|passing %0 to parameter of type %1"
- "|returning %0 from a function with result type %1"
- "|converting %0 to type %1"
- "|initializing %0 with an expression of type %1"
- "|sending %0 to parameter of type %1"
- "|casting %0 to type %1}2"
+ "%select{%diff{assigning $ to $|assigning to different types}1,0"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
" changes retain/release properties of pointer">;
def err_typecheck_comparison_of_distinct_blocks : Error<
- "comparison of distinct block types (%0 and %1)">;
+ "comparison of distinct block types%diff{ ($ and $)|}0,1">;
def err_typecheck_array_not_modifiable_lvalue : Error<
"array type %0 is not assignable">;
@@ -4505,18 +4841,34 @@ def err_typecheck_call_too_few_args : Error<
"too few %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"expected %1, have %2">;
+def err_typecheck_call_too_few_args_one : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "single argument %1 was not specified">;
def err_typecheck_call_too_few_args_at_least : Error<
"too few %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"expected at least %1, have %2">;
+def err_typecheck_call_too_few_args_at_least_one : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "at least argument %1 must be specified">;
def err_typecheck_call_too_many_args : Error<
"too many %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"expected %1, have %2">;
+def err_typecheck_call_too_many_args_one : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected single argument %1, have %2 arguments">;
def err_typecheck_call_too_many_args_at_most : Error<
"too many %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"expected at most %1, have %2">;
+def err_typecheck_call_too_many_args_at_most_one : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at most single argument %1, have %2 arguments">;
def note_callee_decl : Note<
"%0 declared here">;
def note_defined_here : Note<"%0 defined here">;
@@ -4558,11 +4910,19 @@ def err_ref_bad_target : Error<
"reference to %select{__device__|__global__|__host__|__host__ __device__}0 "
"function %1 in %select{__device__|__global__|__host__|__host__ __device__}2 function">;
+def warn_non_pod_vararg_with_format_string : Warning<
+ "cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic "
+ "%select{function|block|method|constructor}2; expected type from format "
+ "string was %3">, InGroup<DiagGroup<"non-pod-varargs">>, DefaultError;
+// The arguments to this diagnostic should match the warning above.
+def err_cannot_pass_objc_interface_to_vararg_format : Error<
+ "cannot pass object with interface type %1 by value to variadic "
+ "%select{function|block|method|constructor}2; expected type from format "
+ "string was %3">;
def err_cannot_pass_objc_interface_to_vararg : Error<
- "cannot pass object with interface type %0 by-value through variadic "
- "%select{function|block|method}1">;
-
+ "cannot pass object with interface type %0 by value through variadic "
+ "%select{function|block|method|constructor}1">;
def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
"cannot pass object of %select{non-POD|non-trivial}0 type %1 through variadic"
" %select{function|block|method|constructor}2; call will abort at runtime">,
@@ -4573,7 +4933,8 @@ def warn_cxx98_compat_pass_non_pod_arg_to_vararg : Warning<
InGroup<CXX98Compat>, DefaultIgnore;
def err_typecheck_call_invalid_ordered_compare : Error<
- "ordered compare requires two args of floating point type (%0 and %1)">;
+ "ordered compare requires two args of floating point type"
+ "%diff{ ($ and $)|}0,1">;
def err_typecheck_call_invalid_unary_fp : Error<
"floating point classification requires argument of floating point type "
"(passed in %0)">;
@@ -4597,17 +4958,18 @@ def err_cast_pointer_to_non_pointer_int : Error<
def err_typecheck_expect_scalar_operand : Error<
"operand of type %0 where arithmetic or pointer type is required">;
def err_typecheck_cond_incompatible_operands : Error<
- "incompatible operand types (%0 and %1)">;
+ "incompatible operand types%diff{ ($ and $)|}0,1">;
def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn<
- "incompatible operand types (%0 and %1) use non-standard composite pointer "
- "type %2">;
+ "incompatible operand types%diff{ ($ and $)|}0,1 use non-standard composite "
+ "pointer type %2">;
def err_cast_selector_expr : Error<
"cannot type cast @selector expression">;
def warn_typecheck_cond_incompatible_pointers : ExtWarn<
- "pointer type mismatch (%0 and %1)">,
+ "pointer type mismatch%diff{ ($ and $)|}0,1">,
InGroup<DiagGroup<"pointer-type-mismatch">>;
def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn<
- "pointer/integer type mismatch in conditional expression (%0 and %1)">,
+ "pointer/integer type mismatch in conditional expression"
+ "%diff{ ($ and $)|}0,1">,
InGroup<DiagGroup<"conditional-type-mismatch">>;
def err_typecheck_choose_expr_requires_constant : Error<
"'__builtin_choose_expr' requires a constant expression">;
@@ -4628,6 +4990,10 @@ def warn_unused_call : Warning<
def warn_unused_result : Warning<
"ignoring return value of function declared with warn_unused_result "
"attribute">, InGroup<DiagGroup<"unused-result">>;
+def warn_unused_volatile : Warning<
+ "expression result unused; assign into a variable to force a volatile load">,
+ InGroup<DiagGroup<"unused-volatile-lvalue">>;
+
def warn_unused_comparison : Warning<
"%select{equality|inequality}0 comparison result unused">,
InGroup<UnusedComparison>;
@@ -4661,7 +5027,8 @@ let CategoryName = "Inline Assembly Issue" in {
def err_asm_invalid_type_in_input : Error<
"invalid type %0 in asm input for constraint '%1'">;
def err_asm_tying_incompatible_types : Error<
- "unsupported inline asm: input with type %0 matching output with type %1">;
+ "unsupported inline asm: input with type "
+ "%diff{$ matching output with type $|}0,1">;
def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
def warn_asm_label_on_auto_decl : Warning<
"ignored asm label '%0' on automatic variable">;
@@ -4673,12 +5040,16 @@ let CategoryName = "Inline Assembly Issue" in {
"invalid use of a cast in a inline asm context requiring an l-value: "
"accepted due to -fheinous-gnu-extensions, but clang may remove support "
"for this in the future">;
+
+ def warn_unsupported_msasm : ExtWarn<
+ "MS-style inline assembly is not supported">, InGroup<Microsoft>;
}
let CategoryName = "Semantic Issue" in {
def err_invalid_conversion_between_vectors : Error<
- "invalid conversion between vector type %0 and %1 of different size">;
+ "invalid conversion between vector type%diff{ $ and $|}0,1 of different "
+ "size">;
def err_invalid_conversion_between_vector_and_integer : Error<
"invalid conversion between vector type %0 and integer type %1 "
"of different size">;
@@ -4730,6 +5101,9 @@ def err_in_class_initializer_literal_type : Error<
"'constexpr' specifier">;
def err_in_class_initializer_non_constant : Error<
"in-class initializer for static data member is not a constant expression">;
+def err_in_class_initializer_references_def_ctor : Error<
+ "defaulted default constructor of %0 cannot be used by non-static data "
+ "member initializer which appears before end of class definition">;
def ext_in_class_initializer_non_constant : Extension<
"in-class initializer for static data member is not a constant expression; "
@@ -4846,9 +5220,9 @@ def err_operator_new_delete_invalid_result_type : Error<
def err_operator_new_delete_dependent_result_type : Error<
"%0 cannot have a dependent return type; use %1 instead">;
def err_operator_new_delete_too_few_parameters : Error<
- "%0 must have at least one parameter.">;
+ "%0 must have at least one parameter">;
def err_operator_new_delete_template_too_few_parameters : Error<
- "%0 template must have at least two parameters.">;
+ "%0 template must have at least two parameters">;
def err_operator_new_dependent_param_type : Error<
"%0 cannot take a dependent type as first parameter; "
@@ -4912,60 +5286,33 @@ def warn_cxx98_compat_explicit_conversion_functions : Warning<
InGroup<CXX98Compat>, DefaultIgnore;
// C++11 defaulted functions
-def err_defaulted_default_ctor_params : Error<
- "an explicitly-defaulted default constructor must have no parameters">;
-def err_defaulted_copy_ctor_params : Error<
- "an explicitly-defaulted copy constructor must have exactly one parameter">;
-def err_defaulted_copy_ctor_volatile_param : Error<
- "the parameter for an explicitly-defaulted copy constructor may not be "
- "volatile">;
-def err_defaulted_copy_ctor_const_param : Error<
- "the parameter for this explicitly-defaulted copy constructor is const, but "
- "a member or base requires it to be non-const">;
-def err_defaulted_copy_assign_params : Error<
- "an explicitly-defaulted copy assignment operator must have exactly one "
- "parameter">;
-def err_defaulted_copy_assign_return_type : Error<
- "an explicitly-defaulted copy assignment operator must return an unqualified "
- "lvalue reference to its class type">;
+def err_defaulted_special_member_params : Error<
+ "an explicitly-defaulted %select{|copy |move }0constructor cannot "
+ "have default arguments">;
+def err_defaulted_special_member_return_type : Error<
+ "explicitly-defaulted %select{copy|move}0 assignment operator must "
+ "return %1">;
+def err_defaulted_special_member_quals : Error<
+ "an explicitly-defaulted %select{copy|move}0 assignment operator may not "
+ "have 'const', 'constexpr' or 'volatile' qualifiers">;
+def err_defaulted_special_member_volatile_param : Error<
+ "the parameter for an explicitly-defaulted %select{<<ERROR>>|"
+ "copy constructor|move constructor|copy assignment operator|"
+ "move assignment operator|<<ERROR>>}0 may not be volatile">;
+def err_defaulted_special_member_move_const_param : Error<
+ "the parameter for an explicitly-defaulted move "
+ "%select{constructor|assignment operator}0 may not be const">;
+def err_defaulted_special_member_copy_const_param : Error<
+ "the parameter for this explicitly-defaulted copy "
+ "%select{constructor|assignment operator}0 is const, but a member or base "
+ "requires it to be non-const">;
+def err_defaulted_special_member_copy_non_const_param : Error<
+ "explicitly-defaulted copy %select{constructor|assignment operator}0 with "
+ "a non-const parameter must be defaulted outside the class, unless a base or "
+ "member requires the parameter to be non-const">;
def err_defaulted_copy_assign_not_ref : Error<
"the parameter for an explicitly-defaulted copy assignment operator must be an "
"lvalue reference type">;
-def err_defaulted_copy_assign_volatile_param : Error<
- "the parameter for an explicitly-defaulted copy assignment operator may not "
- "be volatile">;
-def err_defaulted_copy_assign_const_param : Error<
- "the parameter for this explicitly-defaulted copy assignment operator is "
- "const, but a member or base requires it to be non-const">;
-def err_defaulted_copy_assign_quals : Error<
- "an explicitly-defaulted copy assignment operator may not have 'const', "
- "'constexpr' or 'volatile' qualifiers">;
-def err_defaulted_move_ctor_params : Error<
- "an explicitly-defaulted move constructor must have exactly one parameter">;
-def err_defaulted_move_ctor_volatile_param : Error<
- "the parameter for an explicitly-defaulted move constructor may not be "
- "volatile">;
-def err_defaulted_move_ctor_const_param : Error<
- "the parameter for an explicitly-defaulted move constructor may not be "
- "const">;
-def err_defaulted_move_assign_params : Error<
- "an explicitly-defaulted move assignment operator must have exactly one "
- "parameter">;
-def err_defaulted_move_assign_return_type : Error<
- "an explicitly-defaulted move assignment operator must return an unqualified "
- "lvalue reference to its class type">;
-def err_defaulted_move_assign_not_ref : Error<
- "the parameter for an explicitly-defaulted move assignment operator must be an "
- "rvalue reference type">;
-def err_defaulted_move_assign_volatile_param : Error<
- "the parameter for an explicitly-defaulted move assignment operator may not "
- "be volatile">;
-def err_defaulted_move_assign_const_param : Error<
- "the parameter for an explicitly-defaulted move assignment operator may not "
- "be const">;
-def err_defaulted_move_assign_quals : Error<
- "an explicitly-defaulted move assignment operator may not have 'const', "
- "'constexpr' or 'volatile' qualifiers">;
def err_incorrect_defaulted_exception_spec : Error<
"exception specification of explicitly defaulted %select{default constructor|"
"copy constructor|move constructor|copy assignment operator|move assignment "
@@ -4995,9 +5342,6 @@ def warn_array_index_exceeds_bounds : Warning<
def note_array_index_out_of_bounds : Note<
"array %0 declared here">;
-def warn_printf_write_back : Warning<
- "use of '%%n' in format string discouraged (potentially insecure)">,
- InGroup<FormatSecurity>;
def warn_printf_insufficient_data_args : Warning<
"more '%%' conversions than data arguments">, InGroup<Format>;
def warn_printf_data_arg_not_used : Warning<
@@ -5066,7 +5410,8 @@ def warn_scanf_scanlist_incomplete : Warning<
"no closing ']' for '%%[' in scanf format string">,
InGroup<Format>;
def note_format_string_defined : Note<"format string is defined here">;
-
+def note_printf_c_str: Note<"did you mean to call the %0 method?">;
+
def warn_null_arg : Warning<
"null passed to a callee which requires a non-null argument">,
InGroup<NonNull>;
@@ -5118,6 +5463,10 @@ def warn_stringcompare : Warning<
"unspecified (use strncmp instead)">,
InGroup<DiagGroup<"string-compare">>;
+def warn_identity_field_assign : Warning<
+ "assigning %select{field|instance variable}0 to itself">,
+ InGroup<SelfAssignmentField>;
+
// Generic selections.
def err_assoc_type_incomplete : Error<
"type %0 in generic association incomplete">;
@@ -5141,14 +5490,15 @@ def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks"
def err_block_returning_array_function : Error<
"block cannot return %select{array|function}0 type %1">;
-// Builtin annotation string.
-def err_builtin_annotation_not_string_constant : Error<
- "__builtin_annotation requires a non wide string constant">;
+// Builtin annotation
+def err_builtin_annotation_first_arg : Error<
+ "first argument to __builtin_annotation must be an integer">;
+def err_builtin_annotation_second_arg : Error<
+ "second argument to __builtin_annotation must be a non-wide string constant">;
// CFString checking
def err_cfstring_literal_not_string_constant : Error<
- "CFString literal is not a string constant">,
- InGroup<DiagGroup<"CFString-literal">>;
+ "CFString literal is not a string constant">;
def warn_cfstring_truncated : Warning<
"input conversion stopped due to an input byte that does not "
"belong to the input codeset UTF-8">,
@@ -5168,6 +5518,8 @@ def warn_case_value_overflow : Warning<
"overflow converting case value to switch condition type (%0 to %1)">,
InGroup<DiagGroup<"switch">>;
def err_duplicate_case : Error<"duplicate case value '%0'">;
+def err_duplicate_case_differing_expr : Error<
+ "duplicate case value: '%0' and '%1' both equal '%2'">;
def warn_case_empty_range : Warning<"empty case range specified">;
def warn_missing_case_for_condition :
Warning<"no case matching constant switch condition '%0'">;
@@ -5197,11 +5549,35 @@ def warn_missing_cases : Warning<
"%0 enumeration values not handled in switch: %1, %2, %3...">,
InGroup<Switch>;
+def warn_unannotated_fallthrough : Warning<
+ "unannotated fall-through between switch labels">,
+ InGroup<ImplicitFallthrough>, DefaultIgnore;
+def warn_unannotated_fallthrough_per_function : Warning<
+ "unannotated fall-through between switch labels in partly-annotated "
+ "function">, InGroup<ImplicitFallthroughPerFunction>, DefaultIgnore;
+def note_insert_fallthrough_fixit : Note<
+ "insert '[[clang::fallthrough]];' to silence this warning">;
+def note_insert_break_fixit : Note<
+ "insert 'break;' to avoid fall-through">;
+def err_fallthrough_attr_wrong_target : Error<
+ "clang::fallthrough attribute is only allowed on empty statements">;
+def note_fallthrough_insert_semi_fixit : Note<"did you forget ';'?">;
+def err_fallthrough_attr_outside_switch : Error<
+ "fallthrough annotation is outside switch statement">;
+def warn_fallthrough_attr_invalid_placement : Warning<
+ "fallthrough annotation does not directly precede switch label">,
+ InGroup<ImplicitFallthrough>;
+def warn_fallthrough_attr_unreachable : Warning<
+ "fallthrough annotation in unreachable code">,
+ InGroup<ImplicitFallthrough>;
+
def warn_unreachable_default : Warning<
"default label in switch which covers all enumeration values">,
InGroup<CoveredSwitchDefault>, DefaultIgnore;
def warn_not_in_enum : Warning<"case value not in enumerated type %0">,
InGroup<Switch>;
+def warn_not_in_enum_assignement : Warning<"integer constant not in range "
+ "of enumerated type %0">, InGroup<DiagGroup<"assign-enum">>, DefaultIgnore;
def err_typecheck_statement_requires_scalar : Error<
"statement requires expression of scalar type (%0 invalid)">;
def err_typecheck_statement_requires_integer : Error<
@@ -5229,8 +5605,7 @@ def warn_empty_while_body : Warning<
def warn_empty_switch_body : Warning<
"switch statement has empty body">, InGroup<EmptyBody>;
def note_empty_body_on_separate_line : Note<
- "put the semicolon on a separate line to silence this warning">,
- InGroup<EmptyBody>;
+ "put the semicolon on a separate line to silence this warning">;
def err_va_start_used_in_non_variadic_function : Error<
"'va_start' used in function with fixed args">;
@@ -5318,17 +5693,22 @@ def err_selector_element_not_lvalue : Error<
def err_selector_element_type : Error<
"selector element type %0 is not a valid object">;
def err_collection_expr_type : Error<
- "collection expression type %0 is not a valid object">;
+ "the type %0 is not a pointer to a fast-enumerable object">;
def warn_collection_expr_type : Warning<
"collection expression type %0 may not respond to %1">;
def err_invalid_conversion_between_ext_vectors : Error<
"invalid conversion between ext-vector type %0 and %1">;
+def warn_duplicate_attribute : Warning<
+ "attribute %0 is already applied with different parameters">,
+ InGroup<IgnoredAttributes>;
+
// Type
def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">;
def warn_receiver_forward_class : Warning<
- "receiver %0 is a forward class and corresponding @interface may not exist">;
+ "receiver %0 is a forward class and corresponding @interface may not exist">,
+ InGroup<ForwardClassReceiver>;
def note_method_sent_forward_class : Note<"method %0 is used for the forward class">;
def ext_missing_declspec : ExtWarn<
"declaration specifier missing, defaulting to 'int'">;
@@ -5376,13 +5756,19 @@ def warn_attribute_method_def : Warning<
"attributes on method implementation and its declaration must match">,
InGroup<DiagGroup<"mismatched-method-attributes">>;
def ext_typecheck_base_super : Warning<
- "method parameter type %0 does not match "
- "super class method parameter type %1">, InGroup<SuperSubClassMismatch>, DefaultIgnore;
+ "method parameter type "
+ "%diff{$ does not match super class method parameter type $|"
+ "does not match super class method parameter type}0,1">,
+ InGroup<SuperSubClassMismatch>, DefaultIgnore;
def warn_missing_method_return_type : Warning<
"method has no return type specified; defaults to 'id'">,
InGroup<MissingMethodReturnType>, DefaultIgnore;
+def warn_direct_ivar_access : Warning<"instance variable %0 is being "
+ "directly accessed">, InGroup<DiagGroup<"direct-ivar-access">>, DefaultIgnore;
// Spell-checking diagnostics
+def err_unknown_type_or_class_name_suggest : Error<
+ "unknown %select{type|class}2 name %0; did you mean %1?">;
def err_unknown_typename_suggest : Error<
"unknown type name %0; did you mean %1?">;
def err_unknown_nested_typename_suggest : Error<
@@ -5457,14 +5843,19 @@ def err_filter_expression_integral : Error<
// OpenCL warnings and errors.
def err_invalid_astype_of_different_size : Error<
"invalid reinterpretation: sizes of %0 and %1 must match">;
+def err_static_kernel : Error<
+ "kernel functions cannot be declared static">;
+def err_static_function_scope : Error<
+ "variables in function scope cannot be declared static">;
} // end of sema category
let CategoryName = "Related Result Type Issue" in {
// Objective-C related result type compatibility
def warn_related_result_type_compatibility_class : Warning<
- "method is expected to return an instance of its class type %0, but "
- "is declared to return %1">;
+ "method is expected to return an instance of its class type "
+ "%diff{$, but is declared to return $|"
+ ", but is declared to return different type}0,1">;
def warn_related_result_type_compatibility_protocol : Warning<
"protocol method is expected to return an instance of the implementing "
"class, but is declared to return %0">;
@@ -5494,5 +5885,9 @@ def err_module_private_definition : Error<
"definition of %0 must be imported before it is required">;
}
-} // end of sema component.
+let CategoryName = "Documentation Issue" in {
+def warn_not_a_doxygen_trailing_member_comment : Warning<
+ "not a Doxygen trailing comment">, InGroup<Documentation>, DefaultIgnore;
+} // end of documentation issue category
+} // end of sema component.
diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
index 7f9fe262f7f6..a440e806d735 100644
--- a/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -10,7 +10,7 @@
let Component = "Serialization" in {
def err_fe_unable_to_read_pch_file : Error<
- "unable to read PCH file: '%0'">;
+ "unable to read PCH file %0: '%1'">;
def err_fe_not_a_pch_file : Error<
"input is not a PCH file: '%0'">;
def err_fe_pch_malformed : Error<
@@ -22,6 +22,8 @@ def err_fe_pch_error_at_end_block : Error<
def err_fe_pch_file_modified : Error<
"file '%0' has been modified since the precompiled header was built">,
DefaultFatal;
+def err_fe_pch_file_overridden : Error<
+ "file '%0' from the precompiled header has been overridden">;
def warn_pch_target_triple : Error<
"PCH file was compiled for the target '%0' but the current translation "
diff --git a/include/clang/Basic/ExceptionSpecificationType.h b/include/clang/Basic/ExceptionSpecificationType.h
index e911bde1910a..edd89ec709d7 100644
--- a/include/clang/Basic/ExceptionSpecificationType.h
+++ b/include/clang/Basic/ExceptionSpecificationType.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the ExceptionSpecificationType enumeration and various
-// utility functions.
-//
+///
+/// \file
+/// \brief Defines the ExceptionSpecificationType enumeration and various
+/// utility functions.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H
#define LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H
@@ -24,7 +25,7 @@ enum ExceptionSpecificationType {
EST_MSAny, ///< Microsoft throw(...) extension
EST_BasicNoexcept, ///< noexcept
EST_ComputedNoexcept, ///< noexcept(expression)
- EST_Delayed, ///< not known yet
+ EST_Unevaluated, ///< not evaluated yet, for special member function
EST_Uninstantiated ///< not instantiated yet
};
@@ -36,6 +37,10 @@ inline bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType) {
return ESpecType == EST_BasicNoexcept || ESpecType == EST_ComputedNoexcept;
}
+inline bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType) {
+ return ESpecType == EST_Unevaluated || ESpecType == EST_Uninstantiated;
+}
+
/// \brief Possible results from evaluation of a noexcept expression.
enum CanThrowResult {
CT_Cannot,
diff --git a/include/clang/Basic/ExpressionTraits.h b/include/clang/Basic/ExpressionTraits.h
index c4e6a1c96f1a..e87771572129 100644
--- a/include/clang/Basic/ExpressionTraits.h
+++ b/include/clang/Basic/ExpressionTraits.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines enumerations for expression traits intrinsics.
-//
+///
+/// \file
+/// \brief Defines enumerations for expression traits intrinsics.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_EXPRESSIONTRAITS_H
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
index 5c7d9eba4af1..b00f2b782709 100644
--- a/include/clang/Basic/FileManager.h
+++ b/include/clang/Basic/FileManager.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the FileManager interface.
-//
+///
+/// \file
+/// \brief Defines the clang::FileManager interface and associated types.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FILEMANAGER_H
@@ -40,9 +41,8 @@ namespace clang {
class FileManager;
class FileSystemStatCache;
-/// DirectoryEntry - Cached information about one directory (either on
-/// the disk or in the virtual file system).
-///
+/// \brief Cached information about one directory (either on disk or in
+/// the virtual file system).
class DirectoryEntry {
const char *Name; // Name of the directory.
friend class FileManager;
@@ -51,10 +51,11 @@ public:
const char *getName() const { return Name; }
};
-/// FileEntry - Cached information about one file (either on the disk
-/// or in the virtual file system). If the 'FD' member is valid, then
-/// this FileEntry has an open file descriptor for the file.
+/// \brief Cached information about one file (either on disk
+/// or in the virtual file system).
///
+/// If the 'FD' member is valid, then this FileEntry has an open file
+/// descriptor for the file.
class FileEntry {
const char *Name; // Name of the file.
off_t Size; // File size in bytes.
@@ -96,8 +97,7 @@ public:
time_t getModificationTime() const { return ModTime; }
mode_t getFileMode() const { return FileMode; }
- /// getDir - Return the directory the file lives in.
- ///
+ /// \brief Return the directory the file lives in.
const DirectoryEntry *getDir() const { return Dir; }
bool operator<(const FileEntry &RHS) const {
@@ -105,10 +105,12 @@ public:
}
};
-/// FileManager - Implements support for file system lookup, file system
-/// caching, and directory search management. This also handles more advanced
-/// properties, such as uniquing files based on "inode", so that a file with two
-/// names (e.g. symlinked) will be treated as a single file.
+/// \brief Implements support for file system lookup, file system caching,
+/// and directory search management.
+///
+/// This also handles more advanced properties, such as uniquing files based
+/// on "inode", so that a file with two names (e.g. symlinked) will be treated
+/// as a single file.
///
class FileManager : public RefCountedBase<FileManager> {
FileSystemOptions FileSystemOpts;
@@ -116,30 +118,37 @@ class FileManager : public RefCountedBase<FileManager> {
class UniqueDirContainer;
class UniqueFileContainer;
- /// UniqueRealDirs/UniqueRealFiles - Cache for existing real
- /// directories/files.
- ///
+ /// \brief Cache for existing real directories.
UniqueDirContainer &UniqueRealDirs;
+
+ /// \brief Cache for existing real files.
UniqueFileContainer &UniqueRealFiles;
- /// \brief The virtual directories that we have allocated. For each
- /// virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
+ /// \brief The virtual directories that we have allocated.
+ ///
+ /// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
/// directories (foo/ and foo/bar/) here.
SmallVector<DirectoryEntry*, 4> VirtualDirectoryEntries;
/// \brief The virtual files that we have allocated.
SmallVector<FileEntry*, 4> VirtualFileEntries;
- /// SeenDirEntries/SeenFileEntries - This is a cache that maps paths
- /// to directory/file entries (either real or virtual) we have
- /// looked up. The actual Entries for real directories/files are
+ /// \brief A cache that maps paths to directory entries (either real or
+ /// virtual) we have looked up
+ ///
+ /// The actual Entries for real directories/files are
/// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
/// for virtual directories/files are owned by
/// VirtualDirectoryEntries/VirtualFileEntries above.
///
llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries;
+
+ /// \brief A cache that maps paths to file entries (either real or
+ /// virtual) we have looked up.
+ ///
+ /// \see SeenDirEntries
llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
- /// NextFileUID - Each FileEntry we create is assigned a unique ID #.
+ /// \brief Each FileEntry we create is assigned a unique ID #.
///
unsigned NextFileUID;
@@ -177,8 +186,13 @@ public:
/// \brief Removes the specified FileSystemStatCache object from the manager.
void removeStatCache(FileSystemStatCache *statCache);
- /// getDirectory - Lookup, cache, and verify the specified directory
- /// (real or virtual). This returns NULL if the directory doesn't exist.
+ /// \brief Removes all FileSystemStatCache objects from the manager.
+ void clearStatCaches();
+
+ /// \brief Lookup, cache, and verify the specified directory (real or
+ /// virtual).
+ ///
+ /// This returns NULL if the directory doesn't exist.
///
/// \param CacheFailure If true and the file does not exist, we'll cache
/// the failure to find this file.
@@ -186,7 +200,9 @@ public:
bool CacheFailure = true);
/// \brief Lookup, cache, and verify the specified file (real or
- /// virtual). This returns NULL if the file doesn't exist.
+ /// virtual).
+ ///
+ /// This returns NULL if the file doesn't exist.
///
/// \param OpenFile if true and the file exists, it will be opened.
///
@@ -199,23 +215,29 @@ public:
const FileSystemOptions &getFileSystemOptions() { return FileSystemOpts; }
/// \brief Retrieve a file entry for a "virtual" file that acts as
- /// if there were a file with the given name on disk. The file
- /// itself is not accessed.
+ /// if there were a file with the given name on disk.
+ ///
+ /// The file itself is not accessed.
const FileEntry *getVirtualFile(StringRef Filename, off_t Size,
time_t ModificationTime);
/// \brief Open the specified file as a MemoryBuffer, returning a new
/// MemoryBuffer if successful, otherwise returning null.
llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry,
- std::string *ErrorStr = 0);
+ std::string *ErrorStr = 0,
+ bool isVolatile = false);
llvm::MemoryBuffer *getBufferForFile(StringRef Filename,
std::string *ErrorStr = 0);
- // getNoncachedStatValue - Will get the 'stat' information for the given path.
- // If the path is relative, it will be resolved against the WorkingDir of the
- // FileManager's FileSystemOptions.
+ /// \brief Get the 'stat' information for the given \p Path.
+ ///
+ /// If the path is relative, it will be resolved against the WorkingDir of the
+ /// FileManager's FileSystemOptions.
bool getNoncachedStatValue(StringRef Path, struct stat &StatBuf);
+ /// \brief Remove the real file \p Entry from the cache.
+ void invalidateCache(const FileEntry *Entry);
+
/// \brief If path is not absolute and FileSystemOptions set the working
/// directory, the path is modified to be relative to the given
/// working directory.
@@ -226,6 +248,11 @@ public:
void GetUniqueIDMapping(
SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
+ /// \brief Modifies the size and modification time of a previously created
+ /// FileEntry. Use with caution.
+ static void modifyFileEntry(FileEntry *File, off_t Size,
+ time_t ModificationTime);
+
void PrintStats() const;
};
diff --git a/include/clang/Basic/FileSystemOptions.h b/include/clang/Basic/FileSystemOptions.h
index 81e928da2a70..38f134631248 100644
--- a/include/clang/Basic/FileSystemOptions.h
+++ b/include/clang/Basic/FileSystemOptions.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the FileSystemOptions interface.
-//
+///
+/// \file
+/// \brief Defines the clang::FileSystemOptions interface.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_FILESYSTEMOPTIONS_H
diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h
index 96a2f90ed194..a802c7cc748e 100644
--- a/include/clang/Basic/FileSystemStatCache.h
+++ b/include/clang/Basic/FileSystemStatCache.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the FileSystemStatCache interface.
-//
+///
+/// \file
+/// \brief Defines the FileSystemStatCache interface.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FILESYSTEMSTATCACHE_H
@@ -34,13 +35,14 @@ public:
virtual ~FileSystemStatCache() {}
enum LookupResult {
- CacheExists, //< We know the file exists and its cached stat data.
- CacheMissing //< We know that the file doesn't exist.
+ CacheExists, ///< We know the file exists and its cached stat data.
+ CacheMissing ///< We know that the file doesn't exist.
};
- /// FileSystemStatCache::get - Get the 'stat' information for the specified
- /// path, using the cache to accellerate it if possible. This returns true if
- /// the path does not exist or false if it exists.
+ /// \brief Get the 'stat' information for the specified path, using the cache
+ /// to accelerate it if possible.
+ ///
+ /// \returns \c true if the path does not exist or \c false if it exists.
///
/// If FileDescriptor is non-null, then this lookup should only return success
/// for files (not directories). If it is null this lookup should only return
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index cc0080b8779d..dc6acdaa91ae 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the IdentifierInfo, IdentifierTable, and Selector
-// interfaces.
-//
+///
+/// \file
+/// \brief Defines the clang::IdentifierInfo, clang::IdentifierTable, and
+/// clang::Selector interfaces.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
@@ -37,12 +38,12 @@ namespace clang {
class MultiKeywordSelector; // private class used by Selector
class DeclarationName; // AST class that stores declaration names
- /// IdentifierLocPair - A simple pair of identifier info and location.
+ /// \brief A simple pair of identifier info and location.
typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair;
-/// IdentifierInfo - One of these records is kept for each identifier that
-/// is lexed. This contains information about whether the token was #define'd,
+/// One of these records is kept for each identifier that
+/// is lexed. This contains information about whether the token was \#define'd,
/// is a language keyword, or if it is a front-end token of some sort (e.g. a
/// variable or function name). The preprocessor keeps this information in a
/// set, and all tok::identifier tokens have a pointer to one of these.
@@ -67,7 +68,7 @@ class IdentifierInfo {
bool OutOfDate : 1; // True if there may be additional
// information about this identifier
// stored externally.
- bool IsModulesImport : 1; // True if this is the 'import' contextual
+ bool IsModulesImport : 1; // True if this is the 'import' contextual
// keyword.
// 1 bit left in 32-bit word.
@@ -83,15 +84,16 @@ public:
IdentifierInfo();
- /// isStr - Return true if this is the identifier for the specified string.
+ /// \brief Return true if this is the identifier for the specified string.
+ ///
/// This is intended to be used for string literals only: II->isStr("foo").
template <std::size_t StrLen>
bool isStr(const char (&Str)[StrLen]) const {
return getLength() == StrLen-1 && !memcmp(getNameStart(), Str, StrLen-1);
}
- /// getNameStart - Return the beginning of the actual string for this
- /// identifier. The returned string is properly null terminated.
+ /// \brief Return the beginning of the actual null-terminated string for this
+ /// identifier.
///
const char *getNameStart() const {
if (Entry) return Entry->getKeyData();
@@ -104,7 +106,7 @@ public:
return ((const actualtype*) this)->second;
}
- /// getLength - Efficiently return the length of this identifier info.
+ /// \brief Efficiently return the length of this identifier info.
///
unsigned getLength() const {
if (Entry) return Entry->getKeyLength();
@@ -118,13 +120,12 @@ public:
return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1;
}
- /// getName - Return the actual identifier string.
+ /// \brief Return the actual identifier string.
StringRef getName() const {
return StringRef(getNameStart(), getLength());
}
- /// hasMacroDefinition - Return true if this identifier is #defined to some
- /// other value.
+ /// \brief Return true if this identifier is \#defined to some other value.
bool hasMacroDefinition() const {
return HasMacro;
}
@@ -158,13 +159,14 @@ public:
RevertedTokenID = true;
}
- /// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
+ /// \brief Return the preprocessor keyword ID for this identifier.
+ ///
/// For example, "define" will return tok::pp_define.
tok::PPKeywordKind getPPKeywordID() const;
- /// getObjCKeywordID - Return the Objective-C keyword ID for the this
- /// identifier. For example, 'class' will return tok::objc_class if ObjC is
- /// enabled.
+ /// \brief Return the Objective-C keyword ID for the this identifier.
+ ///
+ /// For example, 'class' will return tok::objc_class if ObjC is enabled.
tok::ObjCKeywordKind getObjCKeywordID() const {
if (ObjCOrBuiltinID < tok::NUM_OBJC_KEYWORDS)
return tok::ObjCKeywordKind(ObjCOrBuiltinID);
@@ -400,10 +402,11 @@ public:
virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0;
};
-/// IdentifierTable - This table implements an efficient mapping from strings to
-/// IdentifierInfo nodes. It has no other purpose, but this is an
-/// extremely performance-critical piece of the code, as each occurrence of
-/// every identifier goes through here when lexed.
+/// \brief Implements an efficient mapping from strings to IdentifierInfo nodes.
+///
+/// This has no other purpose, but this is an extremely performance-critical
+/// piece of the code, as each occurrence of every identifier goes through
+/// here when lexed.
class IdentifierTable {
// Shark shows that using MallocAllocator is *much* slower than using this
// BumpPtrAllocator!
@@ -413,8 +416,8 @@ class IdentifierTable {
IdentifierInfoLookup* ExternalLookup;
public:
- /// IdentifierTable ctor - Create the identifier table, populating it with
- /// info about the language keywords for the language specified by LangOpts.
+ /// \brief Create the identifier table, populating it with info about the
+ /// language keywords for the language specified by \p LangOpts.
IdentifierTable(const LangOptions &LangOpts,
IdentifierInfoLookup* externalLookup = 0);
@@ -432,8 +435,8 @@ public:
return HashTable.getAllocator();
}
- /// get - Return the identifier token info for the specified named identifier.
- ///
+ /// \brief Return the identifier token info for the specified named
+ /// identifier.
IdentifierInfo &get(StringRef Name) {
llvm::StringMapEntry<IdentifierInfo*> &Entry =
HashTable.GetOrCreateValue(Name);
@@ -507,15 +510,16 @@ public:
iterator end() const { return HashTable.end(); }
unsigned size() const { return HashTable.size(); }
- /// PrintStats - Print some statistics to stderr that indicate how well the
+ /// \brief Print some statistics to stderr that indicate how well the
/// hashing is doing.
void PrintStats() const;
void AddKeywords(const LangOptions &LangOpts);
};
-/// ObjCMethodFamily - A family of Objective-C methods. These
-/// families have no inherent meaning in the language, but are
+/// \brief A family of Objective-C methods.
+///
+/// These families have no inherent meaning in the language, but are
/// nonetheless central enough in the existing implementations to
/// merit direct AST support. While, in theory, arbitrary methods can
/// be considered to form families, we focus here on the methods
@@ -562,11 +566,13 @@ enum ObjCMethodFamily {
/// InvalidObjCMethodFamily.
enum { ObjCMethodFamilyBitWidth = 4 };
-/// An invalid value of ObjCMethodFamily.
+/// \brief An invalid value of ObjCMethodFamily.
enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 };
-/// Selector - This smart pointer class efficiently represents Objective-C
-/// method names. This class will either point to an IdentifierInfo or a
+/// \brief Smart pointer class that efficiently represents Objective-C method
+/// names.
+///
+/// This class will either point to an IdentifierInfo or a
/// MultiKeywordSelector (which is private). This enables us to optimize
/// selectors that take no arguments and selectors that take 1 argument, which
/// accounts for 78% of all selectors in Cocoa.h.
@@ -574,9 +580,10 @@ class Selector {
friend class Diagnostic;
enum IdentifierInfoFlag {
- // MultiKeywordSelector = 0.
+ // Empty selector = 0.
ZeroArg = 0x1,
OneArg = 0x2,
+ MultiArg = 0x3,
ArgFlags = ZeroArg|OneArg
};
uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo.
@@ -590,13 +597,18 @@ class Selector {
Selector(MultiKeywordSelector *SI) {
InfoPtr = reinterpret_cast<uintptr_t>(SI);
assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
+ InfoPtr |= MultiArg;
}
IdentifierInfo *getAsIdentifierInfo() const {
- if (getIdentifierInfoFlag())
+ if (getIdentifierInfoFlag() < MultiArg)
return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags);
return 0;
}
+ MultiKeywordSelector *getMultiKeywordSelector() const {
+ return reinterpret_cast<MultiKeywordSelector *>(InfoPtr & ~ArgFlags);
+ }
+
unsigned getIdentifierInfoFlag() const {
return InfoPtr & ArgFlags;
}
@@ -661,11 +673,12 @@ public:
/// name was supplied.
StringRef getNameForSlot(unsigned argIndex) const;
- /// getAsString - Derive the full selector name (e.g. "foo:bar:") and return
+ /// \brief Derive the full selector name (e.g. "foo:bar:") and return
/// it as an std::string.
+ // FIXME: Add a print method that uses a raw_ostream.
std::string getAsString() const;
- /// getMethodFamily - Derive the conventional family of this method.
+ /// \brief Derive the conventional family of this method.
ObjCMethodFamily getMethodFamily() const {
return getMethodFamilyImpl(*this);
}
@@ -678,7 +691,7 @@ public:
}
};
-/// SelectorTable - This table allows us to fully hide how we implement
+/// \brief This table allows us to fully hide how we implement
/// multi-keyword caching.
class SelectorTable {
void *Impl; // Actually a SelectorTableImpl
@@ -688,9 +701,10 @@ public:
SelectorTable();
~SelectorTable();
- /// getSelector - This can create any sort of selector. NumArgs indicates
- /// whether this is a no argument selector "foo", a single argument selector
- /// "foo:" or multi-argument "foo:bar:".
+ /// \brief Can create any sort of selector.
+ ///
+ /// \p NumArgs indicates whether this is a no argument selector "foo", a
+ /// single argument selector "foo:" or multi-argument "foo:bar:".
Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV);
Selector getUnarySelector(IdentifierInfo *ID) {
@@ -700,11 +714,12 @@ public:
return Selector(ID, 0);
}
- /// Return the total amount of memory allocated for managing selectors.
+ /// \brief Return the total amount of memory allocated for managing selectors.
size_t getTotalMemory() const;
- /// constructSetterName - Return the setter name for the given
- /// identifier, i.e. "set" + Name where the initial character of Name
+ /// \brief Return the setter name for the given identifier.
+ ///
+ /// This is "set" + \p Name where the initial character of \p Name
/// has been capitalized.
static Selector constructSetterName(IdentifierTable &Idents,
SelectorTable &SelTable,
diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h
index 813b49ed2353..13c5b445b8ee 100644
--- a/include/clang/Basic/LLVM.h
+++ b/include/clang/Basic/LLVM.h
@@ -7,9 +7,10 @@
//
//===----------------------------------------------------------------------===//
//
-// This file forward declares and imports various common LLVM datatypes that
-// clang wants to use unqualified.
-//
+/// \file
+/// \brief Forward declares and imports various common LLVM datatypes that
+/// clang wants to use unqualified.
+///
//===----------------------------------------------------------------------===//
#ifndef CLANG_BASIC_LLVM_H
diff --git a/include/clang/Basic/Lambda.h b/include/clang/Basic/Lambda.h
index df50d94894ae..b1ad6acda3b4 100644
--- a/include/clang/Basic/Lambda.h
+++ b/include/clang/Basic/Lambda.h
@@ -6,9 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines several types used to describe C++ lambda
-// expressions that are shared between the parser and AST.
+///
+/// \file
+/// \brief Defines several types used to describe C++ lambda expressions
+/// that are shared between the parser and AST.
+///
//===----------------------------------------------------------------------===//
@@ -17,16 +19,15 @@
namespace clang {
-/// LambdaCaptureDefault - The default, if any, capture method for a
-/// lambda expression.
+/// \brief The default, if any, capture method for a lambda expression.
enum LambdaCaptureDefault {
LCD_None,
LCD_ByCopy,
LCD_ByRef
};
-/// LambdaCaptureKind - The different capture forms in a lambda
-/// introducer: 'this' or a copied or referenced variable.
+/// \brief The different capture forms in a lambda introducer: 'this' or a
+/// copied or referenced variable.
enum LambdaCaptureKind {
LCK_This,
LCK_ByCopy,
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index d2ce7c0df63e..fab17a2fe56e 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -50,8 +50,6 @@ LANGOPT(CPlusPlus , 1, 0, "C++")
LANGOPT(CPlusPlus0x , 1, 0, "C++0x")
LANGOPT(ObjC1 , 1, 0, "Objective-C 1")
LANGOPT(ObjC2 , 1, 0, "Objective-C 2")
-LANGOPT(ObjCNonFragileABI , 1, 0, "Objective-C modern abi")
-LANGOPT(ObjCNonFragileABI2 , 1, 0, "Objective-C enhanced modern abi")
BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0,
"Objective-C auto-synthesized properties")
BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1,
@@ -80,7 +78,6 @@ LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling")
LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation")
LANGOPT(RTTI , 1, 1, "run-time type information")
LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout")
-LANGOPT(NeXTRuntime , 1, 1, "NeXT Objective-C runtime")
LANGOPT(Freestanding, 1, 0, "freestanding implementation")
LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
@@ -102,6 +99,7 @@ LANGOPT(GNUInline , 1, 0, "GNU inline semantics")
LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro")
LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro")
LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro")
+LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro")
BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars")
@@ -112,6 +110,7 @@ LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t")
LANGOPT(ShortEnums , 1, 0, "short enum types")
LANGOPT(OpenCL , 1, 0, "OpenCL")
+LANGOPT(OpenCLVersion , 32, 0, "OpenCL version")
LANGOPT(CUDA , 1, 0, "CUDA")
LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators")
@@ -125,7 +124,7 @@ BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden default visibility for inl
BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype")
BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support")
BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type")
-BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger objective-C literals and subscripting support")
+BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and subscripting support")
BENIGN_LANGOPT(AddressSanitizer , 1, 0, "AddressSanitizer enabled")
BENIGN_LANGOPT(ThreadSanitizer , 1, 0, "ThreadSanitizer enabled")
@@ -150,8 +149,9 @@ ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff,
"stack protector mode")
ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,
"signed integer overflow handling")
+ENUM_LANGOPT(FPContractMode, FPContractModeKind, 2, FPC_On, "FP_CONTRACT mode")
-BENIGN_LANGOPT(InstantiationDepth, 32, 1024,
+BENIGN_LANGOPT(InstantiationDepth, 32, 512,
"maximum template instantiation depth")
BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
"maximum constexpr call depth")
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index ce4ff063c628..fbb014e96707 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the LangOptions interface.
-//
+///
+/// \file
+/// \brief Defines the clang::LangOptions interface.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LANGOPTIONS_H
@@ -16,6 +17,7 @@
#include <string>
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Visibility.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -39,8 +41,8 @@ protected:
#include "clang/Basic/LangOptions.def"
};
-/// LangOptions - This class keeps track of the various options that can be
-/// enabled, which controls the dialect of C that is accepted.
+/// \brief Keeps track of the various options that can be
+/// enabled, which controls the dialect of C or C++ that is accepted.
class LangOptions : public RefCountedBase<LangOptions>, public LangOptionsBase {
public:
typedef clang::Visibility Visibility;
@@ -54,10 +56,20 @@ public:
SOB_Trapping // -ftrapv
};
+ enum FPContractModeKind {
+ FPC_Off, // Form fused FP ops only where result will not be affected.
+ FPC_On, // Form fused FP ops according to FP_CONTRACT rules.
+ FPC_Fast // Aggressively fuse FP ops (E.g. FMA).
+ };
+
public:
+ clang::ObjCRuntime ObjCRuntime;
+
std::string ObjCConstantStringClass;
- /// The name of the handler function to be called when -ftrapv is specified.
+ /// \brief The name of the handler function to be called when -ftrapv is
+ /// specified.
+ ///
/// If none is specified, abort (GCC-compatible behaviour).
std::string OverflowHandler;
@@ -82,7 +94,7 @@ public:
void resetNonModularOptions();
};
-/// Floating point control options
+/// \brief Floating point control options
class FPOptions {
public:
unsigned fp_contract : 1;
@@ -93,7 +105,7 @@ public:
fp_contract(LangOpts.DefaultFPContract) {}
};
-/// OpenCL volatile options
+/// \brief OpenCL volatile options
class OpenCLOptions {
public:
#define OPENCLEXT(nm) unsigned nm : 1;
@@ -116,7 +128,6 @@ enum TranslationUnitKind {
TU_Module
};
- /// \brief
} // end namespace clang
#endif
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index 09a5a0b6b1f3..6bc1f5d5ef1c 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Linkage enumeration and various utility
-// functions.
-//
+///
+/// \file
+/// \brief Defines the Linkage enumeration and various utility functions.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_LINKAGE_H
#define LLVM_CLANG_BASIC_LINKAGE_H
@@ -28,8 +28,9 @@ enum Linkage {
/// translation units).
InternalLinkage,
- /// \brief External linkage within a unique namespace. From the
- /// language perspective, these entities have external
+ /// \brief External linkage within a unique namespace.
+ ///
+ /// From the language perspective, these entities have external
/// linkage. However, since they reside in an anonymous namespace,
/// their names are unique to this translation unit, which is
/// equivalent to having internal linkage from the code-generation
@@ -41,8 +42,9 @@ enum Linkage {
ExternalLinkage
};
-/// \brief A more specific kind of linkage. This is relevant to CodeGen and
-/// AST file reading.
+/// \brief A more specific kind of linkage than enum Linkage.
+///
+/// This is relevant to CodeGen and AST file reading.
enum GVALinkage {
GVA_Internal,
GVA_C99Inline,
@@ -52,14 +54,13 @@ enum GVALinkage {
GVA_ExplicitTemplateInstantiation
};
-/// \brief Determine whether the given linkage is semantically
-/// external.
+/// \brief Determine whether the given linkage is semantically external.
inline bool isExternalLinkage(Linkage L) {
return L == UniqueExternalLinkage || L == ExternalLinkage;
}
/// \brief Compute the minimum linkage given two linages.
-static inline Linkage minLinkage(Linkage L1, Linkage L2) {
+inline Linkage minLinkage(Linkage L1, Linkage L2) {
return L1 < L2? L1 : L2;
}
diff --git a/include/clang/Basic/MacroBuilder.h b/include/clang/Basic/MacroBuilder.h
index 1d0f1e899c9e..6df3a383df9d 100644
--- a/include/clang/Basic/MacroBuilder.h
+++ b/include/clang/Basic/MacroBuilder.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the MacroBuilder utility class.
-//
+///
+/// \file
+/// \brief Defines the clang::MacroBuilder utility class.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_MACROBUILDER_H
@@ -24,13 +25,13 @@ class MacroBuilder {
public:
MacroBuilder(raw_ostream &Output) : Out(Output) {}
- /// Append a #define line for macro of the form "#define Name Value\n".
+ /// Append a \#define line for macro of the form "\#define Name Value\n".
void defineMacro(const Twine &Name, const Twine &Value = "1") {
Out << "#define " << Name << ' ' << Value << '\n';
}
- /// Append a #undef line for Name. Name should be of the form XXX
- /// and we emit "#undef XXX".
+ /// Append a \#undef line for Name. Name should be of the form XXX
+ /// and we emit "\#undef XXX".
void undefineMacro(const Twine &Name) {
Out << "#undef " << Name << '\n';
}
diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile
index 702afac1e6b9..6a3313325216 100644
--- a/include/clang/Basic/Makefile
+++ b/include/clang/Basic/Makefile
@@ -1,6 +1,7 @@
CLANG_LEVEL := ../../..
BUILT_SOURCES = \
DiagnosticAnalysisKinds.inc DiagnosticASTKinds.inc \
+ DiagnosticCommentKinds.inc \
DiagnosticCommonKinds.inc DiagnosticDriverKinds.inc \
DiagnosticFrontendKinds.inc DiagnosticLexKinds.inc \
DiagnosticParseKinds.inc DiagnosticSemaKinds.inc \
diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h
index 82dbd5b0c02d..c8027f47028f 100644
--- a/include/clang/Basic/Module.h
+++ b/include/clang/Basic/Module.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Module class, which describes a module in the source
-// code.
-//
+///
+/// \file
+/// \brief Defines the clang::Module class, which describes a module in the
+/// source code.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_MODULE_H
#define LLVM_CLANG_BASIC_MODULE_H
@@ -137,7 +138,7 @@ public:
llvm::SmallVector<ExportDecl, 2> Exports;
/// \brief Describes an exported module that has not yet been resolved
- /// (perhaps because tASThe module it refers to has not yet been loaded).
+ /// (perhaps because the module it refers to has not yet been loaded).
struct UnresolvedExportDecl {
/// \brief The location of the 'export' keyword in the module map file.
SourceLocation ExportLoc;
@@ -243,7 +244,7 @@ public:
return Umbrella && Umbrella.is<const DirectoryEntry *>();
}
- /// \briaf Add the given feature requirement to the list of features
+ /// \brief Add the given feature requirement to the list of features
/// required by this module.
///
/// \param Feature The feature that is required by this module (and
diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h
new file mode 100644
index 000000000000..b24fe7cd9159
--- /dev/null
+++ b/include/clang/Basic/ObjCRuntime.h
@@ -0,0 +1,264 @@
+//===--- ObjCRuntime.h - Objective-C Runtime Configuration ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines types useful for describing an Objective-C runtime.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_OBJCRUNTIME_H
+#define LLVM_CLANG_OBJCRUNTIME_H
+
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+
+/// \brief The basic abstraction for the target Objective-C runtime.
+class ObjCRuntime {
+public:
+ /// \brief The basic Objective-C runtimes that we know about.
+ enum Kind {
+ /// 'macosx' is the Apple-provided NeXT-derived runtime on Mac OS
+ /// X platforms that use the non-fragile ABI; the version is a
+ /// release of that OS.
+ MacOSX,
+
+ /// 'macosx-fragile' is the Apple-provided NeXT-derived runtime on
+ /// Mac OS X platforms that use the fragile ABI; the version is a
+ /// release of that OS.
+ FragileMacOSX,
+
+ /// 'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS
+ /// simulator; it is always non-fragile. The version is a release
+ /// version of iOS.
+ iOS,
+
+ /// 'gcc' is the Objective-C runtime shipped with GCC, implementing a
+ /// fragile Objective-C ABI
+ GCC,
+
+ /// 'gnustep' is the modern non-fragile GNUstep runtime.
+ GNUstep,
+
+ /// 'objfw' is the Objective-C runtime included in ObjFW
+ ObjFW
+ };
+
+private:
+ Kind TheKind;
+ VersionTuple Version;
+
+public:
+ /// A bogus initialization of the runtime.
+ ObjCRuntime() : TheKind(MacOSX) {}
+
+ ObjCRuntime(Kind kind, const VersionTuple &version)
+ : TheKind(kind), Version(version) {}
+
+ void set(Kind kind, VersionTuple version) {
+ TheKind = kind;
+ Version = version;
+ }
+
+ Kind getKind() const { return TheKind; }
+ const VersionTuple &getVersion() const { return Version; }
+
+ /// \brief Does this runtime follow the set of implied behaviors for a
+ /// "non-fragile" ABI?
+ bool isNonFragile() const {
+ switch (getKind()) {
+ case FragileMacOSX: return false;
+ case GCC: return false;
+ case MacOSX: return true;
+ case GNUstep: return true;
+ case ObjFW: return false;
+ case iOS: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// The inverse of isNonFragile(): does this runtime follow the set of
+ /// implied behaviors for a "fragile" ABI?
+ bool isFragile() const { return !isNonFragile(); }
+
+ /// The default dispatch mechanism to use for the specified architecture
+ bool isLegacyDispatchDefaultForArch(llvm::Triple::ArchType Arch) {
+ // The GNUstep runtime uses a newer dispatch method by default from
+ // version 1.6 onwards
+ if (getKind() == GNUstep && getVersion() >= VersionTuple(1, 6)) {
+ if (Arch == llvm::Triple::arm ||
+ Arch == llvm::Triple::x86 ||
+ Arch == llvm::Triple::x86_64)
+ return false;
+ // Mac runtimes use legacy dispatch everywhere except x86-64
+ } else if (isNeXTFamily() && isNonFragile())
+ return Arch != llvm::Triple::x86_64;
+ return true;
+ }
+
+ /// \brief Is this runtime basically of the GNUstep family of runtimes?
+ bool isGNUFamily() const {
+ switch (getKind()) {
+ case FragileMacOSX:
+ case MacOSX:
+ case iOS:
+ return false;
+ case GCC:
+ case GNUstep:
+ case ObjFW:
+ return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Is this runtime basically of the NeXT family of runtimes?
+ bool isNeXTFamily() const {
+ // For now, this is just the inverse of isGNUFamily(), but that's
+ // not inherently true.
+ return !isGNUFamily();
+ }
+
+ /// \brief Does this runtime natively provide the ARC entrypoints?
+ ///
+ /// ARC cannot be directly supported on a platform that does not provide
+ /// these entrypoints, although it may be supportable via a stub
+ /// library.
+ bool hasARC() const {
+ switch (getKind()) {
+ case FragileMacOSX: return false;
+ case MacOSX: return getVersion() >= VersionTuple(10, 7);
+ case iOS: return getVersion() >= VersionTuple(5);
+
+ case GCC: return false;
+ case GNUstep: return getVersion() >= VersionTuple(1, 6);
+ case ObjFW: return false; // XXX: this will change soon
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Does this runtime natively provide ARC-compliant 'weak'
+ /// entrypoints?
+ bool hasWeak() const {
+ // Right now, this is always equivalent to the ARC decision.
+ return hasARC();
+ }
+
+ /// \brief Does this runtime directly support the subscripting methods?
+ ///
+ /// This is really a property of the library, not the runtime.
+ bool hasSubscripting() const {
+ switch (getKind()) {
+ case FragileMacOSX: return false;
+ case MacOSX: return getVersion() >= VersionTuple(10, 8);
+ case iOS: return false;
+
+ // This is really a lie, because some implementations and versions
+ // of the runtime do not support ARC. Probably -fgnu-runtime
+ // should imply a "maximal" runtime or something?
+ case GCC: return true;
+ case GNUstep: return true;
+ case ObjFW: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Does this runtime allow sizeof or alignof on object types?
+ bool allowsSizeofAlignof() const {
+ return isFragile();
+ }
+
+ /// \brief Does this runtime allow pointer arithmetic on objects?
+ ///
+ /// This covers +, -, ++, --, and (if isSubscriptPointerArithmetic()
+ /// yields true) [].
+ bool allowsPointerArithmetic() const {
+ switch (getKind()) {
+ case FragileMacOSX:
+ case GCC:
+ return true;
+ case MacOSX:
+ case iOS:
+ case GNUstep:
+ case ObjFW:
+ return false;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Is subscripting pointer arithmetic?
+ bool isSubscriptPointerArithmetic() const {
+ return allowsPointerArithmetic();
+ }
+
+ /// \brief Does this runtime provide an objc_terminate function?
+ ///
+ /// This is used in handlers for exceptions during the unwind process;
+ /// without it, abort() must be used in pure ObjC files.
+ bool hasTerminate() const {
+ switch (getKind()) {
+ case FragileMacOSX: return getVersion() >= VersionTuple(10, 8);
+ case MacOSX: return getVersion() >= VersionTuple(10, 8);
+ case iOS: return getVersion() >= VersionTuple(5);
+ case GCC: return false;
+ case GNUstep: return false;
+ case ObjFW: return false;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Does this runtime support weakly importing classes?
+ bool hasWeakClassImport() const {
+ switch (getKind()) {
+ case MacOSX: return true;
+ case iOS: return true;
+ case FragileMacOSX: return false;
+ case GCC: return true;
+ case GNUstep: return true;
+ case ObjFW: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+ /// \brief Does this runtime use zero-cost exceptions?
+ bool hasUnwindExceptions() const {
+ switch (getKind()) {
+ case MacOSX: return true;
+ case iOS: return true;
+ case FragileMacOSX: return false;
+ case GCC: return true;
+ case GNUstep: return true;
+ case ObjFW: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Try to parse an Objective-C runtime specification from the given
+ /// string.
+ ///
+ /// \return true on error.
+ bool tryParse(StringRef input);
+
+ std::string getAsString() const;
+
+ friend bool operator==(const ObjCRuntime &left, const ObjCRuntime &right) {
+ return left.getKind() == right.getKind() &&
+ left.getVersion() == right.getVersion();
+ }
+
+ friend bool operator!=(const ObjCRuntime &left, const ObjCRuntime &right) {
+ return !(left == right);
+ }
+};
+
+raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value);
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h
index b92f1cf9c6ae..79273fcc798d 100644
--- a/include/clang/Basic/OnDiskHashTable.h
+++ b/include/clang/Basic/OnDiskHashTable.h
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines facilities for reading and writing on-disk hash
-// tables.
-//
+///
+/// \file
+/// \brief Defines facilities for reading and writing on-disk hash tables.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
#define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
diff --git a/include/clang/Basic/OpenCL.h b/include/clang/Basic/OpenCL.h
index 6f9785f25677..3b3f259252df 100644
--- a/include/clang/Basic/OpenCL.h
+++ b/include/clang/Basic/OpenCL.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines some OpenCL-specific enums.
-//
+///
+/// \file
+/// \brief Defines some OpenCL-specific enums.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_OPENCL_H
@@ -16,7 +17,7 @@
namespace clang {
-/// Names for the OpenCL image access qualifiers (OpenCL 1.1 6.6).
+/// \brief Names for the OpenCL image access qualifiers (OpenCL 1.1 6.6).
enum OpenCLImageAccess {
CLIA_read_only = 1,
CLIA_write_only = 2,
diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h
index c0a95051a72d..108014faabe1 100644
--- a/include/clang/Basic/OperatorKinds.h
+++ b/include/clang/Basic/OperatorKinds.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines C++ overloaded operators.
-//
+///
+/// \file
+/// \brief Defines an enumeration for C++ overloaded operators.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_OPERATOR_KINDS_H
@@ -16,10 +17,10 @@
namespace clang {
-/// OverloadedOperatorKind - Enumeration specifying the different kinds of
-/// C++ overloaded operators.
+/// \brief Enumeration specifying the different kinds of C++ overloaded
+/// operators.
enum OverloadedOperatorKind {
- OO_None, //< Not an overloaded operator
+ OO_None, ///< Not an overloaded operator
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
OO_##Name,
#include "clang/Basic/OperatorKinds.def"
diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h
index 007e6a47603a..3f4626ec0a7e 100644
--- a/include/clang/Basic/PartialDiagnostic.h
+++ b/include/clang/Basic/PartialDiagnostic.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements a partial diagnostic that can be emitted anwyhere
-// in a DiagnosticBuilder stream.
-//
+///
+/// \file
+/// \brief Implements a partial diagnostic that can be emitted anwyhere
+/// in a DiagnosticBuilder stream.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PARTIALDIAGNOSTIC_H
@@ -37,25 +38,26 @@ public:
Storage() : NumDiagArgs(0), NumDiagRanges(0) { }
enum {
- /// MaxArguments - The maximum number of arguments we can hold. We
+ /// \brief The maximum number of arguments we can hold. We
/// currently only support up to 10 arguments (%0-%9).
+ ///
/// A single diagnostic with more than that almost certainly has to
/// be simplified anyway.
MaxArguments = PartialDiagnostic::MaxArguments
};
- /// NumDiagArgs - This contains the number of entries in Arguments.
+ /// \brief The number of entries in Arguments.
unsigned char NumDiagArgs;
- /// NumDiagRanges - This is the number of ranges in the DiagRanges array.
+ /// \brief This is the number of ranges in the DiagRanges array.
unsigned char NumDiagRanges;
- /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
- /// values, with one for each argument. This specifies whether the argument
- /// is in DiagArgumentsStr or in DiagArguments.
+ /// \brief Specifies for each argument whether it is in DiagArgumentsStr
+ /// or in DiagArguments.
unsigned char DiagArgumentsKind[MaxArguments];
- /// DiagArgumentsVal - The values for the various substitution positions.
+ /// \brief The values for the various substitution positions.
+ ///
/// This is used when the argument is not an std::string. The specific value
/// is mangled into an intptr_t and the interpretation depends on exactly
/// what sort of argument kind it is.
@@ -65,12 +67,13 @@ public:
/// string arguments.
std::string DiagArgumentsStr[MaxArguments];
- /// DiagRanges - The list of ranges added to this diagnostic. It currently
- /// only support 10 ranges, could easily be extended if needed.
+ /// \brief The list of ranges added to this diagnostic.
+ ///
+ /// It currently only support 10 ranges, could easily be extended if needed.
CharSourceRange DiagRanges[10];
- /// FixItHints - If valid, provides a hint with some code
- /// to insert, remove, or modify at a particular position.
+ /// \brief If valid, provides a hint with some code to insert, remove, or
+ /// modify at a particular position.
SmallVector<FixItHint, 6> FixItHints;
};
@@ -114,10 +117,10 @@ private:
// in the sense that its bits can be safely memcpy'ed and destructed
// in the new location.
- /// DiagID - The diagnostic ID.
+ /// \brief The diagnostic ID.
mutable unsigned DiagID;
- /// DiagStorage - Storage for args and ranges.
+ /// \brief Storage for args and ranges.
mutable Storage *DiagStorage;
/// \brief Allocator used to allocate storage for this diagnostic.
@@ -179,6 +182,12 @@ private:
}
public:
+ struct NullDiagnostic {};
+ /// \brief Create a null partial diagnostic, which cannot carry a payload,
+ /// and only exists to be swapped with a real partial diagnostic.
+ PartialDiagnostic(NullDiagnostic)
+ : DiagID(0), DiagStorage(0), Allocator(0) { }
+
PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator)
: DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { }
@@ -237,6 +246,12 @@ public:
freeStorage();
}
+ void swap(PartialDiagnostic &PD) {
+ std::swap(DiagID, PD.DiagID);
+ std::swap(DiagStorage, PD.DiagStorage);
+ std::swap(Allocator, PD.Allocator);
+ }
+
unsigned getDiagID() const { return DiagID; }
void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
@@ -283,6 +298,18 @@ public:
DB.AddFixItHint(DiagStorage->FixItHints[i]);
}
+ void EmitToString(DiagnosticsEngine &Diags,
+ llvm::SmallVectorImpl<char> &Buf) const {
+ // FIXME: It should be possible to render a diagnostic to a string without
+ // messing with the state of the diagnostics engine.
+ DiagnosticBuilder DB(Diags.Report(getDiagID()));
+ Emit(DB);
+ DB.FlushCounts();
+ Diagnostic(&Diags).FormatDiagnostic(Buf);
+ DB.Clear();
+ Diags.Clear();
+ }
+
/// \brief Clear out this partial diagnostic, giving it a new diagnostic ID
/// and removing all of its arguments, ranges, and fix-it hints.
void Reset(unsigned DiagID = 0) {
diff --git a/include/clang/Basic/PrettyStackTrace.h b/include/clang/Basic/PrettyStackTrace.h
index 06a12644c36e..967d0d141e5b 100644
--- a/include/clang/Basic/PrettyStackTrace.h
+++ b/include/clang/Basic/PrettyStackTrace.h
@@ -6,11 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the PrettyStackTraceEntry class, which is used to make
-// crashes give more contextual information about what the program was doing
-// when it crashed.
-//
+///
+/// \file
+/// \brief Defines the PrettyStackTraceEntry class, which is used to make
+/// crashes give more contextual information about what the program was doing
+/// when it crashed.
+///
//===----------------------------------------------------------------------===//
#ifndef CLANG_BASIC_PRETTYSTACKTRACE_H
@@ -21,8 +22,8 @@
namespace clang {
- /// PrettyStackTraceLoc - If a crash happens while one of these objects are
- /// live, the message is printed out along with the specified source location.
+ /// If a crash happens while one of these objects are live, the message
+ /// is printed out along with the specified source location.
class PrettyStackTraceLoc : public llvm::PrettyStackTraceEntry {
SourceManager &SM;
SourceLocation Loc;
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index d5fa7e74acf5..d6bba385633d 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/include/clang/Basic/SourceLocation.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the SourceLocation class.
-//
+///
+/// \file
+/// \brief Defines the clang::SourceLocation class and associated facilities.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SOURCELOCATION_H
@@ -31,12 +32,12 @@ namespace clang {
class SourceManager;
-/// FileID - This is an opaque identifier used by SourceManager which refers to
-/// a source file (MemoryBuffer) along with its #include path and #line data.
+/// \brief An opaque identifier used by SourceManager which refers to a
+/// source file (MemoryBuffer) along with its \#include path and \#line data.
///
class FileID {
- /// ID - Opaque identifier, 0 is "invalid". >0 is this module, <-1 is
- /// something loaded from another module.
+ /// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is
+ /// this module, and <-1 is something loaded from another module.
int ID;
public:
FileID() : ID(0) {}
@@ -135,24 +136,28 @@ public:
return L;
}
- /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
- /// an (opaque) 32-bit integer encoding for it. This should only be passed
- /// to SourceLocation::getFromRawEncoding, it should not be inspected
- /// directly.
+ /// \brief When a SourceLocation itself cannot be used, this returns
+ /// an (opaque) 32-bit integer encoding for it.
+ ///
+ /// This should only be passed to SourceLocation::getFromRawEncoding, it
+ /// should not be inspected directly.
unsigned getRawEncoding() const { return ID; }
- /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
+ /// \brief Turn a raw encoding of a SourceLocation object into
/// a real SourceLocation.
+ ///
+ /// \see getRawEncoding.
static SourceLocation getFromRawEncoding(unsigned Encoding) {
SourceLocation X;
X.ID = Encoding;
return X;
}
- /// getPtrEncoding - When a SourceLocation itself cannot be used, this returns
- /// an (opaque) pointer encoding for it. This should only be passed
- /// to SourceLocation::getFromPtrEncoding, it should not be inspected
- /// directly.
+ /// \brief When a SourceLocation itself cannot be used, this returns
+ /// an (opaque) pointer encoding for it.
+ ///
+ /// This should only be passed to SourceLocation::getFromPtrEncoding, it
+ /// should not be inspected directly.
void* getPtrEncoding() const {
// Double cast to avoid a warning "cast to pointer from integer of different
// size".
@@ -161,7 +166,7 @@ public:
/// getFromPtrEncoding - Turn a pointer encoding of a SourceLocation object
/// into a real SourceLocation.
- static SourceLocation getFromPtrEncoding(void *Encoding) {
+ static SourceLocation getFromPtrEncoding(const void *Encoding) {
return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
}
@@ -181,7 +186,7 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
return LHS.getRawEncoding() < RHS.getRawEncoding();
}
-/// SourceRange - a trival tuple used to represent a source range.
+/// \brief A trival tuple used to represent a source range.
class SourceRange {
SourceLocation B;
SourceLocation E;
@@ -208,7 +213,8 @@ public:
}
};
-/// CharSourceRange - This class represents a character granular source range.
+/// \brief Represents a character-granular source range.
+///
/// The underlying SourceRange can either specify the starting/ending character
/// of the range, or it can specify the start or the range and the start of the
/// last token of the range (a "token range"). In the token range case, the
@@ -242,7 +248,7 @@ public:
return getCharRange(SourceRange(B, E));
}
- /// isTokenRange - Return true if the end of this range specifies the start of
+ /// \brief Return true if the end of this range specifies the start of
/// the last token. Return false if the end of this range specifies the last
/// character in the range.
bool isTokenRange() const { return IsTokenRange; }
@@ -259,17 +265,19 @@ public:
bool isInvalid() const { return !isValid(); }
};
-/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful
-/// for argument passing to functions that expect both objects.
+/// \brief A SourceLocation and its associated SourceManager.
+///
+/// This is useful for argument passing to functions that expect both objects.
class FullSourceLoc : public SourceLocation {
const SourceManager *SrcMgr;
public:
- /// Creates a FullSourceLoc where isValid() returns false.
+ /// \brief Creates a FullSourceLoc where isValid() returns \c false.
explicit FullSourceLoc() : SrcMgr(0) {}
explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
: SourceLocation(Loc), SrcMgr(&SM) {}
+ /// \pre This FullSourceLoc has an associated SourceManager.
const SourceManager &getManager() const {
assert(SrcMgr && "SourceManager is NULL.");
return *SrcMgr;
@@ -290,13 +298,14 @@ public:
const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const;
- /// getBufferData - Return a StringRef to the source buffer data for the
+ /// \brief Return a StringRef to the source buffer data for the
/// specified FileID.
StringRef getBufferData(bool *Invalid = 0) const;
- /// getDecomposedLoc - Decompose the specified location into a raw FileID +
- /// Offset pair. The first element is the FileID, the second is the
- /// offset from the start of the buffer of the location.
+ /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ ///
+ /// The first element is the FileID, the second is the offset from the
+ /// start of the buffer of the location.
std::pair<FileID, unsigned> getDecomposedLoc() const;
bool isInSystemHeader() const;
@@ -323,8 +332,9 @@ public:
}
};
- /// Prints information about this FullSourceLoc to stderr. Useful for
- /// debugging.
+ /// \brief Prints information about this FullSourceLoc to stderr.
+ ///
+ /// This is useful for debugging.
LLVM_ATTRIBUTE_USED void dump() const;
friend inline bool
@@ -340,10 +350,11 @@ public:
};
-/// PresumedLoc - This class represents an unpacked "presumed" location which
-/// can be presented to the user. A 'presumed' location can be modified by
-/// #line and GNU line marker directives and is always the expansion point of
-/// a normal location.
+/// \brief Represents an unpacked "presumed" location which can be presented
+/// to the user.
+///
+/// A 'presumed' location can be modified by \#line and GNU line marker
+/// directives and is always the expansion point of a normal location.
///
/// You can get a PresumedLoc from a SourceLocation with SourceManager.
class PresumedLoc {
@@ -356,25 +367,30 @@ public:
: Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
}
- /// isInvalid - Return true if this object is invalid or uninitialized. This
- /// occurs when created with invalid source locations or when walking off
- /// the top of a #include stack.
+ /// \brief Return true if this object is invalid or uninitialized.
+ ///
+ /// This occurs when created with invalid source locations or when walking
+ /// off the top of a \#include stack.
bool isInvalid() const { return Filename == 0; }
bool isValid() const { return Filename != 0; }
- /// getFilename - Return the presumed filename of this location. This can be
- /// affected by #line etc.
+ /// \brief Return the presumed filename of this location.
+ ///
+ /// This can be affected by \#line etc.
const char *getFilename() const { return Filename; }
- /// getLine - Return the presumed line number of this location. This can be
- /// affected by #line etc.
+ /// \brief Return the presumed line number of this location.
+ ///
+ /// This can be affected by \#line etc.
unsigned getLine() const { return Line; }
- /// getColumn - Return the presumed column number of this location. This can
- /// not be affected by #line, but is packaged here for convenience.
+ /// \brief Return the presumed column number of this location.
+ ///
+ /// This cannot be affected by \#line, but is packaged here for convenience.
unsigned getColumn() const { return Col; }
- /// getIncludeLoc - Return the presumed include location of this location.
+ /// \brief Return the presumed include location of this location.
+ ///
/// This can be affected by GNU linemarker directives.
SourceLocation getIncludeLoc() const { return IncludeLoc; }
};
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index bcb2d561a4e4..32268d789d14 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -6,22 +6,46 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the SourceManager interface.
-//
+///
+/// \file
+/// \brief Defines the SourceManager interface.
+///
+/// There are three different types of locations in a file: a spelling
+/// location, an expansion location, and a presumed location.
+///
+/// Given an example of:
+/// \code
+/// #define min(x, y) x < y ? x : y
+/// \endcode
+///
+/// and then later on a use of min:
+/// \code
+/// #line 17
+/// return min(a, b);
+/// \endcode
+///
+/// The expansion location is the line in the source code where the macro
+/// was expanded (the return statement), the spelling location is the
+/// location in the source where the macro was originally defined,
+/// and the presumed location is where the line directive states that
+/// the line is 17, or any other line.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SOURCEMANAGER_H
#define LLVM_CLANG_SOURCEMANAGER_H
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/MemoryBuffer.h"
#include <map>
#include <vector>
@@ -38,38 +62,25 @@ class LangOptions;
class ASTWriter;
class ASTReader;
-/// There are three different types of locations in a file: a spelling
-/// location, an expansion location, and a presumed location.
-///
-/// Given an example of:
-/// #define min(x, y) x < y ? x : y
-///
-/// and then later on a use of min:
-/// #line 17
-/// return min(a, b);
-///
-/// The expansion location is the line in the source code where the macro
-/// was expanded (the return statement), the spelling location is the
-/// location in the source where the macro was originally defined,
-/// and the presumed location is where the line directive states that
-/// the line is 17, or any other line.
-
-/// SrcMgr - Public enums and private classes that are part of the
+/// \namespace
+/// \brief Public enums and private classes that are part of the
/// SourceManager implementation.
///
namespace SrcMgr {
- /// CharacteristicKind - This is used to represent whether a file or directory
- /// holds normal user code, system code, or system code which is implicitly
- /// 'extern "C"' in C++ mode. Entire directories can be tagged with this
- /// (this is maintained by DirectoryLookup and friends) as can specific
- /// FileInfos when a #pragma system_header is seen or various other cases.
+ /// \brief Indicates whether a file or directory holds normal user code,
+ /// system code, or system code which is implicitly 'extern "C"' in C++ mode.
+ ///
+ /// Entire directories can be tagged with this (this is maintained by
+ /// DirectoryLookup and friends) as can specific FileInfos when a \#pragma
+ /// system_header is seen or in various other cases.
///
enum CharacteristicKind {
C_User, C_System, C_ExternCSystem
};
- /// ContentCache - One instance of this struct is kept for every file
- /// loaded or used. This object owns the MemoryBuffer object.
+ /// \brief One instance of this struct is kept for every file loaded or used.
+ ////
+ /// This object owns the MemoryBuffer object.
class ContentCache {
enum CCFlags {
/// \brief Whether the buffer is invalid.
@@ -78,30 +89,37 @@ namespace SrcMgr {
DoNotFreeFlag = 0x02
};
- /// Buffer - The actual buffer containing the characters from the input
- /// file. This is owned by the ContentCache object.
- /// The bits indicate indicates whether the buffer is invalid.
+ /// \brief The actual buffer containing the characters from the input
+ /// file.
+ ///
+ /// This is owned by the ContentCache object. The bits indicate
+ /// whether the buffer is invalid.
mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;
public:
- /// Reference to the file entry representing this ContentCache.
+ /// \brief Reference to the file entry representing this ContentCache.
+ ///
/// This reference does not own the FileEntry object.
- /// It is possible for this to be NULL if
- /// the ContentCache encapsulates an imaginary text buffer.
+ ///
+ /// It is possible for this to be NULL if the ContentCache encapsulates
+ /// an imaginary text buffer.
const FileEntry *OrigEntry;
/// \brief References the file which the contents were actually loaded from.
+ ///
/// Can be different from 'Entry' if we overridden the contents of one file
/// with the contents of another file.
const FileEntry *ContentsEntry;
- /// SourceLineCache - A bump pointer allocated array of offsets for each
- /// source line. This is lazily computed. This is owned by the
- /// SourceManager BumpPointerAllocator object.
+ /// \brief A bump pointer allocated array of offsets for each source line.
+ ///
+ /// This is lazily computed. This is owned by the SourceManager
+ /// BumpPointerAllocator object.
unsigned *SourceLineCache;
- /// NumLines - The number of lines in this ContentCache. This is only valid
- /// if SourceLineCache is non-null.
+ /// \brief The number of lines in this ContentCache.
+ ///
+ /// This is only valid if SourceLineCache is non-null.
unsigned NumLines : 31;
/// \brief Indicates whether the buffer itself was provided to override
@@ -110,22 +128,29 @@ namespace SrcMgr {
/// When true, the original entry may be a virtual file that does not
/// exist.
unsigned BufferOverridden : 1;
+
+ /// \brief True if this content cache was initially created for a source
+ /// file considered as a system one.
+ unsigned IsSystemFile : 1;
ContentCache(const FileEntry *Ent = 0)
: Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent),
- SourceLineCache(0), NumLines(0), BufferOverridden(false) {}
+ SourceLineCache(0), NumLines(0), BufferOverridden(false),
+ IsSystemFile(false) {}
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
: Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt),
- SourceLineCache(0), NumLines(0), BufferOverridden(false) {}
+ SourceLineCache(0), NumLines(0), BufferOverridden(false),
+ IsSystemFile(false) {}
~ContentCache();
/// The copy ctor does not allow copies where source object has either
- /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
- /// is not transferred, so this is a logical error.
+ /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
+ /// is not transferred, so this is a logical error.
ContentCache(const ContentCache &RHS)
- : Buffer(0, false), SourceLineCache(0), BufferOverridden(false)
+ : Buffer(0, false), SourceLineCache(0), BufferOverridden(false),
+ IsSystemFile(false)
{
OrigEntry = RHS.OrigEntry;
ContentsEntry = RHS.ContentsEntry;
@@ -136,13 +161,13 @@ namespace SrcMgr {
NumLines = RHS.NumLines;
}
- /// getBuffer - Returns the memory buffer for the associated content.
+ /// \brief Returns the memory buffer for the associated content.
///
/// \param Diag Object through which diagnostics will be emitted if the
- /// buffer cannot be retrieved.
+ /// buffer cannot be retrieved.
///
/// \param Loc If specified, is the location that invalid file diagnostics
- /// will be emitted at.
+ /// will be emitted at.
///
/// \param Invalid If non-NULL, will be set \c true if an error occurred.
const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag,
@@ -150,15 +175,18 @@ namespace SrcMgr {
SourceLocation Loc = SourceLocation(),
bool *Invalid = 0) const;
- /// getSize - Returns the size of the content encapsulated by this
- /// ContentCache. This can be the size of the source file or the size of an
- /// arbitrary scratch buffer. If the ContentCache encapsulates a source
- /// file this size is retrieved from the file's FileEntry.
+ /// \brief Returns the size of the content encapsulated by this
+ /// ContentCache.
+ ///
+ /// This can be the size of the source file or the size of an
+ /// arbitrary scratch buffer. If the ContentCache encapsulates a source
+ /// file this size is retrieved from the file's FileEntry.
unsigned getSize() const;
- /// getSizeBytesMapped - Returns the number of bytes actually mapped for
- /// this ContentCache. This can be 0 if the MemBuffer was not actually
- /// expanded.
+ /// \brief Returns the number of bytes actually mapped for this
+ /// ContentCache.
+ ///
+ /// This can be 0 if the MemBuffer was not actually expanded.
unsigned getSizeBytesMapped() const;
/// Returns the kind of memory used to back the memory buffer for
@@ -196,35 +224,37 @@ namespace SrcMgr {
ContentCache &operator=(const ContentCache& RHS);
};
- /// FileInfo - Information about a FileID, basically just the logical file
+ /// \brief Information about a FileID, basically just the logical file
/// that it represents and include stack information.
///
/// Each FileInfo has include stack information, indicating where it came
- /// from. This information encodes the #include chain that a token was
+ /// from. This information encodes the \#include chain that a token was
/// expanded from. The main include file has an invalid IncludeLoc.
///
/// FileInfos contain a "ContentCache *", with the contents of the file.
///
class FileInfo {
- /// IncludeLoc - The location of the #include that brought in this file.
- /// This is an invalid SLOC for the main file (top of the #include chain).
+ /// \brief The location of the \#include that brought in this file.
+ ///
+ /// This is an invalid SLOC for the main file (top of the \#include chain).
unsigned IncludeLoc; // Really a SourceLocation
/// \brief Number of FileIDs (files and macros) that were created during
- /// preprocessing of this #include, including this SLocEntry.
+ /// preprocessing of this \#include, including this SLocEntry.
+ ///
/// Zero means the preprocessor didn't provide such info for this SLocEntry.
unsigned NumCreatedFIDs;
- /// Data - This contains the ContentCache* and the bits indicating the
- /// characteristic of the file and whether it has #line info, all bitmangled
- /// together.
+ /// \brief Contains the ContentCache* and the bits indicating the
+ /// characteristic of the file and whether it has \#line info, all
+ /// bitmangled together.
uintptr_t Data;
friend class clang::SourceManager;
friend class clang::ASTWriter;
friend class clang::ASTReader;
public:
- /// get - Return a FileInfo object.
+ /// \brief Return a FileInfo object.
static FileInfo get(SourceLocation IL, const ContentCache *Con,
CharacteristicKind FileCharacter) {
FileInfo X;
@@ -244,36 +274,35 @@ namespace SrcMgr {
return reinterpret_cast<const ContentCache*>(Data & ~7UL);
}
- /// getCharacteristic - Return whether this is a system header or not.
+ /// \brief Return whether this is a system header or not.
CharacteristicKind getFileCharacteristic() const {
return (CharacteristicKind)(Data & 3);
}
- /// hasLineDirectives - Return true if this FileID has #line directives in
- /// it.
+ /// \brief Return true if this FileID has \#line directives in it.
bool hasLineDirectives() const { return (Data & 4) != 0; }
- /// setHasLineDirectives - Set the flag that indicates that this FileID has
+ /// \brief Set the flag that indicates that this FileID has
/// line table entries associated with it.
void setHasLineDirectives() {
Data |= 4;
}
};
- /// ExpansionInfo - Each ExpansionInfo encodes the expansion location - where
+ /// \brief Each ExpansionInfo encodes the expansion location - where
/// the token was ultimately expanded, and the SpellingLoc - where the actual
/// character data for the token came from.
class ExpansionInfo {
// Really these are all SourceLocations.
- /// SpellingLoc - Where the spelling for the token can be found.
+ /// \brief Where the spelling for the token can be found.
unsigned SpellingLoc;
- /// ExpansionLocStart/ExpansionLocEnd - In a macro expansion, these
+ /// In a macro expansion, ExpansionLocStart and ExpansionLocEnd
/// indicate the start and end of the expansion. In object-like macros,
- /// these will be the same. In a function-like macro expansion, the start
+ /// they will be the same. In a function-like macro expansion, the start
/// will be the identifier and the end will be the ')'. Finally, in
- /// macro-argument instantitions, the end will be 'SourceLocation()', an
+ /// macro-argument instantiations, the end will be 'SourceLocation()', an
/// invalid location.
unsigned ExpansionLocStart, ExpansionLocEnd;
@@ -305,11 +334,12 @@ namespace SrcMgr {
getExpansionLocStart() != getExpansionLocEnd();
}
- /// create - Return a ExpansionInfo for an expansion. Start and End specify
- /// the expansion range (where the macro is expanded), and SpellingLoc
- /// specifies the spelling location (where the characters from the token
- /// come from). All three can refer to normal File SLocs or expansion
- /// locations.
+ /// \brief Return a ExpansionInfo for an expansion.
+ ///
+ /// Start and End specify the expansion range (where the macro is
+ /// expanded), and SpellingLoc specifies the spelling location (where
+ /// the characters from the token come from). All three can refer to
+ /// normal File SLocs or expansion locations.
static ExpansionInfo create(SourceLocation SpellingLoc,
SourceLocation Start, SourceLocation End) {
ExpansionInfo X;
@@ -319,14 +349,15 @@ namespace SrcMgr {
return X;
}
- /// createForMacroArg - Return a special ExpansionInfo for the expansion of
- /// a macro argument into a function-like macro's body. ExpansionLoc
- /// specifies the expansion location (where the macro is expanded). This
- /// doesn't need to be a range because a macro is always expanded at
- /// a macro parameter reference, and macro parameters are always exactly
- /// one token. SpellingLoc specifies the spelling location (where the
- /// characters from the token come from). ExpansionLoc and SpellingLoc can
- /// both refer to normal File SLocs or expansion locations.
+ /// \brief Return a special ExpansionInfo for the expansion of
+ /// a macro argument into a function-like macro's body.
+ ///
+ /// ExpansionLoc specifies the expansion location (where the macro is
+ /// expanded). This doesn't need to be a range because a macro is always
+ /// expanded at a macro parameter reference, and macro parameters are
+ /// always exactly one token. SpellingLoc specifies the spelling location
+ /// (where the characters from the token come from). ExpansionLoc and
+ /// SpellingLoc can both refer to normal File SLocs or expansion locations.
///
/// Given the code:
/// \code
@@ -335,7 +366,7 @@ namespace SrcMgr {
/// \endcode
///
/// When expanding '\c F(42)', the '\c x' would call this with an
- /// SpellingLoc pointing at '\c 42' anad an ExpansionLoc pointing at its
+ /// SpellingLoc pointing at '\c 42' and an ExpansionLoc pointing at its
/// location in the definition of '\c F'.
static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc,
SourceLocation ExpansionLoc) {
@@ -346,9 +377,10 @@ namespace SrcMgr {
}
};
- /// SLocEntry - This is a discriminated union of FileInfo and
- /// ExpansionInfo. SourceManager keeps an array of these objects, and
- /// they are uniquely identified by the FileID datatype.
+ /// \brief This is a discriminated union of FileInfo and ExpansionInfo.
+ ///
+ /// SourceManager keeps an array of these objects, and they are uniquely
+ /// identified by the FileID datatype.
class SLocEntry {
unsigned Offset; // low bit is set for expansion info.
union {
@@ -401,37 +433,43 @@ public:
};
-/// IsBeforeInTranslationUnitCache - This class holds the cache used by
-/// isBeforeInTranslationUnit. The cache structure is complex enough to be
-/// worth breaking out of SourceManager.
+/// \brief Holds the cache used by isBeforeInTranslationUnit.
+///
+/// The cache structure is complex enough to be worth breaking out of
+/// SourceManager.
class IsBeforeInTranslationUnitCache {
- /// L/R QueryFID - These are the FID's of the cached query. If these match up
- /// with a subsequent query, the result can be reused.
+ /// \brief The FileID's of the cached query.
+ ///
+ /// If these match up with a subsequent query, the result can be reused.
FileID LQueryFID, RQueryFID;
- /// \brief True if LQueryFID was created before RQueryFID. This is used
- /// to compare macro expansion locations.
+ /// \brief True if LQueryFID was created before RQueryFID.
+ ///
+ /// This is used to compare macro expansion locations.
bool IsLQFIDBeforeRQFID;
- /// CommonFID - This is the file found in common between the two #include
- /// traces. It is the nearest common ancestor of the #include tree.
+ /// \brief The file found in common between the two \#include traces, i.e.,
+ /// the nearest common ancestor of the \#include tree.
FileID CommonFID;
- /// L/R CommonOffset - This is the offset of the previous query in CommonFID.
- /// Usually, this represents the location of the #include for QueryFID, but if
- /// LQueryFID is a parent of RQueryFID (or vise versa) then these can be a
+ /// \brief The offset of the previous query in CommonFID.
+ ///
+ /// Usually, this represents the location of the \#include for QueryFID, but
+ /// if LQueryFID is a parent of RQueryFID (or vice versa) then these can be a
/// random token in the parent.
unsigned LCommonOffset, RCommonOffset;
public:
- /// isCacheValid - Return true if the currently cached values match up with
- /// the specified LHS/RHS query. If not, we can't use the cache.
+ /// \brief Return true if the currently cached values match up with
+ /// the specified LHS/RHS query.
+ ///
+ /// If not, we can't use the cache.
bool isCacheValid(FileID LHS, FileID RHS) const {
return LQueryFID == LHS && RQueryFID == RHS;
}
- /// getCachedResult - If the cache is valid, compute the result given the
- /// specified offsets in the LHS/RHS FID's.
+ /// \brief If the cache is valid, compute the result given the
+ /// specified offsets in the LHS/RHS FileID's.
bool getCachedResult(unsigned LOffset, unsigned ROffset) const {
// If one of the query files is the common file, use the offset. Otherwise,
// use the #include loc in the common file.
@@ -449,7 +487,7 @@ public:
return LOffset < ROffset;
}
- // Set up a new query.
+ /// \brief Set up a new query.
void setQueryFIDs(FileID LHS, FileID RHS, bool isLFIDBeforeRFID) {
assert(LHS != RHS);
LQueryFID = LHS;
@@ -474,7 +512,7 @@ public:
/// \brief This class handles loading and caching of source files into memory.
///
/// This object owns the MemoryBuffer objects for all of the loaded
-/// files and assigns unique FileID's for each unique #include chain.
+/// files and assigns unique FileID's for each unique \#include chain.
///
/// The SourceManager can be queried for information about SourceLocation
/// objects, turning them into either spelling or expansion locations. Spelling
@@ -491,8 +529,10 @@ class SourceManager : public RefCountedBase<SourceManager> {
mutable llvm::BumpPtrAllocator ContentCacheAlloc;
- /// FileInfos - Memoized information about all of the files tracked by this
- /// SourceManager. This set allows us to merge ContentCache entries based
+ /// \brief Memoized information about all of the files tracked by this
+ /// SourceManager.
+ ///
+ /// This map allows us to merge ContentCache entries based
/// on their FileEntry*. All ContentCache objects will thus have unique,
/// non-null, FileEntry pointers.
llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos;
@@ -501,11 +541,31 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// files, should report the original file name. Defaults to true.
bool OverridenFilesKeepOriginalName;
- /// \brief Files that have been overriden with the contents from another file.
- llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;
+ /// \brief True if non-system source files should be treated as volatile
+ /// (likely to change while trying to use them). Defaults to false.
+ bool UserFilesAreVolatile;
+
+ struct OverriddenFilesInfoTy {
+ /// \brief Files that have been overriden with the contents from another
+ /// file.
+ llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;
+ /// \brief Files that were overridden with a memory buffer.
+ llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer;
+ };
+
+ /// \brief Lazily create the object keeping overridden files info, since
+ /// it is uncommonly used.
+ OwningPtr<OverriddenFilesInfoTy> OverriddenFilesInfo;
+
+ OverriddenFilesInfoTy &getOverriddenFilesInfo() {
+ if (!OverriddenFilesInfo)
+ OverriddenFilesInfo.reset(new OverriddenFilesInfoTy);
+ return *OverriddenFilesInfo;
+ }
- /// MemBufferInfos - Information about various memory buffers that we have
- /// read in. All FileEntry* within the stored ContentCache objects are NULL,
+ /// \brief Information about various memory buffers that we have read in.
+ ///
+ /// All FileEntry* within the stored ContentCache objects are NULL,
/// as they do not refer to a file.
std::vector<SrcMgr::ContentCache*> MemBufferInfos;
@@ -545,23 +605,25 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// \brief An external source for source location entries.
ExternalSLocEntrySource *ExternalSLocEntries;
- /// LastFileIDLookup - This is a one-entry cache to speed up getFileID.
+ /// \brief A one-entry cache to speed up getFileID.
+ ///
/// LastFileIDLookup records the last FileID looked up or created, because it
/// is very common to look up many tokens from the same file.
mutable FileID LastFileIDLookup;
- /// LineTable - This holds information for #line directives. It is referenced
- /// by indices from SLocEntryTable.
+ /// \brief Holds information for \#line directives.
+ ///
+ /// This is referenced by indices from SLocEntryTable.
LineTableInfo *LineTable;
- /// LastLineNo - These ivars serve as a cache used in the getLineNumber
+ /// \brief These ivars serve as a cache used in the getLineNumber
/// method which is used to speedup getLineNumber calls to nearby locations.
mutable FileID LastLineNoFileIDQuery;
mutable SrcMgr::ContentCache *LastLineNoContentCache;
mutable unsigned LastLineNoFilePos;
mutable unsigned LastLineNoResult;
- /// MainFileID - The file ID for the main source file of the translation unit.
+ /// \brief The file ID for the main source file of the translation unit.
FileID MainFileID;
/// \brief The file ID for the precompiled preamble there is one.
@@ -588,7 +650,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
explicit SourceManager(const SourceManager&);
void operator=(const SourceManager&);
public:
- SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr);
+ SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
+ bool UserFilesAreVolatile = false);
~SourceManager();
void clearIDTables();
@@ -603,9 +666,15 @@ public:
OverridenFilesKeepOriginalName = value;
}
- /// createMainFileIDForMembuffer - Create the FileID for a memory buffer
- /// that will represent the FileID for the main source. One example
- /// of when this would be used is when the main source is read from STDIN.
+ /// \brief True if non-system source files should be treated as volatile
+ /// (likely to change while trying to use them).
+ bool userFilesAreVolatile() const { return UserFilesAreVolatile; }
+
+ /// \brief Create the FileID for a memory buffer that will represent the
+ /// FileID for the main source.
+ ///
+ /// One example of when this would be used is when the main source is read
+ /// from STDIN.
FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
assert(MainFileID.isInvalid() && "MainFileID already set!");
MainFileID = createFileIDForMemBuffer(Buffer);
@@ -616,10 +685,10 @@ public:
// MainFileID creation and querying methods.
//===--------------------------------------------------------------------===//
- /// getMainFileID - Returns the FileID of the main source file.
+ /// \brief Returns the FileID of the main source file.
FileID getMainFileID() const { return MainFileID; }
- /// createMainFileID - Create the FileID for the main source file.
+ /// \brief Create the FileID for the main source file.
FileID createMainFileID(const FileEntry *SourceFile,
SrcMgr::CharacteristicKind Kind = SrcMgr::C_User) {
assert(MainFileID.isInvalid() && "MainFileID already set!");
@@ -646,20 +715,24 @@ public:
// Methods to create new FileID's and macro expansions.
//===--------------------------------------------------------------------===//
- /// createFileID - Create a new FileID that represents the specified file
- /// being #included from the specified IncludePosition. This translates NULL
- /// into standard input.
+ /// \brief Create a new FileID that represents the specified file
+ /// being \#included from the specified IncludePosition.
+ ///
+ /// This translates NULL into standard input.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
int LoadedID = 0, unsigned LoadedOffset = 0) {
- const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
+ const SrcMgr::ContentCache *
+ IR = getOrCreateContentCache(SourceFile,
+ /*isSystemFile=*/FileCharacter != SrcMgr::C_User);
assert(IR && "getOrCreateContentCache() cannot return NULL");
return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset);
}
- /// createFileIDForMemBuffer - Create a new FileID that represents the
- /// specified memory buffer. This does no caching of the buffer and takes
- /// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
+ /// \brief Create a new FileID that represents the specified memory buffer.
+ ///
+ /// This does no caching of the buffer and takes ownership of the
+ /// MemoryBuffer, so only pass a MemoryBuffer to this once.
FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer,
int LoadedID = 0, unsigned LoadedOffset = 0,
SourceLocation IncludeLoc = SourceLocation()) {
@@ -667,7 +740,7 @@ public:
SrcMgr::C_User, LoadedID, LoadedOffset);
}
- /// createMacroArgExpansionLoc - Return a new SourceLocation that encodes the
+ /// \brief Return a new SourceLocation that encodes the
/// fact that a token from SpellingLoc should actually be referenced from
/// ExpansionLoc, and that it represents the expansion of a macro argument
/// into the function-like macro body.
@@ -675,7 +748,7 @@ public:
SourceLocation ExpansionLoc,
unsigned TokLength);
- /// createExpansionLoc - Return a new SourceLocation that encodes the fact
+ /// \brief Return a new SourceLocation that encodes the fact
/// that a token from SpellingLoc should actually be referenced from
/// ExpansionLoc.
SourceLocation createExpansionLoc(SourceLocation Loc,
@@ -706,7 +779,7 @@ public:
const llvm::MemoryBuffer *Buffer,
bool DoNotFree = false);
- /// \brief Override the the given source file with another one.
+ /// \brief Override the given source file with another one.
///
/// \param SourceFile the source file which will be overriden.
///
@@ -715,13 +788,32 @@ public:
void overrideFileContents(const FileEntry *SourceFile,
const FileEntry *NewFile);
+ /// \brief Returns true if the file contents have been overridden.
+ bool isFileOverridden(const FileEntry *File) {
+ if (OverriddenFilesInfo) {
+ if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File))
+ return true;
+ if (OverriddenFilesInfo->OverriddenFiles.find(File) !=
+ OverriddenFilesInfo->OverriddenFiles.end())
+ return true;
+ }
+ return false;
+ }
+
+ /// \brief Disable overridding the contents of a file, previously enabled
+ /// with #overrideFileContents.
+ ///
+ /// This should be called before parsing has begun.
+ void disableFileContentsOverride(const FileEntry *File);
+
//===--------------------------------------------------------------------===//
// FileID manipulation methods.
//===--------------------------------------------------------------------===//
- /// getBuffer - Return the buffer for the specified FileID. If there is an
- /// error opening this buffer the first time, this manufactures a temporary
- /// buffer and returns a non-empty error string.
+ /// \brief Return the buffer for the specified FileID.
+ ///
+ /// If there is an error opening this buffer the first time, this
+ /// manufactures a temporary buffer and returns a non-empty error string.
const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc,
bool *Invalid = 0) const {
bool MyInvalid = false;
@@ -752,7 +844,7 @@ public:
Invalid);
}
- /// getFileEntryForID - Returns the FileEntry record for the provided FileID.
+ /// \brief Returns the FileEntry record for the provided FileID.
const FileEntry *getFileEntryForID(FileID FID) const {
bool MyInvalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
@@ -765,7 +857,7 @@ public:
return Content->OrigEntry;
}
- /// Returns the FileEntry record for the provided SLocEntry.
+ /// \brief Returns the FileEntry record for the provided SLocEntry.
const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const
{
const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache();
@@ -774,7 +866,7 @@ public:
return Content->OrigEntry;
}
- /// getBufferData - Return a StringRef to the source buffer data for the
+ /// \brief Return a StringRef to the source buffer data for the
/// specified FileID.
///
/// \param FID The file ID whose contents will be returned.
@@ -808,10 +900,11 @@ public:
// SourceLocation manipulation methods.
//===--------------------------------------------------------------------===//
- /// getFileID - Return the FileID for a SourceLocation. This is a very
- /// hot method that is used for all SourceManager queries that start with a
- /// SourceLocation object. It is responsible for finding the entry in
- /// SLocEntryTable which contains the specified location.
+ /// \brief Return the FileID for a SourceLocation.
+ ///
+ /// This is a very hot method that is used for all SourceManager queries
+ /// that start with a SourceLocation object. It is responsible for finding
+ /// the entry in SLocEntryTable which contains the specified location.
///
FileID getFileID(SourceLocation SpellingLoc) const {
unsigned SLocOffset = SpellingLoc.getOffset();
@@ -823,8 +916,15 @@ public:
return getFileIDSlow(SLocOffset);
}
- /// getLocForStartOfFile - Return the source location corresponding to the
- /// first byte of the specified file.
+ /// \brief Return the filename of the file containing a SourceLocation.
+ StringRef getFilename(SourceLocation SpellingLoc) const {
+ if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc)))
+ return F->getName();
+ return StringRef();
+ }
+
+ /// \brief Return the source location corresponding to the first byte of
+ /// the specified file.
SourceLocation getLocForStartOfFile(FileID FID) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
@@ -847,7 +947,7 @@ public:
return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID) - 1);
}
- /// \brief Returns the include location if \p FID is a #include'd file
+ /// \brief Returns the include location if \p FID is a \#include'd file
/// otherwise it returns an invalid location.
SourceLocation getIncludeLoc(FileID FID) const {
bool Invalid = false;
@@ -858,7 +958,7 @@ public:
return Entry.getFile().getIncludeLoc();
}
- /// getExpansionLoc - Given a SourceLocation object, return the expansion
+ /// \brief Given a SourceLocation object \p Loc, return the expansion
/// location referenced by the ID.
SourceLocation getExpansionLoc(SourceLocation Loc) const {
// Handle the non-mapped case inline, defer to out of line code to handle
@@ -875,20 +975,24 @@ public:
return getFileLocSlowCase(Loc);
}
- /// getImmediateExpansionRange - Loc is required to be an expansion location.
- /// Return the start/end of the expansion information.
+ /// \brief Return the start/end of the expansion information for an
+ /// expansion location.
+ ///
+ /// \pre \p Loc is required to be an expansion location.
std::pair<SourceLocation,SourceLocation>
getImmediateExpansionRange(SourceLocation Loc) const;
- /// getExpansionRange - Given a SourceLocation object, return the range of
+ /// \brief Given a SourceLocation object, return the range of
/// tokens covered by the expansion the ultimate file.
std::pair<SourceLocation,SourceLocation>
getExpansionRange(SourceLocation Loc) const;
- /// getSpellingLoc - Given a SourceLocation object, return the spelling
- /// location referenced by the ID. This is the place where the characters
- /// that make up the lexed token can be found.
+ /// \brief Given a SourceLocation object, return the spelling
+ /// location referenced by the ID.
+ ///
+ /// This is the place where the characters that make up the lexed token
+ /// can be found.
SourceLocation getSpellingLoc(SourceLocation Loc) const {
// Handle the non-mapped case inline, defer to out of line code to handle
// expansions.
@@ -896,15 +1000,18 @@ public:
return getSpellingLocSlowCase(Loc);
}
- /// getImmediateSpellingLoc - Given a SourceLocation object, return the
- /// spelling location referenced by the ID. This is the first level down
- /// towards the place where the characters that make up the lexed token can be
- /// found. This should not generally be used by clients.
+ /// \brief Given a SourceLocation object, return the spelling location
+ /// referenced by the ID.
+ ///
+ /// This is the first level down towards the place where the characters
+ /// that make up the lexed token can be found. This should not generally
+ /// be used by clients.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const;
- /// getDecomposedLoc - Decompose the specified location into a raw FileID +
- /// Offset pair. The first element is the FileID, the second is the
- /// offset from the start of the buffer of the location.
+ /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ ///
+ /// The first element is the FileID, the second is the offset from the
+ /// start of the buffer of the location.
std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const {
FileID FID = getFileID(Loc);
bool Invalid = false;
@@ -914,9 +1021,10 @@ public:
return std::make_pair(FID, Loc.getOffset()-E.getOffset());
}
- /// getDecomposedExpansionLoc - Decompose the specified location into a raw
- /// FileID + Offset pair. If the location is an expansion record, walk
- /// through it until we find the final location expanded.
+ /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ ///
+ /// If the location is an expansion record, walk through it until we find
+ /// the final location expanded.
std::pair<FileID, unsigned>
getDecomposedExpansionLoc(SourceLocation Loc) const {
FileID FID = getFileID(Loc);
@@ -932,9 +1040,10 @@ public:
return getDecomposedExpansionLocSlowCase(E);
}
- /// getDecomposedSpellingLoc - Decompose the specified location into a raw
- /// FileID + Offset pair. If the location is an expansion record, walk
- /// through it until we find its spelling record.
+ /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ ///
+ /// If the location is an expansion record, walk through it until we find
+ /// its spelling record.
std::pair<FileID, unsigned>
getDecomposedSpellingLoc(SourceLocation Loc) const {
FileID FID = getFileID(Loc);
@@ -949,22 +1058,25 @@ public:
return getDecomposedSpellingLocSlowCase(E, Offset);
}
- /// getFileOffset - This method returns the offset from the start
- /// of the file that the specified SourceLocation represents. This is not very
- /// meaningful for a macro ID.
+ /// \brief Returns the offset from the start of the file that the
+ /// specified SourceLocation represents.
+ ///
+ /// This is not very meaningful for a macro ID.
unsigned getFileOffset(SourceLocation SpellingLoc) const {
return getDecomposedLoc(SpellingLoc).second;
}
- /// isMacroArgExpansion - This method tests whether the given source location
- /// represents a macro argument's expansion into the function-like macro
- /// definition. Such source locations only appear inside of the expansion
+ /// \brief Tests whether the given source location represents a macro
+ /// argument's expansion into the function-like macro definition.
+ ///
+ /// Such source locations only appear inside of the expansion
/// locations representing where a particular function-like macro was
/// expanded.
bool isMacroArgExpansion(SourceLocation Loc) const;
/// \brief Returns true if \p Loc is inside the [\p Start, +\p Length)
/// chunk of the source location address space.
+ ///
/// If it's true and \p RelativeOffset is non-null, it will be set to the
/// relative offset of \p Loc inside the chunk.
bool isInSLocAddrSpace(SourceLocation Loc,
@@ -988,9 +1100,10 @@ public:
}
/// \brief Return true if both \p LHS and \p RHS are in the local source
- /// location address space or the loaded one. If it's true and \p
- /// RelativeOffset is non-null, it will be set to the offset of \p RHS
- /// relative to \p LHS.
+ /// location address space or the loaded one.
+ ///
+ /// If it's true and \p RelativeOffset is non-null, it will be set to the
+ /// offset of \p RHS relative to \p LHS.
bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS,
int *RelativeOffset) const {
unsigned LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset();
@@ -1010,13 +1123,14 @@ public:
// Queries about the code at a SourceLocation.
//===--------------------------------------------------------------------===//
- /// getCharacterData - Return a pointer to the start of the specified location
+ /// \brief Return a pointer to the start of the specified location
/// in the appropriate spelling MemoryBuffer.
///
/// \param Invalid If non-NULL, will be set \c true if an error occurs.
const char *getCharacterData(SourceLocation SL, bool *Invalid = 0) const;
- /// getColumnNumber - Return the column # for the specified file position.
+ /// \brief Return the column # for the specified file position.
+ ///
/// This is significantly cheaper to compute than the line number. This
/// returns zero if the column number isn't known. This may only be called
/// on a file sloc, so you must choose a spelling or expansion location
@@ -1029,34 +1143,41 @@ public:
unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
- /// getLineNumber - Given a SourceLocation, return the spelling line number
- /// for the position indicated. This requires building and caching a table of
- /// line offsets for the MemoryBuffer, so this is not cheap: use only when
- /// about to emit a diagnostic.
+ /// \brief Given a SourceLocation, return the spelling line number
+ /// for the position indicated.
+ ///
+ /// This requires building and caching a table of line offsets for the
+ /// MemoryBuffer, so this is not cheap: use only when about to emit a
+ /// diagnostic.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const;
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
- /// Return the filename or buffer identifier of the buffer the location is in.
- /// Note that this name does not respect #line directives. Use getPresumedLoc
- /// for normal clients.
+ /// \brief Return the filename or buffer identifier of the buffer the
+ /// location is in.
+ ///
+ /// Note that this name does not respect \#line directives. Use
+ /// getPresumedLoc for normal clients.
const char *getBufferName(SourceLocation Loc, bool *Invalid = 0) const;
- /// getFileCharacteristic - return the file characteristic of the specified
- /// source location, indicating whether this is a normal file, a system
+ /// \brief Return the file characteristic of the specified source
+ /// location, indicating whether this is a normal file, a system
/// header, or an "implicit extern C" system header.
///
/// This state can be modified with flags on GNU linemarker directives like:
+ /// \code
/// # 4 "foo.h" 3
+ /// \endcode
/// which changes all source locations in the current file after that to be
/// considered to be from a system header.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const;
- /// getPresumedLoc - This method returns the "presumed" location of a
- /// SourceLocation specifies. A "presumed location" can be modified by #line
- /// or GNU line marker directives. This provides a view on the data that a
- /// user should see in diagnostics, for example.
+ /// \brief Returns the "presumed" location of a SourceLocation specifies.
+ ///
+ /// A "presumed location" can be modified by \#line or GNU line marker
+ /// directives. This provides a view on the data that a user should see
+ /// in diagnostics, for example.
///
/// Note that a presumed location is always given as the expansion point of
/// an expansion location, not at the spelling location.
@@ -1067,25 +1188,23 @@ public:
/// presumed location.
PresumedLoc getPresumedLoc(SourceLocation Loc) const;
- /// isFromSameFile - Returns true if both SourceLocations correspond to
- /// the same file.
+ /// \brief Returns true if both SourceLocations correspond to the same file.
bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
return getFileID(Loc1) == getFileID(Loc2);
}
- /// isFromMainFile - Returns true if the file of provided SourceLocation is
- /// the main file.
+ /// \brief Returns true if the file of provided SourceLocation is the main
+ /// file.
bool isFromMainFile(SourceLocation Loc) const {
return getFileID(Loc) == getMainFileID();
}
- /// isInSystemHeader - Returns if a SourceLocation is in a system header.
+ /// \brief Returns if a SourceLocation is in a system header.
bool isInSystemHeader(SourceLocation Loc) const {
return getFileCharacteristic(Loc) != SrcMgr::C_User;
}
- /// isInExternCSystemHeader - Returns if a SourceLocation is in an "extern C"
- /// system header.
+ /// \brief Returns if a SourceLocation is in an "extern C" system header.
bool isInExternCSystemHeader(SourceLocation Loc) const {
return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
}
@@ -1117,13 +1236,14 @@ public:
// Line Table Manipulation Routines
//===--------------------------------------------------------------------===//
- /// getLineTableFilenameID - Return the uniqued ID for the specified filename.
+ /// \brief Return the uniqued ID for the specified filename.
///
unsigned getLineTableFilenameID(StringRef Str);
- /// AddLineNote - Add a line note to the line table for the FileID and offset
- /// specified by Loc. If FilenameID is -1, it is considered to be
- /// unspecified.
+ /// \brief Add a line note to the line table for the FileID and offset
+ /// specified by Loc.
+ ///
+ /// If FilenameID is -1, it is considered to be unspecified.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID);
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID,
bool IsFileEntry, bool IsFileExit,
@@ -1139,7 +1259,7 @@ public:
// Queries for performance analysis.
//===--------------------------------------------------------------------===//
- /// Return the total amount of physical memory allocated by the
+ /// \brief Return the total amount of physical memory allocated by the
/// ContentCache allocator.
size_t getContentCacheSize() const {
return ContentCacheAlloc.getTotalMemory();
@@ -1153,12 +1273,12 @@ public:
: malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
};
- /// Return the amount of memory used by memory buffers, breaking down
+ /// \brief Return the amount of memory used by memory buffers, breaking down
/// by heap-backed versus mmap'ed memory.
MemoryBufferSizes getMemoryBufferSizes() const;
- // Return the amount of memory used for various side tables and
- // data structures in the SourceManager.
+ /// \brief Return the amount of memory used for various side tables and
+ /// data structures in the SourceManager.
size_t getDataStructureSizes() const;
//===--------------------------------------------------------------------===//
@@ -1199,19 +1319,6 @@ public:
/// \returns true if LHS source location comes before RHS, false otherwise.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
- /// \brief Comparison function class.
- class LocBeforeThanCompare : public std::binary_function<SourceLocation,
- SourceLocation, bool> {
- SourceManager &SM;
-
- public:
- explicit LocBeforeThanCompare(SourceManager &SM) : SM(SM) { }
-
- bool operator()(SourceLocation LHS, SourceLocation RHS) const {
- return SM.isBeforeInTranslationUnit(LHS, RHS);
- }
- };
-
/// \brief Determines the order of 2 source locations in the "source location
/// address space".
bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {
@@ -1241,7 +1348,7 @@ public:
return FileInfos.find(File) != FileInfos.end();
}
- /// PrintStats - Print statistics to stderr.
+ /// \brief Print statistics to stderr.
///
void PrintStats() const;
@@ -1313,6 +1420,65 @@ public:
return !isLoadedFileID(FID);
}
+ /// Get a presumed location suitable for displaying in a diagnostic message,
+ /// taking into account macro arguments and expansions.
+ PresumedLoc getPresumedLocForDisplay(SourceLocation Loc) const {
+ // This is a condensed form of the algorithm used by emitCaretDiagnostic to
+ // walk to the top of the macro call stack.
+ while (Loc.isMacroID()) {
+ Loc = skipToMacroArgExpansion(Loc);
+ Loc = getImmediateMacroCallerLoc(Loc);
+ }
+
+ return getPresumedLoc(Loc);
+ }
+
+ /// Look through spelling locations for a macro argument expansion, and if
+ /// found skip to it so that we can trace the argument rather than the macros
+ /// in which that argument is used. If no macro argument expansion is found,
+ /// don't skip anything and return the starting location.
+ SourceLocation skipToMacroArgExpansion(SourceLocation StartLoc) const {
+ for (SourceLocation L = StartLoc; L.isMacroID();
+ L = getImmediateSpellingLoc(L)) {
+ if (isMacroArgExpansion(L))
+ return L;
+ }
+ // Otherwise just return initial location, there's nothing to skip.
+ return StartLoc;
+ }
+
+ /// Gets the location of the immediate macro caller, one level up the stack
+ /// toward the initial macro typed into the source.
+ SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const {
+ if (!Loc.isMacroID()) return Loc;
+
+ // When we have the location of (part of) an expanded parameter, its
+ // spelling location points to the argument as typed into the macro call,
+ // and therefore is used to locate the macro caller.
+ if (isMacroArgExpansion(Loc))
+ return getImmediateSpellingLoc(Loc);
+
+ // Otherwise, the caller of the macro is located where this macro is
+ // expanded (while the spelling is part of the macro definition).
+ return getImmediateExpansionRange(Loc).first;
+ }
+
+ /// Gets the location of the immediate macro callee, one level down the stack
+ /// toward the leaf macro.
+ SourceLocation getImmediateMacroCalleeLoc(SourceLocation Loc) const {
+ if (!Loc.isMacroID()) return Loc;
+
+ // When we have the location of (part of) an expanded parameter, its
+ // expansion location points to the unexpanded parameter reference within
+ // the macro definition (or callee).
+ if (isMacroArgExpansion(Loc))
+ return getImmediateExpansionRange(Loc).first;
+
+ // Otherwise, the callee of the macro is located where this location was
+ // spelled inside the macro definition.
+ return getImmediateSpellingLoc(Loc);
+ }
+
private:
const llvm::MemoryBuffer *getFakeBufferForRecovery() const;
const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const;
@@ -1332,15 +1498,14 @@ private:
return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid);
}
- /// createExpansionLoc - Implements the common elements of storing an
- /// expansion info struct into the SLocEntry table and producing a source
- /// location that refers to it.
+ /// Implements the common elements of storing an expansion info struct into
+ /// the SLocEntry table and producing a source location that refers to it.
SourceLocation createExpansionLocImpl(const SrcMgr::ExpansionInfo &Expansion,
unsigned TokLength,
int LoadedID = 0,
unsigned LoadedOffset = 0);
- /// isOffsetInFileID - Return true if the specified FileID contains the
+ /// \brief Return true if the specified FileID contains the
/// specified SourceLocation offset. This is a very hot method.
inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const {
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID);
@@ -1352,28 +1517,29 @@ private:
return true;
// If it is the last local entry, then it does if the location is local.
- if (static_cast<unsigned>(FID.ID+1) == LocalSLocEntryTable.size()) {
+ if (FID.ID+1 == static_cast<int>(LocalSLocEntryTable.size()))
return SLocOffset < NextLocalOffset;
- }
// Otherwise, the entry after it has to not include it. This works for both
// local and loaded entries.
- return SLocOffset < getSLocEntry(FileID::get(FID.ID+1)).getOffset();
+ return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset();
}
- /// createFileID - Create a new fileID for the specified ContentCache and
- /// include position. This works regardless of whether the ContentCache
- /// corresponds to a file or some other input source.
+ /// \brief Create a new fileID for the specified ContentCache and
+ /// include position.
+ ///
+ /// This works regardless of whether the ContentCache corresponds to a
+ /// file or some other input source.
FileID createFileID(const SrcMgr::ContentCache* File,
SourceLocation IncludePos,
SrcMgr::CharacteristicKind DirCharacter,
int LoadedID, unsigned LoadedOffset);
const SrcMgr::ContentCache *
- getOrCreateContentCache(const FileEntry *SourceFile);
+ getOrCreateContentCache(const FileEntry *SourceFile,
+ bool isSystemFile = false);
- /// createMemBufferContentCache - Create a new ContentCache for the specified
- /// memory buffer.
+ /// \brief Create a new ContentCache for the specified memory buffer.
const SrcMgr::ContentCache*
createMemBufferContentCache(const llvm::MemoryBuffer *Buf);
@@ -1396,6 +1562,35 @@ private:
friend class ASTWriter;
};
+/// \brief Comparison function object.
+template<typename T>
+class BeforeThanCompare;
+
+/// \brief Compare two source locations.
+template<>
+class BeforeThanCompare<SourceLocation> {
+ SourceManager &SM;
+
+public:
+ explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { }
+
+ bool operator()(SourceLocation LHS, SourceLocation RHS) const {
+ return SM.isBeforeInTranslationUnit(LHS, RHS);
+ }
+};
+
+/// \brief Compare two non-overlapping source ranges.
+template<>
+class BeforeThanCompare<SourceRange> {
+ SourceManager &SM;
+
+public:
+ explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { }
+
+ bool operator()(SourceRange LHS, SourceRange RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin());
+ }
+};
} // end namespace clang
diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h
index 1cb16b458f41..af95b78883fe 100644
--- a/include/clang/Basic/SourceManagerInternals.h
+++ b/include/clang/Basic/SourceManagerInternals.h
@@ -6,15 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the implementation details of the SourceManager
-// class.
-//
+///
+/// \file
+/// \brief Defines implementation details of the clang::SourceManager class.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SOURCEMANAGER_INTERNALS_H
#define LLVM_CLANG_SOURCEMANAGER_INTERNALS_H
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringMap.h"
#include <map>
@@ -26,22 +27,23 @@ namespace clang {
//===----------------------------------------------------------------------===//
struct LineEntry {
- /// FileOffset - The offset in this file that the line entry occurs at.
+ /// \brief The offset in this file that the line entry occurs at.
unsigned FileOffset;
- /// LineNo - The presumed line number of this line entry: #line 4.
+ /// \brief The presumed line number of this line entry: \#line 4.
unsigned LineNo;
- /// FilenameID - The ID of the filename identified by this line entry:
- /// #line 4 "foo.c". This is -1 if not specified.
+ /// \brief The ID of the filename identified by this line entry:
+ /// \#line 4 "foo.c". This is -1 if not specified.
int FilenameID;
- /// Flags - Set the 0 if no flags, 1 if a system header,
+ /// \brief Set the 0 if no flags, 1 if a system header,
SrcMgr::CharacteristicKind FileKind;
- /// IncludeOffset - This is the offset of the virtual include stack location,
- /// which is manipulated by GNU linemarker directives. If this is 0 then
- /// there is no virtual #includer.
+ /// \brief The offset of the virtual include stack location,
+ /// which is manipulated by GNU linemarker directives.
+ ///
+ /// If this is 0 then there is no virtual \#includer.
unsigned IncludeOffset;
static LineEntry get(unsigned Offs, unsigned Line, int Filename,
@@ -71,20 +73,20 @@ inline bool operator<(unsigned Offset, const LineEntry &E) {
return Offset < E.FileOffset;
}
-/// LineTableInfo - This class is used to hold and unique data used to
-/// represent #line information.
+/// \brief Used to hold and unique data used to represent \#line information.
class LineTableInfo {
- /// FilenameIDs - This map is used to assign unique IDs to filenames in
- /// #line directives. This allows us to unique the filenames that
+ /// \brief Map used to assign unique IDs to filenames in \#line directives.
+ ///
+ /// This allows us to unique the filenames that
/// frequently reoccur and reference them with indices. FilenameIDs holds
/// the mapping from string -> ID, and FilenamesByID holds the mapping of ID
/// to string.
llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs;
std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID;
- /// LineEntries - This is a map from FileIDs to a list of line entries (sorted
- /// by the offset they occur in the file.
- std::map<int, std::vector<LineEntry> > LineEntries;
+ /// \brief Map from FileIDs to a list of line entries (sorted by the offset
+ /// at which they occur in the file).
+ std::map<FileID, std::vector<LineEntry> > LineEntries;
public:
LineTableInfo() {
}
@@ -104,25 +106,26 @@ public:
}
unsigned getNumFilenames() const { return FilenamesByID.size(); }
- void AddLineNote(int FID, unsigned Offset,
+ void AddLineNote(FileID FID, unsigned Offset,
unsigned LineNo, int FilenameID);
- void AddLineNote(int FID, unsigned Offset,
+ void AddLineNote(FileID FID, unsigned Offset,
unsigned LineNo, int FilenameID,
unsigned EntryExit, SrcMgr::CharacteristicKind FileKind);
- /// FindNearestLineEntry - Find the line entry nearest to FID that is before
- /// it. If there is no line entry before Offset in FID, return null.
- const LineEntry *FindNearestLineEntry(int FID, unsigned Offset);
+ /// \brief Find the line entry nearest to FID that is before it.
+ ///
+ /// If there is no line entry before \p Offset in \p FID, returns null.
+ const LineEntry *FindNearestLineEntry(FileID FID, unsigned Offset);
// Low-level access
- typedef std::map<int, std::vector<LineEntry> >::iterator iterator;
+ typedef std::map<FileID, std::vector<LineEntry> >::iterator iterator;
iterator begin() { return LineEntries.begin(); }
iterator end() { return LineEntries.end(); }
/// \brief Add a new line entry that has already been encoded into
/// the internal representation of the line table.
- void AddEntry(int FID, const std::vector<LineEntry> &Entries);
+ void AddEntry(FileID FID, const std::vector<LineEntry> &Entries);
};
} // end namespace clang
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 9e71827b67bc..96cada10571e 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines various enumerations that describe declaration and
-// type specifiers.
-//
+///
+/// \file
+/// \brief Defines various enumerations that describe declaration and
+/// type specifiers.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H
@@ -63,9 +64,8 @@ namespace clang {
TST_error // erroneous type
};
- /// WrittenBuiltinSpecs - Structure that packs information about the
- /// type specifiers that were written in a particular type specifier
- /// sequence.
+ /// \brief Structure that packs information about the type specifiers that
+ /// were written in a particular type specifier sequence.
struct WrittenBuiltinSpecs {
/*DeclSpec::TST*/ unsigned Type : 5;
/*DeclSpec::TSS*/ unsigned Sign : 2;
@@ -73,9 +73,8 @@ namespace clang {
bool ModeAttr : 1;
};
- /// AccessSpecifier - A C++ access specifier (public, private,
- /// protected), plus the special value "none" which means
- /// different things in different contexts.
+ /// \brief A C++ access specifier (public, private, protected), plus the
+ /// special value "none" which means different things in different contexts.
enum AccessSpecifier {
AS_public,
AS_protected,
@@ -83,24 +82,24 @@ namespace clang {
AS_none
};
- /// ExprValueKind - The categorization of expression values,
- /// currently following the C++0x scheme.
+ /// \brief The categorization of expression values, currently following the
+ /// C++11 scheme.
enum ExprValueKind {
- /// An r-value expression (a pr-value in the C++0x taxonomy)
+ /// \brief An r-value expression (a pr-value in the C++11 taxonomy)
/// produces a temporary value.
VK_RValue,
- /// An l-value expression is a reference to an object with
+ /// \brief An l-value expression is a reference to an object with
/// independent storage.
VK_LValue,
- /// An x-value expression is a reference to an object with
+ /// \brief An x-value expression is a reference to an object with
/// independent storage but which can be "moved", i.e.
/// efficiently cannibalized for its resources.
VK_XValue
};
- /// A further classification of the kind of object referenced by an
+ /// \brief A further classification of the kind of object referenced by an
/// l-value or x-value.
enum ExprObjectKind {
/// An ordinary object is located at an address in memory.
@@ -112,13 +111,13 @@ namespace clang {
/// A vector component is an element or range of elements on a vector.
OK_VectorComponent,
- /// An Objective C property is a logical field of an Objective-C
- /// object which is read and written via Objective C method calls.
+ /// An Objective-C property is a logical field of an Objective-C
+ /// object which is read and written via Objective-C method calls.
OK_ObjCProperty,
- /// An Objective C array/dictionary subscripting which reads an object
- /// or writes at the subscripted array/dictionary element via
- /// Objective C method calls.
+ /// An Objective-C array/dictionary subscripting which reads an
+ /// object or writes at the subscripted array/dictionary element via
+ /// Objective-C method calls.
OK_ObjCSubscript
};
@@ -159,15 +158,22 @@ namespace clang {
SC_Register
};
- /// Checks whether the given storage class is legal for functions.
+ /// \brief Checks whether the given storage class is legal for functions.
inline bool isLegalForFunction(StorageClass SC) {
return SC <= SC_PrivateExtern;
}
- /// Checks whether the given storage class is legal for variables.
+ /// \brief Checks whether the given storage class is legal for variables.
inline bool isLegalForVariable(StorageClass SC) {
return true;
}
+
+ /// \brief In-class initialization styles for non-static data members.
+ enum InClassInitStyle {
+ ICIS_NoInit, ///< No in-class initializer.
+ ICIS_CopyInit, ///< Copy initialization.
+ ICIS_ListInit ///< Direct list-initialization.
+ };
} // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index e7718cd80cb3..47738af2907f 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -31,6 +31,9 @@ def DefaultStmt : DStmt<SwitchCase>;
// GNU Extensions
def AsmStmt : Stmt;
+// MS Extensions
+def MSAsmStmt : Stmt;
+
// Obj-C statements
def ObjCAtTryStmt : Stmt;
def ObjCAtCatchStmt : Stmt;
@@ -134,7 +137,7 @@ def LambdaExpr : DStmt<Expr>;
// Obj-C Expressions.
def ObjCStringLiteral : DStmt<Expr>;
-def ObjCNumericLiteral : DStmt<Expr>;
+def ObjCBoxedExpr : DStmt<Expr>;
def ObjCArrayLiteral : DStmt<Expr>;
def ObjCDictionaryLiteral : DStmt<Expr>;
def ObjCEncodeExpr : DStmt<Expr>;
diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index 7c04bf7edf5b..1d5004c37002 100644
--- a/include/clang/Basic/TargetBuiltins.h
+++ b/include/clang/Basic/TargetBuiltins.h
@@ -6,6 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Enumerates target-specific builtins in their own namespaces within
+/// namespace ::clang.
+///
+//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_TARGET_BUILTINS_H
#define LLVM_CLANG_BASIC_TARGET_BUILTINS_H
@@ -15,7 +21,7 @@
namespace clang {
- /// ARM builtins
+ /// \brief ARM builtins
namespace ARM {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -25,7 +31,7 @@ namespace clang {
};
}
- /// PPC builtins
+ /// \brief PPC builtins
namespace PPC {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -35,18 +41,18 @@ namespace clang {
};
}
- /// PTX builtins
- namespace PTX {
+ /// \brief NVPTX builtins
+ namespace NVPTX {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
-#include "clang/Basic/BuiltinsPTX.def"
+#include "clang/Basic/BuiltinsNVPTX.def"
LastTSBuiltin
};
}
- /// X86 builtins
+ /// \brief X86 builtins
namespace X86 {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -56,9 +62,9 @@ namespace clang {
};
}
- /// NeonTypeFlags - Flags to identify the types for overloaded Neon
- /// builtins. These must be kept in sync with the flags in
- /// utils/TableGen/NeonEmitter.h.
+ /// \brief Flags to identify the types for overloaded Neon builtins.
+ ///
+ /// These must be kept in sync with the flags in utils/TableGen/NeonEmitter.h.
class NeonTypeFlags {
enum {
EltTypeMask = 0xf,
@@ -96,7 +102,7 @@ namespace clang {
bool isQuad() const { return (Flags & QuadFlag) != 0; }
};
- /// Hexagon builtins
+ /// \brief Hexagon builtins
namespace Hexagon {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
@@ -105,6 +111,16 @@ namespace clang {
LastTSBuiltin
};
}
+
+ /// \brief MIPS builtins
+ namespace Mips {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsMips.def"
+ LastTSBuiltin
+ };
+ }
} // end namespace clang.
#endif
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index a03cf83ff7db..54d49e6fa559 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the TargetInfo interface.
-//
+///
+/// \file
+/// \brief Defines the clang::TargetInfo interface.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_TARGETINFO_H
@@ -41,7 +42,7 @@ class TargetOptions;
namespace Builtin { struct Info; }
-/// TargetCXXABI - The types of C++ ABIs for which we can generate code.
+/// \brief The types of C++ ABIs for which we can generate code.
enum TargetCXXABI {
/// The generic ("Itanium") C++ ABI, documented at:
/// http://www.codesourcery.com/public/cxx-abi/
@@ -57,7 +58,7 @@ enum TargetCXXABI {
CXXABI_Microsoft
};
-/// TargetInfo - This class exposes information about the current target.
+/// \brief Exposes information about the current target.
///
class TargetInfo : public RefCountedBase<TargetInfo> {
llvm::Triple Triple;
@@ -79,6 +80,7 @@ protected:
unsigned char LongLongWidth, LongLongAlign;
unsigned char SuitableAlign;
unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
+ unsigned short MaxVectorAlign;
const char *DescriptionString;
const char *UserLabelPrefix;
const char *MCountName;
@@ -99,7 +101,7 @@ protected:
TargetInfo(const std::string &T);
public:
- /// CreateTargetInfo - Construct a target for the given options.
+ /// \brief Construct a target for the given options.
///
/// \param Opts - The options to use to initialize the target. The target may
/// modify the options to canonicalize the target feature information to match
@@ -128,11 +130,35 @@ public:
LongDouble
};
+ /// \brief The different kinds of __builtin_va_list types defined by
+ /// the target implementation.
+ enum BuiltinVaListKind {
+ /// typedef char* __builtin_va_list;
+ CharPtrBuiltinVaList = 0,
+
+ /// typedef void* __builtin_va_list;
+ VoidPtrBuiltinVaList,
+
+ /// __builtin_va_list as defined by the PNaCl ABI:
+ /// http://www.chromium.org/nativeclient/pnacl/bitcode-abi#TOC-Machine-Types
+ PNaClABIBuiltinVaList,
+
+ /// __builtin_va_list as defined by the Power ABI:
+ /// https://www.power.org
+ /// /resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Embedded.pdf
+ PowerABIBuiltinVaList,
+
+ /// __builtin_va_list as defined by the x86-64 ABI:
+ /// http://www.x86-64.org/documentation/abi.pdf
+ X86_64ABIBuiltinVaList
+ };
+
protected:
IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType,
WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType;
- /// Flag whether the Objective-C built-in boolean type should be signed char.
+ /// \brief Whether Objective-C's built-in boolean type should be signed char.
+ ///
/// Otherwise, when this flag is not set, the normal built-in boolean type is
/// used.
unsigned UseSignedCharForObjCBool : 1;
@@ -144,10 +170,12 @@ protected:
/// boundary.
unsigned UseBitFieldTypeAlignment : 1;
- /// Control whether zero length bitfields (e.g., int : 0;) force alignment of
- /// the next bitfield. If the alignment of the zero length bitfield is
- /// greater than the member that follows it, `bar', `bar' will be aligned as
- /// the type of the zero-length bitfield.
+ /// \brief Whether zero length bitfields (e.g., int : 0;) force alignment of
+ /// the next bitfield.
+ ///
+ /// If the alignment of the zero length bitfield is greater than the member
+ /// that follows it, `bar', `bar' will be aligned as the type of the
+ /// zero-length bitfield.
unsigned UseZeroLengthBitfieldAlignment : 1;
/// If non-zero, specifies a fixed alignment value for bitfields that follow
@@ -170,19 +198,20 @@ public:
IntType getSigAtomicType() const { return SigAtomicType; }
- /// getTypeWidth - Return the width (in bits) of the specified integer type
- /// enum. For example, SignedInt -> getIntWidth().
+ /// \brief Return the width (in bits) of the specified integer type enum.
+ ///
+ /// For example, SignedInt -> getIntWidth().
unsigned getTypeWidth(IntType T) const;
- /// getTypeAlign - Return the alignment (in bits) of the specified integer
- /// type enum. For example, SignedInt -> getIntAlign().
+ /// \brief Return the alignment (in bits) of the specified integer type enum.
+ ///
+ /// For example, SignedInt -> getIntAlign().
unsigned getTypeAlign(IntType T) const;
- /// isTypeSigned - Return whether an integer types is signed. Returns true if
- /// the type is signed; false otherwise.
+ /// \brief Returns true if the type is signed; false otherwise.
static bool isTypeSigned(IntType T);
- /// getPointerWidth - Return the width of pointers on this target, for the
+ /// \brief Return the width of pointers on this target, for the
/// specified address space.
uint64_t getPointerWidth(unsigned AddrSpace) const {
return AddrSpace == 0 ? PointerWidth : getPointerWidthV(AddrSpace);
@@ -191,17 +220,21 @@ public:
return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace);
}
- /// getBoolWidth/Align - Return the size of '_Bool' and C++ 'bool' for this
- /// target, in bits.
+ /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits.
unsigned getBoolWidth() const { return BoolWidth; }
+
+ /// \brief Return the alignment of '_Bool' and C++ 'bool' for this target.
unsigned getBoolAlign() const { return BoolAlign; }
unsigned getCharWidth() const { return 8; } // FIXME
unsigned getCharAlign() const { return 8; } // FIXME
- /// getShortWidth/Align - Return the size of 'signed short' and
- /// 'unsigned short' for this target, in bits.
+ /// \brief Return the size of 'signed short' and 'unsigned short' for this
+ /// target, in bits.
unsigned getShortWidth() const { return 16; } // FIXME
+
+ /// \brief Return the alignment of 'signed short' and 'unsigned short' for
+ /// this target.
unsigned getShortAlign() const { return 16; } // FIXME
/// getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for
@@ -219,7 +252,7 @@ public:
unsigned getLongLongWidth() const { return LongLongWidth; }
unsigned getLongLongAlign() const { return LongLongAlign; }
- /// getSuitableAlign - Return the alignment that is suitable for storing any
+ /// \brief Return the alignment that is suitable for storing any
/// object with a fundamental alignment requirement.
unsigned getSuitableAlign() const { return SuitableAlign; }
@@ -261,7 +294,7 @@ public:
return *LongDoubleFormat;
}
- /// getFloatEvalMethod - Return the value for the C99 FLT_EVAL_METHOD macro.
+ /// \brief Return the value for the C99 FLT_EVAL_METHOD macro.
virtual unsigned getFloatEvalMethod() const { return 0; }
// getLargeArrayMinWidth/Align - Return the minimum array size that is
@@ -269,21 +302,22 @@ public:
unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; }
unsigned getLargeArrayAlign() const { return LargeArrayAlign; }
- /// getMaxAtomicPromoteWidth - Return the maximum width lock-free atomic
- /// operation which will ever be supported for the given target
+ /// \brief Return the maximum width lock-free atomic operation which will
+ /// ever be supported for the given target
unsigned getMaxAtomicPromoteWidth() const { return MaxAtomicPromoteWidth; }
- /// getMaxAtomicInlineWidth - Return the maximum width lock-free atomic
- /// operation which can be inlined given the supported features of the
- /// given target.
+ /// \brief Return the maximum width lock-free atomic operation which can be
+ /// inlined given the supported features of the given target.
unsigned getMaxAtomicInlineWidth() const { return MaxAtomicInlineWidth; }
- /// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this
- /// target, in bits.
+ /// \brief Return the maximum vector alignment supported for the given target.
+ unsigned getMaxVectorAlign() const { return MaxVectorAlign; }
+
+ /// \brief Return the size of intmax_t and uintmax_t for this target, in bits.
unsigned getIntMaxTWidth() const {
return getTypeWidth(IntMaxType);
}
- /// getRegisterWidth - Return the "preferred" register width on this target.
+ /// \brief Return the "preferred" register width on this target.
uint64_t getRegisterWidth() const {
// Currently we assume the register width on the target matches the pointer
// width, we can introduce a new variable for this if/when some target wants
@@ -291,22 +325,24 @@ public:
return LongWidth;
}
- /// getUserLabelPrefix - This returns the default value of the
- /// __USER_LABEL_PREFIX__ macro, which is the prefix given to user symbols by
- /// default. On most platforms this is "_", but it is "" on some, and "." on
- /// others.
+ /// \brief Returns the default value of the __USER_LABEL_PREFIX__ macro,
+ /// which is the prefix given to user symbols by default.
+ ///
+ /// On most platforms this is "_", but it is "" on some, and "." on others.
const char *getUserLabelPrefix() const {
return UserLabelPrefix;
}
- /// MCountName - This returns name of the mcount instrumentation function.
+ /// \brief Returns the name of the mcount instrumentation function.
const char *getMCountName() const {
return MCountName;
}
- /// useSignedCharForObjCBool - Check if the Objective-C built-in boolean
- /// type should be signed char. Otherwise, if this returns false, the
- /// normal built-in boolean type should also be used for Objective-C.
+ /// \brief Check if the Objective-C built-in boolean type should be signed
+ /// char.
+ ///
+ /// Otherwise, if this returns false, the normal built-in boolean type
+ /// should also be used for Objective-C.
bool useSignedCharForObjCBool() const {
return UseSignedCharForObjCBool;
}
@@ -314,87 +350,91 @@ public:
UseSignedCharForObjCBool = false;
}
- /// useBitFieldTypeAlignment() - Check whether the alignment of bit-field
- /// types is respected when laying out structures.
+ /// \brief Check whether the alignment of bit-field types is respected
+ /// when laying out structures.
bool useBitFieldTypeAlignment() const {
return UseBitFieldTypeAlignment;
}
- /// useZeroLengthBitfieldAlignment() - Check whether zero length bitfields
- /// should force alignment of the next member.
+ /// \brief Check whether zero length bitfields should force alignment of
+ /// the next member.
bool useZeroLengthBitfieldAlignment() const {
return UseZeroLengthBitfieldAlignment;
}
- /// getZeroLengthBitfieldBoundary() - Get the fixed alignment value in bits
- /// for a member that follows a zero length bitfield.
+ /// \brief Get the fixed alignment value in bits for a member that follows
+ /// a zero length bitfield.
unsigned getZeroLengthBitfieldBoundary() const {
return ZeroLengthBitfieldBoundary;
}
- /// hasAlignMac68kSupport - Check whether this target support '#pragma options
- /// align=mac68k'.
+ /// \brief Check whether this target support '\#pragma options align=mac68k'.
bool hasAlignMac68kSupport() const {
return HasAlignMac68kSupport;
}
- /// getTypeName - Return the user string for the specified integer type enum.
+ /// \brief Return the user string for the specified integer type enum.
+ ///
/// For example, SignedShort -> "short".
static const char *getTypeName(IntType T);
- /// getTypeConstantSuffix - Return the constant suffix for the specified
- /// integer type enum. For example, SignedLong -> "L".
+ /// \brief Return the constant suffix for the specified integer type enum.
+ ///
+ /// For example, SignedLong -> "L".
static const char *getTypeConstantSuffix(IntType T);
/// \brief Check whether the given real type should use the "fpret" flavor of
- /// Obj-C message passing on this target.
+ /// Objective-C message passing on this target.
bool useObjCFPRetForRealType(RealType T) const {
return RealTypeUsesObjCFPRet & (1 << T);
}
/// \brief Check whether _Complex long double should use the "fp2ret" flavor
- /// of Obj-C message passing on this target.
+ /// of Objective-C message passing on this target.
bool useObjCFP2RetForComplexLongDouble() const {
return ComplexLongDoubleUsesFP2Ret;
}
///===---- Other target property query methods --------------------------===//
- /// getTargetDefines - Appends the target-specific #define values for this
+ /// \brief Appends the target-specific \#define values for this
/// target set to the specified buffer.
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const = 0;
- /// getTargetBuiltins - Return information about target-specific builtins for
+ /// Return information about target-specific builtins for
/// the current primary target, and info about which builtins are non-portable
/// across the current set of primary and secondary targets.
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const = 0;
- /// isCLZForZeroUndef - The __builtin_clz* and __builtin_ctz* built-in
+ /// The __builtin_clz* and __builtin_ctz* built-in
/// functions are specified to have undefined results for zero inputs, but
/// on targets that support these operations in a way that provides
/// well-defined results for zero without loss of performance, it is a good
/// idea to avoid optimizing based on that undef behavior.
virtual bool isCLZForZeroUndef() const { return true; }
- /// getVAListDeclaration - Return the declaration to use for
- /// __builtin_va_list, which is target-specific.
- virtual const char *getVAListDeclaration() const = 0;
+ /// \brief Returns the kind of __builtin_va_list type that should be used
+ /// with this target.
+ virtual BuiltinVaListKind getBuiltinVaListKind() const = 0;
- /// isValidClobber - Returns whether the passed in string is
- /// a valid clobber in an inline asm statement. This is used by
- /// Sema.
+ /// \brief Returns whether the passed in string is a valid clobber in an
+ /// inline asm statement.
+ ///
+ /// This is used by Sema.
bool isValidClobber(StringRef Name) const;
- /// isValidGCCRegisterName - Returns whether the passed in string
- /// is a valid register name according to GCC. This is used by Sema for
- /// inline asm statements.
+ /// \brief Returns whether the passed in string is a valid register name
+ /// according to GCC.
+ ///
+ /// This is used by Sema for inline asm statements.
bool isValidGCCRegisterName(StringRef Name) const;
- // getNormalizedGCCRegisterName - Returns the "normalized" GCC register name.
- // For example, on x86 it will return "ax" when "eax" is passed in.
+ /// \brief Returns the "normalized" GCC register name.
+ ///
+ /// For example, on x86 it will return "ax" when "eax" is passed in.
StringRef getNormalizedGCCRegisterName(StringRef Name) const;
struct ConstraintInfo {
@@ -421,13 +461,15 @@ public:
bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; }
bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; }
- /// hasMatchingInput - Return true if this output operand has a matching
+ /// \brief Return true if this output operand has a matching
/// (tied) input operand.
bool hasMatchingInput() const { return (Flags & CI_HasMatchingInput) != 0; }
- /// hasTiedOperand() - Return true if this input operand is a matching
- /// constraint that ties it to an output operand. If this returns true,
- /// then getTiedOperand will indicate which output operand this is tied to.
+ /// \brief Return true if this input operand is a matching
+ /// constraint that ties it to an output operand.
+ ///
+ /// If this returns true then getTiedOperand will indicate which output
+ /// operand this is tied to.
bool hasTiedOperand() const { return TiedOperand != -1; }
unsigned getTiedOperand() const {
assert(hasTiedOperand() && "Has no tied operand!");
@@ -439,9 +481,10 @@ public:
void setAllowsRegister() { Flags |= CI_AllowsRegister; }
void setHasMatchingInput() { Flags |= CI_HasMatchingInput; }
- /// setTiedOperand - Indicate that this is an input operand that is tied to
- /// the specified output operand. Copy over the various constraint
- /// information from the output.
+ /// \brief Indicate that this is an input operand that is tied to
+ /// the specified output operand.
+ ///
+ /// Copy over the various constraint information from the output.
void setTiedOperand(unsigned N, ConstraintInfo &Output) {
Output.setHasMatchingInput();
Flags = Output.Flags;
@@ -471,11 +514,11 @@ public:
return std::string(1, *Constraint);
}
- // Returns a string of target-specific clobbers, in LLVM format.
+ /// \brief Returns a string of target-specific clobbers, in LLVM format.
virtual const char *getClobbers() const = 0;
- /// getTriple - Return the target triple of the primary target.
+ /// \brief Returns the target triple of the primary target.
const llvm::Triple &getTriple() const {
return Triple;
}
@@ -494,14 +537,13 @@ public:
const unsigned RegNum;
};
- /// hasProtectedVisibility - Does this target support "protected"
- /// visibility?
+ /// \brief Does this target support "protected" visibility?
///
/// Any target which dynamic libraries will naturally support
/// something like "default" (meaning that the symbol is visible
/// outside this shared object) and "hidden" (meaning that it isn't)
/// visibilities, but "protected" is really an ELF-specific concept
- /// with wierd semantics designed around the convenience of dynamic
+ /// with weird semantics designed around the convenience of dynamic
/// linker implementations. Which is not to suggest that there's
/// consistent target-independent semantics for "default" visibility
/// either; the entire thing is pretty badly mangled.
@@ -509,28 +551,29 @@ public:
virtual bool useGlobalsForAutomaticVariables() const { return false; }
- /// getCFStringSection - Return the section to use for CFString
- /// literals, or 0 if no special section is used.
+ /// \brief Return the section to use for CFString literals, or 0 if no
+ /// special section is used.
virtual const char *getCFStringSection() const {
return "__DATA,__cfstring";
}
- /// getNSStringSection - Return the section to use for NSString
- /// literals, or 0 if no special section is used.
+ /// \brief Return the section to use for NSString literals, or 0 if no
+ /// special section is used.
virtual const char *getNSStringSection() const {
return "__OBJC,__cstring_object,regular,no_dead_strip";
}
- /// getNSStringNonFragileABISection - Return the section to use for
- /// NSString literals, or 0 if no special section is used (NonFragile ABI).
+ /// \brief Return the section to use for NSString literals, or 0 if no
+ /// special section is used (NonFragile ABI).
virtual const char *getNSStringNonFragileABISection() const {
return "__DATA, __objc_stringobj, regular, no_dead_strip";
}
- /// isValidSectionSpecifier - This is an optional hook that targets can
- /// implement to perform semantic checking on attribute((section("foo")))
- /// specifiers. In this case, "foo" is passed in to be checked. If the
- /// section specifier is invalid, the backend should return a non-empty string
+ /// \brief An optional hook that targets can implement to perform semantic
+ /// checking on attribute((section("foo"))) specifiers.
+ ///
+ /// In this case, "foo" is passed in to be checked. If the section
+ /// specifier is invalid, the backend should return a non-empty string
/// that indicates the problem.
///
/// This hook is a simple quality of implementation feature to catch errors
@@ -541,43 +584,44 @@ public:
return "";
}
- /// setForcedLangOptions - Set forced language options.
+ /// \brief Set forced language options.
+ ///
/// Apply changes to the target information with respect to certain
/// language options which change the target configuration.
virtual void setForcedLangOptions(LangOptions &Opts);
- /// getDefaultFeatures - Get the default set of target features for the CPU;
+ /// \brief Get the default set of target features for the CPU;
/// this should include all legal feature strings on the target.
virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const {
}
- /// getABI - Get the ABI in use.
+ /// \brief Get the ABI currently in use.
virtual const char *getABI() const {
return "";
}
- /// getCXXABI - Get the C++ ABI in use.
+ /// \brief Get the C++ ABI currently in use.
virtual TargetCXXABI getCXXABI() const {
return CXXABI;
}
- /// setCPU - Target the specific CPU.
+ /// \brief Target the specified CPU.
///
- /// \return - False on error (invalid CPU name).
+ /// \return False on error (invalid CPU name).
virtual bool setCPU(const std::string &Name) {
return false;
}
- /// setABI - Use the specific ABI.
+ /// \brief Use the specified ABI.
///
- /// \return - False on error (invalid ABI name).
+ /// \return False on error (invalid ABI name).
virtual bool setABI(const std::string &Name) {
return false;
}
- /// setCXXABI - Use this specific C++ ABI.
+ /// \brief Use this specified C++ ABI.
///
- /// \return - False on error (invalid C++ ABI name).
+ /// \return False on error (invalid C++ ABI name).
bool setCXXABI(const std::string &Name) {
static const TargetCXXABI Unknown = static_cast<TargetCXXABI>(-1);
TargetCXXABI ABI = llvm::StringSwitch<TargetCXXABI>(Name)
@@ -589,27 +633,28 @@ public:
return setCXXABI(ABI);
}
- /// setCXXABI - Set the C++ ABI to be used by this implementation.
+ /// \brief Set the C++ ABI to be used by this implementation.
///
- /// \return - False on error (ABI not valid on this target)
+ /// \return False on error (ABI not valid on this target)
virtual bool setCXXABI(TargetCXXABI ABI) {
CXXABI = ABI;
return true;
}
- /// setFeatureEnabled - Enable or disable a specific target feature,
+ /// \brief Enable or disable a specific target feature;
/// the feature name must be valid.
///
- /// \return - False on error (invalid feature name).
+ /// \return False on error (invalid feature name).
virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name,
bool Enabled) const {
return false;
}
- /// HandleTargetOptions - Perform initialization based on the user configured
- /// set of features (e.g., +sse4). The list is guaranteed to have at most one
- /// entry per feature.
+ /// \brief Perform initialization based on the user configured
+ /// set of features (e.g., +sse4).
+ ///
+ /// The list is guaranteed to have at most one entry per feature.
///
/// The target may modify the features list, to change which options are
/// passed onwards to the backend.
@@ -621,19 +666,20 @@ public:
return false;
}
- // getRegParmMax - Returns maximal number of args passed in registers.
+ // \brief Returns maximal number of args passed in registers.
unsigned getRegParmMax() const {
assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle");
return RegParmMax;
}
- /// isTLSSupported - Whether the target supports thread-local storage.
+ /// \brief Whether the target supports thread-local storage.
bool isTLSSupported() const {
return TLSSupported;
}
- /// hasNoAsmVariants - Return true if {|} are normal characters in the
- /// asm string. If this returns false (the default), then {abc|xyz} is syntax
+ /// \brief Return true if {|} are normal characters in the asm string.
+ ///
+ /// If this returns false (the default), then {abc|xyz} is syntax
/// that says that when compiling for asm variant #0, "abc" should be
/// generated, but when compiling for asm variant #1, "xyz" should be
/// generated.
@@ -641,14 +687,13 @@ public:
return NoAsmVariants;
}
- /// getEHDataRegisterNumber - Return the register number that
- /// __builtin_eh_return_regno would return with the specified argument.
+ /// \brief Return the register number that __builtin_eh_return_regno would
+ /// return with the specified argument.
virtual int getEHDataRegisterNumber(unsigned RegNo) const {
return -1;
}
- /// getStaticInitSectionSpecifier - Return the section to use for C++ static
- /// initialization functions.
+ /// \brief Return the section to use for C++ static initialization functions.
virtual const char *getStaticInitSectionSpecifier() const {
return 0;
}
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index f3c206f2cc96..15ececd1df5d 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/include/clang/Basic/TargetOptions.h
@@ -6,6 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::TargetOptions class.
+///
+//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
@@ -15,7 +20,7 @@
namespace clang {
-/// TargetOptions - Options for controlling the target.
+/// \brief Options for controlling the target.
class TargetOptions {
public:
/// If given, the name of the target triple to compile for. If not given the
diff --git a/include/clang/Basic/TemplateKinds.h b/include/clang/Basic/TemplateKinds.h
index c6ea05bb1396..dda011a54e18 100644
--- a/include/clang/Basic/TemplateKinds.h
+++ b/include/clang/Basic/TemplateKinds.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the TemplateNameKind enum.
-//
+///
+/// \file
+/// \brief Defines the clang::TemplateNameKind enum.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TEMPLATEKINDS_H
#define LLVM_CLANG_TEMPLATEKINDS_H
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 2e4d34dff0ba..fc031914a8d0 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -211,6 +211,8 @@ PUNCTUATOR(greatergreatergreater, ">>>")
// KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x
// KEYGNU - This is a keyword if GNU extensions are enabled
// KEYMS - This is a keyword if Microsoft extensions are enabled
+// KEYNOMS - This is a keyword that must never be enabled under
+// Microsoft mode
// KEYOPENCL - This is a keyword in OpenCL
// KEYALTIVEC - This is a keyword in AltiVec
// KEYBORLAND - This is a keyword if Borland extensions are enabled
@@ -251,6 +253,7 @@ KEYWORD(void , KEYALL)
KEYWORD(volatile , KEYALL)
KEYWORD(while , KEYALL)
KEYWORD(_Alignas , KEYALL)
+KEYWORD(_Alignof , KEYALL)
KEYWORD(_Atomic , KEYALL)
KEYWORD(_Bool , KEYNOCXX)
KEYWORD(_Complex , KEYALL)
@@ -310,8 +313,8 @@ CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
// C++0x keywords
KEYWORD(alignas , KEYCXX0X)
KEYWORD(alignof , KEYCXX0X)
-KEYWORD(char16_t , KEYCXX0X)
-KEYWORD(char32_t , KEYCXX0X)
+KEYWORD(char16_t , KEYCXX0X|KEYNOMS)
+KEYWORD(char32_t , KEYCXX0X|KEYNOMS)
KEYWORD(constexpr , KEYCXX0X)
KEYWORD(decltype , KEYCXX0X)
KEYWORD(noexcept , KEYCXX0X)
@@ -342,6 +345,9 @@ KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
// GNU Extensions (outside impl-reserved namespace)
KEYWORD(typeof , KEYGNU)
+// MS Extensions
+KEYWORD(L__FUNCTION__ , KEYMS)
+
// GNU and MS Type Traits
KEYWORD(__has_nothrow_assign , KEYCXX)
KEYWORD(__has_nothrow_copy , KEYCXX)
@@ -486,28 +492,33 @@ ALIAS("__volatile" , volatile , KEYALL)
ALIAS("__volatile__" , volatile , KEYALL)
// Microsoft extensions which should be disabled in strict conformance mode
-KEYWORD(__ptr64 , KEYMS)
-KEYWORD(__ptr32 , KEYMS)
-KEYWORD(__w64 , KEYMS)
-KEYWORD(__uuidof , KEYMS | KEYBORLAND)
-KEYWORD(__try , KEYMS | KEYBORLAND)
-KEYWORD(__finally , KEYMS | KEYBORLAND)
-KEYWORD(__leave , KEYMS | KEYBORLAND)
-KEYWORD(__int64 , KEYMS)
-KEYWORD(__if_exists , KEYMS)
-KEYWORD(__if_not_exists , KEYMS)
-ALIAS("__int8" , char , KEYMS)
-ALIAS("__int16" , short , KEYMS)
-ALIAS("__int32" , int , KEYMS)
-ALIAS("_asm" , asm , KEYMS)
-ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND)
-ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND)
-ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND)
-ALIAS("_thiscall" , __thiscall , KEYMS)
-ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND)
-ALIAS("_inline" , inline , KEYMS)
-ALIAS("_declspec" , __declspec , KEYMS)
-ALIAS("__interface" , struct , KEYMS)
+KEYWORD(__ptr64 , KEYMS)
+KEYWORD(__ptr32 , KEYMS)
+KEYWORD(__w64 , KEYMS)
+KEYWORD(__uuidof , KEYMS | KEYBORLAND)
+KEYWORD(__try , KEYMS | KEYBORLAND)
+KEYWORD(__finally , KEYMS | KEYBORLAND)
+KEYWORD(__leave , KEYMS | KEYBORLAND)
+KEYWORD(__int64 , KEYMS)
+KEYWORD(__if_exists , KEYMS)
+KEYWORD(__if_not_exists , KEYMS)
+KEYWORD(__single_inheritance , KEYMS)
+KEYWORD(__multiple_inheritance , KEYMS)
+KEYWORD(__virtual_inheritance , KEYMS)
+ALIAS("__int8" , char , KEYMS)
+ALIAS("__int16" , short , KEYMS)
+ALIAS("__int32" , int , KEYMS)
+ALIAS("_asm" , asm , KEYMS)
+ALIAS("_alignof" , __alignof , KEYMS)
+ALIAS("__builtin_alignof", __alignof , KEYMS)
+ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND)
+ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND)
+ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND)
+ALIAS("_thiscall" , __thiscall , KEYMS)
+ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND)
+ALIAS("_inline" , inline , KEYMS)
+ALIAS("_declspec" , __declspec , KEYMS)
+ALIAS("__interface" , struct , KEYMS)
// Borland Extensions which should be disabled in strict conformance mode.
ALIAS("_pascal" , __pascal , KEYBORLAND)
@@ -584,6 +595,11 @@ ANNOTATION(pragma_vis)
// handles them.
ANNOTATION(pragma_pack)
+// Annotation for #pragma clang __debug parser_crash...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_parser_crash)
+
#undef ANNOTATION
#undef TESTING_KEYWORD
#undef OBJC2_AT_KEYWORD
diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h
index 515390a8ce93..478add8db5db 100644
--- a/include/clang/Basic/TokenKinds.h
+++ b/include/clang/Basic/TokenKinds.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the TokenKind enum and support functions.
-//
+///
+/// \file
+/// \brief Defines the clang::TokenKind enum and support functions.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOKENKINDS_H
@@ -18,24 +19,23 @@ namespace clang {
namespace tok {
-/// TokenKind - This provides a simple uniform namespace for tokens from all C
-/// languages.
+/// \brief Provides a simple uniform namespace for tokens from all C languages.
enum TokenKind {
#define TOK(X) X,
#include "clang/Basic/TokenKinds.def"
NUM_TOKENS
};
-/// PPKeywordKind - This provides a namespace for preprocessor keywords which
-/// start with a '#' at the beginning of the line.
+/// \brief Provides a namespace for preprocessor keywords which start with a
+/// '#' at the beginning of the line.
enum PPKeywordKind {
#define PPKEYWORD(X) pp_##X,
#include "clang/Basic/TokenKinds.def"
NUM_PP_KEYWORDS
};
-/// ObjCKeywordKind - This provides a namespace for Objective-C keywords which
-/// start with an '@'.
+/// \brief Provides a namespace for Objective-C keywords which start with
+/// an '@'.
enum ObjCKeywordKind {
#define OBJC1_AT_KEYWORD(X) objc_##X,
#define OBJC2_AT_KEYWORD(X) objc_##X,
@@ -43,8 +43,7 @@ enum ObjCKeywordKind {
NUM_OBJC_KEYWORDS
};
-/// OnOffSwitch - This defines the possible values of an on-off-switch
-/// (C99 6.10.6p2).
+/// \brief Defines the possible values of an on-off-switch (C99 6.10.6p2).
enum OnOffSwitch {
OOS_ON, OOS_OFF, OOS_DEFAULT
};
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index 721f44f40815..0a5a8643a36e 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines enumerations for the type traits support.
-//
+///
+/// \file
+/// \brief Defines enumerations for the type traits support.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TYPETRAITS_H
@@ -16,7 +17,7 @@
namespace clang {
- /// UnaryTypeTrait - Names for the unary type traits.
+ /// \brief Names for the unary type traits.
enum UnaryTypeTrait {
UTT_HasNothrowAssign,
UTT_HasNothrowCopy,
@@ -62,7 +63,7 @@ namespace clang {
UTT_IsVolatile
};
- /// BinaryTypeTrait - Names for the binary type traits.
+ /// \brief Names for the binary type traits.
enum BinaryTypeTrait {
BTT_IsBaseOf,
BTT_IsConvertible,
@@ -72,13 +73,13 @@ namespace clang {
BTT_IsTriviallyAssignable
};
- /// ArrayTypeTrait - Names for the array type traits.
+ /// \brief Names for the array type traits.
enum ArrayTypeTrait {
ATT_ArrayRank,
ATT_ArrayExtent
};
- /// UnaryExprOrTypeTrait - Names for the "expression or type" traits.
+ /// \brief Names for the "expression or type" traits.
enum UnaryExprOrTypeTrait {
UETT_SizeOf,
UETT_AlignOf,
diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h
index f3f5b5a53a99..3f1b4d83b95e 100644
--- a/include/clang/Basic/Version.h
+++ b/include/clang/Basic/Version.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This header defines version macros and version-related utility functions
-// for Clang.
-//
+///
+/// \file
+/// \brief Defines version macros and version-related utility functions
+/// for Clang.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_VERSION_H
@@ -26,8 +27,7 @@
/// \brief Helper macro for CLANG_VERSION_STRING.
#define CLANG_MAKE_VERSION_STRING(X,Y,Z) CLANG_MAKE_VERSION_STRING2(X.Y.Z)
-/// \brief A string that describes the Clang version number, e.g.,
-/// "1.0".
+/// \brief A string that describes the Clang version number, e.g., "1.0".
#define CLANG_VERSION_STRING \
CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR, \
CLANG_VERSION_PATCHLEVEL)
@@ -35,8 +35,7 @@
/// \brief Helper macro for CLANG_VERSION_STRING.
#define CLANG_MAKE_VERSION_STRING(X,Y) CLANG_MAKE_VERSION_STRING2(X.Y)
-/// \brief A string that describes the Clang version number, e.g.,
-/// "1.0".
+/// \brief A string that describes the Clang version number, e.g., "1.0".
#define CLANG_VERSION_STRING \
CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR)
#endif
@@ -47,31 +46,34 @@ namespace clang {
/// Clang was built.
std::string getClangRepositoryPath();
- /// \brief Retrieves the repository path from which LLVM was built. Supports
- /// LLVM residing in a separate repository from clang.
+ /// \brief Retrieves the repository path from which LLVM was built.
+ ///
+ /// This supports LLVM residing in a separate repository from clang.
std::string getLLVMRepositoryPath();
/// \brief Retrieves the repository revision number (or identifer) from which
- /// this Clang was built.
+ /// this Clang was built.
std::string getClangRevision();
/// \brief Retrieves the repository revision number (or identifer) from which
- /// LLVM was built. If Clang and LLVM are in the same repository, this returns
- /// the same string as getClangRevision.
+ /// LLVM was built.
+ ///
+ /// If Clang and LLVM are in the same repository, this returns the same
+ /// string as getClangRevision.
std::string getLLVMRevision();
/// \brief Retrieves the full repository version that is an amalgamation of
- /// the information in getClangRepositoryPath() and getClangRevision().
+ /// the information in getClangRepositoryPath() and getClangRevision().
std::string getClangFullRepositoryVersion();
/// \brief Retrieves a string representing the complete clang version,
- /// which includes the clang version number, the repository version,
- /// and the vendor tag.
+ /// which includes the clang version number, the repository version,
+ /// and the vendor tag.
std::string getClangFullVersion();
/// \brief Retrieves a string representing the complete clang version suitable
- /// for use in the CPP __VERSION__ macro, which includes the clang version
- /// number, the repository version, and the vendor tag.
+ /// for use in the CPP __VERSION__ macro, which includes the clang version
+ /// number, the repository version, and the vendor tag.
std::string getClangFullCPPVersion();
}
diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h
index 30ef6641efc1..a94f76c182bb 100644
--- a/include/clang/Basic/VersionTuple.h
+++ b/include/clang/Basic/VersionTuple.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This header defines the VersionTuple class, which represents a version in
-// the form major[.minor[.subminor]].
-//
+///
+/// \file
+/// \brief Defines the clang::VersionTuple class, which represents a version in
+/// the form major[.minor[.subminor]].
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_VERSIONTUPLE_H
#define LLVM_CLANG_BASIC_VERSIONTUPLE_H
@@ -73,15 +74,18 @@ public:
return X.Major == Y.Major && X.Minor == Y.Minor && X.Subminor == Y.Subminor;
}
- /// \brief Determine if two version numbers are not equivalent. If
- /// not provided, minor and subminor version numbers are considered to be
+ /// \brief Determine if two version numbers are not equivalent.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
/// zero.
friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) {
return !(X == Y);
}
- /// \brief Determine whether one version number precedes another. If not
- /// provided, minor and subminor version numbers are considered to be zero.
+ /// \brief Determine whether one version number precedes another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
friend bool operator<(const VersionTuple &X, const VersionTuple &Y) {
if (X.Major != Y.Major)
return X.Major < Y.Major;
@@ -92,28 +96,39 @@ public:
return X.Subminor < Y.Subminor;
}
- /// \brief Determine whether one version number follows another. If not
- /// provided, minor and subminor version numbers are considered to be zero.
+ /// \brief Determine whether one version number follows another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
friend bool operator>(const VersionTuple &X, const VersionTuple &Y) {
return Y < X;
}
/// \brief Determine whether one version number precedes or is
- /// equivalent to another. If not provided, minor and subminor
- /// version numbers are considered to be zero.
+ /// equivalent to another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) {
return !(Y < X);
}
/// \brief Determine whether one version number follows or is
- /// equivalent to another. If not provided, minor and subminor
- /// version numbers are considered to be zero.
+ /// equivalent to another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) {
return !(X < Y);
}
- /// \brief Retrieve a string representation of the version number/
+ /// \brief Retrieve a string representation of the version number.
std::string getAsString() const;
+
+ /// \brief Try to parse the given string as a version number.
+ /// \returns \c true if the string does not match the regular expression
+ /// [0-9]+(\.[0-9]+(\.[0-9]+))
+ bool tryParse(StringRef string);
};
/// \brief Print a version number.
diff --git a/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h
index 90e288a224ec..e81ad91a06c9 100644
--- a/include/clang/Basic/Visibility.h
+++ b/include/clang/Basic/Visibility.h
@@ -6,20 +6,23 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Visibility enumeration and various utility
-// functions.
-//
+///
+/// \file
+/// \brief Defines the clang::Visibility enumeration and various utility
+/// functions.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_VISIBILITY_H
#define LLVM_CLANG_BASIC_VISIBILITY_H
namespace clang {
-/// \link Describes the different kinds of visibility that a
-/// declaration may have. Visibility determines how a declaration
-/// interacts with the dynamic linker. It may also affect whether the
-/// symbol can be found by runtime symbol lookup APIs.
+/// \brief Describes the different kinds of visibility that a declaration
+/// may have.
+///
+/// Visibility determines how a declaration interacts with the dynamic
+/// linker. It may also affect whether the symbol can be found by runtime
+/// symbol lookup APIs.
///
/// Visibility is not described in any language standard and
/// (nonetheless) sometimes has odd behavior. Not all platforms
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index 71a0aa2726c0..451d56292363 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -15,6 +15,7 @@
class Op;
def OP_NONE : Op;
+def OP_UNAVAILABLE : Op;
def OP_ADD : Op;
def OP_ADDL : Op;
def OP_ADDW : Op;
diff --git a/include/clang/Driver/Arg.h b/include/clang/Driver/Arg.h
index e8625bbd5175..e466cc323173 100644
--- a/include/clang/Driver/Arg.h
+++ b/include/clang/Driver/Arg.h
@@ -6,6 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::driver::Arg class for parsed arguments.
+///
+//===----------------------------------------------------------------------===//
#ifndef CLANG_DRIVER_ARG_H_
#define CLANG_DRIVER_ARG_H_
@@ -20,7 +25,7 @@ namespace driver {
class ArgList;
class Option;
- /// Arg - A concrete instance of a particular driver option.
+ /// \brief A concrete instance of a particular driver option.
///
/// The Arg class encodes just enough information to be able to
/// derive the argument values efficiently. In addition, Arg
@@ -32,25 +37,26 @@ namespace driver {
void operator=(const Arg &); // DO NOT IMPLEMENT
private:
- /// The option this argument is an instance of.
+ /// \brief The option this argument is an instance of.
const Option *Opt;
- /// The argument this argument was derived from (during tool chain
+ /// \brief The argument this argument was derived from (during tool chain
/// argument translation), if any.
const Arg *BaseArg;
- /// The index at which this argument appears in the containing
+ /// \brief The index at which this argument appears in the containing
/// ArgList.
unsigned Index;
- /// Was this argument used to effect compilation; used for generating
- /// "argument unused" diagnostics.
+ /// \brief Was this argument used to effect compilation?
+ ///
+ /// This is used for generating "argument unused" diagnostics.
mutable unsigned Claimed : 1;
- /// Does this argument own its values.
+ /// \brief Does this argument own its values?
mutable unsigned OwnsValues : 1;
- /// The argument values, as C strings.
+ /// \brief The argument values, as C strings.
SmallVector<const char *, 2> Values;
public:
@@ -64,8 +70,9 @@ namespace driver {
const Option &getOption() const { return *Opt; }
unsigned getIndex() const { return Index; }
- /// getBaseArg - Return the base argument which generated this
- /// arg; this is either the argument itself or the argument it was
+ /// \brief Return the base argument which generated this arg.
+ ///
+ /// This is either the argument itself or the argument it was
/// derived from during tool chain specific argument translation.
const Arg &getBaseArg() const {
return BaseArg ? *BaseArg : *this;
@@ -79,7 +86,7 @@ namespace driver {
bool isClaimed() const { return getBaseArg().Claimed; }
- /// claim - Set the Arg claimed bit.
+ /// \brief Set the Arg claimed bit.
void claim() const { getBaseArg().Claimed = true; }
unsigned getNumValues() const { return Values.size(); }
@@ -98,20 +105,21 @@ namespace driver {
return false;
}
- /// render - Append the argument onto the given array as strings.
+ /// \brief Append the argument onto the given array as strings.
void render(const ArgList &Args, ArgStringList &Output) const;
- /// renderAsInput - Append the argument, render as an input, onto
- /// the given array as strings. The distinction is that some
- /// options only render their values when rendered as a input
- /// (e.g., Xlinker).
+ /// \brief Append the argument, render as an input, onto the given
+ /// array as strings.
+ ///
+ /// The distinction is that some options only render their values
+ /// when rendered as a input (e.g., Xlinker).
void renderAsInput(const ArgList &Args, ArgStringList &Output) const;
static bool classof(const Arg *) { return true; }
void dump() const;
- /// getAsString - Return a formatted version of the argument and
+ /// \brief Return a formatted version of the argument and
/// its values, for debugging and diagnostics.
std::string getAsString(const ArgList &Args) const;
};
diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h
index 3affb009fc37..b7e490ccf7ca 100644
--- a/include/clang/Driver/ArgList.h
+++ b/include/clang/Driver/ArgList.h
@@ -187,6 +187,14 @@ namespace driver {
OptSpecifier Id3) const;
Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
OptSpecifier Id3, OptSpecifier Id4) const;
+ Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
+ OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5) const;
+ Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
+ OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5,
+ OptSpecifier Id6) const;
+ Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
+ OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5,
+ OptSpecifier Id6, OptSpecifier Id7) const;
/// getArgString - Return the input argument string at \arg Index.
virtual const char *getArgString(unsigned Index) const = 0;
diff --git a/include/clang/Driver/CC1Options.h b/include/clang/Driver/CC1Options.h
index 4a8bbe5feb77..e69de29bb2d1 100644
--- a/include/clang/Driver/CC1Options.h
+++ b/include/clang/Driver/CC1Options.h
@@ -1,32 +0,0 @@
-//===--- CC1Options.h - Clang CC1 Options Table -----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_DRIVER_CC1OPTIONS_H
-#define CLANG_DRIVER_CC1OPTIONS_H
-
-namespace clang {
-namespace driver {
- class OptTable;
-
-namespace cc1options {
- enum ID {
- OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) OPT_##ID,
-#include "clang/Driver/CC1Options.inc"
- LastOption
-#undef OPTION
- };
-}
-
- OptTable *createCC1OptTable();
-}
-}
-
-#endif
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 83c988abd13d..6e4d7f2d31d5 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -11,8 +11,7 @@
//
//===----------------------------------------------------------------------===//
-// Include the common option parsing interfaces.
-include "OptParser.td"
+let Flags = [CC1Option] in {
//===----------------------------------------------------------------------===//
// Target Options
@@ -40,8 +39,6 @@ def analysis_UnoptimizedCFG : Flag<"-unoptimized-cfg">,
HelpText<"Generate unoptimized CFGs for all analyses">;
def analysis_CFGAddImplicitDtors : Flag<"-cfg-add-implicit-dtors">,
HelpText<"Add C++ implicit destructors to CFGs for all analyses">;
-def analysis_CFGAddInitializers : Flag<"-cfg-add-initializers">,
- HelpText<"Add C++ initializers to CFGs for all analyses">;
def analyzer_store : Separate<"-analyzer-store">,
HelpText<"Source Code Analysis - Abstract Memory Store Models">;
@@ -145,46 +142,12 @@ def fdebug_compilation_dir : Separate<"-fdebug-compilation-dir">,
HelpText<"The compilation directory to embed in the debug info.">;
def dwarf_debug_flags : Separate<"-dwarf-debug-flags">,
HelpText<"The string to embed in the Dwarf debug flags record.">;
-def faddress_sanitizer: Flag<"-faddress-sanitizer">,
- HelpText<"Enable AddressSanitizer instrumentation (memory error detection)">;
-def fthread_sanitizer: Flag<"-fthread-sanitizer">,
- HelpText<"Enable ThreadSanitizer instrumentation (race detection)">;
def fforbid_guard_variables : Flag<"-fforbid-guard-variables">,
HelpText<"Emit an error if a C++ static local initializer would need a guard variable">;
-def g : Flag<"-g">, HelpText<"Generate source level debug information">;
-def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">,
- HelpText<"Don't use the cfi directives">;
-def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">,
- HelpText<"Don't separate directory and filename in .file directives">;
-def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">,
- HelpText<"Generate runtime checks for undefined behavior.">;
-def flimit_debug_info : Flag<"-flimit-debug-info">,
- HelpText<"Limit debug information produced to reduce size of debug binary">;
-def fno_common : Flag<"-fno-common">,
- HelpText<"Compile common globals like normal definitions">;
def no_implicit_float : Flag<"-no-implicit-float">,
- HelpText<"Don't generate implicit floating point instructions (x86-only)">;
-def finstrument_functions : Flag<"-finstrument-functions">,
- HelpText<"Generate calls to instrument function entry and exit">;
-def fno_limit_debug_info : Flag<"-fno-limit-debug-info">,
- HelpText<"Do not limit debug information produced to reduce size of debug binary">;
-def fno_merge_all_constants : Flag<"-fno-merge-all-constants">,
- HelpText<"Disallow merging of constants.">;
-def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">,
- HelpText<"Do not emit code to make initialization of local statics thread safe">;
+ HelpText<"Don't generate implicit floating point instructions">;
def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">,
HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">;
-def ffunction_sections : Flag<"-ffunction-sections">,
- HelpText<"Place each function in its own section (ELF Only)">;
-def fdata_sections : Flag<"-fdata-sections">,
- HelpText<"Place each data in its own section (ELF Only)">;
-def fstrict_enums : Flag<"-fstrict-enums">,
- HelpText<"Enable optimizations based on the strict definition of an enum's "
- "value range.">;
-def ftrap_function_EQ : Joined<"-ftrap-function=">,
- HelpText<"Issue call to specified function rather than a trap instruction">;
-def funroll_loops : Flag<"-funroll-loops">,
- HelpText<"Turn on loop unroller">;
def femit_coverage_notes : Flag<"-femit-coverage-notes">,
HelpText<"Emit a gcov coverage notes file when compiling.">;
def femit_coverage_data: Flag<"-femit-coverage-data">,
@@ -215,66 +178,37 @@ def menable_unsafe_fp_math : Flag<"-menable-unsafe-fp-math">,
"precision">;
def mfloat_abi : Separate<"-mfloat-abi">,
HelpText<"The float ABI to use">;
-def mno_global_merge : Flag<"-mno-global-merge">,
- HelpText<"Disable merging of globals">;
def mlimit_float_precision : Separate<"-mlimit-float-precision">,
HelpText<"Limit float precision to the given value">;
def mno_exec_stack : Flag<"-mnoexecstack">,
HelpText<"Mark the file as not needing an executable stack">;
def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">,
HelpText<"Do not put zero initialized data in the BSS">;
-def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">,
- HelpText<"Omit frame pointer setup for leaf functions.">;
-def msoft_float : Flag<"-msoft-float">,
- HelpText<"Use software floating point">;
def backend_option : Separate<"-backend-option">,
HelpText<"Additional arguments to forward to LLVM backend (during code gen)">;
def mregparm : Separate<"-mregparm">,
HelpText<"Limit the number of registers available for integer arguments">;
-def mrelax_all : Flag<"-mrelax-all">,
- HelpText<"(integrated-as) Relax all machine instructions">;
def msave_temp_labels : Flag<"-msave-temp-labels">,
HelpText<"(integrated-as) Save temporary labels">;
-def mrtd: Flag<"-mrtd">,
- HelpText<"Make StdCall calling convention the default">;
def mrelocation_model : Separate<"-mrelocation-model">,
HelpText<"The relocation model to use">;
def munwind_tables : Flag<"-munwind-tables">,
HelpText<"Generate unwinding tables for all functions">;
+def fuse_init_array : Flag<"-fuse-init-array">,
+ HelpText<"Use .init_array instead of .ctors">;
def mconstructor_aliases : Flag<"-mconstructor-aliases">,
HelpText<"Emit complete constructors and destructors as aliases when possible">;
-def mms_bitfields : Flag<"-mms-bitfields">,
- HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">;
-def mstackrealign : Flag<"-mstackrealign">,
- HelpText<"Force realign the stack at entry to every function.">;
-def mstack_alignment : Joined<"-mstack-alignment=">,
- HelpText<"Set the stack alignment">;
def mlink_bitcode_file : Separate<"-mlink-bitcode-file">,
HelpText<"Link the given bitcode file before performing optimizations.">;
-def O : Joined<"-O">, HelpText<"Optimization level">;
-def Os : Flag<"-Os">, HelpText<"Optimize for size">;
-def Oz : Flag<"-Oz">, HelpText<"Optimize for size, regardless of performance">;
-def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">;
//===----------------------------------------------------------------------===//
// Dependency Output Options
//===----------------------------------------------------------------------===//
-def dependency_file : Separate<"-dependency-file">,
- HelpText<"Filename (or -) to write dependency output to">;
-def dependency_dot : Separate<"-dependency-dot">,
- HelpText<"Filename to write DOT-formatted header dependencies to">;
def sys_header_deps : Flag<"-sys-header-deps">,
HelpText<"Include system headers in dependency output">;
def header_include_file : Separate<"-header-include-file">,
HelpText<"Filename (or -) to write header include output to">;
-def H : Flag<"-H">,
- HelpText<"Show header includes and nesting depth">;
-def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">;
-def MT : Separate<"-MT">, HelpText<"Specify target for dependency">;
-def MP : Flag<"-MP">,
- HelpText<"Create phony target for each dependency (other than main file)">;
-def MG : Flag<"-MG">, HelpText<"Add missing headers to dependency list">;
//===----------------------------------------------------------------------===//
// Diagnostic Options
@@ -288,44 +222,11 @@ def diagnostic_log_file : Separate<"-diagnostic-log-file">,
def diagnostic_serialized_file : Separate<"-serialize-diagnostic-file">,
MetaVarName<"<filename>">,
HelpText<"File for serializing diagnostics in a binary format">;
-def fno_show_column : Flag<"-fno-show-column">,
- HelpText<"Do not include column number on diagnostics">;
-def fshow_column : Flag<"-fshow-column">,
- HelpText<"Include column number on diagnostics">;
-def fno_show_source_location : Flag<"-fno-show-source-location">,
- HelpText<"Do not include source location information with diagnostics">;
-def fshow_overloads_EQ : Joined<"-fshow-overloads=">,
- HelpText<"Which overload candidates to show when overload resolution fails: "
- "best|all; defaults to all">;
-def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">,
- HelpText<"Do not include source line and caret with diagnostics">;
-def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">,
- HelpText<"Do not include fixit information in diagnostics">;
-def fno_diagnostics_show_note_include_stack :
- Flag<"-fno-diagnostics-show-note-include-stack">,
- HelpText<"Display include stacks for diagnostic notes">;
-def w : Flag<"-w">, HelpText<"Suppress all warnings">;
-def pedantic : Flag<"-pedantic">;
-def pedantic_errors : Flag<"-pedantic-errors">;
-
-// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The
-// driver has stripped off -Wa,foo etc. The driver has also translated -W to
-// -Wextra, so we don't need to worry about it.
-def W : Joined<"-W">;
-
-def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">,
- HelpText<"Print source range spans in numeric form">;
-def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">,
- HelpText<"Print fix-its in machine parseable form">;
-def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
- HelpText<"Print option name with mappable diagnostics">;
+
def fdiagnostics_format : Separate<"-fdiagnostics-format">,
HelpText<"Change diagnostic formatting to match IDE and command line tools">;
def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">,
HelpText<"Print diagnostic category">;
-def fdiagnostics_show_note_include_stack :
- Flag<"-fdiagnostics-show-note-include-stack">,
- HelpText<"Display include stacks for diagnostic notes">;
def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">,
HelpText<"Set the tab stop distance.">;
def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">,
@@ -338,12 +239,8 @@ def fconstexpr_backtrace_limit : Separate<"-fconstexpr-backtrace-limit">, MetaVa
HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">;
def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">,
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
-def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
- HelpText<"Use colors in diagnostics">;
def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">,
HelpText<"Silence ObjC rewriting warnings">;
-def verify : Flag<"-verify">,
- HelpText<"Verify emitted diagnostics and warnings">;
//===----------------------------------------------------------------------===//
// Frontend Options
@@ -370,13 +267,10 @@ def code_completion_patterns : Flag<"-code-completion-patterns">,
HelpText<"Include code patterns in code-completion results">;
def no_code_completion_globals : Flag<"-no-code-completion-globals">,
HelpText<"Do not include global declarations in code-completion results.">;
+def code_completion_brief_comments : Flag<"-code-completion-brief-comments">,
+ HelpText<"Include brief documentation comments in code-completion results.">;
def disable_free : Flag<"-disable-free">,
HelpText<"Disable freeing of memory on exit">;
-def help : Flag<"-help">,
- HelpText<"Print this help text">;
-def _help : Flag<"--help">, Alias<help>;
-def x : Separate<"-x">, HelpText<"Input language type">;
-def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">;
def load : Separate<"-load">, MetaVarName<"<dsopath>">,
HelpText<"Load the named plugin (dynamic shared object)">;
def plugin : Separate<"-plugin">, MetaVarName<"<name>">,
@@ -390,15 +284,16 @@ def resource_dir : Separate<"-resource-dir">,
HelpText<"The directory which holds the compiler resource files">;
def version : Flag<"-version">,
HelpText<"Print the compiler version">;
-def _version : Flag<"--version">, Alias<version>;
+def ast_dump_filter : Separate<"-ast-dump-filter">,
+ MetaVarName<"<dump_filter>">,
+ HelpText<"Use with -ast-dump or -ast-print to dump/print only AST declaration"
+ " nodes having a certain substring in a qualified name. Use"
+ " -ast-list to list all filterable declaration node names.">;
-def Action_Group : OptionGroup<"<action group>">;
let Group = Action_Group in {
def Eonly : Flag<"-Eonly">,
HelpText<"Just run preprocessor, no output (for timings)">;
-def E : Flag<"-E">,
- HelpText<"Run preprocessor, emit preprocessed file">;
def dump_raw_tokens : Flag<"-dump-raw-tokens">,
HelpText<"Lex file in raw mode and dump raw tokens">;
def analyze : Flag<"-analyze">,
@@ -407,8 +302,6 @@ def dump_tokens : Flag<"-dump-tokens">,
HelpText<"Run preprocessor, dump internal rep of tokens">;
def init_only : Flag<"-init-only">,
HelpText<"Only execute frontend initialization">;
-def fsyntax_only : Flag<"-fsyntax-only">,
- HelpText<"Run parser and perform semantic analysis">;
def fixit : Flag<"-fixit">,
HelpText<"Apply fix-it advice to the input source">;
def fixit_EQ : Joined<"-fixit=">,
@@ -420,6 +313,8 @@ def emit_html : Flag<"-emit-html">,
HelpText<"Output input source as HTML">;
def ast_print : Flag<"-ast-print">,
HelpText<"Build ASTs and then pretty-print them">;
+def ast_list : Flag<"-ast-list">,
+ HelpText<"Build ASTs and print the list of declaration node qualified names">;
def ast_dump : Flag<"-ast-dump">,
HelpText<"Build ASTs and then debug dump them">;
def ast_dump_xml : Flag<"-ast-dump-xml">,
@@ -434,10 +329,6 @@ def emit_pth : Flag<"-emit-pth">,
HelpText<"Generate pre-tokenized header file">;
def emit_pch : Flag<"-emit-pch">,
HelpText<"Generate pre-compiled header file">;
-def S : Flag<"-S">,
- HelpText<"Emit native assembly code">;
-def emit_llvm : Flag<"-emit-llvm">,
- HelpText<"Build ASTs then convert to LLVM, emit .ll file">;
def emit_llvm_bc : Flag<"-emit-llvm-bc">,
HelpText<"Build ASTs then convert to LLVM, emit .bc file">;
def emit_llvm_only : Flag<"-emit-llvm-only">,
@@ -448,8 +339,6 @@ def emit_obj : Flag<"-emit-obj">,
HelpText<"Emit native object files">;
def rewrite_test : Flag<"-rewrite-test">,
HelpText<"Rewriter playground">;
-def rewrite_objc : Flag<"-rewrite-objc">,
- HelpText<"Rewrite ObjC into C (code rewriter example)">;
def rewrite_macros : Flag<"-rewrite-macros">,
HelpText<"Expand macros without full preprocessing">;
def migrate : Flag<"-migrate">,
@@ -464,27 +353,11 @@ def arcmt_modify : Flag<"-arcmt-modify">,
HelpText<"Apply modifications to files to conform to ARC">;
def arcmt_migrate : Flag<"-arcmt-migrate">,
HelpText<"Apply modifications and produces temporary files that conform to ARC">;
-def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">,
- HelpText<"Output path for the plist report">;
-def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">,
- HelpText<"Emit ARC errors even if the migrator can fix them">;
-
-def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">,
- HelpText<"Enable migration to modern ObjC literals">;
-def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">,
- HelpText<"Enable migration to modern ObjC subscripting">;
-
-def working_directory : JoinedOrSeparate<"-working-directory">,
- HelpText<"Resolve file paths relative to the specified directory">;
-def working_directory_EQ : Joined<"-working-directory=">,
- Alias<working_directory>;
def relocatable_pch : Flag<"-relocatable-pch">,
HelpText<"Whether to build a relocatable precompiled header">;
def print_stats : Flag<"-print-stats">,
HelpText<"Print performance metrics and statistics">;
-def ftime_report : Flag<"-ftime-report">,
- HelpText<"Print the amount of time each phase of compilation takes">;
def fdump_record_layouts : Flag<"-fdump-record-layouts">,
HelpText<"Dump record layout information">;
def fdump_record_layouts_simple : Flag<"-fdump-record-layouts-simple">,
@@ -498,11 +371,6 @@ def fixit_recompile : Flag<"-fixit-recompile">,
def fixit_to_temp : Flag<"-fixit-to-temporary">,
HelpText<"Apply fix-it changes to temporary files">;
-// Generic forwarding to LLVM options. This should only be used for debugging
-// and experimental features.
-def mllvm : Separate<"-mllvm">,
- HelpText<"Additional arguments to forward to LLVM's option processing">;
-
def foverride_record_layout_EQ : Joined<"-foverride-record-layout=">,
HelpText<"Override record layouts with those in the given file">;
@@ -510,135 +378,31 @@ def foverride_record_layout_EQ : Joined<"-foverride-record-layout=">,
// Language Options
//===----------------------------------------------------------------------===//
-def fno_builtin : Flag<"-fno-builtin">,
- HelpText<"Disable implicit builtin knowledge of functions">;
-def faltivec : Flag<"-faltivec">,
- HelpText<"Enable AltiVec vector initializer syntax">;
-def fno_access_control : Flag<"-fno-access-control">,
- HelpText<"Disable C++ access control">;
-def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">,
- HelpText<"Don't assume that C++'s global operator new can't alias any pointer">;
-def fgnu_keywords : Flag<"-fgnu-keywords">,
- HelpText<"Allow GNU-extension keywords regardless of language standard">;
-def fgnu89_inline : Flag<"-fgnu89-inline">,
- HelpText<"Use the gnu89 inline semantics">;
-def fno_inline : Flag<"-fno-inline">,
- HelpText<"Disable use of the inline keyword">;
-def fno_inline_functions : Flag<"-fno-inline-functions">,
- HelpText<"Disable automatic function inlining">;
-def fno_gnu_keywords : Flag<"-fno-gnu-keywords">,
- HelpText<"Disallow GNU-extension keywords regardless of language standard">;
-def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">,
- HelpText<"Allow '$' in identifiers">;
-def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">,
- HelpText<"Disallow '$' in identifiers">;
-def femit_all_decls : Flag<"-femit-all-decls">,
- HelpText<"Emit all declarations, even if unused">;
-def fblocks : Flag<"-fblocks">,
- HelpText<"Enable the 'blocks' language feature">;
def fblocks_runtime_optional : Flag<"-fblocks-runtime-optional">,
HelpText<"Weakly link in the blocks runtime">;
-def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
-def fexceptions : Flag<"-fexceptions">,
- HelpText<"Enable support for exception handling">;
-def fobjc_exceptions : Flag<"-fobjc-exceptions">,
- HelpText<"Enable Objective-C exceptions">;
-def fcxx_exceptions : Flag<"-fcxx-exceptions">,
- HelpText<"Enable C++ exceptions">;
def fsjlj_exceptions : Flag<"-fsjlj-exceptions">,
HelpText<"Use SjLj style exceptions">;
-def ffast_math : Flag<"-ffast-math">,
- HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on "
- "optimizations, but provides a preprocessor macro __FAST_MATH__ the "
- "same as GCC's -ffast-math flag.">;
-def ffreestanding : Flag<"-ffreestanding">,
- HelpText<"Assert that the compilation takes place in a freestanding environment">;
-def fgnu_runtime : Flag<"-fgnu-runtime">,
- HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
def fhidden_weak_vtables : Flag<"-fhidden-weak-vtables">,
HelpText<"Generate weak vtables and RTTI with hidden visibility">;
-def std_EQ : Joined<"-std=">,
- HelpText<"Language standard to compile for">;
-def stdlib_EQ : Joined<"-stdlib=">,
- HelpText<"C++ standard library to use">;
-def fmath_errno : Flag<"-fmath-errno">,
- HelpText<"Require math functions to indicate errors by setting errno">;
-def fms_extensions : Flag<"-fms-extensions">,
- HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">;
-def fms_compatibility : Flag<"-fms-compatibility">,
- HelpText<"Enable Microsoft compatibility mode">;
-def fmsc_version : Joined<"-fmsc-version=">,
- HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">;
-def fborland_extensions : Flag<"-fborland-extensions">,
- HelpText<"Accept non-standard constructs supported by the Borland compiler">;
def main_file_name : Separate<"-main-file-name">,
HelpText<"Main file name to use for debug info">;
-def fno_elide_constructors : Flag<"-fno-elide-constructors">,
- HelpText<"Disable C++ copy constructor elision">;
-def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">,
- HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">;
-def fno_operator_names : Flag<"-fno-operator-names">,
- HelpText<"Do not treat C++ operator name keywords as synonyms for operators">;
def fno_signed_char : Flag<"-fno-signed-char">,
HelpText<"Char is unsigned">;
-def fno_spell_checking : Flag<"-fno-spell-checking">,
- HelpText<"Disable spell-checking">;
-def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">,
- HelpText<"Don't use __cxa_atexit for calling destructors">;
def fconstant_string_class : Separate<"-fconstant-string-class">,
MetaVarName<"<class name>">,
HelpText<"Specify the class to use for constant Objective-C string objects.">;
-def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">,
- HelpText<"Enable creation of CodeFoundation-type constant strings">;
-def fobjc_arc : Flag<"-fobjc-arc">,
- HelpText<"Synthesize retain and release calls for Objective-C pointers">;
def fobjc_arc_cxxlib_EQ : Joined<"-fobjc-arc-cxxlib=">,
HelpText<"Objective-C++ Automatic Reference Counting standard library kind">;
-def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">,
- HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">;
-def fobjc_runtime_has_arc : Flag<"-fobjc-runtime-has-arc">,
- HelpText<"The target Objective-C runtime provides ARC entrypoints">;
def fobjc_runtime_has_weak : Flag<"-fobjc-runtime-has-weak">,
HelpText<"The target Objective-C runtime supports ARC weak operations">;
-def fobjc_runtime_has_terminate : Flag<"-fobjc-runtime-has-terminate">,
- HelpText<"The target Objective-C runtime provides an objc_terminate entrypoint">;
-def fobjc_gc : Flag<"-fobjc-gc">,
- HelpText<"Enable Objective-C garbage collection">;
-def fobjc_gc_only : Flag<"-fobjc-gc-only">,
- HelpText<"Use GC exclusively for Objective-C related memory management">;
-def fapple_kext : Flag<"-fapple-kext">,
- HelpText<"Use Apple's kernel extensions ABI">;
def fobjc_dispatch_method_EQ : Joined<"-fobjc-dispatch-method=">,
HelpText<"Objective-C dispatch method to use">;
def fobjc_default_synthesize_properties : Flag<"-fobjc-default-synthesize-properties">,
HelpText<"enable the default synthesis of Objective-C properties">;
-def print_ivar_layout : Flag<"-print-ivar-layout">,
- HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
-def fobjc_fragile_abi : Flag<"-fobjc-fragile-abi">,
- HelpText<"Use Objective-C's fragile ABI">;
-def fno_objc_infer_related_result_type : Flag<
- "-fno-objc-infer-related-result-type">,
- HelpText<
- "do not infer Objective-C related result type based on method family">;
-def ftrapv : Flag<"-ftrapv">,
- HelpText<"Trap on integer overflow">;
-def ftrapv_handler : Separate<"-ftrapv-handler">,
- MetaVarName<"<function name>">,
- HelpText<"Specify the function to be called on overflow.">;
-def fwrapv : Flag<"-fwrapv">,
- HelpText<"Treat signed integer overflow as two's complement">;
def pic_level : Separate<"-pic-level">,
HelpText<"Value for __PIC__">;
def pie_level : Separate<"-pie-level">,
HelpText<"Value for __PIE__">;
-def pthread : Flag<"-pthread">,
- HelpText<"Support POSIX threads in generated code">;
-def fpack_struct : Separate<"-fpack-struct">,
- HelpText<"Specify the default maximum struct packing alignment">;
-def fpascal_strings : Flag<"-fpascal-strings">,
- HelpText<"Recognize and construct Pascal-style string literals">;
-def fno_rtti : Flag<"-fno-rtti">,
- HelpText<"Disable generation of rtti information">;
def fno_validate_pch : Flag<"-fno-validate-pch">,
HelpText<"Disable validation of precompiled headers">;
def dump_deserialized_pch_decls : Flag<"-dump-deserialized-decls">,
@@ -647,44 +411,24 @@ def error_on_deserialized_pch_decl : Separate<"-error-on-deserialized-decl">,
HelpText<"Emit error if a specific declaration is deserialized from PCH, for testing">;
def error_on_deserialized_pch_decl_EQ : Joined<"-error-on-deserialized-decl=">,
Alias<error_on_deserialized_pch_decl>;
-def fshort_wchar : Flag<"-fshort-wchar">,
- HelpText<"Force wchar_t to be a short unsigned int">;
-def fshort_enums : Flag<"-fshort-enums">,
- HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">;
def static_define : Flag<"-static-define">,
HelpText<"Should __STATIC__ be defined">;
def stack_protector : Separate<"-stack-protector">,
HelpText<"Enable stack protectors">;
def fvisibility : Separate<"-fvisibility">,
HelpText<"Default symbol visibility">;
-def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">,
- HelpText<"Give inline C++ member functions default visibility by default">;
def ftemplate_depth : Separate<"-ftemplate-depth">,
HelpText<"Maximum depth of recursive template instantiation">;
def fconstexpr_depth : Separate<"-fconstexpr-depth">,
HelpText<"Maximum depth of recursive constexpr function calls">;
-def Wlarge_by_value_copy : Separate<"-Wlarge-by-value-copy">,
- HelpText<"Warn if a function definition returns or accepts an object larger "
- "in bytes that a given value">;
-def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">,
- Alias<Wlarge_by_value_copy>;
-def trigraphs : Flag<"-trigraphs">,
- HelpText<"Process trigraph sequences">;
-def fwritable_strings : Flag<"-fwritable-strings">,
- HelpText<"Store string literals as writable data">;
def fconst_strings : Flag<"-fconst-strings">,
HelpText<"Use a const qualified type for string literals in C and ObjC">;
def fno_const_strings : Flag<"-fno-const-strings">,
HelpText<"Don't use a const qualified type for string literals in C and ObjC">;
def fno_bitfield_type_align : Flag<"-fno-bitfield-type-align">,
HelpText<"Ignore bit-field types when aligning structures">;
-def traditional_cpp : Flag<"-traditional-cpp">,
- HelpText<"Enable some traditional CPP emulation">;
def ffake_address_space_map : Flag<"-ffake-address-space-map">,
HelpText<"Use a fake address space map; OpenCL testing purposes only">;
-def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">,
- HelpText<"Parse templated function definitions at the end of the "
- "translation unit ">;
def funknown_anytype : Flag<"-funknown-anytype">,
HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">;
def fdebugger_support : Flag<"-fdebugger-support">,
@@ -692,13 +436,11 @@ def fdebugger_support : Flag<"-fdebugger-support">,
def fdebugger_cast_result_to_id : Flag<"-fdebugger-cast-result-to-id">,
HelpText<"Enable casting unknown expression results to id">;
def fdebugger_objc_literal : Flag<"-fdebugger-objc-literal">,
- HelpText<"Enable special debugger support for objective-C subscripting and literals">;
+ HelpText<"Enable special debugger support for Objective-C subscripting and literals">;
def fdeprecated_macro : Flag<"-fdeprecated-macro">,
HelpText<"Defines the __DEPRECATED macro">;
def fno_deprecated_macro : Flag<"-fno-deprecated-macro">,
HelpText<"Undefines the __DEPRECATED macro">;
-def fapple_pragma_pack : Flag<"-fapple-pragma-pack">,
- HelpText<"Enable Apple gcc-compatible #pragma pack handling">;
//===----------------------------------------------------------------------===//
// Header Search Options
@@ -706,48 +448,19 @@ def fapple_pragma_pack : Flag<"-fapple-pragma-pack">,
def nostdsysteminc : Flag<"-nostdsysteminc">,
HelpText<"Disable standard system #include directories">;
-def nostdincxx : Flag<"-nostdinc++">,
- HelpText<"Disable standard #include directories for the C++ standard library">;
-def nobuiltininc : Flag<"-nobuiltininc">,
- HelpText<"Disable builtin #include directories">;
-def fmodule_cache_path : Separate<"-fmodule-cache-path">,
- MetaVarName<"<directory>">,
- HelpText<"Specify the module cache path">;
def fmodule_name : Joined<"-fmodule-name=">,
MetaVarName<"<name>">,
HelpText<"Specify the name of the module to build">;
def fdisable_module_hash : Flag<"-fdisable-module-hash">,
HelpText<"Disable the module hash">;
-def fmodules : Flag<"-fmodules">,
- HelpText<"Enable the 'modules' language feature">;
-
-def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">,
- HelpText<"Add directory to framework include search path">;
-def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">,
- HelpText<"Add directory to include search path">;
-def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">,
- HelpText<"Add directory to AFTER include search path">;
-def index_header_map : Flag<"-index-header-map">,
- HelpText<"Make the next included directory (-I or -F) an indexer header map">;
-def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">,
- HelpText<"Add directory to QUOTE include search path">;
def c_isystem : JoinedOrSeparate<"-c-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to the C SYSTEM include search path">;
-def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, MetaVarName<"<directory>">,
- HelpText<"Add directory to the C++ SYSTEM include search path">;
def objc_isystem : JoinedOrSeparate<"-objc-isystem">,
MetaVarName<"<directory>">,
HelpText<"Add directory to the ObjC SYSTEM include search path">;
def objcxx_isystem : JoinedOrSeparate<"-objcxx-isystem">,
MetaVarName<"<directory>">,
HelpText<"Add directory to the ObjC++ SYSTEM include search path">;
-def iframework : JoinedOrSeparate<"-iframework">, MetaVarName<"<directory>">,
- HelpText<"Add directory to SYSTEM framework search path">;
-def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">,
- HelpText<"Add directory to SYSTEM include search path">;
-def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">,
- HelpText<"Add directory to SYSTEM include search path, "
- "absolute paths are relative to -isysroot">;
def internal_isystem : JoinedOrSeparate<"-internal-isystem">,
MetaVarName<"<directory>">,
HelpText<"Add directory to the internal system include search path; these "
@@ -759,29 +472,19 @@ def internal_externc_isystem : JoinedOrSeparate<"-internal-externc-isystem">,
"implicit extern \"C\" semantics; these are assumed to not be "
"user-provided and are used to model system and standard headers' "
"paths.">;
-def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">,
- HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">;
-def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">,
- HelpText<"Set directory to SYSTEM include search path with prefix">;
-def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">,
- MetaVarName<"<dir>">,
- HelpText<"Set directory to include search path with prefix">;
-def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">,
- HelpText<"Set the system root directory (usually /)">;
-def v : Flag<"-v">, HelpText<"Enable verbose output">;
+def isystem_prefix : JoinedOrSeparate<"-isystem-prefix">,
+ MetaVarName<"<prefix>">,
+ HelpText<"Treat all #include paths starting with <prefix> as including a "
+ "system header.">;
+def ino_system_prefix : JoinedOrSeparate<"-ino-system-prefix">,
+ MetaVarName<"<prefix>">,
+ HelpText<"Treat all #include paths starting with <prefix> as not including a "
+ "system header.">;
//===----------------------------------------------------------------------===//
// Preprocessor Options
//===----------------------------------------------------------------------===//
-def D : JoinedOrSeparate<"-D">, MetaVarName<"<macro>">,
- HelpText<"Predefine the specified macro">;
-def include_ : JoinedOrSeparate<"-include">, MetaVarName<"<file>">, EnumName<"include">,
- HelpText<"Include file before parsing">;
-def imacros : JoinedOrSeparate<"-imacros">, MetaVarName<"<file>">,
- HelpText<"Include macros from file before parsing">;
-def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">,
- HelpText<"Include precompiled header file">;
def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">,
HelpText<"Include file before parsing">;
def chain_include : Separate<"-chain-include">, MetaVarName<"<file>">,
@@ -791,29 +494,8 @@ def preamble_bytes_EQ : Joined<"-preamble-bytes=">,
"covering the first N bytes of the main file">;
def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">,
HelpText<"Use specified token cache file">;
-def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">,
- HelpText<"Undefine the specified macro">;
-def undef : Flag<"-undef">, MetaVarName<"<macro>">,
- HelpText<"undef all system defines">;
def detailed_preprocessing_record : Flag<"-detailed-preprocessing-record">,
HelpText<"include a detailed record of preprocessing actions">;
-def mqdsp6_compat : Flag<"-mqdsp6-compat">,
- HelpText<"Enable hexagon-qdsp6 backward compatibility">;
-
-//===----------------------------------------------------------------------===//
-// Preprocessed Output Options
-//===----------------------------------------------------------------------===//
-
-def P : Flag<"-P">,
- HelpText<"Disable linemarker output in -E mode">;
-def C : Flag<"-C">,
- HelpText<"Enable comment output in -E mode">;
-def CC : Flag<"-CC">,
- HelpText<"Enable comment output in -E mode, even from macro expansions">;
-def dM : Flag<"-dM">,
- HelpText<"Print macro definitions in -E mode instead of normal output">;
-def dD : Flag<"-dD">,
- HelpText<"Print macro definitions in -E mode in addition to normal output">;
//===----------------------------------------------------------------------===//
// OpenCL Options
@@ -840,3 +522,5 @@ def cl_std_EQ : Joined<"-cl-std=">,
def fcuda_is_device : Flag<"-fcuda-is-device">,
HelpText<"Generate code for CUDA device">;
+
+} // let Flags = [CC1Option]
diff --git a/include/clang/Driver/CMakeLists.txt b/include/clang/Driver/CMakeLists.txt
index abd4cfe50129..1277d51edb82 100644
--- a/include/clang/Driver/CMakeLists.txt
+++ b/include/clang/Driver/CMakeLists.txt
@@ -2,10 +2,6 @@ clang_tablegen(Options.inc -gen-opt-parser-defs
SOURCE Options.td
TARGET ClangDriverOptions)
-clang_tablegen(CC1Options.inc -gen-opt-parser-defs
- SOURCE CC1Options.td
- TARGET ClangCC1Options)
-
clang_tablegen(CC1AsOptions.inc -gen-opt-parser-defs
SOURCE CC1AsOptions.td
TARGET ClangCC1AsOptions)
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 6f1a2217cd1c..7a10d567354b 100644
--- a/include/clang/Driver/Compilation.h
+++ b/include/clang/Driver/Compilation.h
@@ -76,6 +76,8 @@ public:
const DerivedArgList &getArgs() const { return *TranslatedArgs; }
+ DerivedArgList &getArgs() { return *TranslatedArgs; }
+
ActionList &getActions() { return Actions; }
const ActionList &getActions() const { return Actions; }
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index 0538334fc009..609505597a70 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -156,6 +156,9 @@ private:
/// used where an integrated CPP would).
unsigned CCCUseClangCPP : 1;
+ /// \brief Force use of clang frontend.
+ unsigned ForcedClangUse : 1;
+
public:
/// Use lazy precompiled headers for PCH support.
unsigned CCCUsePCH : 1;
@@ -174,7 +177,7 @@ private:
/// \brief Cache of all the ToolChains in use by the driver.
///
/// This maps from the string representation of a triple to a ToolChain
- /// created targetting that triple. The driver owns all the ToolChain objects
+ /// created targeting that triple. The driver owns all the ToolChain objects
/// stored in it, and will clean them up when torn down.
mutable llvm::StringMap<ToolChain *> ToolChains;
@@ -229,6 +232,9 @@ public:
InstalledDir = Value;
}
+ bool shouldForceClangUse() const { return ForcedClangUse; }
+ void setForcedClangUse(bool V = true) { ForcedClangUse = V; }
+
/// @}
/// @name Primary Functionality
/// @{
diff --git a/include/clang/Driver/Makefile b/include/clang/Driver/Makefile
index 45bc40f3b715..7d066c77b377 100644
--- a/include/clang/Driver/Makefile
+++ b/include/clang/Driver/Makefile
@@ -1,18 +1,14 @@
CLANG_LEVEL := ../../..
-BUILT_SOURCES = Options.inc CC1Options.inc CC1AsOptions.inc
+BUILT_SOURCES = Options.inc CC1AsOptions.inc
TABLEGEN_INC_FILES_COMMON = 1
include $(CLANG_LEVEL)/Makefile
-$(ObjDir)/Options.inc.tmp : Options.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir
+$(ObjDir)/Options.inc.tmp : Options.td CC1Options.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang Driver Option tables with tblgen"
$(Verb) $(ClangTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
-$(ObjDir)/CC1Options.inc.tmp : CC1Options.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir
- $(Echo) "Building Clang CC1 Option tables with tblgen"
- $(Verb) $(ClangTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
-
$(ObjDir)/CC1AsOptions.inc.tmp : CC1AsOptions.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang CC1 Assembler Option tables with tblgen"
$(Verb) $(ClangTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
diff --git a/include/clang/Driver/ObjCRuntime.h b/include/clang/Driver/ObjCRuntime.h
deleted file mode 100644
index 094873a7d17f..000000000000
--- a/include/clang/Driver/ObjCRuntime.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===--- ObjCRuntime.h - Objective C runtime features -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_DRIVER_OBJCRUNTIME_H_
-#define CLANG_DRIVER_OBJCRUNTIME_H_
-
-namespace clang {
-namespace driver {
-
-class ObjCRuntime {
-public:
- enum Kind { GNU, NeXT };
-private:
- unsigned RuntimeKind : 1;
-public:
- void setKind(Kind k) { RuntimeKind = k; }
- Kind getKind() const { return static_cast<Kind>(RuntimeKind); }
-
- /// True if the runtime provides native ARC entrypoints. ARC may
- /// still be usable without this if the tool-chain provides a
- /// statically-linked runtime support library.
- unsigned HasARC : 1;
-
- /// True if the runtime supports ARC zeroing __weak.
- unsigned HasWeak : 1;
-
- /// \brief True if the runtime supports subscripting methods.
- unsigned HasSubscripting : 1;
-
- /// True if the runtime provides the following entrypoint:
- /// void objc_terminate(void);
- /// If available, this will be called instead of abort() when an
- /// exception is thrown out of an EH cleanup.
- unsigned HasTerminate : 1;
-
- ObjCRuntime() : RuntimeKind(NeXT), HasARC(false), HasWeak(false),
- HasSubscripting(false), HasTerminate(false) {}
-};
-
-}
-}
-
-#endif
diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td
index 25ecbc35f92e..9e6d5b9118e8 100644
--- a/include/clang/Driver/OptParser.td
+++ b/include/clang/Driver/OptParser.td
@@ -85,6 +85,9 @@ def HelpHidden : OptionFlag;
// NoForward - The option should not be implicitly forwarded to other tools.
def NoForward : OptionFlag;
+// CC1Option - This option should be accepted by clang -cc1.
+def CC1Option : OptionFlag;
+
// Define the option group class.
class OptionGroup<string name> {
@@ -134,5 +137,5 @@ class MetaVarName<string name> { string MetaVarName = name; }
// FIXME: Have generator validate that these appear in correct position (and
// aren't duplicated).
-def INPUT : Option<"<input>", KIND_INPUT>, Flags<[DriverOption]>;
+def INPUT : Option<"<input>", KIND_INPUT>, Flags<[DriverOption,CC1Option]>;
def UNKNOWN : Option<"<unknown>", KIND_UNKNOWN>;
diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h
index 3af6f8fa3ec9..27bd11985a67 100644
--- a/include/clang/Driver/OptTable.h
+++ b/include/clang/Driver/OptTable.h
@@ -25,7 +25,8 @@ namespace options {
RenderAsInput = (1 << 5),
RenderJoined = (1 << 6),
RenderSeparate = (1 << 7),
- Unsupported = (1 << 8)
+ Unsupported = (1 << 8),
+ CC1Option = (1 << 9)
};
}
@@ -34,7 +35,7 @@ namespace options {
class InputArgList;
class Option;
- /// OptTable - Provide access to the Option info table.
+ /// \brief Provide access to the Option info table.
///
/// The OptTable class provides a layer of indirection which allows Option
/// instance to be created lazily. In the common case, only a few options will
@@ -43,7 +44,7 @@ namespace options {
/// parts of the driver still use Option instances where convenient.
class OptTable {
public:
- /// Info - Entry for a single option instance in the option data table.
+ /// \brief Entry for a single option instance in the option data table.
struct Info {
const char *Name;
const char *HelpText;
@@ -56,17 +57,17 @@ namespace options {
};
private:
- /// The static option information table.
+ /// \brief The static option information table.
const Info *OptionInfos;
unsigned NumOptionInfos;
- /// The lazily constructed options table, indexed by option::ID - 1.
+ /// \brief The lazily constructed options table, indexed by option::ID - 1.
mutable Option **Options;
- /// Prebound input option instance.
+ /// \brief Prebound input option instance.
const Option *TheInputOption;
- /// Prebound unknown option instance.
+ /// \brief Prebound unknown option instance.
const Option *TheUnknownOption;
/// The index of the first option which can be parsed (i.e., is not a
@@ -87,10 +88,10 @@ namespace options {
public:
~OptTable();
- /// getNumOptions - Return the total number of option classes.
+ /// \brief Return the total number of option classes.
unsigned getNumOptions() const { return NumOptionInfos; }
- /// getOption - Get the given \arg id's Option instance, lazily creating it
+ /// \brief Get the given Opt's Option instance, lazily creating it
/// if necessary.
///
/// \return The option, or null for the INVALID option id.
@@ -106,72 +107,71 @@ namespace options {
return Entry;
}
- /// getOptionName - Lookup the name of the given option.
+ /// \brief Lookup the name of the given option.
const char *getOptionName(OptSpecifier id) const {
return getInfo(id).Name;
}
- /// getOptionKind - Get the kind of the given option.
+ /// \brief Get the kind of the given option.
unsigned getOptionKind(OptSpecifier id) const {
return getInfo(id).Kind;
}
- /// getOptionGroupID - Get the group id for the given option.
+ /// \brief Get the group id for the given option.
unsigned getOptionGroupID(OptSpecifier id) const {
return getInfo(id).GroupID;
}
- /// isOptionHelpHidden - Should the help for the given option be hidden by
- /// default.
+ /// \brief Should the help for the given option be hidden by default.
bool isOptionHelpHidden(OptSpecifier id) const {
return getInfo(id).Flags & options::HelpHidden;
}
- /// getOptionHelpText - Get the help text to use to describe this option.
+ /// \brief Get the help text to use to describe this option.
const char *getOptionHelpText(OptSpecifier id) const {
return getInfo(id).HelpText;
}
- /// getOptionMetaVar - Get the meta-variable name to use when describing
+ /// \brief Get the meta-variable name to use when describing
/// this options values in the help text.
const char *getOptionMetaVar(OptSpecifier id) const {
return getInfo(id).MetaVar;
}
- /// ParseOneArg - Parse a single argument; returning the new argument and
+ /// \brief Parse a single argument; returning the new argument and
/// updating Index.
///
- /// \param [in] [out] Index - The current parsing position in the argument
+ /// \param [in,out] Index - The current parsing position in the argument
/// string list; on return this will be the index of the next argument
/// string to parse.
///
- /// \return - The parsed argument, or 0 if the argument is missing values
+ /// \return The parsed argument, or 0 if the argument is missing values
/// (in which case Index still points at the conceptual next argument string
/// to parse).
Arg *ParseOneArg(const ArgList &Args, unsigned &Index) const;
- /// ParseArgs - Parse an list of arguments into an InputArgList.
+ /// \brief Parse an list of arguments into an InputArgList.
///
- /// The resulting InputArgList will reference the strings in [ArgBegin,
- /// ArgEnd), and their lifetime should extend past that of the returned
+ /// The resulting InputArgList will reference the strings in [\p ArgBegin,
+ /// \p ArgEnd), and their lifetime should extend past that of the returned
/// InputArgList.
///
/// The only error that can occur in this routine is if an argument is
- /// missing values; in this case \arg MissingArgCount will be non-zero.
+ /// missing values; in this case \p MissingArgCount will be non-zero.
///
/// \param ArgBegin - The beginning of the argument vector.
/// \param ArgEnd - The end of the argument vector.
/// \param MissingArgIndex - On error, the index of the option which could
/// not be parsed.
/// \param MissingArgCount - On error, the number of missing options.
- /// \return - An InputArgList; on error this will contain all the options
+ /// \return An InputArgList; on error this will contain all the options
/// which could be parsed.
InputArgList *ParseArgs(const char* const *ArgBegin,
const char* const *ArgEnd,
unsigned &MissingArgIndex,
unsigned &MissingArgCount) const;
- /// PrintHelp - Render the help text for an option table.
+ /// \brief Render the help text for an option table.
///
/// \param OS - The stream to write the help text to.
/// \param Name - The name to use in the usage line.
diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h
index 8243f6d69314..e6c4e12e0d1b 100644
--- a/include/clang/Driver/Option.h
+++ b/include/clang/Driver/Option.h
@@ -91,6 +91,9 @@ namespace driver {
/// This option should not be implicitly forwarded.
bool NoForward : 1;
+ /// CC1Option - This option should be accepted by clang -cc1.
+ bool CC1Option : 1;
+
protected:
Option(OptionClass Kind, OptSpecifier ID, const char *Name,
const OptionGroup *Group, const Option *Alias);
@@ -126,6 +129,9 @@ namespace driver {
bool hasNoForward() const { return NoForward; }
void setNoForward(bool Value) { NoForward = Value; }
+ bool isCC1Option() const { return CC1Option; }
+ void setIsCC1Option(bool Value) { CC1Option = Value; }
+
bool hasForwardToGCC() const {
return !NoForward && !DriverOption && !LinkerInput;
}
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index b7967716be88..c7698a28f910 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -19,6 +19,7 @@ include "OptParser.td"
// Meta-group which defines
def CompileOnly_Group : OptionGroup<"<CompileOnly group>">;
+def Action_Group : OptionGroup<"<action group>">;
def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>;
def L_Group : OptionGroup<"<L group>">, Group<CompileOnly_Group>;
@@ -32,10 +33,13 @@ def d_Group : OptionGroup<"<d group>">;
def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>;
def f_clang_Group : OptionGroup<"<f (clang-only) group>">, Group<CompileOnly_Group>;
def g_Group : OptionGroup<"<g group>">;
+def g_flags_Group : OptionGroup<"<g flags group>">;
def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>;
def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>;
def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>;
def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>;
+def m_hexagon_Features_Group : OptionGroup<"<m hexagon features group>">, Group<m_Group>;
+def opencl_Group : OptionGroup<"<opencl group>">;
def u_Group : OptionGroup<"<u group>">;
def pedantic_Group : OptionGroup<"<pedantic group>">,
@@ -120,18 +124,19 @@ def ccc_arrmt_modify : Flag<"-ccc-arrmt-modify">, Alias<ccc_arcmt_modify>;
def ccc_arcmt_migrate : Separate<"-ccc-arcmt-migrate">, CCCDriverOpt,
HelpText<"Apply modifications and produces temporary files that conform to ARC">;
def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">,
- HelpText<"Output path for the plist report">;
+ HelpText<"Output path for the plist report">, Flags<[CC1Option]>;
def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">,
- HelpText<"Emit ARC errors even if the migrator can fix them">;
+ HelpText<"Emit ARC errors even if the migrator can fix them">,
+ Flags<[CC1Option]>;
def _migrate : Flag<"--migrate">, Flags<[DriverOption]>,
HelpText<"Run the migrator">;
def ccc_objcmt_migrate : Separate<"-ccc-objcmt-migrate">, CCCDriverOpt,
HelpText<"Apply modifications and produces temporary files to migrate to "
"modern ObjC syntax">;
-def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">,
+def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC literals">;
-def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">,
+def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC subscripting">;
// Make sure all other -ccc- options are rejected.
@@ -146,66 +151,76 @@ def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>,
def _DASH_DASH : Flag<"--">, Flags<[DriverOption]>;
def A : JoinedOrSeparate<"-A">;
def B : JoinedOrSeparate<"-B">;
-def CC : Flag<"-CC">;
-def C : Flag<"-C">;
-def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>;
-def E : Flag<"-E">, Flags<[DriverOption]>,
+def CC : Flag<"-CC">, Flags<[CC1Option]>;
+def C : Flag<"-C">, Flags<[CC1Option]>;
+def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>, Flags<[CC1Option]>;
+def E : Flag<"-E">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
HelpText<"Only run the preprocessor">;
-def F : JoinedOrSeparate<"-F">, Flags<[RenderJoined]>;
+def F : JoinedOrSeparate<"-F">, Flags<[RenderJoined,CC1Option]>,
+ HelpText<"Add directory to framework include search path">;
def G : Separate<"-G">, Flags<[DriverOption]>;
-def H : Flag<"-H">;
+def H : Flag<"-H">, Flags<[CC1Option]>,
+ HelpText<"Show header includes and nesting depth">;
def I_ : Flag<"-I-">, Group<I_Group>;
-def I : JoinedOrSeparate<"-I">, Group<I_Group>;
+def I : JoinedOrSeparate<"-I">, Group<I_Group>, Flags<[CC1Option]>,
+ HelpText<"Add directory to include search path">;
def L : JoinedOrSeparate<"-L">, Flags<[RenderJoined]>;
def MD : Flag<"-MD">, Group<M_Group>;
def MF : JoinedOrSeparate<"-MF">, Group<M_Group>;
-def MG : Flag<"-MG">, Group<M_Group>;
+def MG : Flag<"-MG">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Add missing headers to dependency list">;
def MMD : Flag<"-MMD">, Group<M_Group>;
def MM : Flag<"-MM">, Group<M_Group>;
-def MP : Flag<"-MP">, Group<M_Group>;
-def MQ : JoinedOrSeparate<"-MQ">, Group<M_Group>;
-def MT : JoinedOrSeparate<"-MT">, Group<M_Group>;
+def MP : Flag<"-MP">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Create phony target for each dependency (other than main file)">;
+def MQ : JoinedOrSeparate<"-MQ">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Specify target to quote for dependency">;
+def MT : JoinedOrSeparate<"-MT">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Specify target for dependency">;
def Mach : Flag<"-Mach">;
def M : Flag<"-M">, Group<M_Group>;
-def O0 : Joined<"-O0">, Group<O_Group>;
-def O4 : Joined<"-O4">, Group<O_Group>;
+def O0 : Joined<"-O0">, Group<O_Group>, Flags<[CC1Option]>;
+def O4 : Joined<"-O4">, Group<O_Group>, Flags<[CC1Option]>;
def ObjCXX : Flag<"-ObjC++">, Flags<[DriverOption]>,
HelpText<"Treat source input files as Objective-C++ inputs">;
def ObjC : Flag<"-ObjC">, Flags<[DriverOption]>,
HelpText<"Treat source input files as Objective-C inputs">;
-def O : Joined<"-O">, Group<O_Group>;
-def P : Flag<"-P">;
+def O : Joined<"-O">, Group<O_Group>, Flags<[CC1Option]>;
+def P : Flag<"-P">, Flags<[CC1Option]>,
+ HelpText<"Disable linemarker output in -E mode">;
def Qn : Flag<"-Qn">;
def Qunused_arguments : Flag<"-Qunused-arguments">, Flags<[DriverOption]>,
HelpText<"Don't emit warning for unused driver arguments">;
def Q : Flag<"-Q">;
def R : Flag<"-R">;
-def S : Flag<"-S">, Flags<[DriverOption]>,
+def S : Flag<"-S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
HelpText<"Only run preprocess and compilation steps">;
def Tbss : JoinedOrSeparate<"-Tbss">, Group<T_Group>;
def Tdata : JoinedOrSeparate<"-Tdata">, Group<T_Group>;
def Ttext : JoinedOrSeparate<"-Ttext">, Group<T_Group>;
def T : JoinedOrSeparate<"-T">, Group<T_Group>;
-def U : JoinedOrSeparate<"-U">, Group<CompileOnly_Group>;
+def U : JoinedOrSeparate<"-U">, Group<CompileOnly_Group>, Flags<[CC1Option]>;
def V : JoinedOrSeparate<"-V">, Flags<[DriverOption, Unsupported]>;
def Wa_COMMA : CommaJoined<"-Wa,">,
HelpText<"Pass the comma separated arguments in <arg> to the assembler">,
MetaVarName<"<arg>">;
-def Wall : Flag<"-Wall">, Group<W_Group>;
-def Wdeprecated : Flag<"-Wdeprecated">, Group<W_Group>;
-def Wno_deprecated : Flag<"-Wno-deprecated">, Group<W_Group>;
-def Wextra : Flag<"-Wextra">, Group<W_Group>;
+def Wall : Flag<"-Wall">, Group<W_Group>, Flags<[CC1Option]>;
+def Wdeprecated : Flag<"-Wdeprecated">, Group<W_Group>, Flags<[CC1Option]>;
+def Wno_deprecated : Flag<"-Wno-deprecated">, Group<W_Group>, Flags<[CC1Option]>;
+def Wextra : Flag<"-Wextra">, Group<W_Group>, Flags<[CC1Option]>;
def Wl_COMMA : CommaJoined<"-Wl,">, Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass the comma separated arguments in <arg> to the linker">,
MetaVarName<"<arg>">;
-def Wno_nonportable_cfstrings : Joined<"-Wno-nonportable-cfstrings">, Group<W_Group>;
-def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group<W_Group>;
+def Wno_nonportable_cfstrings : Joined<"-Wno-nonportable-cfstrings">, Group<W_Group>,
+ Flags<[CC1Option]>;
+def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group<W_Group>,
+ Flags<[CC1Option]>;
def Wp_COMMA : CommaJoined<"-Wp,">,
HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">,
MetaVarName<"<arg>">;
-def Wwrite_strings : Flag<"-Wwrite-strings">, Group<W_Group>;
-def Wno_write_strings : Flag<"-Wno-write-strings">, Group<W_Group>;
-def W_Joined : Joined<"-W">, Group<W_Group>;
+def Wwrite_strings : Flag<"-Wwrite-strings">, Group<W_Group>, Flags<[CC1Option]>;
+def Wno_write_strings : Flag<"-Wno-write-strings">, Group<W_Group>, Flags<[CC1Option]>;
+def W_Joined : Joined<"-W">, Group<W_Group>, Flags<[CC1Option]>;
def Xanalyzer : Separate<"-Xanalyzer">,
HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">;
def Xarch__ : JoinedAndSeparate<"-Xarch_">, Flags<[DriverOption]>;
@@ -233,20 +248,29 @@ def bind__at__load : Flag<"-bind_at_load">;
def bundle__loader : Separate<"-bundle_loader">;
def bundle : Flag<"-bundle">;
def b : JoinedOrSeparate<"-b">, Flags<[Unsupported]>;
+def cl_kernel_arg_info : Flag<"-cl-kernel-arg-info">, Flags<[CC1Option]>, Group<opencl_Group>,
+HelpText<"OpenCL only. This option allows the compiler to store information about the arguments of a kernel(s)"> ;
def client__name : JoinedOrSeparate<"-client_name">;
def combine : Flag<"-combine">, Flags<[DriverOption, Unsupported]>;
def compatibility__version : JoinedOrSeparate<"-compatibility_version">;
def coverage : Flag<"-coverage">;
def cpp_precomp : Flag<"-cpp-precomp">, Group<clang_ignored_f_Group>;
def current__version : JoinedOrSeparate<"-current_version">;
-def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, Group<clang_i_Group>;
+def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, Group<clang_i_Group>,
+ HelpText<"Add directory to the C++ SYSTEM include search path">, Flags<[CC1Option]>,
+ MetaVarName<"<directory>">;
def c : Flag<"-c">, Flags<[DriverOption]>,
HelpText<"Only run preprocess, compile, and assemble steps">;
def dA : Flag<"-dA">, Group<d_Group>;
-def dD : Flag<"-dD">, Group<d_Group>;
-def dM : Flag<"-dM">, Group<d_Group>;
+def dD : Flag<"-dD">, Group<d_Group>, Flags<[CC1Option]>,
+ HelpText<"Print macro definitions in -E mode in addition to normal output">;
+def dM : Flag<"-dM">, Group<d_Group>, Flags<[CC1Option]>,
+ HelpText<"Print macro definitions in -E mode instead of normal output">;
def dead__strip : Flag<"-dead_strip">;
-def dependency_file : Separate<"-dependency-file">;
+def dependency_file : Separate<"-dependency-file">, Flags<[CC1Option]>,
+ HelpText<"Filename (or -) to write dependency output to">;
+def dependency_dot : Separate<"-dependency-dot">, Flags<[CC1Option]>,
+ HelpText<"Filename to write DOT-formatted header dependencies to">;
def dumpmachine : Flag<"-dumpmachine">;
def dumpspecs : Flag<"-dumpspecs">, Flags<[Unsupported]>;
def dumpversion : Flag<"-dumpversion">;
@@ -259,7 +283,7 @@ def d_Flag : Flag<"-d">, Group<d_Group>;
def d_Joined : Joined<"-d">, Group<d_Group>;
def emit_ast : Flag<"-emit-ast">,
HelpText<"Emit Clang AST files for source inputs">;
-def emit_llvm : Flag<"-emit-llvm">,
+def emit_llvm : Flag<"-emit-llvm">, Flags<[CC1Option]>, Group<Action_Group>,
HelpText<"Use the LLVM representation for assembler and object files">;
def exported__symbols__list : Separate<"-exported_symbols_list">;
def e : JoinedOrSeparate<"-e">;
@@ -269,13 +293,18 @@ def fPIE : Flag<"-fPIE">, Group<f_Group>;
def fno_PIE : Flag<"-fno-PIE">, Group<f_Group>;
def faccess_control : Flag<"-faccess-control">, Group<f_Group>;
def fallow_unsupported : Flag<"-fallow-unsupported">, Group<f_Group>;
-def faltivec : Flag<"-faltivec">, Group<f_Group>;
-def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>;
-def fapple_pragma_pack : Flag<"-fapple-pragma-pack">, Group<f_Group>;
-def faddress_sanitizer : Flag<"-faddress-sanitizer">, Group<f_Group>;
-def fno_address_sanitizer : Flag<"-fno-address-sanitizer">, Group<f_Group>;
-def fthread_sanitizer : Flag<"-fthread-sanitizer">, Group<f_Group>;
-def fno_thread_sanitizer : Flag<"-fno-thread-sanitizer">, Group<f_Group>;
+def faltivec : Flag<"-faltivec">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable AltiVec vector initializer syntax">;
+def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use Apple's kernel extensions ABI">;
+def fapple_pragma_pack : Flag<"-fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable Apple gcc-compatible #pragma pack handling">;
+def faddress_sanitizer : Flag<"-faddress-sanitizer">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable AddressSanitizer instrumentation (memory error detection)">;
+def fno_address_sanitizer : Flag<"-fno-address-sanitizer">, Group<f_Group>, Flags<[CC1Option]>;
+def fthread_sanitizer : Flag<"-fthread-sanitizer">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable ThreadSanitizer instrumentation (race detection)">;
+def fno_thread_sanitizer : Flag<"-fno-thread-sanitizer">, Group<f_Group>, Flags<[CC1Option]>;
def fasm : Flag<"-fasm">, Group<f_Group>;
def fasm_blocks : Flag<"-fasm-blocks">, Group<f_Group>;
@@ -286,17 +315,24 @@ def fastcp : Flag<"-fastcp">, Group<f_Group>;
def fastf : Flag<"-fastf">, Group<f_Group>;
def fast : Flag<"-fast">, Group<f_Group>;
def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>;
-def fblocks : Flag<"-fblocks">, Group<f_Group>;
+def fblocks : Flag<"-fblocks">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable the 'blocks' language feature">;
def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>;
-def fborland_extensions : Flag<"-fborland-extensions">, Group<f_Group>;
+def fborland_extensions : Flag<"-fborland-extensions">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Accept non-standard constructs supported by the Borland compiler">;
+def fbounds_checking : Flag<"-fbounds-checking">, Group<f_Group>,
+ HelpText<"Enable run-time bounds checks.">;
+def fbounds_checking_EQ : Joined<"-fbounds-checking=">, Flags<[CC1Option]>,
+ Group<f_Group>;
def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>;
def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>;
def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>;
def fcaret_diagnostics : Flag<"-fcaret-diagnostics">, Group<f_Group>;
-def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">,
- Group<f_Group>, HelpText<"Generate runtime checks for undefined behavior.">;
+def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, Flags<[CC1Option]>,
+ Group<f_Group>, HelpText<"Generate runtime checks for undefined behavior.">;
def fclasspath_EQ : Joined<"-fclasspath=">, Group<f_Group>;
-def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>;
+def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use colors in diagnostics">;
def fcommon : Flag<"-fcommon">, Group<f_Group>;
def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group<f_Group>;
def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group<f_Group>;
@@ -306,32 +342,53 @@ def fconstexpr_backtrace_limit_EQ : Joined<"-fconstexpr-backtrace-limit=">,
Group<f_Group>;
def fno_crash_diagnostics : Flag<"-fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>;
def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>;
-def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group<f_Group>;
+def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group<f_Group>,
+ HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>;
def fcxx_modules : Flag <"-fcxx-modules">, Group<f_Group>, Flags<[NoForward]>;
def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>;
def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>;
def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_clang_Group>;
-def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_clang_Group>;
-def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_clang_Group>;
-def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>;
-def fdiagnostics_show_note_include_stack : Flag<"-fdiagnostics-show-note-include-stack">, Group<f_Group>;
+def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_clang_Group>,
+ Flags<[CC1Option]>, HelpText<"Print fix-its in machine parseable form">;
+def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Print source range spans in numeric form">;
+def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">;
+def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Print diagnostic name">;
+def fdiagnostics_show_note_include_stack : Flag<"-fdiagnostics-show-note-include-stack">,
+ Group<f_Group>, Flags<[CC1Option]>, HelpText<"Display include stacks for diagnostic notes">;
def fdiagnostics_format_EQ : Joined<"-fdiagnostics-format=">, Group<f_clang_Group>;
def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_clang_Group>;
-def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>;
+def fdiagnostics_show_template_tree : Flag<"-fdiagnostics-show-template-tree">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Print a template comparison tree for differing templates">;
+def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>,
+ HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>;
def fdwarf2_cfi_asm : Flag<"-fdwarf2-cfi-asm">, Group<f_Group>;
-def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, Group<f_Group>;
+def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, Group<f_Group>, Flags<[CC1Option]>;
def fdwarf_directory_asm : Flag<"-fdwarf-directory-asm">, Group<f_Group>;
-def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">, Group<f_Group>;
+def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">, Group<f_Group>, Flags<[CC1Option]>;
def felide_constructors : Flag<"-felide-constructors">, Group<f_Group>;
+def fno_elide_type : Flag<"-fno-elide-type">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Do not elide types when printing diagnostics">;
def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group<f_Group>;
-def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>;
+def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Emit all declarations, even if unused">;
def fencoding_EQ : Joined<"-fencoding=">, Group<f_Group>;
def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>;
-def fexceptions : Flag<"-fexceptions">, Group<f_Group>;
+def fexceptions : Flag<"-fexceptions">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable support for exception handling">;
def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>;
def fhosted : Flag<"-fhosted">, Group<f_Group>;
-def ffast_math : Flag<"-ffast-math">, Group<f_Group>;
-def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>;
+def ffast_math : Flag<"-ffast-math">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on "
+ "optimizations, but provides a preprocessor macro __FAST_MATH__ the "
+ "same as GCC's -ffast-math flag.">;
+def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Require math functions to indicate errors by setting errno">;
def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>;
def fsignaling_math : Flag<"-fsignaling-math">, Group<f_Group>;
def fno_signaling_math : Flag<"-fno-signaling-math">, Group<f_Group>;
@@ -343,7 +400,7 @@ def fassociative_math : Flag<"-fassociative-math">, Group<f_Group>;
def fno_associative_math : Flag<"-fno-associative-math">, Group<f_Group>;
def freciprocal_math : Flag<"-freciprocal-math">, Group<f_Group>;
def fno_reciprocal_math : Flag<"-fno-reciprocal-math">, Group<f_Group>;
-def ffinite_math_only : Flag<"-ffinite-math-only">, Group<f_Group>;
+def ffinite_math_only : Flag<"-ffinite-math-only">, Group<f_Group>, Flags<[CC1Option]>;
def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group<f_Group>;
def fsigned_zeros : Flag<"-fsigned-zeros">, Group<f_Group>;
def fno_signed_zeros : Flag<"-fno-signed-zeros">, Group<f_Group>;
@@ -352,31 +409,41 @@ def fno_honor_nans : Flag<"-fno-honor-nans">, Group<f_Group>;
def fhonor_infinities : Flag<"-fhonor-infinities">, Group<f_Group>;
def fno_honor_infinities : Flag<"-fno-honor-infinities">, Group<f_Group>;
// Sic. This option was misspelled originally.
-def fhonor_infinites : Flag<"-fhonor-infinites">, Group<f_Group>,
- Alias<fhonor_infinities>;
-def fno_honor_infinites : Flag<"-fno-honor-infinites">, Group<f_Group>,
- Alias<fno_honor_infinities>;
+def fhonor_infinites : Flag<"-fhonor-infinites">, Alias<fhonor_infinities>;
+def fno_honor_infinites : Flag<"-fno-honor-infinites">, Alias<fno_honor_infinities>;
def ftrapping_math : Flag<"-ftrapping-math">, Group<f_Group>;
def fno_trapping_math : Flag<"-fno-trapping-math">, Group<f_Group>;
+def ffp_contract : Joined<"-ffp-contract=">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
+ " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">;
def ffor_scope : Flag<"-ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<"-fno-for-scope">, Group<f_Group>;
-def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>;
-def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>;
-def fgnu89_inline : Flag<"-fgnu89-inline">, Group<f_Group>;
+def frewrite_includes : Flag<"-frewrite-includes">, Group<f_Group>,
+ Flags<[CC1Option]>;
+def fno_rewrite_includes : Flag<"-fno-rewrite-includes">, Group<f_Group>;
+
+def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Assert that the compilation takes place in a freestanding environment">;
+def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Allow GNU-extension keywords regardless of language standard">;
+def fgnu89_inline : Flag<"-fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use the gnu89 inline semantics">;
def fno_gnu89_inline : Flag<"-fno-gnu89-inline">, Group<f_Group>;
-def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>;
-def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
+def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>,
+ HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
+def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">, Flags<[CC1Option]>;
def filelist : Separate<"-filelist">, Flags<[LinkerInput]>;
def findirect_virtual_calls : Flag<"-findirect-virtual-calls">, Alias<fapple_kext>;
def finline_functions : Flag<"-finline-functions">, Group<clang_ignored_f_Group>;
def finline : Flag<"-finline">, Group<clang_ignored_f_Group>;
-def finstrument_functions : Flag<"-finstrument-functions">, Group<f_Group>;
+def finstrument_functions : Flag<"-finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Generate calls to instrument function entry and exit">;
def fkeep_inline_functions : Flag<"-fkeep-inline-functions">, Group<clang_ignored_f_Group>;
def flat__namespace : Flag<"-flat_namespace">;
def flax_vector_conversions : Flag<"-flax-vector-conversions">, Group<f_Group>;
-def flimit_debug_info : Flag<"-flimit-debug-info">, Group<f_Group>,
+def flimit_debug_info : Flag<"-flimit-debug-info">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Limit debug information produced to reduce size of debug binary">;
def flimited_precision_EQ : Joined<"-flimited-precision=">, Group<f_Group>;
def flto : Flag<"-flto">, Group<f_Group>;
@@ -385,49 +452,73 @@ def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">,
Group<f_Group>;
def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>;
def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>;
-def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>;
-def fms_compatibility : Flag<"-fms-compatibility">, Group<f_Group>;
-def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>;
-def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, Group<f_Group>;
+def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">;
+def fenable_experimental_ms_inline_asm : Flag<"-fenable-experimental-ms-inline-asm">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable support for Microsoft style inine assembly">;
+def fms_compatibility : Flag<"-fms-compatibility">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable Microsoft compatibility mode">;
+def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">;
+def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, Group<f_Group>,
+ HelpText<"Parse templated function definitions at the end of the "
+ "translation unit ">, Flags<[CC1Option]>;
def fmodule_cache_path : Separate<"-fmodule-cache-path">, Group<i_Group>,
- Flags<[NoForward]>;
-def fmodules : Flag <"-fmodules">, Group<f_Group>, Flags<[NoForward]>;
+ Flags<[NoForward,CC1Option]>, MetaVarName<"<directory>">,
+ HelpText<"Specify the module cache path">;
+def fmodules : Flag <"-fmodules">, Group<f_Group>, Flags<[NoForward,CC1Option]>,
+ HelpText<"Enable the 'modules' language feature">;
def fmudflapth : Flag<"-fmudflapth">, Group<f_Group>;
def fmudflap : Flag<"-fmudflap">, Group<f_Group>;
def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>;
def fnext_runtime : Flag<"-fnext-runtime">, Group<f_Group>;
-def fno_access_control : Flag<"-fno-access-control">, Group<f_Group>;
+def fno_access_control : Flag<"-fno-access-control">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable C++ access control">;
def fno_apple_pragma_pack : Flag<"-fno-apple-pragma-pack">, Group<f_Group>;
def fno_asm : Flag<"-fno-asm">, Group<f_Group>;
def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>;
-def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>;
+def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>,
+ HelpText<"Don't assume that C++'s global operator new can't alias any pointer">,
+ Flags<[CC1Option]>;
def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>;
def fno_borland_extensions : Flag<"-fno-borland-extensions">, Group<f_Group>;
def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>;
def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>;
-def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>;
-def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group<f_Group>;
+def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable implicit builtin knowledge of functions">;
+def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group<f_Group>,
+ Flags<[CC1Option]>;
def fno_color_diagnostics : Flag<"-fno-color-diagnostics">, Group<f_Group>;
-def fno_common : Flag<"-fno-common">, Group<f_Group>;
-def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group<f_Group>;
+def fno_common : Flag<"-fno-common">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Compile common globals like normal definitions">;
+def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Disable creation of CodeFoundation-type constant strings">;
def fno_cxx_exceptions: Flag<"-fno-cxx-exceptions">, Group<f_Group>;
def fno_cxx_modules : Flag <"-fno-cxx-modules">, Group<f_Group>, Flags<[NoForward]>;
-def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>;
+def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">;
+def fno_diagnostics_show_name : Flag<"-fno-diagnostics-show-name">, Group<f_Group>;
def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_Group>;
-def fno_diagnostics_show_note_include_stack : Flag<"-fno-diagnostics-show-note-include-stack">, Group<f_Group>;
-def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>;
-def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group<f_Group>;
+def fno_diagnostics_show_note_include_stack : Flag<"-fno-diagnostics-show-note-include-stack">,
+ Flags<[CC1Option]>, Group<f_Group>, HelpText<"Display include stacks for diagnostic notes">;
+def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>,
+ HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>;
+def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group<f_Group>,
+ HelpText<"Disable C++ copy constructor elision">, Flags<[CC1Option]>;
def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>;
def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>;
-def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>;
-def fno_inline_functions : Flag<"-fno-inline-functions">, Group<f_Group>;
-def fno_inline : Flag<"-fno-inline">, Group<f_Group>;
+def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>, Flags<[CC1Option]>;
+def fno_inline_functions : Flag<"-fno-inline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>;
+def fno_inline : Flag<"-fno-inline">, Group<f_clang_Group>, Flags<[CC1Option]>;
def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group<clang_ignored_f_Group>;
-def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group<f_Group>;
-def fno_limit_debug_info : Flag<"-fno-limit-debug-info">, Group<f_Group>,
+def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group<f_Group>,
+ HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>;
+def fno_limit_debug_info : Flag<"-fno-limit-debug-info">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Do not limit debug information produced to reduce size of debug binary">;
-def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>;
+def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Disallow merging of constants.">;
def fno_modules : Flag <"-fno-modules">, Group<f_Group>, Flags<[NoForward]>;
def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group<f_Group>;
def fno_ms_compatibility : Flag<"-fno-ms-compatibility">, Group<f_Group>;
@@ -435,44 +526,62 @@ def fno_delayed_template_parsing : Flag<"-fno-delayed-template-parsing">, Group<
def fno_objc_exceptions: Flag<"-fno-objc-exceptions">, Group<f_Group>;
def fno_objc_legacy_dispatch : Flag<"-fno-objc-legacy-dispatch">, Group<f_Group>;
def fno_omit_frame_pointer : Flag<"-fno-omit-frame-pointer">, Group<f_Group>;
-def fno_operator_names : Flag<"-fno-operator-names">, Group<f_Group>;
+def fno_operator_names : Flag<"-fno-operator-names">, Group<f_Group>,
+ HelpText<"Do not treat C++ operator name keywords as synonyms for operators">,
+ Flags<[CC1Option]>;
def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group<f_Group>;
-def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>;
+def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable generation of rtti information">;
def fno_short_enums : Flag<"-fno-short-enums">, Group<f_Group>;
-def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>;
-def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group>;
-def fno_spell_checking : Flag<"-fno-spell-checking">, Group<f_Group>;
+def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Do not include column number on diagnostics">;
+def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Do not include source location information with diagnostics">;
+def fno_spell_checking : Flag<"-fno-spell-checking">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable spell-checking">;
def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>;
def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<f_Group>;
def fno_strict_enums : Flag<"-fno-strict-enums">, Group<f_Group>;
def fno_strict_overflow : Flag<"-fno-strict-overflow">, Group<f_Group>;
-def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>;
-def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>;
+def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">;
+def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Don't use __cxa_atexit for calling destructors">;
def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>;
def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>;
def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group<f_Group>;
def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>;
def fno_wrapv : Flag<"-fno-wrapv">, Group<f_Group>;
def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>;
-def fobjc_arc : Flag<"-fobjc-arc">, Group<f_Group>;
+def fobjc_arc : Flag<"-fobjc-arc">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Synthesize retain and release calls for Objective-C pointers">;
def fno_objc_arc : Flag<"-fno-objc-arc">, Group<f_Group>;
-def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, Group<f_Group>;
+def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">;
def fno_objc_arc_exceptions : Flag<"-fno-objc-arc-exceptions">, Group<f_Group>;
def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>;
def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>;
-def fobjc_exceptions: Flag<"-fobjc-exceptions">, Group<f_Group>;
+def fobjc_exceptions: Flag<"-fobjc-exceptions">, Group<f_Group>,
+ HelpText<"Enable Objective-C exceptions">, Flags<[CC1Option]>;
-def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>;
-def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>;
+def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use GC exclusively for Objective-C related memory management">;
+def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable Objective-C garbage collection">;
def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group<f_Group>;
def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>;
def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">,
Group<f_Group>;
def fno_objc_infer_related_result_type : Flag<
- "-fno-objc-infer-related-result-type">, Group<f_Group>;
+ "-fno-objc-infer-related-result-type">, Group<f_Group>,
+ HelpText<
+ "do not infer Objective-C related result type based on method family">,
+ Flags<[CC1Option]>;
def fobjc_link_runtime: Flag<"-fobjc-link-runtime">, Group<f_Group>;
// Objective-C ABI options.
+def fobjc_runtime_EQ : Joined<"-fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Specify the target Objective-C runtime kind and version">;
def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>;
def fobjc_nonfragile_abi_version_EQ : Joined<"-fobjc-nonfragile-abi-version=">, Group<f_Group>;
def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, Group<f_Group>;
@@ -490,8 +599,10 @@ def force__load : Separate<"-force_load">;
def foutput_class_dir_EQ : Joined<"-foutput-class-dir=">, Group<f_Group>;
def fpack_struct : Flag<"-fpack-struct">, Group<f_Group>;
def fno_pack_struct : Flag<"-fno-pack-struct">, Group<f_Group>;
-def fpack_struct_EQ : Joined<"-fpack-struct=">, Group<f_Group>;
-def fpascal_strings : Flag<"-fpascal-strings">, Group<f_Group>;
+def fpack_struct_EQ : Joined<"-fpack-struct=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Specify the default maximum struct packing alignment">;
+def fpascal_strings : Flag<"-fpascal-strings">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Recognize and construct Pascal-style string literals">;
def fpch_preprocess : Flag<"-fpch-preprocess">, Group<f_Group>;
def fpic : Flag<"-fpic">, Group<f_Group>;
def fno_pic : Flag<"-fno-pic">, Group<f_Group>;
@@ -503,11 +614,15 @@ def framework : Separate<"-framework">, Flags<[LinkerInput]>;
def frandom_seed_EQ : Joined<"-frandom-seed=">, Group<clang_ignored_f_Group>;
def frtti : Flag<"-frtti">, Group<f_Group>;
def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>;
-def fshort_enums : Flag<"-fshort-enums">, Group<f_Group>;
+def fshort_enums : Flag<"-fshort-enums">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">;
def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>;
-def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>;
-def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group<f_Group>;
-def fshow_column : Flag<"-fshow-column">, Group<f_Group>;
+def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Force wchar_t to be a short unsigned int">;
+def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Which overload candidates to show when overload resolution fails: "
+ "best|all; defaults to all">;
+def fshow_column : Flag<"-fshow-column">, Group<f_Group>, Flags<[CC1Option]>;
def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>;
def fspell_checking : Flag<"-fspell-checking">, Group<f_Group>;
def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>;
@@ -515,17 +630,21 @@ def fsigned_char : Flag<"-fsigned-char">, Group<f_Group>;
def fstack_protector_all : Flag<"-fstack-protector-all">, Group<f_Group>;
def fstack_protector : Flag<"-fstack-protector">, Group<f_Group>;
def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<f_Group>;
-def fstrict_enums : Flag<"-fstrict-enums">, Group<f_Group>;
+def fstrict_enums : Flag<"-fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable optimizations based on the strict definition of an enum's "
+ "value range.">;
def fstrict_overflow : Flag<"-fstrict-overflow">, Group<f_Group>;
-def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>;
+def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>;
def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>;
def ftemplate_depth_EQ : Joined<"-ftemplate-depth=">, Group<f_Group>;
def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>;
def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">,
Group<f_Group>;
def ftest_coverage : Flag<"-ftest-coverage">, Group<f_Group>;
-def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">;
-def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">;
+def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">,
+ HelpText<"Warn if a function definition returns or accepts an object larger "
+ "in bytes that a given value">;
+def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">, Flags<[CC1Option]>;
// Just silence warnings about -Wlarger-than, -Wframe-larger-than for now.
def Wlarger_than : Separate<"-Wlarger-than">, Group<clang_ignored_f_Group>;
@@ -536,68 +655,116 @@ def Wframe_larger_than_EQ : Joined<"-Wframe-larger-than=">, Alias<Wframe_larger_
def fterminated_vtables : Flag<"-fterminated-vtables">, Alias<fapple_kext>;
def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>;
-def ftime_report : Flag<"-ftime-report">, Group<f_Group>;
-def ftrapv : Flag<"-ftrapv">, Group<f_Group>;
-def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group<f_Group>;
-def ftrap_function_EQ : Joined<"-ftrap-function=">, Group<f_Group>,
+def ftime_report : Flag<"-ftime-report">, Group<f_Group>, Flags<[CC1Option]>;
+def ftlsmodel_EQ : Joined<"-ftls-model=">, Group<f_Group>, Flags<[CC1Option]>;
+def ftrapv : Flag<"-ftrapv">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Trap on integer overflow">;
+def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group<f_Group>,
+ MetaVarName<"<function name>">,
+ HelpText<"Specify the function to be called on overflow.">;
+def ftrapv_handler : Separate<"-ftrapv-handler">, Group<f_Group>, Flags<[CC1Option]>;
+def ftrap_function_EQ : Joined<"-ftrap-function=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Issue call to specified function rather than a trap instruction">;
def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>;
-def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>;
+def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>,
+ HelpText<"Turn on loop unroller">, Flags<[CC1Option]>;
def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>;
def funsigned_char : Flag<"-funsigned-char">, Group<f_Group>;
def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>;
def fuse_cxa_atexit : Flag<"-fuse-cxa-atexit">, Group<f_Group>;
def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>;
def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>;
-def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, Group<f_Group>;
-def fwrapv : Flag<"-fwrapv">, Group<f_Group>;
-def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>;
+def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, Group<f_Group>,
+ HelpText<"Give inline C++ member functions default visibility by default">,
+ Flags<[CC1Option]>;
+def fwrapv : Flag<"-fwrapv">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Treat signed integer overflow as two's complement">;
+def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Store string literals as writable data">;
def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group<f_Group>;
-def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>;
-def fdata_sections : Flag <"-fdata-sections">, Group<f_Group>;
+def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Place each function in its own section (ELF Only)">;
+def fdata_sections : Flag <"-fdata-sections">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Place each data in its own section (ELF Only)">;
def f : Joined<"-f">, Group<f_Group>;
+def g_Flag : Flag<"-g">, Group<g_Group>,
+ HelpText<"Generate source level debug information">, Flags<[CC1Option]>;
+def gline_tables_only : Flag<"-gline-tables-only">, Group<g_Group>,
+ HelpText<"Emit debug line number tables only">, Flags<[CC1Option]>;
def g0 : Flag<"-g0">, Group<g_Group>;
+def g1 : Flag<"-g1">, Group<g_Group>;
def g2 : Flag<"-g2">, Group<g_Group>;
def g3 : Flag<"-g3">, Group<g_Group>;
-def gdwarf2 : Flag<"-gdwarf-2">, Group<g_Group>;
-def gfull : Flag<"-gfull">, Group<g_Group>;
def ggdb : Flag<"-ggdb">, Group<g_Group>;
-def gstabs : Flag<"-gstabs">, Group<g_Group>;
-def gstabsplus : Flag<"-gstabs+">, Group<g_Group>;
-def gstabs1 : Flag<"-gstabs1">, Group<g_Group>;
-def gstabs2 : Flag<"-gstabs2">, Group<g_Group>;
+def ggdb0 : Flag<"-ggdb0">, Group<g_Group>;
+def ggdb1 : Flag<"-ggdb1">, Group<g_Group>;
+def ggdb2 : Flag<"-ggdb2">, Group<g_Group>;
+def ggdb3 : Flag<"-ggdb3">, Group<g_Group>;
+def gdwarf_2 : Flag<"-gdwarf-2">, Group<g_Group>;
+def gdwarf_3 : Flag<"-gdwarf-3">, Group<g_Group>;
+def gdwarf_4 : Flag<"-gdwarf-4">, Group<g_Group>;
+def gfull : Flag<"-gfull">, Group<g_Group>;
def gused : Flag<"-gused">, Group<g_Group>;
-def g_Flag : Flag<"-g">, Group<g_Group>;
+def gstabs : Joined<"-gstabs">, Group<g_Group>, Flags<[Unsupported]>;
+def gcoff : Joined<"-gcoff">, Group<g_Group>, Flags<[Unsupported]>;
+def gxcoff : Joined<"-gxcoff">, Group<g_Group>, Flags<[Unsupported]>;
+def gvms : Joined<"-gvms">, Group<g_Group>, Flags<[Unsupported]>;
+def gtoggle : Flag<"-gtoggle">, Group<g_flags_Group>, Flags<[Unsupported]>;
+def grecord_gcc_switches : Flag<"-grecord-gcc-switches">, Group<g_flags_Group>;
+def gno_record_gcc_switches : Flag<"-gno-record-gcc-switches">,
+ Group<g_flags_Group>;
+def gstrict_dwarf : Flag<"-gstrict-dwarf">, Group<g_flags_Group>;
+def gno_strict_dwarf : Flag<"-gno-strict-dwarf">, Group<g_flags_Group>;
def headerpad__max__install__names : Joined<"-headerpad_max_install_names">;
-def index_header_map : Flag<"-index-header-map">;
-def idirafter : JoinedOrSeparate<"-idirafter">, Group<clang_i_Group>;
-def iframework : Joined<"-iframework">, Group<clang_i_Group>;
-def imacros : JoinedOrSeparate<"-imacros">, Group<clang_i_Group>;
+def help : Flag<"-help">, Flags<[CC1Option]>,
+ HelpText<"Display available options">;
+def index_header_map : Flag<"-index-header-map">, Flags<[CC1Option]>,
+ HelpText<"Make the next included directory (-I or -F) an indexer header map">;
+def idirafter : JoinedOrSeparate<"-idirafter">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Add directory to AFTER include search path">;
+def iframework : Joined<"-iframework">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Add directory to SYSTEM framework search path">;
+def imacros : JoinedOrSeparate<"-imacros">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Include macros from file before parsing">, MetaVarName<"<file>">;
def image__base : Separate<"-image_base">;
-def include_ : JoinedOrSeparate<"-include">, Group<clang_i_Group>, EnumName<"include">;
-def include_pch : Separate<"-include-pch">, Group<clang_i_Group>;
+def include_ : JoinedOrSeparate<"-include">, Group<clang_i_Group>, EnumName<"include">,
+ MetaVarName<"<file>">, HelpText<"Include file before parsing">, Flags<[CC1Option]>;
+def include_pch : Separate<"-include-pch">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Include precompiled header file">, MetaVarName<"<file>">;
def init : Separate<"-init">;
def install__name : Separate<"-install_name">;
def integrated_as : Flag<"-integrated-as">, Flags<[DriverOption]>;
-def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>;
-def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>;
-def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>;
-def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>;
-def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>;
-def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>;
-def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<clang_i_Group>;
+def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">, MetaVarName<"<dir>">;
+def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Add directory to QUOTE include search path">, MetaVarName<"<directory>">;
+def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Set the system root directory (usually /)">, MetaVarName<"<dir>">;
+def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Add directory to SYSTEM include search path">, MetaVarName<"<directory>">;
+def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>,
+ HelpText<"Set directory to include search path with prefix">, MetaVarName<"<dir>">,
+ Flags<[CC1Option]>;
+def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Set directory to SYSTEM include search path with prefix">, MetaVarName<"<dir>">;
+def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<clang_i_Group>,
+ HelpText<"Add directory to SYSTEM include search path, "
+ "absolute paths are relative to -isysroot">, MetaVarName<"<directory>">,
+ Flags<[CC1Option]>;
def i : Joined<"-i">, Group<i_Group>;
def keep__private__externs : Flag<"-keep_private_externs">;
def l : JoinedOrSeparate<"-l">, Flags<[LinkerInput, RenderJoined]>;
def lazy__framework : Separate<"-lazy_framework">, Flags<[LinkerInput]>;
def lazy__library : Separate<"-lazy_library">, Flags<[LinkerInput]>;
def m32 : Flag<"-m32">, Group<m_Group>, Flags<[DriverOption]>;
-def mqdsp6_compat : Flag<"-mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption]>;
+def mqdsp6_compat : Flag<"-mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption,CC1Option]>,
+ HelpText<"Enable hexagon-qdsp6 backward compatibility">;
def m3dnowa : Flag<"-m3dnowa">, Group<m_x86_Features_Group>;
def m3dnow : Flag<"-m3dnow">, Group<m_x86_Features_Group>;
def m64 : Flag<"-m64">, Group<m_Group>, Flags<[DriverOption]>;
def mabi_EQ : Joined<"-mabi=">, Group<m_Group>;
def march_EQ : Joined<"-march=">, Group<m_Group>;
+def maltivec : Flag<"-maltivec">, Alias<faltivec>;
def mcmodel_EQ : Joined<"-mcmodel=">, Group<m_Group>;
def mconstant_cfstrings : Flag<"-mconstant-cfstrings">, Group<clang_ignored_m_Group>;
def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>;
@@ -613,16 +780,21 @@ def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias<miphoneos_version_
def mios_simulator_version_min_EQ : Joined<"-mios-simulator-version-min=">, Group<m_Group>;
def mkernel : Flag<"-mkernel">, Group<m_Group>;
def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>;
-def mllvm : Separate<"-mllvm">;
+def mllvm : Separate<"-mllvm">, Flags<[CC1Option]>,
+ HelpText<"Additional arguments to forward to LLVM's option processing">;
def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>;
-def mms_bitfields : Flag<"-mms-bitfields">, Group<m_Group>;
-def mstackrealign : Flag<"-mstackrealign">, Group<m_Group>;
-def mstack_alignment : Joined<"-mstack-alignment=">, Group<m_Group>;
+def mms_bitfields : Flag<"-mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">;
+def mstackrealign : Flag<"-mstackrealign">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Force realign the stack at entry to every function.">;
+def mstack_alignment : Joined<"-mstack-alignment=">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Set the stack alignment">;
def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>;
def mno_3dnowa : Flag<"-mno-3dnowa">, Group<m_x86_Features_Group>;
def mno_3dnow : Flag<"-mno-3dnow">, Group<m_x86_Features_Group>;
def mno_constant_cfstrings : Flag<"-mno-constant-cfstrings">, Group<m_Group>;
-def mno_global_merge : Flag<"-mno-global-merge">, Group<m_Group>;
+def mno_global_merge : Flag<"-mno-global-merge">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable merging of globals">;
def mno_mmx : Flag<"-mno-mmx">, Group<m_x86_Features_Group>;
def mno_pascal_strings : Flag<"-mno-pascal-strings">, Group<m_Group>;
def mno_red_zone : Flag<"-mno-red-zone">, Group<m_Group>;
@@ -641,25 +813,35 @@ def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>;
def mno_aes : Flag<"-mno-aes">, Group<m_x86_Features_Group>;
def mno_avx : Flag<"-mno-avx">, Group<m_x86_Features_Group>;
def mno_avx2 : Flag<"-mno-avx2">, Group<m_x86_Features_Group>;
+def mno_pclmul : Flag<"-mno-pclmul">, Group<m_x86_Features_Group>;
def mno_lzcnt : Flag<"-mno-lzcnt">, Group<m_x86_Features_Group>;
+def mno_rdrnd : Flag<"-mno-rdrnd">, Group<m_x86_Features_Group>;
def mno_bmi : Flag<"-mno-bmi">, Group<m_x86_Features_Group>;
def mno_bmi2 : Flag<"-mno-bmi2">, Group<m_x86_Features_Group>;
def mno_popcnt : Flag<"-mno-popcnt">, Group<m_x86_Features_Group>;
def mno_fma4 : Flag<"-mno-fma4">, Group<m_x86_Features_Group>;
+def mno_fma : Flag<"-mno-fma">, Group<m_x86_Features_Group>;
+def mno_xop : Flag<"-mno-xop">, Group<m_x86_Features_Group>;
def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>;
def marm : Flag<"-marm">, Alias<mno_thumb>;
def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group<m_Group>;
def mno_omit_leaf_frame_pointer : Flag<"-mno-omit-leaf-frame-pointer">, Group<f_Group>;
-def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, Group<f_Group>;
+def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, Group<f_Group>,
+ HelpText<"Omit frame pointer setup for leaf functions.">, Flags<[CC1Option]>;
def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>;
def mred_zone : Flag<"-mred-zone">, Group<m_Group>;
def mregparm_EQ : Joined<"-mregparm=">, Group<m_Group>;
-def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>;
-def mrtd: Flag<"-mrtd">, Group<m_Group>;
+def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"(integrated-as) Relax all machine instructions">;
+def mrtd : Flag<"-mrtd">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Make StdCall calling convention the default">;
def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group<m_Group>;
-def msoft_float : Flag<"-msoft-float">, Group<m_Group>;
+def msoft_float : Flag<"-msoft-float">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Use software floating point">;
+def mno_implicit_float : Flag<"-mno-implicit-float">, Group<m_Group>,
+ HelpText<"Don't generate implicit floating point instructions">;
def msse2 : Flag<"-msse2">, Group<m_x86_Features_Group>;
def msse3 : Flag<"-msse3">, Group<m_x86_Features_Group>;
def msse4a : Flag<"-msse4a">, Group<m_x86_Features_Group>;
@@ -671,11 +853,21 @@ def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>;
def maes : Flag<"-maes">, Group<m_x86_Features_Group>;
def mavx : Flag<"-mavx">, Group<m_x86_Features_Group>;
def mavx2 : Flag<"-mavx2">, Group<m_x86_Features_Group>;
+def mpclmul : Flag<"-mpclmul">, Group<m_x86_Features_Group>;
def mlzcnt : Flag<"-mlzcnt">, Group<m_x86_Features_Group>;
+def mrdrnd : Flag<"-mrdrnd">, Group<m_x86_Features_Group>;
def mbmi : Flag<"-mbmi">, Group<m_x86_Features_Group>;
def mbmi2 : Flag<"-mbmi2">, Group<m_x86_Features_Group>;
def mpopcnt : Flag<"-mpopcnt">, Group<m_x86_Features_Group>;
def mfma4 : Flag<"-mfma4">, Group<m_x86_Features_Group>;
+def mfma : Flag<"-mfma">, Group<m_x86_Features_Group>;
+def mxop : Flag<"-mxop">, Group<m_x86_Features_Group>;
+def mips16 : Flag<"-mips16">, Group<m_Group>;
+def mno_mips16 : Flag<"-mno-mips16">, Group<m_Group>;
+def mdsp : Flag<"-mdsp">, Group<m_Group>;
+def mno_dsp : Flag<"-mno-dsp">, Group<m_Group>;
+def mdspr2 : Flag<"-mdspr2">, Group<m_Group>;
+def mno_dspr2 : Flag<"-mno-dspr2">, Group<m_Group>;
def mthumb : Flag<"-mthumb">, Group<m_Group>;
def mtune_EQ : Joined<"-mtune=">, Group<m_Group>;
def multi__module : Flag<"-multi_module">;
@@ -689,8 +881,10 @@ def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[HelpHidden]>,
def no_cpp_precomp : Flag<"-no-cpp-precomp">, Group<clang_ignored_f_Group>;
def no_integrated_as : Flag<"-no-integrated-as">, Flags<[DriverOption]>;
def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>;
+def no_pedantic : Flag<"-no-pedantic">, Group<pedantic_Group>;
def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">;
-def nobuiltininc : Flag<"-nobuiltininc">;
+def nobuiltininc : Flag<"-nobuiltininc">, Flags<[CC1Option]>,
+ HelpText<"Disable builtin #include directories">;
def nodefaultlibs : Flag<"-nodefaultlibs">;
def nofixprebinding : Flag<"-nofixprebinding">;
def nolibc : Flag<"-nolibc">;
@@ -700,16 +894,17 @@ def noseglinkedit : Flag<"-noseglinkedit">;
def nostartfiles : Flag<"-nostartfiles">;
def nostdinc : Flag<"-nostdinc">;
def nostdlibinc : Flag<"-nostdlibinc">;
-def nostdincxx : Flag<"-nostdinc++">;
+def nostdincxx : Flag<"-nostdinc++">, Flags<[CC1Option]>,
+ HelpText<"Disable standard #include directories for the C++ standard library">;
def nostdlib : Flag<"-nostdlib">;
def object : Flag<"-object">;
-def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput]>,
+def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput, CC1Option]>,
HelpText<"Write output to <file>">, MetaVarName<"<file>">;
def pagezero__size : JoinedOrSeparate<"-pagezero_size">;
def pass_exit_codes : Flag<"-pass-exit-codes">, Flags<[Unsupported]>;
-def pedantic_errors : Flag<"-pedantic-errors">, Group<pedantic_Group>;
-def pedantic : Flag<"-pedantic">, Group<pedantic_Group>;
-def pg : Flag<"-pg">;
+def pedantic_errors : Flag<"-pedantic-errors">, Group<pedantic_Group>, Flags<[CC1Option]>;
+def pedantic : Flag<"-pedantic">, Group<pedantic_Group>, Flags<[CC1Option]>;
+def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">, Flags<[CC1Option]>;
def pipe : Flag<"-pipe">,
HelpText<"Use pipes between commands, when possible">;
def prebind__all__twolevel__modules : Flag<"-prebind_all_twolevel_modules">;
@@ -717,7 +912,8 @@ def prebind : Flag<"-prebind">;
def preload : Flag<"-preload">;
def print_file_name_EQ : Joined<"-print-file-name=">,
HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">;
-def print_ivar_layout : Flag<"-print-ivar-layout">;
+def print_ivar_layout : Flag<"-print-ivar-layout">, Flags<[CC1Option]>,
+ HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
def print_libgcc_file_name : Flag<"-print-libgcc-file-name">,
HelpText<"Print the library path for \"libgcc.a\"">;
def print_multi_directory : Flag<"-print-multi-directory">;
@@ -729,13 +925,14 @@ def print_search_dirs : Flag<"-print-search-dirs">,
HelpText<"Print the paths used for finding libraries and programs">;
def private__bundle : Flag<"-private_bundle">;
def pthreads : Flag<"-pthreads">;
-def pthread : Flag<"-pthread">;
+def pthread : Flag<"-pthread">, Flags<[CC1Option]>,
+ HelpText<"Support POSIX threads in generated code">;
def p : Flag<"-p">;
def pie : Flag<"-pie">;
def read__only__relocs : Separate<"-read_only_relocs">;
def remap : Flag<"-remap">;
-def rewrite_objc : Flag<"-rewrite-objc">, Flags<[DriverOption]>,
- HelpText<"Rewrite Objective-C source to C++">;
+def rewrite_objc : Flag<"-rewrite-objc">, Flags<[DriverOption,CC1Option]>,
+ HelpText<"Rewrite Objective-C source to C++">, Group<Action_Group>;
def rewrite_legacy_objc : Flag<"-rewrite-legacy-objc">, Flags<[DriverOption]>,
HelpText<"Rewrite Legacy Objective-C source to C++">;
def rdynamic : Flag<"-rdynamic">;
@@ -767,8 +964,10 @@ def static_libgcc : Flag<"-static-libgcc">;
def static_libstdcxx : Flag<"-static-libstdc++">;
def static : Flag<"-static">, Flags<[NoArgumentUnused]>;
def std_default_EQ : Joined<"-std-default=">;
-def std_EQ : Joined<"-std=">, Group<L_Group>;
-def stdlib_EQ : Joined<"-stdlib=">;
+def std_EQ : Joined<"-std=">, Flags<[CC1Option]>, Group<L_Group>,
+ HelpText<"Language standard to compile for">;
+def stdlib_EQ : Joined<"-stdlib=">, Flags<[CC1Option]>,
+ HelpText<"C++ standard library to use">;
def sub__library : JoinedOrSeparate<"-sub_library">;
def sub__umbrella : JoinedOrSeparate<"-sub_umbrella">;
def s : Flag<"-s">;
@@ -780,21 +979,24 @@ def gcc_toolchain : Separate<"-gcc-toolchain">, Flags<[DriverOption]>,
def ccc_host_triple : Separate<"-ccc-host-triple">, Alias<target>;
def time : Flag<"-time">,
HelpText<"Time individual commands">;
-def traditional_cpp : Flag<"-traditional-cpp">;
+def traditional_cpp : Flag<"-traditional-cpp">, Flags<[CC1Option]>,
+ HelpText<"Enable some traditional CPP emulation">;
def traditional : Flag<"-traditional">;
-def trigraphs : Flag<"-trigraphs">;
+def trigraphs : Flag<"-trigraphs">, Flags<[CC1Option]>,
+ HelpText<"Process trigraph sequences">;
def twolevel__namespace__hints : Flag<"-twolevel_namespace_hints">;
def twolevel__namespace : Flag<"-twolevel_namespace">;
def t : Flag<"-t">;
def umbrella : Separate<"-umbrella">;
def undefined : JoinedOrSeparate<"-undefined">, Group<u_Group>;
-def undef : Flag<"-undef">, Group<u_Group>;
+def undef : Flag<"-undef">, Group<u_Group>, Flags<[CC1Option]>,
+ HelpText<"undef all system defines">;
def unexported__symbols__list : Separate<"-unexported_symbols_list">;
def u : JoinedOrSeparate<"-u">, Group<u_Group>;
def use_gold_plugin : Flag<"-use-gold-plugin">;
-def v : Flag<"-v">,
+def v : Flag<"-v">, Flags<[CC1Option]>,
HelpText<"Show commands to run and use verbose output">;
-def verify : Flag<"-verify">, Flags<[DriverOption]>,
+def verify : Flag<"-verify">, Flags<[DriverOption,CC1Option]>,
HelpText<"Verify output using a verifier.">;
def weak_l : Joined<"-weak-l">, Flags<[LinkerInput]>;
def weak__framework : Separate<"-weak_framework">, Flags<[LinkerInput]>;
@@ -802,15 +1004,15 @@ def weak__library : Separate<"-weak_library">, Flags<[LinkerInput]>;
def weak__reference__mismatches : Separate<"-weak_reference_mismatches">;
def whatsloaded : Flag<"-whatsloaded">;
def whyload : Flag<"-whyload">;
-def w : Flag<"-w">;
-def x : JoinedOrSeparate<"-x">, Flags<[DriverOption]>,
+def w : Flag<"-w">, HelpText<"Suppress all warnings.">, Flags<[CC1Option]>;
+def x : JoinedOrSeparate<"-x">, Flags<[DriverOption,CC1Option]>,
HelpText<"Treat subsequent input files as having type <language>">,
MetaVarName<"<language>">;
def y : Joined<"-y">;
-def working_directory : Separate<"-working-directory">,
+def working_directory : JoinedOrSeparate<"-working-directory">, Flags<[CC1Option]>,
HelpText<"Resolve file paths relative to the specified directory">;
-def working_directory_EQ : Joined<"-working-directory=">,
+def working_directory_EQ : Joined<"-working-directory=">, Flags<[CC1Option]>,
Alias<working_directory>;
// Double dash options, which are usually an alias for one of the previous
@@ -854,8 +1056,7 @@ def _for_linker : Separate<"--for-linker">, Alias<Xlinker>;
def _force_link_EQ : Joined<"--force-link=">, Alias<u>;
def _force_link : Separate<"--force-link">, Alias<u>;
def _help_hidden : Flag<"--help-hidden">;
-def _help : Flag<"--help">,
- HelpText<"Display available options">;
+def _help : Flag<"--help">, Alias<help>;
def _imacros_EQ : Joined<"--imacros=">, Alias<imacros>;
def _imacros : Separate<"--imacros">, Alias<imacros>;
def _include_barrier : Flag<"--include-barrier">, Alias<I_>;
@@ -883,6 +1084,7 @@ def _machine_EQ : Joined<"--machine=">, Alias<m_Joined>;
def _machine : Separate<"--machine">, Alias<m_Joined>;
def _no_integrated_cpp : Flag<"--no-integrated-cpp">, Alias<no_integrated_cpp>;
def _no_line_commands : Flag<"--no-line-commands">, Alias<P>;
+def _no_pedantic : Flag<"--no-pedantic">, Alias<no_pedantic>;
def _no_standard_includes : Flag<"--no-standard-includes">, Alias<nostdinc>;
def _no_standard_libraries : Flag<"--no-standard-libraries">, Alias<nostdlib>;
def _no_undefined : Flag<"--no-undefined">, Flags<[LinkerInput]>;
@@ -945,12 +1147,14 @@ def _undefine_macro : Separate<"--undefine-macro">, Alias<U>;
def _unsigned_char : Flag<"--unsigned-char">, Alias<funsigned_char>;
def _user_dependencies : Flag<"--user-dependencies">, Alias<MM>;
def _verbose : Flag<"--verbose">, Alias<v>;
-def _version : Flag<"--version">;
+def _version : Flag<"--version">, Flags<[CC1Option]>;
def _warn__EQ : Joined<"--warn-=">, Alias<W_Joined>;
def _warn_ : Joined<"--warn-">, Alias<W_Joined>;
def _write_dependencies : Flag<"--write-dependencies">, Alias<MD>;
def _write_user_dependencies : Flag<"--write-user-dependencies">, Alias<MMD>;
def _ : Joined<"--">, Flags<[Unsupported]>;
+def mieee_rnd_near : Flag<"-mieee-rnd-near">, Group<m_hexagon_Features_Group>;
+def serialize_diags : Separate<"-serialize-diagnostics">, Alias<_serialize_diags>;
// Special internal option to handle -Xlinker --no-demangle.
def Z_Xlinker__no_demangle : Flag<"-Z-Xlinker-no-demangle">,
@@ -965,3 +1169,5 @@ def Z_reserved_lib_stdcxx : Flag<"-Z-reserved-lib-stdc++">,
Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>;
def Z_reserved_lib_cckext : Flag<"-Z-reserved-lib-cckext">,
Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>;
+
+include "CC1Options.td"
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index c35cf673dee4..ab417bb577cb 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -18,6 +18,8 @@
#include <string>
namespace clang {
+ class ObjCRuntime;
+
namespace driver {
class ArgList;
class Compilation;
@@ -25,7 +27,6 @@ namespace driver {
class Driver;
class InputArgList;
class JobAction;
- class ObjCRuntime;
class Tool;
/// ToolChain - Access to tools for a single platform.
@@ -137,6 +138,9 @@ public:
/// default.
virtual bool IsStrictAliasingDefault() const { return true; }
+ /// IsMathErrnoDefault - Does this tool chain use -fmath-errno by default.
+ virtual bool IsMathErrnoDefault() const { return true; }
+
/// IsObjCDefaultSynthPropertiesDefault - Does this tool chain enable
/// -fobjc-default-synthesize-properties by default.
virtual bool IsObjCDefaultSynthPropertiesDefault() const { return false; }
@@ -145,11 +149,6 @@ public:
/// -fobjc-nonfragile-abi by default.
virtual bool IsObjCNonFragileABIDefault() const { return false; }
- /// IsObjCLegacyDispatchDefault - Does this tool chain set
- /// -fobjc-legacy-dispatch by default (this is only used with the non-fragile
- /// ABI).
- virtual bool IsObjCLegacyDispatchDefault() const { return true; }
-
/// UseObjCMixedDispatchDefault - When using non-legacy dispatch, should the
/// mixed dispatch method be used?
virtual bool UseObjCMixedDispatch() const { return false; }
@@ -207,11 +206,11 @@ public:
virtual std::string ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType = types::TY_INVALID) const;
- /// configureObjCRuntime - Configure the known properties of the
- /// Objective-C runtime for this platform.
+ /// getDefaultObjCRuntime - Return the default Objective-C runtime
+ /// for this platform.
///
/// FIXME: this really belongs on some sort of DeploymentTarget abstraction
- virtual void configureObjCRuntime(ObjCRuntime &runtime) const;
+ virtual ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const;
/// hasBlocksRuntime - Given that the user is compiling with
/// -fblocks, does this tool chain guarantee the existence of a
@@ -227,6 +226,10 @@ public:
virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
+ // addClangTargetOptions - Add options that need to be passed to cc1 for
+ // this target.
+ virtual void addClangTargetOptions(ArgStringList &CC1Args) const;
+
// GetRuntimeLibType - Determine the runtime library type to use with the
// given compilation arguments.
virtual RuntimeLibType GetRuntimeLibType(const ArgList &Args) const;
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index b107dfb247b1..318c55ad6366 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -40,17 +40,17 @@
// C family source language (with and without preprocessing).
TYPE("cpp-output", PP_C, INVALID, "i", "u")
-TYPE("c", C, PP_C, 0, "u")
-TYPE("cl", CL, PP_C, 0, "u")
-TYPE("cuda", CUDA, PP_CXX, 0, "u")
+TYPE("c", C, PP_C, "c", "u")
+TYPE("cl", CL, PP_C, "cl", "u")
+TYPE("cuda", CUDA, PP_CXX, "cpp", "u")
TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", "u")
-TYPE("objective-c", ObjC, PP_ObjC, 0, "u")
+TYPE("objective-c", ObjC, PP_ObjC, "m", "u")
TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", "u")
-TYPE("c++", CXX, PP_CXX, 0, "u")
+TYPE("c++", CXX, PP_CXX, "cpp", "u")
TYPE("objective-c++-cpp-output", PP_ObjCXX, INVALID, "mii", "u")
TYPE("objc++-cpp-output", PP_ObjCXX_Alias, INVALID, "mii", "u")
-TYPE("objective-c++", ObjCXX, PP_ObjCXX, 0, "u")
+TYPE("objective-c++", ObjCXX, PP_ObjCXX, "mm", "u")
// C family input files to precompile.
TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", "p")
diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h
index 9187529833ac..3dea471cca42 100644
--- a/include/clang/Driver/Types.h
+++ b/include/clang/Driver/Types.h
@@ -23,7 +23,7 @@ namespace types {
TY_LAST
};
- /// getTypeName - Return the name of the type for \arg Id.
+ /// getTypeName - Return the name of the type for \p Id.
const char *getTypeName(ID Id);
/// getPreprocessedType - Get the ID of the type for this input when
@@ -70,7 +70,7 @@ namespace types {
bool isObjC(ID Id);
/// lookupTypeForExtension - Lookup the type to use for the file
- /// extension \arg Ext.
+ /// extension \p Ext.
ID lookupTypeForExtension(const char *Ext);
/// lookupTypeForTypSpecifier - Lookup the type to use for a user
@@ -81,7 +81,7 @@ namespace types {
/// to be done for this type.
unsigned getNumCompilationPhases(ID Id);
- /// getCompilationPhase - Return the \args N th compilation phase to
+ /// getCompilationPhase - Return the \p N th compilation phase to
/// be done for this type.
phases::ID getCompilationPhase(ID Id, unsigned N);
diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
index cef9509a9793..3731478403ef 100644
--- a/include/clang/Frontend/ASTConsumers.h
+++ b/include/clang/Frontend/ASTConsumers.h
@@ -33,11 +33,15 @@ class TargetOptions;
// original C code. The output is intended to be in a format such that
// clang could re-parse the output back into the same AST, but the
// implementation is still incomplete.
-ASTConsumer *CreateASTPrinter(raw_ostream *OS);
+ASTConsumer *CreateASTPrinter(raw_ostream *OS, StringRef FilterString);
// AST dumper: dumps the raw AST in human-readable form to stderr; this is
// intended for debugging.
-ASTConsumer *CreateASTDumper();
+ASTConsumer *CreateASTDumper(StringRef FilterString);
+
+// AST Decl node lister: prints qualified names of all filterable AST Decl
+// nodes.
+ASTConsumer *CreateASTDeclNodeLister();
// AST XML-dumper: dumps out the AST to stderr in a very detailed XML
// format; this is intended for particularly intense debugging.
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 041eabb5b992..144b79642d5c 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -19,6 +19,7 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
@@ -248,7 +249,15 @@ private:
std::vector<serialization::DeclID> TopLevelDeclsInPreamble;
/// \brief Whether we should be caching code-completion results.
- bool ShouldCacheCodeCompletionResults;
+ bool ShouldCacheCodeCompletionResults : 1;
+
+ /// \brief Whether to include brief documentation within the set of code
+ /// completions cached.
+ bool IncludeBriefCommentsInCodeCompletion : 1;
+
+ /// \brief True if non-system source files should be treated as volatile
+ /// (likely to change while trying to use them).
+ bool UserFilesAreVolatile : 1;
/// \brief The language options used when we load an AST file.
LangOptions ASTFileLangOpts;
@@ -275,12 +284,11 @@ public:
/// \brief A bitmask that indicates which code-completion contexts should
/// contain this completion result.
///
- /// The bits in the bitmask correspond to the values of
- /// CodeCompleteContext::Kind. To map from a completion context kind to a
- /// bit, subtract one from the completion context kind and shift 1 by that
- /// number of bits. Many completions can occur in several different
- /// contexts.
- unsigned ShowInContexts;
+ /// The bits in the bitmask correspond to the values of
+ /// CodeCompleteContext::Kind. To map from a completion context kind to a
+ /// bit, shift 1 by that number of bits. Many completions can occur in
+ /// several different contexts.
+ uint64_t ShowInContexts;
/// \brief The priority given to this code-completion result.
unsigned Priority;
@@ -396,7 +404,9 @@ private:
/// just about any usage.
/// Becomes a noop in release mode; only useful for debug mode checking.
class ConcurrencyState {
+#ifndef NDEBUG
void *Mutex; // a llvm::sys::MutexImpl in debug;
+#endif
public:
ConcurrencyState();
@@ -612,7 +622,8 @@ public:
/// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation.
static ASTUnit *create(CompilerInvocation *CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- bool CaptureDiagnostics = false);
+ bool CaptureDiagnostics,
+ bool UserFilesAreVolatile);
/// \brief Create a ASTUnit from an AST file.
///
@@ -629,7 +640,8 @@ public:
RemappedFile *RemappedFiles = 0,
unsigned NumRemappedFiles = 0,
bool CaptureDiagnostics = false,
- bool AllowPCHWithCompilerErrors = false);
+ bool AllowPCHWithCompilerErrors = false,
+ bool UserFilesAreVolatile = false);
private:
/// \brief Helper function for \c LoadFromCompilerInvocation() and
@@ -679,6 +691,8 @@ public:
bool CaptureDiagnostics = false,
bool PrecompilePreamble = false,
bool CacheCodeCompletionResults = false,
+ bool IncludeBriefCommentsInCodeCompletion = false,
+ bool UserFilesAreVolatile = false,
OwningPtr<ASTUnit> *ErrAST = 0);
/// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
@@ -698,7 +712,9 @@ public:
bool CaptureDiagnostics = false,
bool PrecompilePreamble = false,
TranslationUnitKind TUKind = TU_Complete,
- bool CacheCodeCompletionResults = false);
+ bool CacheCodeCompletionResults = false,
+ bool IncludeBriefCommentsInCodeCompletion = false,
+ bool UserFilesAreVolatile = false);
/// LoadFromCommandLine - Create an ASTUnit from a vector of command line
/// arguments, which must specify exactly one source file.
@@ -730,8 +746,10 @@ public:
bool PrecompilePreamble = false,
TranslationUnitKind TUKind = TU_Complete,
bool CacheCodeCompletionResults = false,
+ bool IncludeBriefCommentsInCodeCompletion = false,
bool AllowPCHWithCompilerErrors = false,
bool SkipFunctionBodies = false,
+ bool UserFilesAreVolatile = false,
OwningPtr<ASTUnit> *ErrAST = 0);
/// \brief Reparse the source files using the same command-line options that
@@ -757,11 +775,15 @@ public:
/// \param IncludeCodePatterns Whether to include code patterns (such as a
/// for loop) in the code-completion results.
///
+ /// \param IncludeBriefComments Whether to include brief documentation within
+ /// the set of code completions returned.
+ ///
/// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and
/// OwnedBuffers parameters are all disgusting hacks. They will go away.
void CodeComplete(StringRef File, unsigned Line, unsigned Column,
RemappedFile *RemappedFiles, unsigned NumRemappedFiles,
bool IncludeMacros, bool IncludeCodePatterns,
+ bool IncludeBriefComments,
CodeCompleteConsumer &Consumer,
DiagnosticsEngine &Diag, LangOptions &LangOpts,
SourceManager &SourceMgr, FileManager &FileMgr,
diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def
index b5b9394af3d8..29ddc9e176b4 100644
--- a/include/clang/Frontend/Analyses.def
+++ b/include/clang/Frontend/Analyses.def
@@ -47,7 +47,9 @@ ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constrain
#endif
ANALYSIS_IPA(None, "none", "Perform only intra-procedural analysis")
-ANALYSIS_IPA(Inlining, "inlining", "Experimental: Inline callees when their definitions are available")
+ANALYSIS_IPA(Inlining, "inlining", "Inline callees when their definitions are available")
+ANALYSIS_IPA(DynamicDispatch, "dynamic", "Experimental: Enable inlining of dynamically dispatched methods")
+ANALYSIS_IPA(DynamicDispatchBifurcate, "dynamic-bifurcate", "Experimental: Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailable")
#ifndef ANALYSIS_INLINING_MODE
#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC)
diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h
index 847bfbd64b16..4e489fea7423 100644
--- a/include/clang/Frontend/AnalyzerOptions.h
+++ b/include/clang/Frontend/AnalyzerOptions.h
@@ -96,7 +96,6 @@ public:
unsigned VisualizeEGUbi : 1;
unsigned UnoptimizedCFG : 1;
unsigned CFGAddImplicitDtors : 1;
- unsigned CFGAddInitializers : 1;
unsigned EagerlyTrimEGraph : 1;
unsigned PrintStats : 1;
unsigned NoRetryExhausted : 1;
@@ -121,7 +120,6 @@ public:
VisualizeEGUbi = 0;
UnoptimizedCFG = 0;
CFGAddImplicitDtors = 0;
- CFGAddInitializers = 0;
EagerlyTrimEGraph = 0;
PrintStats = 0;
NoRetryExhausted = 0;
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index e844f8869c40..3e3409335208 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -35,84 +35,101 @@ public:
Mixed = 2
};
- unsigned AsmVerbose : 1; /// -dA, -fverbose-asm.
- unsigned ObjCAutoRefCountExceptions : 1; /// Whether ARC should be EH-safe.
- unsigned CUDAIsDevice : 1; /// Set when compiling for CUDA device.
- unsigned CXAAtExit : 1; /// Use __cxa_atexit for calling destructors.
- unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker
- /// aliases to base ctors when possible.
- unsigned DataSections : 1; /// Set when -fdata-sections is enabled
- unsigned DebugInfo : 1; /// Should generate debug info (-g).
- unsigned LimitDebugInfo : 1; /// Limit generated debug info to reduce size.
- unsigned DisableFPElim : 1; /// Set when -fomit-frame-pointer is enabled.
- unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in
- /// getting .bc files that correspond to the
- /// internal state before optimizations are
- /// done.
- unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled.
- unsigned DisableTailCalls : 1; /// Do not emit tail calls.
- unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what
- /// Decl* various IR entities came from. Only
- /// useful when running CodeGen as a
- /// subroutine.
- unsigned EmitGcovArcs : 1; /// Emit coverage data files, aka. GCDA.
- unsigned EmitGcovNotes : 1; /// Emit coverage "notes" files, aka GCNO.
- unsigned ForbidGuardVariables : 1; /// Issue errors if C++ guard variables
- /// are required
- unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled
- unsigned HiddenWeakTemplateVTables : 1; /// Emit weak vtables and RTTI for
- /// template classes with hidden visibility
- unsigned HiddenWeakVTables : 1; /// Emit weak vtables, RTTI, and thunks with
- /// hidden visibility.
- unsigned InstrumentFunctions : 1; /// Set when -finstrument-functions is
- /// enabled.
- unsigned InstrumentForProfiling : 1; /// Set when -pg is enabled
- unsigned LessPreciseFPMAD : 1; /// Enable less precise MAD instructions to be
- /// generated.
- unsigned MergeAllConstants : 1; /// Merge identical constants.
- unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
- unsigned NoDwarf2CFIAsm : 1; /// Set when -fno-dwarf2-cfi-asm is enabled.
- unsigned NoDwarfDirectoryAsm : 1; /// Set when -fno-dwarf-directory-asm is
- /// enabled.
- unsigned NoExecStack : 1; /// Set when -Wa,--noexecstack is enabled.
- unsigned NoGlobalMerge : 1; /// Set when -mno-global-merge is enabled.
- unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled.
- unsigned NoInfsFPMath : 1; /// Assume FP arguments, results not +-Inf.
- unsigned NoInline : 1; /// Set when -fno-inline is enabled. Disables
- /// use of the inline keyword.
- unsigned NoNaNsFPMath : 1; /// Assume FP arguments, results not NaN.
- unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss
- unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use.
- unsigned ObjCRuntimeHasARC : 1; /// The target runtime supports ARC natively
- unsigned ObjCRuntimeHasTerminate : 1; /// The ObjC runtime has objc_terminate
- unsigned OmitLeafFramePointer : 1; /// Set when -momit-leaf-frame-pointer is
- /// enabled.
- unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
- unsigned OptimizeSize : 2; /// If -Os (==1) or -Oz (==2) is specified.
- unsigned RelaxAll : 1; /// Relax all machine code instructions.
- unsigned RelaxedAliasing : 1; /// Set when -fno-strict-aliasing is enabled.
- unsigned SaveTempLabels : 1; /// Save temporary labels.
- unsigned SimplifyLibCalls : 1; /// Set when -fbuiltin is enabled.
- unsigned SoftFloat : 1; /// -soft-float.
- unsigned StrictEnums : 1; /// Optimize based on strict enum definition.
- unsigned TimePasses : 1; /// Set when -ftime-report is enabled.
- unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization
- /// selection.
- unsigned UnrollLoops : 1; /// Control whether loops are unrolled.
- unsigned UnsafeFPMath : 1; /// Allow unsafe floating point optzns.
- unsigned UnwindTables : 1; /// Emit unwind tables.
+ enum DebugInfoKind {
+ NoDebugInfo, // Don't generate debug info.
+ DebugLineTablesOnly, // Emit only debug info necessary for generating
+ // line number tables (-gline-tables-only).
+ LimitedDebugInfo, // Limit generated debug info to reduce size
+ // (-flimit-debug-info).
+ FullDebugInfo // Generate complete debug info.
+ };
+
+ enum TLSModel {
+ GeneralDynamicTLSModel,
+ LocalDynamicTLSModel,
+ InitialExecTLSModel,
+ LocalExecTLSModel
+ };
+
+ unsigned AsmVerbose : 1; ///< -dA, -fverbose-asm.
+ unsigned ObjCAutoRefCountExceptions : 1; ///< Whether ARC should be EH-safe.
+ unsigned CUDAIsDevice : 1; ///< Set when compiling for CUDA device.
+ unsigned CXAAtExit : 1; ///< Use __cxa_atexit for calling destructors.
+ unsigned CXXCtorDtorAliases: 1; ///< Emit complete ctors/dtors as linker
+ ///< aliases to base ctors when possible.
+ unsigned DataSections : 1; ///< Set when -fdata-sections is enabled.
+ unsigned DisableFPElim : 1; ///< Set when -fomit-frame-pointer is enabled.
+ unsigned DisableLLVMOpts : 1; ///< Don't run any optimizations, for use in
+ ///< getting .bc files that correspond to the
+ ///< internal state before optimizations are
+ ///< done.
+ unsigned DisableRedZone : 1; ///< Set when -mno-red-zone is enabled.
+ unsigned DisableTailCalls : 1; ///< Do not emit tail calls.
+ unsigned EmitDeclMetadata : 1; ///< Emit special metadata indicating what
+ ///< Decl* various IR entities came from. Only
+ ///< useful when running CodeGen as a
+ ///< subroutine.
+ unsigned EmitGcovArcs : 1; ///< Emit coverage data files, aka. GCDA.
+ unsigned EmitGcovNotes : 1; ///< Emit coverage "notes" files, aka GCNO.
+ unsigned EmitOpenCLArgMetadata : 1; ///< Emit OpenCL kernel arg metadata.
+ unsigned EmitMicrosoftInlineAsm : 1; ///< Enable emission of MS-style inline
+ ///< assembly.
+ unsigned ForbidGuardVariables : 1; ///< Issue errors if C++ guard variables
+ ///< are required.
+ unsigned FunctionSections : 1; ///< Set when -ffunction-sections is enabled.
+ unsigned HiddenWeakTemplateVTables : 1; ///< Emit weak vtables and RTTI for
+ ///< template classes with hidden visibility
+ unsigned HiddenWeakVTables : 1; ///< Emit weak vtables, RTTI, and thunks with
+ ///< hidden visibility.
+ unsigned InstrumentFunctions : 1; ///< Set when -finstrument-functions is
+ ///< enabled.
+ unsigned InstrumentForProfiling : 1; ///< Set when -pg is enabled.
+ unsigned LessPreciseFPMAD : 1; ///< Enable less precise MAD instructions to
+ ///< be generated.
+ unsigned MergeAllConstants : 1; ///< Merge identical constants.
+ unsigned NoCommon : 1; ///< Set when -fno-common or C++ is enabled.
+ unsigned NoDwarf2CFIAsm : 1; ///< Set when -fno-dwarf2-cfi-asm is enabled.
+ unsigned NoDwarfDirectoryAsm : 1; ///< Set when -fno-dwarf-directory-asm is
+ ///< enabled.
+ unsigned NoExecStack : 1; ///< Set when -Wa,--noexecstack is enabled.
+ unsigned NoGlobalMerge : 1; ///< Set when -mno-global-merge is enabled.
+ unsigned NoImplicitFloat : 1; ///< Set when -mno-implicit-float is enabled.
+ unsigned NoInfsFPMath : 1; ///< Assume FP arguments, results not +-Inf.
+ unsigned NoInline : 1; ///< Set when -fno-inline is enabled. Disables
+ ///< use of the inline keyword.
+ unsigned NoNaNsFPMath : 1; ///< Assume FP arguments, results not NaN.
+ unsigned NoZeroInitializedInBSS : 1; ///< -fno-zero-initialized-in-bss.
+ unsigned ObjCDispatchMethod : 2; ///< Method of Objective-C dispatch to use.
+ unsigned OmitLeafFramePointer : 1; ///< Set when -momit-leaf-frame-pointer is
+ ///< enabled.
+ unsigned OptimizationLevel : 3; ///< The -O[0-4] option specified.
+ unsigned OptimizeSize : 2; ///< If -Os (==1) or -Oz (==2) is specified.
+ unsigned RelaxAll : 1; ///< Relax all machine code instructions.
+ unsigned RelaxedAliasing : 1; ///< Set when -fno-strict-aliasing is enabled.
+ unsigned SaveTempLabels : 1; ///< Save temporary labels.
+ unsigned SimplifyLibCalls : 1; ///< Set when -fbuiltin is enabled.
+ unsigned SoftFloat : 1; ///< -soft-float.
+ unsigned StrictEnums : 1; ///< Optimize based on strict enum definition.
+ unsigned TimePasses : 1; ///< Set when -ftime-report is enabled.
+ unsigned UnitAtATime : 1; ///< Unused. For mirroring GCC optimization
+ ///< selection.
+ unsigned UnrollLoops : 1; ///< Control whether loops are unrolled.
+ unsigned UnsafeFPMath : 1; ///< Allow unsafe floating point optzns.
+ unsigned UnwindTables : 1; ///< Emit unwind tables.
/// Attempt to use register sized accesses to bit-fields in structures, when
/// possible.
unsigned UseRegisterSizedBitfieldAccess : 1;
- unsigned VerifyModule : 1; /// Control whether the module should be run
- /// through the LLVM Verifier.
+ unsigned VerifyModule : 1; ///< Control whether the module should be run
+ ///< through the LLVM Verifier.
- unsigned StackRealignment : 1; /// Control whether to permit stack
- /// realignment.
- unsigned StackAlignment; /// Overrides default stack alignment,
- /// if not 0.
+ unsigned StackRealignment : 1; ///< Control whether to permit stack
+ ///< realignment.
+ unsigned UseInitArray : 1; ///< Control whether to use .init_array or
+ ///< .ctors.
+ unsigned StackAlignment; ///< Overrides default stack alignment,
+ ///< if not 0.
/// The code model to use (-mcmodel).
std::string CodeModel;
@@ -127,6 +144,9 @@ public:
/// The string to embed in debug information as the current working directory.
std::string DebugCompilationDir;
+ /// The kind of generated debug info.
+ DebugInfoKind DebugInfo;
+
/// The string to embed in the debug information for the compile unit, if
/// non-empty.
std::string DwarfDebugFlags;
@@ -162,6 +182,12 @@ public:
/// or 0 if unspecified.
unsigned NumRegisterParameters;
+ /// The run-time penalty for bounds checking, or 0 to disable.
+ unsigned char BoundsChecking;
+
+ /// The default TLS model to use.
+ TLSModel DefaultTLSModel;
+
public:
CodeGenOptions() {
AsmVerbose = 0;
@@ -169,8 +195,6 @@ public:
CXAAtExit = 1;
CXXCtorDtorAliases = 0;
DataSections = 0;
- DebugInfo = 0;
- LimitDebugInfo = 0;
DisableFPElim = 0;
DisableLLVMOpts = 0;
DisableRedZone = 0;
@@ -178,6 +202,8 @@ public:
EmitDeclMetadata = 0;
EmitGcovArcs = 0;
EmitGcovNotes = 0;
+ EmitOpenCLArgMetadata = 0;
+ EmitMicrosoftInlineAsm = 0;
ForbidGuardVariables = 0;
FunctionSections = 0;
HiddenWeakTemplateVTables = 0;
@@ -196,8 +222,6 @@ public:
NumRegisterParameters = 0;
ObjCAutoRefCountExceptions = 0;
ObjCDispatchMethod = Legacy;
- ObjCRuntimeHasARC = 0;
- ObjCRuntimeHasTerminate = 0;
OmitLeafFramePointer = 0;
OptimizationLevel = 0;
OptimizeSize = 0;
@@ -216,9 +240,13 @@ public:
VerifyModule = 1;
StackRealignment = 0;
StackAlignment = 0;
+ BoundsChecking = 0;
+ UseInitArray = 0;
+ DebugInfo = NoDebugInfo;
Inlining = NoInlining;
RelocationModel = "pic";
+ DefaultTLSModel = GeneralDynamicTLSModel;
}
ObjCDispatchMethodKind getObjCDispatchMethod() const {
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 1bb76952d5a9..b28e1031b835 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -560,8 +560,7 @@ public:
static CodeCompleteConsumer *
createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename,
unsigned Line, unsigned Column,
- bool ShowMacros,
- bool ShowCodePatterns, bool ShowGlobals,
+ const CodeCompleteOptions &Opts,
raw_ostream &OS);
/// \brief Create the Sema object to be used for parsing.
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index 0d2260acbc69..d6fe003da0fd 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -38,10 +38,13 @@ namespace driver {
class ArgList;
}
-/// CompilerInvocation - Fill out Opts based on the options given in Args.
+/// \brief Fill out Opts based on the options given in Args.
+///
/// Args must have been created from the OptTable returned by
-/// createCC1OptTable(). When errors are encountered, return false and,
-/// if Diags is non-null, report the error(s).
+/// createCC1OptTable().
+///
+/// When errors are encountered, return false and, if Diags is non-null,
+/// report the error(s).
bool ParseDiagnosticArgs(DiagnosticOptions &Opts, driver::ArgList &Args,
DiagnosticsEngine *Diags = 0);
@@ -58,8 +61,7 @@ public:
const LangOptions *getLangOpts() const { return LangOpts.getPtr(); }
};
-/// CompilerInvocation - Helper class for holding the data necessary to invoke
-/// the compiler.
+/// \brief Helper class for holding the data necessary to invoke the compiler.
///
/// This class is designed to represent an abstract "invocation" of the
/// compiler, including data such as the include paths, the code generation
@@ -85,10 +87,10 @@ class CompilerInvocation : public CompilerInvocationBase {
/// Options controlling the frontend itself.
FrontendOptions FrontendOpts;
- /// Options controlling the #include directive.
+ /// Options controlling the \#include directive.
HeaderSearchOptions HeaderSearchOpts;
- /// Options controlling the preprocessor (aside from #include handling).
+ /// Options controlling the preprocessor (aside from \#include handling).
PreprocessorOptions PreprocessorOpts;
/// Options controlling preprocessed output.
@@ -103,10 +105,10 @@ public:
/// @name Utility Methods
/// @{
- /// CreateFromArgs - Create a compiler invocation from a list of input
- /// options. Returns true on success.
+ /// \brief Create a compiler invocation from a list of input options.
+ /// \returns true on success.
///
- /// \param Res [out] - The resulting invocation.
+ /// \param [out] Res - The resulting invocation.
/// \param ArgBegin - The first element in the argument vector.
/// \param ArgEnd - The last element in the argument vector.
/// \param Diags - The diagnostic engine to use for errors.
@@ -115,7 +117,7 @@ public:
const char* const *ArgEnd,
DiagnosticsEngine &Diags);
- /// GetBuiltinIncludePath - Get the directory where the compiler headers
+ /// \brief Get the directory where the compiler headers
/// reside, relative to the compiler binary (found by the passed in
/// arguments).
///
@@ -125,24 +127,14 @@ public:
/// executable), for finding the builtin compiler path.
static std::string GetResourcesPath(const char *Argv0, void *MainAddr);
- /// toArgs - Convert the CompilerInvocation to a list of strings suitable for
+ /// \brief Convert the CompilerInvocation to a list of strings suitable for
/// passing to CreateFromArgs.
- void toArgs(std::vector<std::string> &Res);
-
- /// setLangDefaults - Set language defaults for the given input language and
- /// language standard in this CompilerInvocation.
- ///
- /// \param IK - The input language.
- /// \param LangStd - The input language standard.
- void setLangDefaults(InputKind IK,
- LangStandard::Kind LangStd = LangStandard::lang_unspecified) {
- setLangDefaults(*getLangOpts(), IK, LangStd);
- }
+ void toArgs(std::vector<std::string> &Res) const;
- /// setLangDefaults - Set language defaults for the given input language and
+ /// \brief Set language defaults for the given input language and
/// language standard in the given LangOptions object.
///
- /// \param LangOpts - The LangOptions object to set up.
+ /// \param Opts - The LangOptions object to set up.
/// \param IK - The input language.
/// \param LangStd - The input language standard.
static void setLangDefaults(LangOptions &Opts, InputKind IK,
diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h
index 1c6ba6acc3c0..8dec37ca0311 100644
--- a/include/clang/Frontend/DiagnosticOptions.h
+++ b/include/clang/Frontend/DiagnosticOptions.h
@@ -47,6 +47,9 @@ public:
/// diagnostics, indicated by markers in the
/// input source file.
+ unsigned ElideType: 1; /// Elide identical types in template diffing
+ unsigned ShowTemplateTree: 1; /// Print a template tree when diffing
+
unsigned ErrorLimit; /// Limit # errors emitted.
unsigned MacroBacktraceLimit; /// Limit depth of macro expansion backtrace.
unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace.
diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h
index 5ad88a8a5364..09d7ecb51d80 100644
--- a/include/clang/Frontend/DiagnosticRenderer.h
+++ b/include/clang/Frontend/DiagnosticRenderer.h
@@ -43,7 +43,6 @@ typedef llvm::PointerUnion<const Diagnostic *,
/// class.
class DiagnosticRenderer {
protected:
- const SourceManager &SM;
const LangOptions &LangOpts;
const DiagnosticOptions &DiagOpts;
@@ -66,8 +65,7 @@ protected:
/// which change the amount of information displayed.
DiagnosticsEngine::Level LastLevel;
- DiagnosticRenderer(const SourceManager &SM,
- const LangOptions &LangOpts,
+ DiagnosticRenderer(const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts);
virtual ~DiagnosticRenderer();
@@ -76,20 +74,24 @@ protected:
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
+ const SourceManager *SM,
DiagOrStoredDiag Info) = 0;
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges) = 0;
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM) = 0;
virtual void emitBasicNote(StringRef Message) = 0;
virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints) = 0;
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) = 0;
- virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc) = 0;
+ virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
+ const SourceManager &SM) = 0;
virtual void beginDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) {}
@@ -98,12 +100,14 @@ protected:
private:
- void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level);
- void emitIncludeStackRecursively(SourceLocation Loc);
+ void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level,
+ const SourceManager &SM);
+ void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
void emitMacroExpansionsAndCarets(SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints,
+ const SourceManager &SM,
unsigned &MacroDepth,
unsigned OnMacroInst = 0);
public:
@@ -119,9 +123,12 @@ public:
/// \param Message The diagnostic message to emit.
/// \param Ranges The underlined ranges for this code snippet.
/// \param FixItHints The FixIt hints active for this diagnostic.
+ /// \param SM The SourceManager; will be null if the diagnostic came from the
+ /// frontend, thus \param Loc will be invalid.
void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
StringRef Message, ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixItHints,
+ const SourceManager *SM,
DiagOrStoredDiag D = (Diagnostic *)0);
void emitStoredDiagnostic(StoredDiagnostic &Diag);
@@ -131,19 +138,20 @@ public:
/// notes. It is up to subclasses to further define the behavior.
class DiagnosticNoteRenderer : public DiagnosticRenderer {
public:
- DiagnosticNoteRenderer(const SourceManager &SM,
- const LangOptions &LangOpts,
+ DiagnosticNoteRenderer(const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts)
- : DiagnosticRenderer(SM, LangOpts, DiagOpts) {}
+ : DiagnosticRenderer(LangOpts, DiagOpts) {}
virtual ~DiagnosticNoteRenderer();
virtual void emitBasicNote(StringRef Message);
virtual void emitIncludeLocation(SourceLocation Loc,
- PresumedLoc PLoc);
+ PresumedLoc PLoc,
+ const SourceManager &SM);
- virtual void emitNote(SourceLocation Loc, StringRef Message) = 0;
+ virtual void emitNote(SourceLocation Loc, StringRef Message,
+ const SourceManager *SM) = 0;
};
} // end clang namespace
#endif
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index 6839028f9784..c0056de5cae3 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -188,7 +188,7 @@ public:
bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input);
/// Execute - Set the source managers main input file, and run the action.
- void Execute();
+ bool Execute();
/// EndSourceFile - Perform any per-file post processing, deallocate per-file
/// objects, and run statistics and output file cleanup code.
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index 8f7fe87ee67d..477ac45a9570 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -50,6 +50,12 @@ protected:
StringRef InFile);
};
+class ASTDeclListAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile);
+};
+
class ASTDumpXMLAction : public ASTFrontendAction {
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 888388c310e4..ce1cd9b2d3bc 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
#include "clang/Frontend/CommandLineSourceLoc.h"
+#include "clang/Sema/CodeCompleteOptions.h"
#include "llvm/ADT/StringRef.h"
#include <string>
#include <vector>
@@ -19,6 +20,7 @@ namespace clang {
namespace frontend {
enum ActionKind {
+ ASTDeclList, ///< Parse ASTs and list Decl nodes.
ASTDump, ///< Parse ASTs and dump them.
ASTDumpXML, ///< Parse ASTs and dump them in XML.
ASTPrint, ///< Parse ASTs and print them.
@@ -42,7 +44,7 @@ namespace frontend {
PrintDeclContext, ///< Print DeclContext and their Decls.
PrintPreamble, ///< Print the "preamble" of the input file
PrintPreprocessedInput, ///< -E mode.
- RewriteMacros, ///< Expand macros but not #includes.
+ RewriteMacros, ///< Expand macros but not \#includes.
RewriteObjC, ///< ObjC->C Rewriter.
RewriteTest, ///< Rewriter playground
RunAnalysis, ///< Run one or more source code analyses.
@@ -84,7 +86,7 @@ struct FrontendInputFile {
FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
: File(File.str()), Kind(Kind), IsSystem(IsSystem) { }
};
-
+
/// FrontendOptions - Options for controlling the behavior of the frontend.
class FrontendOptions {
public:
@@ -93,12 +95,6 @@ public:
/// instruct the AST writer to create
/// relocatable PCH files.
unsigned ShowHelp : 1; ///< Show the -help text.
- unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion
- /// results.
- unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code
- /// completion results.
- unsigned ShowGlobalSymbolsInCodeCompletion : 1; ///< Show top-level decls in
- /// code completion results.
unsigned ShowStats : 1; ///< Show frontend performance
/// metrics and statistics.
unsigned ShowTimers : 1; ///< Show timers for individual
@@ -116,6 +112,8 @@ public:
/// not need them (e.g. with code
/// completion).
+ CodeCompleteOptions CodeCompleteOpts;
+
enum {
ARCMT_None,
ARCMT_Check,
@@ -144,6 +142,9 @@ public:
/// If given, the new suffix for fix-it rewritten files.
std::string FixItSuffix;
+ /// If given, filter dumped AST Decl nodes by this substring.
+ std::string ASTDumpFilter;
+
/// If given, enable code completion at the provided location.
ParsedSourceLocation CodeCompletionAt;
@@ -183,9 +184,6 @@ public:
ActionName = "";
RelocatablePCH = 0;
ShowHelp = 0;
- ShowMacrosInCodeCompletion = 0;
- ShowCodePatternsInCodeCompletion = 0;
- ShowGlobalSymbolsInCodeCompletion = 1;
ShowStats = 0;
ShowTimers = 0;
ShowVersion = 0;
diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h
index 687f439fe1ff..ebc8f264b2a2 100644
--- a/include/clang/Frontend/HeaderSearchOptions.h
+++ b/include/clang/Frontend/HeaderSearchOptions.h
@@ -17,12 +17,12 @@ namespace clang {
namespace frontend {
/// IncludeDirGroup - Identifiers the group a include entry belongs to, which
- /// represents its relative positive in the search list. A #include of a ""
+ /// represents its relative positive in the search list. A \#include of a ""
/// path starts at the -iquote group, then searches the Angled group, then
/// searches the system group, etc.
enum IncludeDirGroup {
- Quoted = 0, ///< '#include ""' paths, added by'gcc -iquote'.
- Angled, ///< Paths for '#include <>' added by '-I'.
+ Quoted = 0, ///< '\#include ""' paths, added by 'gcc -iquote'.
+ Angled, ///< Paths for '\#include <>' added by '-I'.
IndexHeaderMap, ///< Like Angled, but marks header maps used when
/// building frameworks.
System, ///< Like Angled, but marks system directories.
@@ -69,6 +69,18 @@ public:
IsInternal(isInternal), ImplicitExternC(implicitExternC) {}
};
+ struct SystemHeaderPrefix {
+ /// A prefix to be matched against paths in \#include directives.
+ std::string Prefix;
+
+ /// True if paths beginning with this prefix should be treated as system
+ /// headers.
+ bool IsSystemHeader;
+
+ SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader)
+ : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {}
+ };
+
/// If non-empty, the directory to use as a "virtual system root" for include
/// paths.
std::string Sysroot;
@@ -76,6 +88,9 @@ public:
/// User specified include entries.
std::vector<Entry> UserEntries;
+ /// User-specified system header prefixes.
+ std::vector<SystemHeaderPrefix> SystemHeaderPrefixes;
+
/// The directory which holds the compiler resource files (builtin includes,
/// etc.).
std::string ResourceDir;
@@ -117,6 +132,13 @@ public:
UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework,
IgnoreSysRoot, IsInternal, ImplicitExternC));
}
+
+ /// AddSystemHeaderPrefix - Override whether \#include directives naming a
+ /// path starting with \arg Prefix should be considered as naming a system
+ /// header.
+ void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
+ SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader));
+ }
};
} // end namespace clang
diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def
index 4bcff4a92b50..a604d4bff658 100644
--- a/include/clang/Frontend/LangStandards.def
+++ b/include/clang/Frontend/LangStandards.def
@@ -111,6 +111,12 @@ LANGSTANDARD(gnucxx11, "gnu++11",
LANGSTANDARD(opencl, "cl",
"OpenCL 1.0",
BCPLComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(opencl11, "CL1.1",
+ "OpenCL 1.1",
+ BCPLComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(opencl12, "CL1.2",
+ "OpenCL 1.2",
+ BCPLComment | C99 | Digraphs | HexFloat)
// CUDA
LANGSTANDARD(cuda, "cuda",
diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h
index 1eda0d40275e..9793aa6fa7ae 100644
--- a/include/clang/Frontend/PreprocessorOutputOptions.h
+++ b/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -18,9 +18,10 @@ class PreprocessorOutputOptions {
public:
unsigned ShowCPP : 1; ///< Print normal preprocessed output.
unsigned ShowComments : 1; ///< Show comments.
- unsigned ShowLineMarkers : 1; ///< Show #line markers.
+ unsigned ShowLineMarkers : 1; ///< Show \#line markers.
unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
unsigned ShowMacros : 1; ///< Print macro definitions.
+ unsigned RewriteIncludes : 1; ///< Preprocess include directives only.
public:
PreprocessorOutputOptions() {
@@ -29,6 +30,7 @@ public:
ShowLineMarkers = 1;
ShowMacroComments = 0;
ShowMacros = 0;
+ RewriteIncludes = 0;
}
};
diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h
index 314003bce2c5..c869c08c0fc2 100644
--- a/include/clang/Frontend/TextDiagnostic.h
+++ b/include/clang/Frontend/TextDiagnostic.h
@@ -39,7 +39,6 @@ class TextDiagnostic : public DiagnosticRenderer {
public:
TextDiagnostic(raw_ostream &OS,
- const SourceManager &SM,
const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts);
@@ -60,7 +59,7 @@ public:
///
/// This is a static helper to handle the line wrapping, colorizing, and
/// rendering of a diagnostic message to a particular ostream. It is
- /// publically visible so that clients which do not have sufficient state to
+ /// publicly visible so that clients which do not have sufficient state to
/// build a complete TextDiagnostic object can still get consistent
/// formatting of their diagnostic messages.
///
@@ -83,39 +82,46 @@ protected:
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
+ const SourceManager *SM,
DiagOrStoredDiag D);
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges);
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM);
virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints) {
- emitSnippetAndCaret(Loc, Level, Ranges, Hints);
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) {
+ emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM);
}
virtual void emitBasicNote(StringRef Message);
- virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc);
+ virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
+ const SourceManager &SM);
private:
void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints);
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM);
void emitSnippet(StringRef SourceLine);
void highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID,
const SourceColumnMap &map,
- std::string &CaretLine);
+ std::string &CaretLine,
+ const SourceManager &SM);
std::string buildFixItInsertionLine(unsigned LineNo,
const SourceColumnMap &map,
- ArrayRef<FixItHint> Hints);
- void emitParseableFixits(ArrayRef<FixItHint> Hints);
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM);
+ void emitParseableFixits(ArrayRef<FixItHint> Hints, const SourceManager &SM);
};
} // end namespace clang
diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h
index 9b6ac24cca7e..23cf5211cd01 100644
--- a/include/clang/Frontend/TextDiagnosticPrinter.h
+++ b/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -26,9 +26,7 @@ class TextDiagnostic;
class TextDiagnosticPrinter : public DiagnosticConsumer {
raw_ostream &OS;
- const LangOptions *LangOpts;
const DiagnosticOptions *DiagOpts;
- const SourceManager *SM;
/// \brief Handle to the currently active text diagnostic emitter.
OwningPtr<TextDiagnostic> TextDiag;
diff --git a/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h
index 2fc6ccc36d55..a74589edc94a 100644
--- a/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ b/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -11,12 +11,18 @@
#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include <climits>
namespace clang {
class DiagnosticsEngine;
class TextDiagnosticBuffer;
+class FileEntry;
/// VerifyDiagnosticConsumer - Create a diagnostic client which will use
/// markers in the input source to check that all the emitted diagnostics match
@@ -35,18 +41,58 @@ class TextDiagnosticBuffer;
///
/// Here's an example:
///
+/// \code
/// int A = B; // expected-error {{use of undeclared identifier 'B'}}
+/// \endcode
///
/// You can place as many diagnostics on one line as you wish. To make the code
/// more readable, you can use slash-newline to separate out the diagnostics.
///
+/// Alternatively, it is possible to specify the line on which the diagnostic
+/// should appear by appending "@<line>" to "expected-<type>", for example:
+///
+/// \code
+/// #warning some text
+/// // expected-warning@10 {{some text}}
+/// \endcode
+///
+/// The line number may be absolute (as above), or relative to the current
+/// line by prefixing the number with either '+' or '-'.
+///
/// The simple syntax above allows each specification to match exactly one
/// error. You can use the extended syntax to customize this. The extended
-/// syntax is "expected-<type> <n> {{diag text}}", where <type> is one of
-/// "error", "warning" or "note", and <n> is a positive integer. This allows the
-/// diagnostic to appear as many times as specified. Example:
+/// syntax is "expected-<type> <n> {{diag text}}", where \<type> is one of
+/// "error", "warning" or "note", and \<n> is a positive integer. This allows
+/// the diagnostic to appear as many times as specified. Example:
///
+/// \code
/// void f(); // expected-note 2 {{previous declaration is here}}
+/// \endcode
+///
+/// Where the diagnostic is expected to occur a minimum number of times, this
+/// can be specified by appending a '+' to the number. Example:
+///
+/// \code
+/// void f(); // expected-note 0+ {{previous declaration is here}}
+/// void g(); // expected-note 1+ {{previous declaration is here}}
+/// \endcode
+///
+/// In the first example, the diagnostic becomes optional, i.e. it will be
+/// swallowed if it occurs, but will not generate an error if it does not
+/// occur. In the second example, the diagnostic must occur at least once.
+/// As a short-hand, "one or more" can be specified simply by '+'. Example:
+///
+/// \code
+/// void g(); // expected-note + {{previous declaration is here}}
+/// \endcode
+///
+/// A range can also be specified by "<n>-<m>". Example:
+///
+/// \code
+/// void f(); // expected-note 0-1 {{previous declaration is here}}
+/// \endcode
+///
+/// In this example, the diagnostic may appear only once, if at all.
///
/// Regex matching mode may be selected by appending '-re' to type. Example:
///
@@ -62,20 +108,85 @@ class TextDiagnosticBuffer;
/// // expected-error-re {{variable has has type 'struct (.*)'}}
/// // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}}
///
-class VerifyDiagnosticConsumer: public DiagnosticConsumer {
+class VerifyDiagnosticConsumer: public DiagnosticConsumer,
+ public CommentHandler {
public:
+ /// Directive - Abstract class representing a parsed verify directive.
+ ///
+ class Directive {
+ public:
+ static Directive *create(bool RegexKind, SourceLocation DirectiveLoc,
+ SourceLocation DiagnosticLoc,
+ StringRef Text, unsigned Min, unsigned Max);
+ public:
+ /// Constant representing n or more matches.
+ static const unsigned MaxCount = UINT_MAX;
+
+ SourceLocation DirectiveLoc;
+ SourceLocation DiagnosticLoc;
+ const std::string Text;
+ unsigned Min, Max;
+
+ virtual ~Directive() { }
+
+ // Returns true if directive text is valid.
+ // Otherwise returns false and populates E.
+ virtual bool isValid(std::string &Error) = 0;
+
+ // Returns true on match.
+ virtual bool match(StringRef S) = 0;
+
+ protected:
+ Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
+ StringRef Text, unsigned Min, unsigned Max)
+ : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
+ Text(Text), Min(Min), Max(Max) {
+ assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
+ assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!");
+ }
+
+ private:
+ Directive(const Directive&); // DO NOT IMPLEMENT
+ void operator=(const Directive&); // DO NOT IMPLEMENT
+ };
+
+ typedef std::vector<Directive*> DirectiveList;
+
+ /// ExpectedData - owns directive objects and deletes on destructor.
+ ///
+ struct ExpectedData {
+ DirectiveList Errors;
+ DirectiveList Warnings;
+ DirectiveList Notes;
+
+ ~ExpectedData() {
+ llvm::DeleteContainerPointers(Errors);
+ llvm::DeleteContainerPointers(Warnings);
+ llvm::DeleteContainerPointers(Notes);
+ }
+ };
+
+#ifndef NDEBUG
+ typedef llvm::DenseSet<FileID> FilesWithDiagnosticsSet;
+ typedef llvm::SmallPtrSet<const FileEntry *, 4> FilesParsedForDirectivesSet;
+#endif
+
+private:
DiagnosticsEngine &Diags;
DiagnosticConsumer *PrimaryClient;
bool OwnsPrimaryClient;
OwningPtr<TextDiagnosticBuffer> Buffer;
- Preprocessor *CurrentPreprocessor;
-
-private:
- FileID FirstErrorFID; // FileID of first diagnostic
+ const Preprocessor *CurrentPreprocessor;
+ unsigned ActiveSourceFiles;
+#ifndef NDEBUG
+ FilesWithDiagnosticsSet FilesWithDiagnostics;
+ FilesParsedForDirectivesSet FilesParsedForDirectives;
+#endif
+ ExpectedData ED;
void CheckDiagnostics();
public:
- /// Create a new verifying diagnostic client, which will issue errors to \arg
+ /// Create a new verifying diagnostic client, which will issue errors to
/// the currently-attached diagnostic client when a diagnostic does not match
/// what is expected (as indicated in the source file).
VerifyDiagnosticConsumer(DiagnosticsEngine &Diags);
@@ -86,6 +197,15 @@ public:
virtual void EndSourceFile();
+ /// \brief Manually register a file as parsed.
+ inline void appendParsedFile(const FileEntry *File) {
+#ifndef NDEBUG
+ FilesParsedForDirectives.insert(File);
+#endif
+ }
+
+ virtual bool HandleComment(Preprocessor &PP, SourceRange Comment);
+
virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info);
diff --git a/include/clang/Lex/CodeCompletionHandler.h b/include/clang/Lex/CodeCompletionHandler.h
index d876776c927c..91c3b7811f07 100644
--- a/include/clang/Lex/CodeCompletionHandler.h
+++ b/include/clang/Lex/CodeCompletionHandler.h
@@ -43,11 +43,11 @@ public:
/// where the name of a macro is expected.
///
/// \param IsDefinition Whether this is the definition of a macro, e.g.,
- /// in a #define.
+ /// in a \#define.
virtual void CodeCompleteMacroName(bool IsDefinition) { }
/// \brief Callback invoked when performing code completion in a preprocessor
- /// expression, such as the condition of an #if or #elif directive.
+ /// expression, such as the condition of an \#if or \#elif directive.
virtual void CodeCompletePreprocessorExpression() { }
/// \brief Callback invoked when performing code completion inside a
@@ -62,7 +62,7 @@ public:
/// \brief Callback invoked when performing code completion in a part of the
/// file where we expect natural language, e.g., a comment, string, or
- /// #error directive.
+ /// \#error directive.
virtual void CodeCompleteNaturalLanguage() { }
};
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
index 95f0d2735093..d773fc6fb15f 100644
--- a/include/clang/Lex/DirectoryLookup.h
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -25,7 +25,7 @@ class HeaderSearch;
class Module;
/// DirectoryLookup - This class represents one entry in the search list that
-/// specifies the search order for directories in #include directives. It
+/// specifies the search order for directories in \#include directives. It
/// represents either a directory, a framework, or a headermap.
///
class DirectoryLookup {
@@ -146,14 +146,14 @@ public:
/// part of a known module, this will be set to the module that should
/// be imported instead of preprocessing/parsing the file found.
///
- /// \param InUserSpecifiedSystemHeader [out] If the file is found, set to true
- /// if the file is located in a framework that has been user-specified to be
- /// treated as a system framework.
+ /// \param [out] InUserSpecifiedSystemFramework If the file is found,
+ /// set to true if the file is located in a framework that has been
+ /// user-specified to be treated as a system framework.
const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
Module **SuggestedModule,
- bool &InUserSpecifiedSystemHeader) const;
+ bool &InUserSpecifiedSystemFramework) const;
private:
const FileEntry *DoFrameworkLookup(
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
index 08bc5b64bc12..107408dced10 100644
--- a/include/clang/Lex/HeaderMap.h
+++ b/include/clang/Lex/HeaderMap.h
@@ -26,7 +26,7 @@ namespace clang {
struct HMapHeader;
/// This class represents an Apple concept known as a 'header map'. To the
-/// #include file resolution process, it basically acts like a directory of
+/// \#include file resolution process, it basically acts like a directory of
/// symlinks to files. Its advantages are that it is dense and more efficient
/// to create and process than a directory of symlinks.
class HeaderMap {
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 5128ce6c1144..8e9491fdc339 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -16,6 +16,7 @@
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/ModuleMap.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Allocator.h"
@@ -30,18 +31,18 @@ class FileEntry;
class FileManager;
class IdentifierInfo;
-/// HeaderFileInfo - The preprocessor keeps track of this information for each
-/// file that is #included.
+/// \brief The preprocessor keeps track of this information for each
+/// file that is \#included.
struct HeaderFileInfo {
- /// isImport - True if this is a #import'd or #pragma once file.
+ /// \brief True if this is a \#import'd or \#pragma once file.
unsigned isImport : 1;
- /// isPragmaOnce - True if this is #pragma once file.
+ /// \brief True if this is a \#pragma once file.
unsigned isPragmaOnce : 1;
/// DirInfo - Keep track of whether this is a system header, and if so,
/// whether it is C++ clean or not. This can be set by the include paths or
- /// by #pragma gcc system_header. This is an instance of
+ /// by \#pragma gcc system_header. This is an instance of
/// SrcMgr::CharacteristicKind.
unsigned DirInfo : 2;
@@ -61,8 +62,7 @@ struct HeaderFileInfo {
/// those framework headers.
unsigned IndexHeaderMapHeader : 1;
- /// NumIncludes - This is the number of times the file has been included
- /// already.
+ /// \brief The number of times the file has been included already.
unsigned short NumIncludes;
/// \brief The ID number of the controlling macro.
@@ -72,8 +72,8 @@ struct HeaderFileInfo {
/// external storage.
unsigned ControllingMacroID;
- /// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard
- /// that protects the entire contents of the file, this is the identifier
+ /// If this file has a \#ifndef XXX (or equivalent) guard that
+ /// protects the entire contents of the file, this is the identifier
/// for the macro that controls whether or not it has any effect.
///
/// Note: Most clients should use getControllingMacro() to access
@@ -117,8 +117,8 @@ public:
virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0;
};
-/// HeaderSearch - This class encapsulates the information needed to find the
-/// file referenced by a #include or #include_next, (sub-)framework lookup, etc.
+/// \brief Encapsulates the information needed to find the file referenced
+/// by a \#include or \#include_next, (sub-)framework lookup, etc.
class HeaderSearch {
/// This structure is used to record entries in our framework cache.
struct FrameworkCacheEntry {
@@ -133,8 +133,8 @@ class HeaderSearch {
FileManager &FileMgr;
DiagnosticsEngine &Diags;
- /// #include search path information. Requests for #include "x" search the
- /// directory of the #including file first, then each directory in SearchDirs
+ /// \#include search path information. Requests for \#include "x" search the
+ /// directory of the \#including file first, then each directory in SearchDirs
/// consecutively. Requests for <x> search the current dir first, then each
/// directory in SearchDirs, starting at AngledDirIdx, consecutively. If
/// NoCurDirSearch is true, then the check for the file in the current
@@ -144,24 +144,32 @@ class HeaderSearch {
unsigned SystemDirIdx;
bool NoCurDirSearch;
+ /// \brief \#include prefixes for which the 'system header' property is
+ /// overridden.
+ ///
+ /// For a \#include "x" or \#include \<x> directive, the last string in this
+ /// list which is a prefix of 'x' determines whether the file is treated as
+ /// a system header.
+ std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
+
/// \brief The path to the module cache.
std::string ModuleCachePath;
- /// FileInfo - This contains all of the preprocessor-specific data about files
- /// that are included. The vector is indexed by the FileEntry's UID.
- ///
+ /// \brief All of the preprocessor-specific data about files that are
+ /// included, indexed by the FileEntry's UID.
std::vector<HeaderFileInfo> FileInfo;
- /// LookupFileCache - This is keeps track of each lookup performed by
- /// LookupFile. The first part of the value is the starting index in
- /// SearchDirs that the cached search was performed from. If there is a hit
- /// and this value doesn't match the current query, the cache has to be
- /// ignored. The second value is the entry in SearchDirs that satisfied the
- /// query.
+ /// \brief Keeps track of each lookup performed by LookupFile.
+ ///
+ /// The first part of the value is the starting index in SearchDirs
+ /// that the cached search was performed from. If there is a hit and
+ /// this value doesn't match the current query, the cache has to be
+ /// ignored. The second value is the entry in SearchDirs that satisfied
+ /// the query.
llvm::StringMap<std::pair<unsigned, unsigned>, llvm::BumpPtrAllocator>
LookupFileCache;
- /// FrameworkMap - This is a collection mapping a framework or subframework
+ /// \brief Collection mapping a framework or subframework
/// name like "Carbon" to the Carbon.framework directory.
llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap;
@@ -212,8 +220,7 @@ public:
FileManager &getFileMgr() const { return FileMgr; }
- /// SetSearchPaths - Interface for setting the file search paths.
- ///
+ /// \brief Interface for setting the file search paths.
void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
unsigned angledDirIdx, unsigned systemDirIdx,
bool noCurDirSearch) {
@@ -226,7 +233,7 @@ public:
//LookupFileCache.clear();
}
- /// AddSearchPath - Add an additional search path.
+ /// \brief Add an additional search path.
void AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
SearchDirs.insert(SearchDirs.begin() + idx, dir);
@@ -235,12 +242,18 @@ public:
SystemDirIdx++;
}
- /// HasIncludeAliasMap - Checks whether the map exists or not
+ /// \brief Set the list of system header prefixes.
+ void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool> > P) {
+ SystemHeaderPrefixes.assign(P.begin(), P.end());
+ }
+
+ /// \brief Checks whether the map exists or not.
bool HasIncludeAliasMap() const {
return IncludeAliases;
}
- /// AddIncludeAlias - Map the source include name to the dest include name.
+ /// \brief Map the source include name to the dest include name.
+ ///
/// The Source should include the angle brackets or quotes, the dest
/// should not. This allows for distinction between <> and "" headers.
void AddIncludeAlias(StringRef Source, StringRef Dest) {
@@ -271,7 +284,7 @@ public:
/// \brief Retrieve the path to the module cache.
StringRef getModuleCachePath() const { return ModuleCachePath; }
- /// ClearFileInfo - Forget everything we know about headers so far.
+ /// \brief Forget everything we know about headers so far.
void ClearFileInfo() {
FileInfo.clear();
}
@@ -293,7 +306,7 @@ public:
/// already known.
void setTarget(const TargetInfo &Target);
- /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
+ /// \brief Given a "foo" or \<foo> reference, look up the indicated file,
/// return null on failure.
///
/// \returns If successful, this returns 'UsedDir', the DirectoryLookup member
@@ -302,9 +315,9 @@ public:
/// \param isAngled indicates whether the file reference is a <> reference.
///
/// \param CurDir If non-null, the file was found in the specified directory
- /// search location. This is used to implement #include_next.
+ /// search location. This is used to implement \#include_next.
///
- /// \param CurFileEnt If non-null, indicates where the #including file is, in
+ /// \param CurFileEnt If non-null, indicates where the \#including file is, in
/// case a relative search is needed.
///
/// \param SearchPath If non-null, will be set to the search path relative
@@ -327,73 +340,76 @@ public:
Module **SuggestedModule,
bool SkipCache = false);
- /// LookupSubframeworkHeader - Look up a subframework for the specified
- /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from
- /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
- /// is a subframework within Carbon.framework. If so, return the FileEntry
- /// for the designated file, otherwise return null.
+ /// \brief Look up a subframework for the specified \#include file.
+ ///
+ /// For example, if \#include'ing <HIToolbox/HIToolbox.h> from
+ /// within ".../Carbon.framework/Headers/Carbon.h", check to see if
+ /// HIToolbox is a subframework within Carbon.framework. If so, return
+ /// the FileEntry for the designated file, otherwise return null.
const FileEntry *LookupSubframeworkHeader(
StringRef Filename,
const FileEntry *RelativeFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath);
- /// LookupFrameworkCache - Look up the specified framework name in our
- /// framework cache, returning the DirectoryEntry it is in if we know,
- /// otherwise, return null.
+ /// \brief Look up the specified framework name in our framework cache.
+ /// \returns The DirectoryEntry it is in if we know, null otherwise.
FrameworkCacheEntry &LookupFrameworkCache(StringRef FWName) {
return FrameworkMap.GetOrCreateValue(FWName).getValue();
}
- /// ShouldEnterIncludeFile - Mark the specified file as a target of of a
- /// #include, #include_next, or #import directive. Return false if #including
- /// the file will have no effect or true if we should include it.
+ /// \brief Mark the specified file as a target of of a \#include,
+ /// \#include_next, or \#import directive.
+ ///
+ /// \return false if \#including the file will have no effect or true
+ /// if we should include it.
bool ShouldEnterIncludeFile(const FileEntry *File, bool isImport);
- /// getFileDirFlavor - Return whether the specified file is a normal header,
+ /// \brief Return whether the specified file is a normal header,
/// a system header, or a C++ friendly system header.
SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) {
return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo;
}
- /// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g.
- /// due to #pragma once.
+ /// \brief Mark the specified file as a "once only" file, e.g. due to
+ /// \#pragma once.
void MarkFileIncludeOnce(const FileEntry *File) {
HeaderFileInfo &FI = getFileInfo(File);
FI.isImport = true;
FI.isPragmaOnce = true;
}
- /// MarkFileSystemHeader - Mark the specified file as a system header, e.g.
- /// due to #pragma GCC system_header.
+ /// \brief Mark the specified file as a system header, e.g. due to
+ /// \#pragma GCC system_header.
void MarkFileSystemHeader(const FileEntry *File) {
getFileInfo(File).DirInfo = SrcMgr::C_System;
}
- /// IncrementIncludeCount - Increment the count for the number of times the
- /// specified FileEntry has been entered.
+ /// \brief Increment the count for the number of times the specified
+ /// FileEntry has been entered.
void IncrementIncludeCount(const FileEntry *File) {
++getFileInfo(File).NumIncludes;
}
- /// SetFileControllingMacro - Mark the specified file as having a controlling
- /// macro. This is used by the multiple-include optimization to eliminate
- /// no-op #includes.
+ /// \brief Mark the specified file as having a controlling macro.
+ ///
+ /// This is used by the multiple-include optimization to eliminate
+ /// no-op \#includes.
void SetFileControllingMacro(const FileEntry *File,
const IdentifierInfo *ControllingMacro) {
getFileInfo(File).ControllingMacro = ControllingMacro;
}
/// \brief Determine whether this file is intended to be safe from
- /// multiple inclusions, e.g., it has #pragma once or a controlling
+ /// multiple inclusions, e.g., it has \#pragma once or a controlling
/// macro.
///
- /// This routine does not consider the effect of #import
+ /// This routine does not consider the effect of \#import
bool isFileMultipleIncludeGuarded(const FileEntry *File);
/// CreateHeaderMap - This method returns a HeaderMap for the specified
- /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
+ /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
const HeaderMap *CreateHeaderMap(const FileEntry *FE);
/// \brief Retrieve the name of the module file that should be used to
@@ -408,7 +424,7 @@ public:
/// \brief Retrieve the name of the module file that should be used to
/// load a module with the given name.
///
- /// \param Module The module whose module file name will be returned.
+ /// \param ModuleName The module whose module file name will be returned.
///
/// \returns The name of the module file that corresponds to this module,
/// or an empty string if this module does not correspond to any module file.
@@ -445,8 +461,6 @@ public:
///
/// \param File The module map file.
///
- /// \param OnlyModule If non-NULL, this will receive the
- ///
/// \returns true if an error occurred, false otherwise.
bool loadModuleMapFile(const FileEntry *File);
@@ -480,8 +494,7 @@ public:
// Used by ASTReader.
void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
- /// getFileInfo - Return the HeaderFileInfo structure for the specified
- /// FileEntry.
+ /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
const HeaderFileInfo &getFileInfo(const FileEntry *FE) const {
return const_cast<HeaderSearch*>(this)->getFileInfo(FE);
}
@@ -552,8 +565,7 @@ private:
/// named directory.
LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir);
- /// getFileInfo - Return the HeaderFileInfo structure for the specified
- /// FileEntry.
+ /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
HeaderFileInfo &getFileInfo(const FileEntry *FE);
};
diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index 04bcead6d45e..ca233de71c39 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -97,14 +97,14 @@ public:
Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, Preprocessor &PP);
/// Lexer constructor - Create a new raw lexer object. This object is only
- /// suitable for calls to 'LexRawToken'. This lexer assumes that the text
- /// range will outlive it, so it doesn't take ownership of it.
+ /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the
+ /// text range will outlive it, so it doesn't take ownership of it.
Lexer(SourceLocation FileLoc, const LangOptions &LangOpts,
const char *BufStart, const char *BufPtr, const char *BufEnd);
/// Lexer constructor - Create a new raw lexer object. This object is only
- /// suitable for calls to 'LexRawToken'. This lexer assumes that the text
- /// range will outlive it, so it doesn't take ownership of it.
+ /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the
+ /// text range will outlive it, so it doesn't take ownership of it.
Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer,
const SourceManager &SM, const LangOptions &LangOpts);
@@ -200,7 +200,7 @@ public:
/// ReadToEndOfLine - Read the rest of the current preprocessor line as an
/// uninterpreted string. This switches the lexer out of directive mode.
- std::string ReadToEndOfLine();
+ void ReadToEndOfLine(SmallVectorImpl<char> *Result = 0);
/// Diag - Forwarding function for diagnostics. This translate a source
@@ -335,6 +335,28 @@ public:
///
/// Returns a null range if a part of the range resides inside a macro
/// expansion or the range does not reside on the same FileID.
+ ///
+ /// This function is trying to deal with macros and return a range based on
+ /// file locations. The cases where it can successfully handle macros are:
+ ///
+ /// -begin or end range lies at the start or end of a macro expansion, in
+ /// which case the location will be set to the expansion point, e.g:
+ /// \#define M 1 2
+ /// a M
+ /// If you have a range [a, 2] (where 2 came from the macro), the function
+ /// will return a range for "a M"
+ /// if you have range [a, 1], the function will fail because the range
+ /// overlaps with only a part of the macro
+ ///
+ /// -The macro is a function macro and the range can be mapped to the macro
+ /// arguments, e.g:
+ /// \#define M 1 2
+ /// \#define FM(x) x
+ /// FM(a b M)
+ /// if you have range [b, 2], the function will return the file range "b M"
+ /// inside the macro arguments.
+ /// if you have range [a, 2], the function will return the file range
+ /// "FM(a b M)" since the range includes all of the macro expansion.
static CharSourceRange makeFileCharRange(CharSourceRange Range,
const SourceManager &SM,
const LangOptions &LangOpts);
@@ -519,6 +541,9 @@ public:
const LangOptions &LangOpts,
bool SkipTrailingWhitespaceAndNewLine);
+ /// \brief Returns true if the given character could appear in an identifier.
+ static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts);
+
private:
/// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
index 7e7f82f05fa1..bbce62d1d48a 100644
--- a/include/clang/Lex/LiteralSupport.h
+++ b/include/clang/Lex/LiteralSupport.h
@@ -232,6 +232,7 @@ private:
void init(const Token *StringToks, unsigned NumStringToks);
bool CopyStringFragment(StringRef Fragment);
bool DiagnoseBadString(const Token& Tok);
+ void DiagnoseLexingError(SourceLocation Loc);
};
} // end namespace clang
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index 8775d39fe8dd..cbd201f849de 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -22,7 +22,7 @@
namespace clang {
class Preprocessor;
-/// MacroInfo - Each identifier that is #define'd has an instance of this class
+/// MacroInfo - Each identifier that is \#define'd has an instance of this class
/// associated with it, used to implement macro expansion.
class MacroInfo {
//===--------------------------------------------------------------------===//
@@ -35,7 +35,7 @@ class MacroInfo {
/// Arguments - The list of arguments for a function-like macro. This can be
/// empty, for, e.g. "#define X()". In a C99-style variadic macro, this
- /// includes the __VA_ARGS__ identifier on the list.
+ /// includes the \c __VA_ARGS__ identifier on the list.
IdentifierInfo **ArgumentList;
unsigned NumArguments;
@@ -45,15 +45,14 @@ class MacroInfo {
/// If invalid, this macro has not been explicitly given any visibility.
SourceLocation VisibilityLocation;
- /// ReplacementTokens - This is the list of tokens that the macro is defined
- /// to.
+ /// \brief This is the list of tokens that the macro is defined to.
SmallVector<Token, 8> ReplacementTokens;
/// \brief Length in characters of the macro definition.
mutable unsigned DefinitionLength;
mutable bool IsDefinitionLengthCached : 1;
- /// IsFunctionLike - True if this macro is a function-like macro, false if it
+ /// \brief True if this macro is a function-like macro, false if it
/// is an object-like macro.
bool IsFunctionLike : 1;
@@ -71,7 +70,7 @@ class MacroInfo {
/// it has not yet been redefined or undefined.
bool IsBuiltinMacro : 1;
- /// IsFromAST - True if this macro was loaded from an AST file.
+ /// \brief True if this macro was loaded from an AST file.
bool IsFromAST : 1;
/// \brief Whether this macro changed after it was loaded from an AST file.
@@ -82,8 +81,8 @@ private:
// State that changes as the macro is used.
/// IsDisabled - True if we have started an expansion of this macro already.
- /// This disbles recursive expansion, which would be quite bad for things like
- /// #define A A.
+ /// This disables recursive expansion, which would be quite bad for things
+ /// like \#define A A.
bool IsDisabled : 1;
/// IsUsed - True if this macro is either defined in the main file and has
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index 4ebb1d42bf3d..fe5abdfba7ad 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -126,7 +126,7 @@ public:
/// \brief Retrieve a module with the given name.
///
- /// \param The name of the module to look up.
+ /// \param Name The name of the module to look up.
///
/// \returns The named module, if known; otherwise, returns null.
Module *findModule(StringRef Name);
@@ -134,7 +134,7 @@ public:
/// \brief Retrieve a module with the given name using lexical name lookup,
/// starting at the given context.
///
- /// \param The name of the module to look up.
+ /// \param Name The name of the module to look up.
///
/// \param Context The module context, from which we will perform lexical
/// name lookup.
@@ -145,7 +145,7 @@ public:
/// \brief Retrieve a module with the given name within the given context,
/// using direct (qualified) name lookup.
///
- /// \param The name of the module to look up.
+ /// \param Name The name of the module to look up.
///
/// \param Context The module for which we will look for a submodule. If
/// null, we will look for a top-level module.
diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h
index 95b00dfcf366..a2a5a77c73d7 100644
--- a/include/clang/Lex/MultipleIncludeOpt.h
+++ b/include/clang/Lex/MultipleIncludeOpt.h
@@ -6,8 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the MultipleIncludeOpt interface.
+///
+/// \file
+/// \brief Defines the MultipleIncludeOpt interface.
//
//===----------------------------------------------------------------------===//
@@ -17,17 +18,18 @@
namespace clang {
class IdentifierInfo;
-/// MultipleIncludeOpt - This class implements the simple state machine that the
-/// Lexer class uses to detect files subject to the 'multiple-include'
-/// optimization. The public methods in this class are triggered by various
+/// \brief Implements the simple state machine that the Lexer class uses to
+/// detect files subject to the 'multiple-include' optimization.
+///
+/// The public methods in this class are triggered by various
/// events that occur when a file is lexed, and after the entire file is lexed,
/// information about which macro (if any) controls the header is returned.
class MultipleIncludeOpt {
/// ReadAnyTokens - This is set to false when a file is first opened and true
/// any time a token is returned to the client or a (non-multiple-include)
- /// directive is parsed. When the final #endif is parsed this is reset back
- /// to false, that way any tokens before the first #ifdef or after the last
- /// #endif can be easily detected.
+ /// directive is parsed. When the final \#endif is parsed this is reset back
+ /// to false, that way any tokens before the first \#ifdef or after the last
+ /// \#endif can be easily detected.
bool ReadAnyTokens;
/// ReadAnyTokens - This is set to false when a file is first opened and true
@@ -56,7 +58,7 @@ public:
TheMacro = 0;
}
- /// getHasReadAnyTokensVal - This is used for the #ifndef hande-shake at the
+ /// getHasReadAnyTokensVal - This is used for the \#ifndef hande-shake at the
/// top of the file when reading preprocessor directives. Otherwise, reading
/// the "ifndef x" would count as reading tokens.
bool getHasReadAnyTokensVal() const { return ReadAnyTokens; }
@@ -68,14 +70,13 @@ public:
/// buffer, this method is called to disable the MIOpt if needed.
void ExpandedMacro() { DidMacroExpansion = true; }
- /// EnterTopLevelIFNDEF - When entering a top-level #ifndef directive (or the
- /// "#if !defined" equivalent) without any preceding tokens, this method is
- /// called.
+ /// \brief Called when entering a top-level \#ifndef directive (or the
+ /// "\#if !defined" equivalent) without any preceding tokens.
///
/// Note, we don't care about the input value of 'ReadAnyTokens'. The caller
/// ensures that this is only called if there are no tokens read before the
- /// #ifndef. The caller is required to do this, because reading the #if line
- /// obviously reads in in tokens.
+ /// \#ifndef. The caller is required to do this, because reading the \#if
+ /// line obviously reads in in tokens.
void EnterTopLevelIFNDEF(const IdentifierInfo *M) {
// If the macro is already set, this is after the top-level #endif.
if (TheMacro)
@@ -93,16 +94,14 @@ public:
TheMacro = M;
}
- /// EnterTopLevelConditional - This is invoked when a top level conditional
- /// (except #ifndef) is found.
+ /// \brief Invoked when a top level conditional (except \#ifndef) is found.
void EnterTopLevelConditional() {
- /// If a conditional directive (except #ifndef) is found at the top level,
- /// there is a chunk of the file not guarded by the controlling macro.
+ // If a conditional directive (except #ifndef) is found at the top level,
+ // there is a chunk of the file not guarded by the controlling macro.
Invalidate();
}
- /// ExitTopLevelConditional - This method is called when the lexer exits the
- /// top-level conditional.
+ /// \brief Called when the lexer exits the top-level conditional.
void ExitTopLevelConditional() {
// If we have a macro, that means the top of the file was ok. Set our state
// back to "not having read any tokens" so we can detect anything after the
@@ -114,8 +113,8 @@ public:
ReadAnyTokens = false;
}
- /// GetControllingMacroAtEndOfFile - Once the entire file has been lexed, if
- /// there is a controlling macro, return it.
+ /// \brief Once the entire file has been lexed, if there is a controlling
+ /// macro, return it.
const IdentifierInfo *GetControllingMacroAtEndOfFile() const {
// If we haven't read any tokens after the #endif, return the controlling
// macro if it's valid (if it isn't, it will be null).
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index 33558c8dfdc9..962b4df6c492 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the PPCallbacks interface.
-//
+///
+/// \file
+/// \brief Defines the PPCallbacks interface.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_PPCALLBACKS_H
@@ -26,9 +27,10 @@ namespace clang {
class IdentifierInfo;
class MacroInfo;
-/// PPCallbacks - This interface provides a way to observe the actions of the
-/// preprocessor as it does its thing. Clients can define their hooks here to
-/// implement preprocessor level tools.
+/// \brief This interface provides a way to observe the actions of the
+/// preprocessor as it does its thing.
+///
+/// Clients can define their hooks here to implement preprocessor level tools.
class PPCallbacks {
public:
virtual ~PPCallbacks();
@@ -37,29 +39,29 @@ public:
EnterFile, ExitFile, SystemHeaderPragma, RenameFile
};
- /// FileChanged - This callback is invoked whenever a source file is
- /// entered or exited. The SourceLocation indicates the new location, and
- /// EnteringFile indicates whether this is because we are entering a new
- /// #include'd file (when true) or whether we're exiting one because we ran
- /// off the end (when false).
+ /// \brief Callback invoked whenever a source file is entered or exited.
///
- /// \param PrevFID the file that was exited if \arg Reason is ExitFile.
+ /// \param Loc Indicates the new location.
+ /// \param PrevFID the file that was exited if \p Reason is ExitFile.
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
FileID PrevFID = FileID()) {
}
- /// FileSkipped - This callback is invoked whenever a source file is
- /// skipped as the result of header guard optimization. ParentFile
- /// is the file that #includes the skipped file. FilenameTok is the
- /// token in ParentFile that indicates the skipped file.
+ /// \brief Callback invoked whenever a source file is skipped as the result
+ /// of header guard optimization.
+ ///
+ /// \param ParentFile The file that \#included the skipped file.
+ ///
+ /// \param FilenameTok The token in ParentFile that indicates the
+ /// skipped file.
virtual void FileSkipped(const FileEntry &ParentFile,
const Token &FilenameTok,
SrcMgr::CharacteristicKind FileType) {
}
- /// FileNotFound - This callback is invoked whenever an inclusion directive
- /// results in a file-not-found error.
+ /// \brief Callback invoked whenever an inclusion directive results in a
+ /// file-not-found error.
///
/// \param FileName The name of the file being included, as written in the
/// source code.
@@ -75,8 +77,8 @@ public:
return false;
}
- /// \brief This callback is invoked whenever an inclusion directive of
- /// any kind (\c #include, \c #import, etc.) has been processed, regardless
+ /// \brief Callback invoked whenever an inclusion directive of
+ /// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
/// of whether the inclusion will actually result in an inclusion.
///
/// \param HashLoc The location of the '#' that starts the inclusion
@@ -118,119 +120,116 @@ public:
StringRef RelativePath) {
}
- /// EndOfMainFile - This callback is invoked when the end of the main file is
- /// reach, no subsequent callbacks will be made.
+ /// \brief Callback invoked when the end of the main file is reached.
+ ///
+ /// No subsequent callbacks will be made.
virtual void EndOfMainFile() {
}
- /// Ident - This callback is invoked when a #ident or #sccs directive is read.
+ /// \brief Callback invoked when a \#ident or \#sccs directive is read.
/// \param Loc The location of the directive.
/// \param str The text of the directive.
///
virtual void Ident(SourceLocation Loc, const std::string &str) {
}
- /// PragmaComment - This callback is invoked when a #pragma comment directive
- /// is read.
- ///
+ /// \brief Callback invoked when a \#pragma comment directive is read.
virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
const std::string &Str) {
}
- /// PragmaMessage - This callback is invoked when a #pragma message directive
- /// is read.
+ /// \brief Callback invoked when a \#pragma message directive is read.
/// \param Loc The location of the message directive.
- /// \param str The text of the message directive.
- ///
+ /// \param Str The text of the message directive.
virtual void PragmaMessage(SourceLocation Loc, StringRef Str) {
}
- /// PragmaDiagnosticPush - This callback is invoked when a
- /// #pragma gcc dianostic push directive is read.
+ /// \brief Callback invoked when a \#pragma gcc dianostic push directive
+ /// is read.
virtual void PragmaDiagnosticPush(SourceLocation Loc,
StringRef Namespace) {
}
- /// PragmaDiagnosticPop - This callback is invoked when a
- /// #pragma gcc dianostic pop directive is read.
+ /// \brief Callback invoked when a \#pragma gcc dianostic pop directive
+ /// is read.
virtual void PragmaDiagnosticPop(SourceLocation Loc,
StringRef Namespace) {
}
- /// PragmaDiagnostic - This callback is invoked when a
- /// #pragma gcc dianostic directive is read.
+ /// \brief Callback invoked when a \#pragma gcc dianostic directive is read.
virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
diag::Mapping mapping, StringRef Str) {
}
- /// MacroExpands - This is called by
- /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is
- /// found.
+ /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a
+ /// macro invocation is found.
virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI,
SourceRange Range) {
}
- /// MacroDefined - This hook is called whenever a macro definition is seen.
+ /// \brief Hook called whenever a macro definition is seen.
virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
}
- /// MacroUndefined - This hook is called whenever a macro #undef is seen.
+ /// \brief Hook called whenever a macro \#undef is seen.
+ ///
/// MI is released immediately following this callback.
virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
}
- /// Defined - This hook is called whenever the 'defined' operator is seen.
+ /// \brief Hook called whenever the 'defined' operator is seen.
virtual void Defined(const Token &MacroNameTok) {
}
- /// SourceRangeSkipped - This hook is called when a source range is skipped.
+ /// \brief Hook called when a source range is skipped.
/// \param Range The SourceRange that was skipped. The range begins at the
- /// #if/#else directive and ends after the #endif/#else directive.
+ /// \#if/\#else directive and ends after the \#endif/\#else directive.
virtual void SourceRangeSkipped(SourceRange Range) {
}
- /// If -- This hook is called whenever an #if is seen.
+ /// \brief Hook called whenever an \#if is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
+ ///
// FIXME: better to pass in a list (or tree!) of Tokens.
virtual void If(SourceLocation Loc, SourceRange ConditionRange) {
}
- /// Elif -- This hook is called whenever an #elif is seen.
+ /// \brief Hook called whenever an \#elif is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
- /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
// FIXME: better to pass in a list (or tree!) of Tokens.
virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
SourceLocation IfLoc) {
}
- /// Ifdef -- This hook is called whenever an #ifdef is seen.
+ /// \brief Hook called whenever an \#ifdef is seen.
/// \param Loc the source location of the directive.
- /// \param II Information on the token being tested.
+ /// \param MacroNameTok Information on the token being tested.
virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) {
}
- /// Ifndef -- This hook is called whenever an #ifndef is seen.
+ /// \brief Hook called whenever an \#ifndef is seen.
/// \param Loc the source location of the directive.
- /// \param II Information on the token being tested.
+ /// \param MacroNameTok Information on the token being tested.
virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) {
}
- /// Else -- This hook is called whenever an #else is seen.
+ /// \brief Hook called whenever an \#else is seen.
/// \param Loc the source location of the directive.
- /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
}
- /// Endif -- This hook is called whenever an #endif is seen.
+ /// \brief Hook called whenever an \#endif is seen.
/// \param Loc the source location of the directive.
- /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
}
};
-/// PPChainedCallbacks - Simple wrapper class for chaining callbacks.
+/// \brief Simple wrapper class for chaining callbacks.
class PPChainedCallbacks : public PPCallbacks {
virtual void anchor();
PPCallbacks *First, *Second;
@@ -342,38 +341,38 @@ public:
Second->SourceRangeSkipped(Range);
}
- /// If -- This hook is called whenever an #if is seen.
+ /// \brief Hook called whenever an \#if is seen.
virtual void If(SourceLocation Loc, SourceRange ConditionRange) {
First->If(Loc, ConditionRange);
Second->If(Loc, ConditionRange);
}
- /// Elif -- This hook is called whenever an #if is seen.
+ /// \brief Hook called whenever an \#if is seen.
virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
SourceLocation IfLoc) {
First->Elif(Loc, ConditionRange, IfLoc);
Second->Elif(Loc, ConditionRange, IfLoc);
}
- /// Ifdef -- This hook is called whenever an #ifdef is seen.
+ /// \brief Hook called whenever an \#ifdef is seen.
virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) {
First->Ifdef(Loc, MacroNameTok);
Second->Ifdef(Loc, MacroNameTok);
}
- /// Ifndef -- This hook is called whenever an #ifndef is seen.
+ /// \brief Hook called whenever an \#ifndef is seen.
virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) {
First->Ifndef(Loc, MacroNameTok);
Second->Ifndef(Loc, MacroNameTok);
}
- /// Else -- This hook is called whenever an #else is seen.
+ /// \brief Hook called whenever an \#else is seen.
virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
First->Else(Loc, IfLoc);
Second->Else(Loc, IfLoc);
}
- /// Endif -- This hook is called whenever an #endif is seen.
+ /// \brief Hook called whenever an \#endif is seen.
virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
First->Endif(Loc, IfLoc);
Second->Endif(Loc, IfLoc);
diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h
index 4868811e7036..087448fbc5ff 100644
--- a/include/clang/Lex/Pragma.h
+++ b/include/clang/Lex/Pragma.h
@@ -26,12 +26,12 @@ namespace clang {
class PragmaNamespace;
/**
- * \brief Describes how the pragma was introduced, e.g., with #pragma,
+ * \brief Describes how the pragma was introduced, e.g., with \#pragma,
* _Pragma, or __pragma.
*/
enum PragmaIntroducerKind {
/**
- * \brief The pragma was introduced via #pragma.
+ * \brief The pragma was introduced via \#pragma.
*/
PIK_HashPragma,
@@ -54,7 +54,7 @@ namespace clang {
/// pragmas the handler with a null identifier is invoked, if it exists.
///
/// Note that the PragmaNamespace class can be used to subdivide pragmas, e.g.
-/// we treat "#pragma STDC" and "#pragma GCC" as namespaces that contain other
+/// we treat "\#pragma STDC" and "\#pragma GCC" as namespaces that contain other
/// pragmas.
class PragmaHandler {
std::string Name;
@@ -84,8 +84,8 @@ public:
/// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas,
/// allowing hierarchical pragmas to be defined. Common examples of namespaces
-/// are "#pragma GCC", "#pragma STDC", and "#pragma omp", but any namespaces may
-/// be (potentially recursively) defined.
+/// are "\#pragma GCC", "\#pragma STDC", and "\#pragma omp", but any namespaces
+/// may be (potentially recursively) defined.
class PragmaNamespace : public PragmaHandler {
/// Handlers - This is a map of the handlers in this namespace with their name
/// as key.
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index 45e3a5d64730..fb3e081961bf 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -59,8 +59,8 @@ namespace clang {
/// \brief A macro definition.
MacroDefinitionKind,
- /// \brief An inclusion directive, such as \c #include, \c
- /// #import, or \c #include_next.
+ /// \brief An inclusion directive, such as \c \#include, \c
+ /// \#import, or \c \#include_next.
InclusionDirectiveKind,
/// @}
@@ -197,19 +197,19 @@ namespace clang {
};
/// \brief Record the location of an inclusion directive, such as an
- /// \c #include or \c #import statement.
+ /// \c \#include or \c \#import statement.
class InclusionDirective : public PreprocessingDirective {
public:
/// \brief The kind of inclusion directives known to the
/// preprocessor.
enum InclusionKind {
- /// \brief An \c #include directive.
+ /// \brief An \c \#include directive.
Include,
- /// \brief An Objective-C \c #import directive.
+ /// \brief An Objective-C \c \#import directive.
Import,
- /// \brief A GNU \c #include_next directive.
+ /// \brief A GNU \c \#include_next directive.
IncludeNext,
- /// \brief A Clang \c #__include_macros directive.
+ /// \brief A Clang \c \#__include_macros directive.
IncludeMacros
};
@@ -551,7 +551,7 @@ namespace clang {
///
/// Can be used to avoid implicit deserializations of preallocated
/// preprocessed entities if we only care about entities of a specific file
- /// and not from files #included in the range given at
+ /// and not from files \#included in the range given at
/// \see getPreprocessedEntitiesInRange.
bool isEntityInFileID(iterator PPEI, FileID FID);
@@ -565,7 +565,7 @@ namespace clang {
}
/// \brief Returns true if the given range intersects with a conditional
- /// directive. if a #if/#endif block is fully contained within the range,
+ /// directive. if a \#if/\#endif block is fully contained within the range,
/// this function will return false.
bool rangeIntersectsConditionalDirective(SourceRange Range) const;
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 055008fd44ce..02e3f1e7e439 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -58,7 +58,7 @@ class ModuleLoader;
/// Preprocessor - This object engages in a tight little dance with the lexer to
/// efficiently preprocess tokens. Lexers know only about tokens within a
/// single source file, and don't know anything about preprocessor-level issues
-/// like the #include stack, token expansion, etc.
+/// like the \#include stack, token expansion, etc.
///
class Preprocessor : public RefCountedBase<Preprocessor> {
DiagnosticsEngine *Diags;
@@ -103,7 +103,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
unsigned CounterValue; // Next __COUNTER__ value.
enum {
- /// MaxIncludeStackDepth - Maximum depth of #includes.
+ /// MaxIncludeStackDepth - Maximum depth of \#includes.
MaxAllowedIncludeStackDepth = 200
};
@@ -121,9 +121,19 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
/// DisableMacroExpansion - True if macro expansion is disabled.
bool DisableMacroExpansion : 1;
+ /// MacroExpansionInDirectivesOverride - Temporarily disables
+ /// DisableMacroExpansion (i.e. enables expansion) when parsing preprocessor
+ /// directives.
+ bool MacroExpansionInDirectivesOverride : 1;
+
+ class ResetMacroExpansionHelper;
+
/// \brief Whether we have already loaded macros from the external source.
mutable bool ReadMacrosFromExternalSource : 1;
+ /// \brief True if pragmas are enabled.
+ bool PragmasEnabled : 1;
+
/// \brief True if we are pre-expanding macro arguments.
bool InMacroArgPreExpansion;
@@ -165,11 +175,12 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
unsigned CodeCompletionOffset;
/// \brief The location for the code-completion point. This gets instantiated
- /// when the CodeCompletionFile gets #include'ed for preprocessing.
+ /// when the CodeCompletionFile gets \#include'ed for preprocessing.
SourceLocation CodeCompletionLoc;
/// \brief The start location for the file of the code-completion point.
- /// This gets instantiated when the CodeCompletionFile gets #include'ed
+ ///
+ /// This gets instantiated when the CodeCompletionFile gets \#include'ed
/// for preprocessing.
SourceLocation CodeCompletionFileLoc;
@@ -215,7 +226,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
/// CurLookup - The DirectoryLookup structure used to find the current
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
- /// implement #include_next and find directory-specific properties.
+ /// implement \#include_next and find directory-specific properties.
const DirectoryLookup *CurDirLookup;
/// CurTokenLexer - This is the current macro we are expanding, if we are
@@ -232,7 +243,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
} CurLexerKind;
/// IncludeMacroStack - This keeps track of the stack of files currently
- /// #included, and macros currently being expanded from, not counting
+ /// \#included, and macros currently being expanded from, not counting
/// CurLexer/CurTokenLexer.
struct IncludeStackInfo {
enum CurLexerKind CurLexerKind;
@@ -251,9 +262,18 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
std::vector<IncludeStackInfo> IncludeMacroStack;
/// Callbacks - These are actions invoked when some preprocessor activity is
- /// encountered (e.g. a file is #included, etc).
+ /// encountered (e.g. a file is \#included, etc).
PPCallbacks *Callbacks;
+ struct MacroExpandsInfo {
+ Token Tok;
+ MacroInfo *MI;
+ SourceRange Range;
+ MacroExpandsInfo(Token Tok, MacroInfo *MI, SourceRange Range)
+ : Tok(Tok), MI(MI), Range(Range) { }
+ };
+ SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks;
+
/// Macros - For each IdentifierInfo with 'HasMacro' set, we keep a mapping
/// to the actual definition of the macro.
llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros;
@@ -400,6 +420,9 @@ public:
bool getCommentRetentionState() const { return KeepComments; }
+ void setPragmasEnabled(bool Enabled) { PragmasEnabled = Enabled; }
+ bool getPragmasEnabled() const { return PragmasEnabled; }
+
void SetSuppressIncludeNotFoundError(bool Suppress) {
SuppressIncludeNotFoundError = Suppress;
}
@@ -434,8 +457,8 @@ public:
Callbacks = C;
}
- /// getMacroInfo - Given an identifier, return the MacroInfo it is #defined to
- /// or null if it isn't #define'd.
+ /// \brief Given an identifier, return the MacroInfo it is \#defined to
+ /// or null if it isn't \#define'd.
MacroInfo *getMacroInfo(IdentifierInfo *II) const {
if (!II->hasMacroDefinition())
return 0;
@@ -443,8 +466,7 @@ public:
return getInfoForMacro(II);
}
- /// setMacroInfo - Specify a macro for this identifier.
- ///
+ /// \brief Specify a macro for this identifier.
void setMacroInfo(IdentifierInfo *II, MacroInfo *MI,
bool LoadedFromAST = false);
@@ -488,12 +510,12 @@ public:
}
/// \brief Add the specified comment handler to the preprocessor.
- void AddCommentHandler(CommentHandler *Handler);
+ void addCommentHandler(CommentHandler *Handler);
/// \brief Remove the specified comment handler.
///
/// It is an error to remove a handler that has not been registered.
- void RemoveCommentHandler(CommentHandler *Handler);
+ void removeCommentHandler(CommentHandler *Handler);
/// \brief Set the code completion handler to the given object.
void setCodeCompletionHandler(CodeCompletionHandler &Handler) {
@@ -634,6 +656,12 @@ public:
while (Result.getKind() == tok::comment);
}
+ /// Disables macro expansion everywhere except for preprocessor directives.
+ void SetMacroExpansionOnlyInDirectives() {
+ DisableMacroExpansion = true;
+ MacroExpansionInDirectivesOverride = true;
+ }
+
/// LookAhead - This peeks ahead N tokens and returns that token without
/// consuming any tokens. LookAhead(0) returns the next token that would be
/// returned by Lex(), LookAhead(1) returns the token after it, etc. This
@@ -752,25 +780,24 @@ public:
getDiagnostics().setSuppressAllDiagnostics(true);
}
- /// \brief The location of the currently-active #pragma clang
+ /// \brief The location of the currently-active \#pragma clang
/// arc_cf_code_audited begin. Returns an invalid location if there
/// is no such pragma active.
SourceLocation getPragmaARCCFCodeAuditedLoc() const {
return PragmaARCCFCodeAuditedLoc;
}
- /// \brief Set the location of the currently-active #pragma clang
+ /// \brief Set the location of the currently-active \#pragma clang
/// arc_cf_code_audited begin. An invalid location ends the pragma.
void setPragmaARCCFCodeAuditedLoc(SourceLocation Loc) {
PragmaARCCFCodeAuditedLoc = Loc;
}
- /// \brief Instruct the preprocessor to skip part of the main
- /// the main source file.
+ /// \brief Instruct the preprocessor to skip part of the main source file.
///
- /// \brief Bytes The number of bytes in the preamble to skip.
+ /// \param Bytes The number of bytes in the preamble to skip.
///
- /// \brief StartOfLine Whether skipping these bytes puts the lexer at the
+ /// \param StartOfLine Whether skipping these bytes puts the lexer at the
/// start of a line.
void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) {
SkipMainFilePreamble.first = Bytes;
@@ -1035,24 +1062,27 @@ public:
/// \brief Retrieves the module that we're currently building, if any.
Module *getCurrentModule();
- /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide
- /// SourceLocation.
+ /// \brief Allocate a new MacroInfo object with the provided SourceLocation.
MacroInfo *AllocateMacroInfo(SourceLocation L);
- /// CloneMacroInfo - Allocate a new MacroInfo object which is clone of MI.
+ /// \brief Allocate a new MacroInfo object which is clone of \p MI.
MacroInfo *CloneMacroInfo(const MacroInfo &MI);
- /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
- /// checked and spelled filename, e.g. as an operand of #include. This returns
- /// true if the input filename was in <>'s or false if it were in ""'s. The
- /// caller is expected to provide a buffer that is large enough to hold the
- /// spelling of the filename, but is also expected to handle the case when
- /// this method decides to use a different buffer.
+ /// \brief Turn the specified lexer token into a fully checked and spelled
+ /// filename, e.g. as an operand of \#include.
+ ///
+ /// The caller is expected to provide a buffer that is large enough to hold
+ /// the spelling of the filename, but is also expected to handle the case
+ /// when this method decides to use a different buffer.
+ ///
+ /// \returns true if the input filename was in <>'s or false if it was
+ /// in ""'s.
bool GetIncludeFilenameSpelling(SourceLocation Loc,StringRef &Filename);
- /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
- /// return null on failure. isAngled indicates whether the file reference is
- /// for system #include's or not (i.e. using <> instead of "").
+ /// \brief Given a "foo" or \<foo> reference, look up the indicated file.
+ ///
+ /// Returns null on failure. \p isAngled indicates whether the file
+ /// reference is for system \#include's or not (i.e. using <> instead of "").
const FileEntry *LookupFile(StringRef Filename,
bool isAngled, const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir,
@@ -1063,18 +1093,19 @@ public:
/// GetCurLookup - The DirectoryLookup structure used to find the current
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
- /// implement #include_next and find directory-specific properties.
+ /// implement \#include_next and find directory-specific properties.
const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; }
- /// isInPrimaryFile - Return true if we're in the top-level file, not in a
- /// #include.
+ /// \brief Return true if we're in the top-level file, not in a \#include.
bool isInPrimaryFile() const;
- /// ConcatenateIncludeName - Handle cases where the #include name is expanded
+ /// ConcatenateIncludeName - Handle cases where the \#include name is expanded
/// from a macro as multiple tokens, which need to be glued together. This
/// occurs for code like:
- /// #define FOO <a/b.h>
- /// #include FOO
+ /// \code
+ /// \#define FOO <a/b.h>
+ /// \#include FOO
+ /// \endcode
/// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
///
/// This code concatenates and consumes tokens up to the '>' token. It
@@ -1109,15 +1140,16 @@ private:
IncludeMacroStack.pop_back();
}
- /// AllocateMacroInfo - Allocate a new MacroInfo object.
+ /// \brief Allocate a new MacroInfo object.
MacroInfo *AllocateMacroInfo();
- /// ReleaseMacroInfo - Release the specified MacroInfo. This memory will
- /// be reused for allocating new MacroInfo objects.
+ /// \brief Release the specified MacroInfo for re-use.
+ ///
+ /// This memory will be reused for allocating new MacroInfo objects.
void ReleaseMacroInfo(MacroInfo* MI);
/// ReadMacroName - Lex and validate a macro name, which occurs after a
- /// #define or #undef. This emits a diagnostic, sets the token kind to eod,
+ /// \#define or \#undef. This emits a diagnostic, sets the token kind to eod,
/// and discards the rest of the macro line if the macro name is invalid.
void ReadMacroName(Token &MacroNameTok, char isDefineUndef = 0);
@@ -1128,20 +1160,19 @@ private:
/// Return true if an error occurs parsing the arg list.
bool ReadMacroDefinitionArgList(MacroInfo *MI, Token& LastTok);
- /// SkipExcludedConditionalBlock - We just read a #if or related directive and
- /// decided that the subsequent tokens are in the #if'd out portion of the
- /// file. Lex the rest of the file, until we see an #endif. If
+ /// We just read a \#if or related directive and decided that the
+ /// subsequent tokens are in the \#if'd out portion of the
+ /// file. Lex the rest of the file, until we see an \#endif. If \p
/// FoundNonSkipPortion is true, then we have already emitted code for part of
- /// this #if directive, so #else/#elif blocks should never be entered. If
- /// FoundElse is false, then #else directives are ok, if not, then we have
- /// already seen one so a #else directive is a duplicate. When this returns,
+ /// this \#if directive, so \#else/\#elif blocks should never be entered. If
+ /// \p FoundElse is false, then \#else directives are ok, if not, then we have
+ /// already seen one so a \#else directive is a duplicate. When this returns,
/// the caller can lex the first valid token.
void SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
bool FoundNonSkipPortion, bool FoundElse,
SourceLocation ElseLoc = SourceLocation());
- /// PTHSkipExcludedConditionalBlock - A fast PTH version of
- /// SkipExcludedConditionalBlock.
+ /// \brief A fast PTH version of SkipExcludedConditionalBlock.
void PTHSkipExcludedConditionalBlock();
/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
@@ -1150,11 +1181,10 @@ private:
bool EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro);
/// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
- /// #pragma GCC poison/system_header/dependency and #pragma once.
+ /// \#pragma GCC poison/system_header/dependency and \#pragma once.
void RegisterBuiltinPragmas();
- /// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
- /// identifier table.
+ /// \brief Register builtin macros such as __LINE__ with the identifier table.
void RegisterBuiltinMacros();
/// HandleMacroExpandedIdentifier - If an identifier token is read that is to
diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h
index b551cd431018..8a0b3cf51acc 100644
--- a/include/clang/Lex/PreprocessorLexer.h
+++ b/include/clang/Lex/PreprocessorLexer.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the PreprocessorLexer interface.
-//
+///
+/// \file
+/// \brief Defines the PreprocessorLexer interface.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PreprocessorLexer_H
@@ -38,16 +39,17 @@ protected:
// Context-specific lexing flags set by the preprocessor.
//===--------------------------------------------------------------------===//
- /// ParsingPreprocessorDirective - This is true when parsing #XXX. This turns
- /// '\n' into a tok::eod token.
+ /// \brief True when parsing \#XXX; turns '\\n' into a tok::eod token.
bool ParsingPreprocessorDirective;
- /// ParsingFilename - True after #include: this turns <xx> into a
- /// tok::angle_string_literal token.
+ /// \brief True after \#include; turns \<xx> into a tok::angle_string_literal
+ /// token.
bool ParsingFilename;
- /// LexingRawMode - True if in raw mode: This flag disables interpretation of
- /// tokens and is a far faster mode to lex in than non-raw-mode. This flag:
+ /// \brief True if in raw mode.
+ ///
+ /// Raw mode disables interpretation of tokens and is a far faster mode to
+ /// lex in than non-raw-mode. This flag:
/// 1. If EOF of the current lexer is found, the include stack isn't popped.
/// 2. Identifier information is not looked up for identifier tokens. As an
/// effect of this, implicit macro expansion is naturally disabled.
@@ -59,11 +61,11 @@ protected:
/// Note that in raw mode that the PP pointer may be null.
bool LexingRawMode;
- /// MIOpt - This is a state machine that detects the #ifndef-wrapping a file
+ /// \brief A state machine that detects the \#ifndef-wrapping a file
/// idiom for the multiple-include optimization.
MultipleIncludeOpt MIOpt;
- /// ConditionalStack - Information about the set of #if/#ifdef/#ifndef blocks
+ /// \brief Information about the set of \#if/\#ifdef/\#ifndef blocks
/// we are currently in.
SmallVector<PPConditionalInfo, 4> ConditionalStack;
@@ -83,16 +85,15 @@ protected:
virtual void IndirectLex(Token& Result) = 0;
- /// getSourceLocation - Return the source location for the next observable
- /// location.
+ /// \brief Return the source location for the next observable location.
virtual SourceLocation getSourceLocation() = 0;
//===--------------------------------------------------------------------===//
// #if directive handling.
- /// pushConditionalLevel - When we enter a #if directive, this keeps track of
- /// what we are currently in for diagnostic emission (e.g. #if with missing
- /// #endif).
+ /// pushConditionalLevel - When we enter a \#if directive, this keeps track of
+ /// what we are currently in for diagnostic emission (e.g. \#if with missing
+ /// \#endif).
void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping,
bool FoundNonSkip, bool FoundElse) {
PPConditionalInfo CI;
@@ -116,8 +117,8 @@ protected:
return false;
}
- /// peekConditionalLevel - Return the top of the conditional stack. This
- /// requires that there be a conditional active.
+ /// \brief Return the top of the conditional stack.
+ /// \pre This requires that there be a conditional active.
PPConditionalInfo &peekConditionalLevel() {
assert(!ConditionalStack.empty() && "No conditionals active!");
return ConditionalStack.back();
@@ -130,21 +131,23 @@ public:
//===--------------------------------------------------------------------===//
// Misc. lexing methods.
- /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
- /// (potentially) macro expand the filename. If the sequence parsed is not
- /// lexically legal, emit a diagnostic and return a result EOD token.
+ /// \brief After the preprocessor has parsed a \#include, lex and
+ /// (potentially) macro expand the filename.
+ ///
+ /// If the sequence parsed is not lexically legal, emit a diagnostic and
+ /// return a result EOD token.
void LexIncludeFilename(Token &Result);
- /// setParsingPreprocessorDirective - Inform the lexer whether or not
- /// we are currently lexing a preprocessor directive.
+ /// \brief Inform the lexer whether or not we are currently lexing a
+ /// preprocessor directive.
void setParsingPreprocessorDirective(bool f) {
ParsingPreprocessorDirective = f;
}
- /// isLexingRawMode - Return true if this lexer is in raw mode or not.
+ /// \brief Return true if this lexer is in raw mode or not.
bool isLexingRawMode() const { return LexingRawMode; }
- /// getPP - Return the preprocessor object for this lexer.
+ /// \brief Return the preprocessor object for this lexer.
Preprocessor *getPP() const { return PP; }
FileID getFileID() const {
@@ -163,7 +166,7 @@ public:
const FileEntry *getFileEntry() const;
/// \brief Iterator that traverses the current stack of preprocessor
- /// conditional directives (#if/#ifdef/#ifndef).
+ /// conditional directives (\#if/\#ifdef/\#ifndef).
typedef SmallVectorImpl<PPConditionalInfo>::const_iterator
conditional_iterator;
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index a88f607298e8..9c5a023f30d9 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -87,7 +87,7 @@ public:
bool is(tok::TokenKind K) const { return Kind == (unsigned) K; }
bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; }
- /// isAnyIdentifier - Return true if this is a raw identifier (when lexing
+ /// \brief Return true if this is a raw identifier (when lexing
/// in raw mode) or a non-keyword identifier (when lexing in non-raw mode).
bool isAnyIdentifier() const {
return is(tok::identifier) || is(tok::raw_identifier);
@@ -112,7 +112,7 @@ public:
return false;
}
- /// getLocation - Return a source location identifier for the specified
+ /// \brief Return a source location identifier for the specified
/// offset in the current file.
SourceLocation getLocation() const { return Loc; }
unsigned getLength() const {
@@ -139,8 +139,8 @@ public:
return isAnnotation() ? getAnnotationEndLoc() : getLocation();
}
- /// getAnnotationRange - SourceRange of the group of tokens that this
- /// annotation token represents.
+ /// \brief SourceRange of the group of tokens that this annotation token
+ /// represents.
SourceRange getAnnotationRange() const {
return SourceRange(getLocation(), getAnnotationEndLoc());
}
@@ -153,8 +153,7 @@ public:
return tok::getTokenName( (tok::TokenKind) Kind);
}
- /// startToken - Reset all flags to cleared.
- ///
+ /// \brief Reset all flags to cleared.
void startToken() {
Kind = tok::unknown;
Flags = 0;
@@ -208,24 +207,25 @@ public:
PtrData = val;
}
- /// setFlag - Set the specified flag.
+ /// \brief Set the specified flag.
void setFlag(TokenFlags Flag) {
Flags |= Flag;
}
- /// clearFlag - Unset the specified flag.
+ /// \brief Unset the specified flag.
void clearFlag(TokenFlags Flag) {
Flags &= ~Flag;
}
- /// getFlags - Return the internal represtation of the flags.
- /// Only intended for low-level operations such as writing tokens to
- // disk.
+ /// \brief Return the internal represtation of the flags.
+ ///
+ /// This is only intended for low-level operations such as writing tokens to
+ /// disk.
unsigned getFlags() const {
return Flags;
}
- /// setFlagValue - Set a flag to either true or false.
+ /// \brief Set a flag to either true or false.
void setFlagValue(TokenFlags Flag, bool Val) {
if (Val)
setFlag(Flag);
@@ -237,25 +237,23 @@ public:
///
bool isAtStartOfLine() const { return (Flags & StartOfLine) ? true : false; }
- /// hasLeadingSpace - Return true if this token has whitespace before it.
+ /// \brief Return true if this token has whitespace before it.
///
bool hasLeadingSpace() const { return (Flags & LeadingSpace) ? true : false; }
- /// isExpandDisabled - Return true if this identifier token should never
+ /// \brief Return true if this identifier token should never
/// be expanded in the future, due to C99 6.10.3.4p2.
bool isExpandDisabled() const {
return (Flags & DisableExpand) ? true : false;
}
- /// isObjCAtKeyword - Return true if we have an ObjC keyword identifier.
+ /// \brief Return true if we have an ObjC keyword identifier.
bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const;
- /// getObjCKeywordID - Return the ObjC keyword kind.
+ /// \brief Return the ObjC keyword kind.
tok::ObjCKeywordKind getObjCKeywordID() const;
- /// needsCleaning - Return true if this token has trigraphs or escaped
- /// newlines in it.
- ///
+ /// \brief Return true if this token has trigraphs or escaped newlines in it.
bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; }
/// \brief Return true if this token has an empty macro before it.
@@ -269,23 +267,22 @@ public:
bool hasUDSuffix() const { return (Flags & HasUDSuffix) ? true : false; }
};
-/// PPConditionalInfo - Information about the conditional stack (#if directives)
+/// \brief Information about the conditional stack (\#if directives)
/// currently active.
struct PPConditionalInfo {
- /// IfLoc - Location where the conditional started.
- ///
+ /// \brief Location where the conditional started.
SourceLocation IfLoc;
- /// WasSkipping - True if this was contained in a skipping directive, e.g.
- /// in a "#if 0" block.
+ /// \brief True if this was contained in a skipping directive, e.g.,
+ /// in a "\#if 0" block.
bool WasSkipping;
- /// FoundNonSkip - True if we have emitted tokens already, and now we're in
- /// an #else block or something. Only useful in Skipping blocks.
+ /// \brief True if we have emitted tokens already, and now we're in
+ /// an \#else block or something. Only useful in Skipping blocks.
bool FoundNonSkip;
- /// FoundElse - True if we've seen a #else in this block. If so,
- /// #elif/#else directives are not allowed.
+ /// \brief True if we've seen a \#else in this block. If so,
+ /// \#elif/\#else directives are not allowed.
bool FoundElse;
};
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 0ae5dc8e0361..353b59e0ae32 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -23,14 +23,20 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/SaveAndRestore.h"
#include <stack>
namespace clang {
class PragmaHandler;
class Scope;
+ class BalancedDelimiterTracker;
class DeclGroupRef;
class DiagnosticBuilder;
class Parser;
+ class ParsingDeclRAIIObject;
+ class ParsingDeclSpec;
+ class ParsingDeclarator;
+ class ParsingFieldDeclarator;
class PragmaUnusedHandler;
class ColonProtectionRAIIObject;
class InMessageExpressionRAIIObject;
@@ -79,7 +85,9 @@ class Parser : public CodeCompletionHandler {
friend class ColonProtectionRAIIObject;
friend class InMessageExpressionRAIIObject;
friend class PoisonSEHIdentifiersRAIIObject;
+ friend class ObjCDeclContextSwitch;
friend class ParenBraceBracketBalancer;
+ friend class BalancedDelimiterTracker;
Preprocessor &PP;
@@ -94,7 +102,7 @@ class Parser : public CodeCompletionHandler {
SourceLocation PrevTokLocation;
unsigned short ParenCount, BracketCount, BraceCount;
-
+
/// Actions - These are the callbacks we invoke as we parse various constructs
/// in the file.
Sema &Actions;
@@ -165,6 +173,7 @@ class Parser : public CodeCompletionHandler {
OwningPtr<PragmaHandler> RedefineExtnameHandler;
OwningPtr<PragmaHandler> FPContractHandler;
OwningPtr<PragmaHandler> OpenCLExtensionHandler;
+ OwningPtr<CommentHandler> CommentSemaHandler;
/// Whether the '>' token acts as an operator or not. This will be
/// true except when we are parsing an expression within a C++
@@ -197,6 +206,13 @@ class Parser : public CodeCompletionHandler {
IdentifierInfo *getSEHExceptKeyword();
+ /// True if we are within an Objective-C container while parsing C-like decls.
+ ///
+ /// This is necessary because Sema thinks we have left the container
+ /// to parse the C-like decls, meaning Actions.getObjCDeclContext() will
+ /// be NULL.
+ bool ParsingInObjCContainer;
+
bool SkipFunctionBodies;
public:
@@ -207,6 +223,7 @@ public:
const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
Preprocessor &getPreprocessor() const { return PP; }
Sema &getActions() const { return Actions; }
+ AttributeFactory &getAttrFactory() { return AttrFactory; }
const Token &getCurToken() const { return Tok; }
Scope *getCurScope() const { return Actions.getCurScope(); }
@@ -434,78 +451,6 @@ private:
return PP.LookAhead(0);
}
- /// \brief RAII class that helps handle the parsing of an open/close delimiter
- /// pair, such as braces { ... } or parentheses ( ... ).
- class BalancedDelimiterTracker {
- Parser& P;
- tok::TokenKind Kind, Close;
- SourceLocation (Parser::*Consumer)();
- SourceLocation LOpen, LClose;
-
- unsigned short &getDepth() {
- switch (Kind) {
- case tok::l_brace: return P.BraceCount;
- case tok::l_square: return P.BracketCount;
- case tok::l_paren: return P.ParenCount;
- default: llvm_unreachable("Wrong token kind");
- }
- }
-
- enum { MaxDepth = 256 };
-
- bool diagnoseOverflow();
- bool diagnoseMissingClose();
-
- public:
- BalancedDelimiterTracker(Parser& p, tok::TokenKind k) : P(p), Kind(k) {
- switch (Kind) {
- default: llvm_unreachable("Unexpected balanced token");
- case tok::l_brace:
- Close = tok::r_brace;
- Consumer = &Parser::ConsumeBrace;
- break;
- case tok::l_paren:
- Close = tok::r_paren;
- Consumer = &Parser::ConsumeParen;
- break;
-
- case tok::l_square:
- Close = tok::r_square;
- Consumer = &Parser::ConsumeBracket;
- break;
- }
- }
-
- SourceLocation getOpenLocation() const { return LOpen; }
- SourceLocation getCloseLocation() const { return LClose; }
- SourceRange getRange() const { return SourceRange(LOpen, LClose); }
-
- bool consumeOpen() {
- if (!P.Tok.is(Kind))
- return true;
-
- if (getDepth() < MaxDepth) {
- LOpen = (P.*Consumer)();
- return false;
- }
-
- return diagnoseOverflow();
- }
-
- bool expectAndConsume(unsigned DiagID,
- const char *Msg = "",
- tok::TokenKind SkipToTok = tok::unknown);
- bool consumeClose() {
- if (P.Tok.is(Close)) {
- LClose = (P.*Consumer)();
- return false;
- }
-
- return diagnoseMissingClose();
- }
- void skipToEnd();
- };
-
/// getTypeAnnotation - Read a parsed type out of an annotation token.
static ParsedType getTypeAnnotation(Token &Tok) {
return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue());
@@ -621,9 +566,11 @@ private:
class ObjCDeclContextSwitch {
Parser &P;
Decl *DC;
+ SaveAndRestore<bool> WithinObjCContainer;
public:
- explicit ObjCDeclContextSwitch(Parser &p) : P(p),
- DC(p.getObjCDeclContext()) {
+ explicit ObjCDeclContextSwitch(Parser &p)
+ : P(p), DC(p.getObjCDeclContext()),
+ WithinObjCContainer(P.ParsingInObjCContainer, DC != 0) {
if (DC)
P.Actions.ActOnObjCTemporaryExitContainerContext(cast<DeclContext>(DC));
}
@@ -650,6 +597,17 @@ private:
/// to the semicolon, consumes that extra token.
bool ExpectAndConsumeSemi(unsigned DiagID);
+ /// \brief The kind of extra semi diagnostic to emit.
+ enum ExtraSemiKind {
+ OutsideFunction = 0,
+ InsideStruct = 1,
+ InstanceVariableList = 2,
+ AfterMemberFunctionDefinition = 3
+ };
+
+ /// \brief Consume any extra semi-colons until the end of the line.
+ void ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST = TST_unspecified);
+
//===--------------------------------------------------------------------===//
// Scope manipulation
@@ -715,6 +673,9 @@ private:
public:
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID);
+ DiagnosticBuilder Diag(unsigned DiagID) {
+ return Diag(Tok, DiagID);
+ }
private:
void SuggestParentheses(SourceLocation Loc, unsigned DK,
@@ -951,120 +912,7 @@ private:
return *ClassStack.top();
}
- /// \brief RAII object used to inform the actions that we're
- /// currently parsing a declaration. This is active when parsing a
- /// variable's initializer, but not when parsing the body of a
- /// class or function definition.
- class ParsingDeclRAIIObject {
- Sema &Actions;
- Sema::ParsingDeclState State;
- bool Popped;
-
- public:
- ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
- push();
- }
-
- ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *Other)
- : Actions(P.Actions) {
- if (Other) steal(*Other);
- else push();
- }
-
- /// Creates a RAII object which steals the state from a different
- /// object instead of pushing.
- ParsingDeclRAIIObject(ParsingDeclRAIIObject &Other)
- : Actions(Other.Actions) {
- steal(Other);
- }
-
- ~ParsingDeclRAIIObject() {
- abort();
- }
-
- /// Resets the RAII object for a new declaration.
- void reset() {
- abort();
- push();
- }
-
- /// Signals that the context was completed without an appropriate
- /// declaration being parsed.
- void abort() {
- pop(0);
- }
-
- void complete(Decl *D) {
- assert(!Popped && "ParsingDeclaration has already been popped!");
- pop(D);
- }
-
- private:
- void steal(ParsingDeclRAIIObject &Other) {
- State = Other.State;
- Popped = Other.Popped;
- Other.Popped = true;
- }
-
- void push() {
- State = Actions.PushParsingDeclaration();
- Popped = false;
- }
-
- void pop(Decl *D) {
- if (!Popped) {
- Actions.PopParsingDeclaration(State, D);
- Popped = true;
- }
- }
- };
-
- /// A class for parsing a DeclSpec.
- class ParsingDeclSpec : public DeclSpec {
- ParsingDeclRAIIObject ParsingRAII;
-
- public:
- ParsingDeclSpec(Parser &P) : DeclSpec(P.AttrFactory), ParsingRAII(P) {}
- ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
- : DeclSpec(P.AttrFactory), ParsingRAII(P, RAII) {}
-
- void complete(Decl *D) {
- ParsingRAII.complete(D);
- }
-
- void abort() {
- ParsingRAII.abort();
- }
- };
-
- /// A class for parsing a declarator.
- class ParsingDeclarator : public Declarator {
- ParsingDeclRAIIObject ParsingRAII;
-
- public:
- ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
- : Declarator(DS, C), ParsingRAII(P) {
- }
-
- const ParsingDeclSpec &getDeclSpec() const {
- return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
- }
-
- ParsingDeclSpec &getMutableDeclSpec() const {
- return const_cast<ParsingDeclSpec&>(getDeclSpec());
- }
-
- void clear() {
- Declarator::clear();
- ParsingRAII.reset();
- }
-
- void complete(Decl *D) {
- ParsingRAII.complete(D);
- }
- };
-
- /// \brief RAII object used to
+ /// \brief RAII object used to manage the parsing of a class definition.
class ParsingClassDefinition {
Parser &P;
bool Popped;
@@ -1183,7 +1031,7 @@ private:
void ParseLexedMethodDef(LexedMethod &LM);
void ParseLexedMemberInitializers(ParsingClass &Class);
void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
- Decl *ParseLexedObjCMethodDefs(LexedMethod &LM);
+ void ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod);
bool ConsumeAndStoreFunctionPrologue(CachedTokens &Toks);
bool ConsumeAndStoreUntil(tok::TokenKind T1,
CachedTokens &Toks,
@@ -1209,10 +1057,13 @@ private:
ParsingDeclSpec *DS = 0);
bool isDeclarationAfterDeclarator();
bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
- DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
- AccessSpecifier AS = AS_none);
- DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
+ ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec *DS = 0,
AccessSpecifier AS = AS_none);
+ DeclGroupPtrTy ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec &DS,
+ AccessSpecifier AS);
Decl *ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
@@ -1245,11 +1096,12 @@ private:
struct ObjCImplParsingDataRAII {
Parser &P;
Decl *Dcl;
+ bool HasCFunction;
typedef SmallVector<LexedMethod*, 8> LateParsedObjCMethodContainer;
LateParsedObjCMethodContainer LateParsedObjCMethods;
ObjCImplParsingDataRAII(Parser &parser, Decl *D)
- : P(parser), Dcl(D) {
+ : P(parser), Dcl(D), HasCFunction(false) {
P.CurParsedObjCImpl = this;
Finished = false;
}
@@ -1262,6 +1114,7 @@ private:
bool Finished;
};
ObjCImplParsingDataRAII *CurParsedObjCImpl;
+ void StashAwayMethodOrFunctionBodyTokens(Decl *MDecl);
DeclGroupPtrTy ParseObjCAtImplementationDeclaration(SourceLocation AtLoc);
DeclGroupPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd);
@@ -1380,6 +1233,8 @@ private:
// C++ Expressions
ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
+ bool areTokensAdjacent(const Token &A, const Token &B);
+
void CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectTypePtr,
bool EnteringContext, IdentifierInfo &II,
CXXScopeSpec &SS);
@@ -1452,8 +1307,6 @@ private:
// C++ 5.2.3: Explicit type conversion (functional notation)
ExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
- bool isCXXSimpleTypeSpecifier() const;
-
/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
/// This should only be called when the current token is known to be part of
/// simple-type-specifier.
@@ -1508,6 +1361,7 @@ private:
ExprResult ParseObjCBooleanLiteral(SourceLocation AtLoc, bool ArgValue);
ExprResult ParseObjCArrayLiteral(SourceLocation AtLoc);
ExprResult ParseObjCDictionaryLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCBoxedExpr(SourceLocation AtLoc);
ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
@@ -1639,7 +1493,7 @@ private:
enum DeclSpecContext {
DSC_normal, // normal context
DSC_class, // class context, enables 'friend'
- DSC_type_specifier, // C++ type-specifier-seq
+ DSC_type_specifier, // C++ type-specifier-seq or C specifier-qualifier-list
DSC_trailing, // C++11 trailing-type-specifier in a trailing return type
DSC_top_level // top-level/namespace declaration context
};
@@ -1659,7 +1513,7 @@ private:
DeclGroupPtrTy ParseSimpleDeclaration(StmtVector &Stmts,
unsigned Context,
SourceLocation &DeclEnd,
- ParsedAttributes &attrs,
+ ParsedAttributesWithRange &attrs,
bool RequireSemi,
ForRangeInit *FRI = 0);
bool MightBeDeclarator(unsigned Context);
@@ -1705,7 +1559,7 @@ private:
Decl *TagDecl);
struct FieldCallback {
- virtual Decl *invoke(FieldDeclarator &Field) = 0;
+ virtual void invoke(ParsingFieldDeclarator &Field) = 0;
virtual ~FieldCallback() {}
private:
@@ -1713,7 +1567,7 @@ private:
};
struct ObjCPropertyCallback;
- void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback);
+ void ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Callback);
bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false);
bool isTypeSpecifierQualifier();
@@ -1789,11 +1643,11 @@ private:
/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
/// a constructor-style initializer, when parsing declaration statements.
/// Returns true for function declarator and false for constructor-style
- /// initializer. If 'warnIfAmbiguous' is true a warning will be emitted to
- /// indicate that the parens were disambiguated as function declarator.
+ /// initializer. Sets 'IsAmbiguous' to true to indicate that this declaration
+ /// might be a constructor-style initializer.
/// If during the disambiguation process a parsing error is encountered,
/// the function returns true to let the declaration parsing code handle it.
- bool isCXXFunctionDeclarator(bool warnIfAmbiguous);
+ bool isCXXFunctionDeclarator(bool *IsAmbiguous = 0);
/// isCXXConditionDeclaration - Disambiguates between a declaration or an
/// expression for a condition of a if/switch/while/for statement.
@@ -1850,7 +1704,8 @@ private:
/// BracedCastResult.
/// Doesn't consume tokens.
TPResult
- isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False());
+ isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False(),
+ bool *HasMissingTypename = 0);
// "Tentative parsing" functions, used for disambiguation. If a parsing error
// is encountered they will return TPResult::Error().
@@ -1859,13 +1714,13 @@ private:
// that more tentative parsing is necessary for disambiguation.
// They all consume tokens, so backtracking should be used after calling them.
- TPResult TryParseDeclarationSpecifier();
+ TPResult TryParseDeclarationSpecifier(bool *HasMissingTypename = 0);
TPResult TryParseSimpleDeclaration(bool AllowForRangeDecl);
TPResult TryParseTypeofSpecifier();
TPResult TryParseProtocolQualifiers();
TPResult TryParseInitDeclaratorList();
TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
- TPResult TryParseParameterDeclarationClause();
+ TPResult TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = 0);
TPResult TryParseFunctionDeclarator();
TPResult TryParseBracketDeclarator();
@@ -1874,7 +1729,7 @@ private:
= Declarator::TypeNameContext,
AccessSpecifier AS = AS_none,
Decl **OwnedType = 0);
- void ParseBlockId();
+ void ParseBlockId(SourceLocation CaretLoc);
// Check for the start of a C++11 attribute-specifier-seq in a context where
// an attribute is not allowed.
@@ -1953,8 +1808,16 @@ private:
}
void ParseMicrosoftAttributes(ParsedAttributes &attrs,
SourceLocation *endLoc = 0);
- void ParseMicrosoftDeclSpec(ParsedAttributes &attrs);
+ void ParseMicrosoftDeclSpec(ParsedAttributes &Attrs);
+ bool IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident);
+ void ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
+ SourceLocation Loc,
+ ParsedAttributes &Attrs);
+ void ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs);
void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
+ void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
void ParseOpenCLAttributes(ParsedAttributes &attrs);
void ParseOpenCLQualifiers(DeclSpec &DS);
@@ -2040,6 +1903,7 @@ private:
void ParseFunctionDeclarator(Declarator &D,
ParsedAttributes &attrs,
BalancedDelimiterTracker &Tracker,
+ bool IsAmbiguous,
bool RequiresArg = false);
bool isFunctionDeclaratorIdentifierList();
void ParseFunctionDeclaratorIdentifierList(
@@ -2100,6 +1964,7 @@ private:
//===--------------------------------------------------------------------===//
// C++ 9: classes [class] and C structs/unions.
+ bool isValidAfterTypeSpecifier(bool CouldBeBitfield);
void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS, bool EnteringContext,
diff --git a/include/clang/Rewrite/FrontendActions.h b/include/clang/Rewrite/FrontendActions.h
index 6e9ecace672f..ea876d9980f6 100644
--- a/include/clang/Rewrite/FrontendActions.h
+++ b/include/clang/Rewrite/FrontendActions.h
@@ -73,6 +73,11 @@ protected:
void ExecuteAction();
};
+class RewriteIncludesAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h
index f1358a0c8534..5ffd88b05df5 100644
--- a/include/clang/Rewrite/Rewriter.h
+++ b/include/clang/Rewrite/Rewriter.h
@@ -279,6 +279,13 @@ public:
buffer_iterator buffer_begin() { return RewriteBuffers.begin(); }
buffer_iterator buffer_end() { return RewriteBuffers.end(); }
+ /// SaveFiles - Save all changed files to disk.
+ ///
+ /// Returns whether not all changes were saved successfully.
+ /// Outputs diagnostics via the source manager's diagnostic engine
+ /// in case of an error.
+ bool overwriteChangedFiles();
+
private:
unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const;
};
diff --git a/include/clang/Rewrite/Rewriters.h b/include/clang/Rewrite/Rewriters.h
index 203b9bc18b35..f5ade5ad35d3 100644
--- a/include/clang/Rewrite/Rewriters.h
+++ b/include/clang/Rewrite/Rewriters.h
@@ -18,6 +18,7 @@
namespace clang {
class Preprocessor;
+class PreprocessorOutputOptions;
/// RewriteMacrosInInput - Implement -rewrite-macros mode.
void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS);
@@ -25,6 +26,10 @@ void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS);
/// DoRewriteTest - A simple test for the TokenRewriter class.
void DoRewriteTest(Preprocessor &PP, raw_ostream *OS);
+/// RewriteIncludesInInput - Implement -frewrite-includes mode.
+void RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
+ const PreprocessorOutputOptions &Opts);
+
} // end namespace clang
#endif
diff --git a/include/clang/Rewrite/TokenRewriter.h b/include/clang/Rewrite/TokenRewriter.h
index 9ebd33a51970..894db0953f7f 100644
--- a/include/clang/Rewrite/TokenRewriter.h
+++ b/include/clang/Rewrite/TokenRewriter.h
@@ -16,12 +16,12 @@
#define LLVM_CLANG_TOKENREWRITER_H
#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Token.h"
#include "llvm/ADT/OwningPtr.h"
#include <list>
#include <map>
namespace clang {
- class Token;
class LangOptions;
class ScratchBuffer;
diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h
index 142f1444f382..5239044e6708 100644
--- a/include/clang/Sema/AttributeList.h
+++ b/include/clang/Sema/AttributeList.h
@@ -52,6 +52,16 @@ struct AvailabilityChange {
/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
///
class AttributeList { // TODO: This should really be called ParsedAttribute
+public:
+ /// The style used to specify an attribute.
+ enum Syntax {
+ AS_GNU,
+ AS_CXX11,
+ AS_Declspec,
+ // eg) __w64, __ptr32, etc. It is implied that an MSTypespec is also
+ // a declspec.
+ AS_MSTypespec
+ };
private:
IdentifierInfo *AttrName;
IdentifierInfo *ScopeName;
@@ -64,11 +74,8 @@ private:
/// The expressions themselves are stored after the object.
unsigned NumArgs : 16;
- /// True if Microsoft style: declspec(foo).
- unsigned DeclspecAttribute : 1;
-
- /// True if C++0x-style: [[foo]].
- unsigned CXX0XAttribute : 1;
+ /// Corresponds to the Syntax enum.
+ unsigned SyntaxUsed : 2;
/// True if already diagnosed as invalid.
mutable unsigned Invalid : 1;
@@ -123,15 +130,14 @@ private:
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
Expr **args, unsigned numArgs,
- bool declspec, bool cxx0x)
+ Syntax syntaxUsed)
: AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
- NumArgs(numArgs),
- DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false),
+ NumArgs(numArgs), SyntaxUsed(syntaxUsed), Invalid(false),
UsedAsTypeAttr(false), IsAvailability(false),
NextInPosition(0), NextInPool(0) {
if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
- AttrKind = getKind(getName());
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
@@ -142,17 +148,17 @@ private:
const AvailabilityChange &obsoleted,
SourceLocation unavailable,
const Expr *messageExpr,
- bool declspec, bool cxx0x)
+ Syntax syntaxUsed)
: AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
- NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x),
+ NumArgs(0), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
UnavailableLoc(unavailable), MessageExpr(messageExpr),
NextInPosition(0), NextInPool(0) {
new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
- AttrKind = getKind(getName());
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
friend class AttributePool;
@@ -162,17 +168,6 @@ public:
enum Kind {
#define PARSED_ATTR(NAME) AT_##NAME,
#include "clang/Sema/AttrParsedAttrList.inc"
- PARSED_ATTR(address_space)
- PARSED_ATTR(base_check)
- PARSED_ATTR(cf_returns_autoreleased)
- PARSED_ATTR(ext_vector_type)
- PARSED_ATTR(mode)
- PARSED_ATTR(neon_polyvector_type)
- PARSED_ATTR(neon_vector_type)
- PARSED_ATTR(objc_gc)
- PARSED_ATTR(objc_ownership)
- PARSED_ATTR(opencl_image_access)
- PARSED_ATTR(vector_size)
#undef PARSED_ATTR
IgnoredAttribute,
UnknownAttribute
@@ -189,8 +184,12 @@ public:
IdentifierInfo *getParameterName() const { return ParmName; }
SourceLocation getParameterLoc() const { return ParmLoc; }
- bool isDeclspecAttribute() const { return DeclspecAttribute; }
- bool isCXX0XAttribute() const { return CXX0XAttribute; }
+ /// Returns true if the attribute is a pure __declspec or a synthesized
+ /// declspec representing a type specification (like __w64 or __ptr32).
+ bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec ||
+ SyntaxUsed == AS_MSTypespec; }
+ bool isCXX0XAttribute() const { return SyntaxUsed == AS_CXX11; }
+ bool isMSTypespecAttribute() const { return SyntaxUsed == AS_MSTypespec; }
bool isInvalid() const { return Invalid; }
void setInvalid(bool b = true) const { Invalid = b; }
@@ -199,7 +198,8 @@ public:
void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
Kind getKind() const { return Kind(AttrKind); }
- static Kind getKind(const IdentifierInfo *Name);
+ static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
+ Syntax SyntaxUsed);
AttributeList *getNext() const { return NextInPosition; }
void setNext(AttributeList *N) { NextInPosition = N; }
@@ -256,27 +256,27 @@ public:
}
const AvailabilityChange &getAvailabilityIntroduced() const {
- assert(getKind() == AT_availability && "Not an availability attribute");
+ assert(getKind() == AT_Availability && "Not an availability attribute");
return getAvailabilitySlot(IntroducedSlot);
}
const AvailabilityChange &getAvailabilityDeprecated() const {
- assert(getKind() == AT_availability && "Not an availability attribute");
+ assert(getKind() == AT_Availability && "Not an availability attribute");
return getAvailabilitySlot(DeprecatedSlot);
}
const AvailabilityChange &getAvailabilityObsoleted() const {
- assert(getKind() == AT_availability && "Not an availability attribute");
+ assert(getKind() == AT_Availability && "Not an availability attribute");
return getAvailabilitySlot(ObsoletedSlot);
}
SourceLocation getUnavailableLoc() const {
- assert(getKind() == AT_availability && "Not an availability attribute");
+ assert(getKind() == AT_Availability && "Not an availability attribute");
return UnavailableLoc;
}
const Expr * getMessageExpr() const {
- assert(getKind() == AT_availability && "Not an availability attribute");
+ assert(getKind() == AT_Availability && "Not an availability attribute");
return MessageExpr;
}
};
@@ -383,14 +383,13 @@ public:
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
Expr **args, unsigned numArgs,
- bool declspec = false, bool cxx0x = false) {
+ AttributeList::Syntax syntax) {
void *memory = allocate(sizeof(AttributeList)
+ numArgs * sizeof(Expr*));
return add(new (memory) AttributeList(attrName, attrRange,
scopeName, scopeLoc,
parmName, parmLoc,
- args, numArgs,
- declspec, cxx0x));
+ args, numArgs, syntax));
}
AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
@@ -401,14 +400,13 @@ public:
const AvailabilityChange &obsoleted,
SourceLocation unavailable,
const Expr *MessageExpr,
- bool declspec = false, bool cxx0x = false) {
+ AttributeList::Syntax syntax) {
void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
return add(new (memory) AttributeList(attrName, attrRange,
scopeName, scopeLoc,
parmName, parmLoc,
introduced, deprecated, obsoleted,
- unavailable, MessageExpr,
- declspec, cxx0x));
+ unavailable, MessageExpr, syntax));
}
AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
@@ -510,10 +508,10 @@ public:
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
Expr **args, unsigned numArgs,
- bool declspec = false, bool cxx0x = false) {
+ AttributeList::Syntax syntax) {
AttributeList *attr =
pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
- args, numArgs, declspec, cxx0x);
+ args, numArgs, syntax);
add(attr);
return attr;
}
@@ -526,12 +524,11 @@ public:
const AvailabilityChange &obsoleted,
SourceLocation unavailable,
const Expr *MessageExpr,
- bool declspec = false, bool cxx0x = false) {
+ AttributeList::Syntax syntax) {
AttributeList *attr =
pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
introduced, deprecated, obsoleted, unavailable,
- MessageExpr,
- declspec, cxx0x);
+ MessageExpr, syntax);
add(attr);
return attr;
}
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index fe9bed5c8693..d43aaafb2924 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -15,6 +15,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/CanonicalType.h"
+#include "clang/Sema/CodeCompleteOptions.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
@@ -237,7 +238,7 @@ public:
/// This context usually implies that no completions should be added,
/// unless they come from an appropriate natural-language dictionary.
CCC_NaturalLanguage,
- /// \brief Code completion for a selector, as in an @selector expression.
+ /// \brief Code completion for a selector, as in an \@selector expression.
CCC_SelectorName,
/// \brief Code completion within a type-qualifier list.
CCC_TypeQualifiers,
@@ -379,7 +380,7 @@ public:
CK_Equal,
/// \brief Horizontal whitespace (' ').
CK_HorizontalSpace,
- /// \brief Verticle whitespace ('\n' or '\r\n', depending on the
+ /// \brief Vertical whitespace ('\\n' or '\\r\\n', depending on the
/// platform).
CK_VerticalSpace
};
@@ -444,6 +445,10 @@ private:
/// \brief The name of the parent context.
StringRef ParentName;
+
+ /// \brief A brief documentation comment attached to the declaration of
+ /// entity being completed by this result.
+ const char *BriefComment;
CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT
CodeCompletionString &operator=(const CodeCompletionString &); // DITTO
@@ -451,7 +456,8 @@ private:
CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
unsigned Priority, CXAvailabilityKind Availability,
const char **Annotations, unsigned NumAnnotations,
- CXCursorKind ParentKind, StringRef ParentName);
+ CXCursorKind ParentKind, StringRef ParentName,
+ const char *BriefComment);
~CodeCompletionString() { }
friend class CodeCompletionBuilder;
@@ -493,6 +499,10 @@ public:
StringRef getParentContextName() const {
return ParentName;
}
+
+ const char *getBriefComment() const {
+ return BriefComment;
+ }
/// \brief Retrieve a string representation of the code completion string,
/// which is mainly useful for debugging.
@@ -569,6 +579,7 @@ private:
CXAvailabilityKind Availability;
CXCursorKind ParentKind;
StringRef ParentName;
+ const char *BriefComment;
/// \brief The chunks stored in this string.
SmallVector<Chunk, 4> Chunks;
@@ -580,14 +591,14 @@ public:
CodeCompletionTUInfo &CCTUInfo)
: Allocator(Allocator), CCTUInfo(CCTUInfo),
Priority(0), Availability(CXAvailability_Available),
- ParentKind(CXCursor_NotImplemented) { }
+ ParentKind(CXCursor_NotImplemented), BriefComment(NULL) { }
CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
unsigned Priority, CXAvailabilityKind Availability)
: Allocator(Allocator), CCTUInfo(CCTUInfo),
Priority(Priority), Availability(Availability),
- ParentKind(CXCursor_NotImplemented) { }
+ ParentKind(CXCursor_NotImplemented), BriefComment(NULL) { }
/// \brief Retrieve the allocator into which the code completion
/// strings should be allocated.
@@ -628,6 +639,8 @@ public:
/// \brief Add the parent context information to this code completion.
void addParentContext(DeclContext *DC);
+
+ void addBriefComment(StringRef Comment);
CXCursorKind getParentKind() const { return ParentKind; }
StringRef getParentName() const { return ParentName; }
@@ -638,15 +651,12 @@ class CodeCompletionResult {
public:
/// \brief Describes the kind of result generated.
enum ResultKind {
- RK_Declaration = 0, //< Refers to a declaration
- RK_Keyword, //< Refers to a keyword or symbol.
- RK_Macro, //< Refers to a macro
- RK_Pattern //< Refers to a precomputed pattern.
+ RK_Declaration = 0, ///< Refers to a declaration
+ RK_Keyword, ///< Refers to a keyword or symbol.
+ RK_Macro, ///< Refers to a macro
+ RK_Pattern ///< Refers to a precomputed pattern.
};
- /// \brief The kind of result stored here.
- ResultKind Kind;
-
/// \brief When Kind == RK_Declaration or RK_Pattern, the declaration we are
/// referring to. In the latter case, the declaration might be NULL.
NamedDecl *Declaration;
@@ -667,16 +677,19 @@ public:
/// \brief The priority of this particular code-completion result.
unsigned Priority;
+ /// \brief Specifies which parameter (of a function, Objective-C method,
+ /// macro, etc.) we should start with when formatting the result.
+ unsigned StartParameter;
+
+ /// \brief The kind of result stored here.
+ ResultKind Kind;
+
/// \brief The cursor kind that describes this result.
CXCursorKind CursorKind;
/// \brief The availability of this result.
CXAvailabilityKind Availability;
- /// \brief Specifies which parameter (of a function, Objective-C method,
- /// macro, etc.) we should start with when formatting the result.
- unsigned StartParameter;
-
/// \brief Whether this result is hidden by another name.
bool Hidden : 1;
@@ -705,10 +718,10 @@ public:
NestedNameSpecifier *Qualifier = 0,
bool QualifierIsInformative = false,
bool Accessible = true)
- : Kind(RK_Declaration), Declaration(Declaration),
- Priority(getPriorityFromDecl(Declaration)),
- Availability(CXAvailability_Available), StartParameter(0),
- Hidden(false), QualifierIsInformative(QualifierIsInformative),
+ : Declaration(Declaration), Priority(getPriorityFromDecl(Declaration)),
+ StartParameter(0), Kind(RK_Declaration),
+ Availability(CXAvailability_Available), Hidden(false),
+ QualifierIsInformative(QualifierIsInformative),
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
DeclaringEntity(false), Qualifier(Qualifier) {
computeCursorKindAndAvailability(Accessible);
@@ -716,22 +729,22 @@ public:
/// \brief Build a result that refers to a keyword or symbol.
CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
- : Kind(RK_Keyword), Declaration(0), Keyword(Keyword), Priority(Priority),
- Availability(CXAvailability_Available),
- StartParameter(0), Hidden(false), QualifierIsInformative(0),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(0) {
- computeCursorKindAndAvailability();
+ : Declaration(0), Keyword(Keyword), Priority(Priority), StartParameter(0),
+ Kind(RK_Keyword), CursorKind(CXCursor_NotImplemented),
+ Availability(CXAvailability_Available), Hidden(false),
+ QualifierIsInformative(0), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(0)
+ {
}
/// \brief Build a result that refers to a macro.
CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
- : Kind(RK_Macro), Declaration(0), Macro(Macro), Priority(Priority),
- Availability(CXAvailability_Available), StartParameter(0),
- Hidden(false), QualifierIsInformative(0),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(0) {
- computeCursorKindAndAvailability();
+ : Declaration(0), Macro(Macro), Priority(Priority), StartParameter(0),
+ Kind(RK_Macro), CursorKind(CXCursor_MacroDefinition),
+ Availability(CXAvailability_Available), Hidden(false),
+ QualifierIsInformative(0), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(0)
+ {
}
/// \brief Build a result that refers to a pattern.
@@ -740,8 +753,8 @@ public:
CXCursorKind CursorKind = CXCursor_NotImplemented,
CXAvailabilityKind Availability = CXAvailability_Available,
NamedDecl *D = 0)
- : Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority),
- CursorKind(CursorKind), Availability(Availability), StartParameter(0),
+ : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0),
+ Kind(RK_Pattern), CursorKind(CursorKind), Availability(Availability),
Hidden(false), QualifierIsInformative(0),
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
DeclaringEntity(false), Qualifier(0)
@@ -752,11 +765,10 @@ public:
/// declaration.
CodeCompletionResult(CodeCompletionString *Pattern, NamedDecl *D,
unsigned Priority)
- : Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority),
- Availability(CXAvailability_Available), StartParameter(0),
- Hidden(false), QualifierIsInformative(false),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(0) {
+ : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0),
+ Kind(RK_Pattern), Availability(CXAvailability_Available), Hidden(false),
+ QualifierIsInformative(false), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(0) {
computeCursorKindAndAvailability();
}
@@ -781,11 +793,13 @@ public:
/// string itself.
CodeCompletionString *CreateCodeCompletionString(Sema &S,
CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo);
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments);
CodeCompletionString *CreateCodeCompletionString(ASTContext &Ctx,
Preprocessor &PP,
CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo);
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments);
/// \brief Determine a base priority for the given declaration.
static unsigned getPriorityFromDecl(NamedDecl *ND);
@@ -819,16 +833,7 @@ raw_ostream &operator<<(raw_ostream &OS,
/// information.
class CodeCompleteConsumer {
protected:
- /// \brief Whether to include macros in the code-completion results.
- bool IncludeMacros;
-
- /// \brief Whether to include code patterns (such as for loops) within
- /// the completion results.
- bool IncludeCodePatterns;
-
- /// \brief Whether to include global (top-level) declarations and names in
- /// the completion results.
- bool IncludeGlobals;
+ const CodeCompleteOptions CodeCompleteOpts;
/// \brief Whether the output format for the code-completion consumer is
/// binary.
@@ -901,22 +906,31 @@ public:
CodeCompletionTUInfo &CCTUInfo) const;
};
- CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false),
- IncludeGlobals(true), OutputIsBinary(false) { }
-
- CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
- bool IncludeGlobals, bool OutputIsBinary)
- : IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns),
- IncludeGlobals(IncludeGlobals), OutputIsBinary(OutputIsBinary) { }
+ CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts,
+ bool OutputIsBinary)
+ : CodeCompleteOpts(CodeCompleteOpts), OutputIsBinary(OutputIsBinary)
+ { }
/// \brief Whether the code-completion consumer wants to see macros.
- bool includeMacros() const { return IncludeMacros; }
+ bool includeMacros() const {
+ return CodeCompleteOpts.IncludeMacros;
+ }
/// \brief Whether the code-completion consumer wants to see code patterns.
- bool includeCodePatterns() const { return IncludeCodePatterns; }
+ bool includeCodePatterns() const {
+ return CodeCompleteOpts.IncludeCodePatterns;
+ }
/// \brief Whether to include global (top-level) declaration results.
- bool includeGlobals() const { return IncludeGlobals; }
+ bool includeGlobals() const {
+ return CodeCompleteOpts.IncludeGlobals;
+ }
+
+ /// \brief Whether to include brief documentation comments within the set of
+ /// code completions returned.
+ bool includeBriefComments() const {
+ return CodeCompleteOpts.IncludeBriefComments;
+ }
/// \brief Determine whether the output of this consumer is binary.
bool isOutputBinary() const { return OutputIsBinary; }
@@ -963,11 +977,9 @@ class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
public:
/// \brief Create a new printing code-completion consumer that prints its
/// results to the given raw output stream.
- PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
- bool IncludeGlobals,
+ PrintingCodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts,
raw_ostream &OS)
- : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
- false), OS(OS),
+ : CodeCompleteConsumer(CodeCompleteOpts, false), OS(OS),
CCTUInfo(new GlobalCodeCompletionAllocator) {}
/// \brief Prints the finalized code-completion results.
diff --git a/include/clang/Sema/CodeCompleteOptions.h b/include/clang/Sema/CodeCompleteOptions.h
new file mode 100644
index 000000000000..30712dbad116
--- /dev/null
+++ b/include/clang/Sema/CodeCompleteOptions.h
@@ -0,0 +1,37 @@
+//===---- CodeCompleteOptions.h - Code Completion Options -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H
+#define LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H
+
+/// Options controlling the behavior of code completion.
+class CodeCompleteOptions {
+public:
+ ///< Show macros in code completion results.
+ unsigned IncludeMacros : 1;
+
+ ///< Show code patterns in code completion results.
+ unsigned IncludeCodePatterns : 1;
+
+ ///< Show top-level decls in code completion results.
+ unsigned IncludeGlobals : 1;
+
+ ///< Show brief documentation comments in code completion results.
+ unsigned IncludeBriefComments : 1;
+
+ CodeCompleteOptions() :
+ IncludeMacros(0),
+ IncludeCodePatterns(0),
+ IncludeGlobals(1),
+ IncludeBriefComments(0)
+ { }
+};
+
+#endif
+
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 67fd3939f35d..792b0c643d8d 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -6,15 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the classes used to store parsed information about
-// declaration-specifiers and declarators.
-//
-// static const int volatile x, *y, *(*(*z)[10])(const void *x);
-// ------------------------- - -- ---------------------------
-// declaration-specifiers \ | /
-// declarators
-//
+///
+/// \file
+/// \brief This file defines the classes used to store parsed information about
+/// declaration-specifiers and declarators.
+///
+/// \verbatim
+/// static const int volatile x, *y, *(*(*z)[10])(const void *x);
+/// ------------------------- - -- ---------------------------
+/// declaration-specifiers \ | /
+/// declarators
+/// \endverbatim
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SEMA_DECLSPEC_H
@@ -48,8 +51,9 @@ namespace clang {
class Declarator;
struct TemplateIdAnnotation;
-/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope
-/// specifier. These can be in 3 states:
+/// \brief Represents a C++ nested-name-specifier or a global scope specifier.
+///
+/// These can be in 3 states:
/// 1) Not present, identified by isEmpty()
/// 2) Present, identified by isNotEmpty()
/// 2.a) Valid, idenified by isValid()
@@ -158,9 +162,14 @@ public:
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
/// \brief Retrieve the location of the name in the last qualifier
- /// in this nested name specifier. For example:
- /// ::foo::bar<0>::
- /// ^~~
+ /// in this nested name specifier.
+ ///
+ /// For example, the location of \c bar
+ /// in
+ /// \verbatim
+ /// \::foo::bar<0>::
+ /// ^~~
+ /// \endverbatim
SourceLocation getLastQualifierNameLoc() const;
/// No scope specifier.
@@ -199,13 +208,14 @@ public:
unsigned location_size() const { return Builder.getBuffer().second; }
};
-/// DeclSpec - This class captures information about "declaration specifiers",
-/// which encompasses storage-class-specifiers, type-specifiers,
-/// type-qualifiers, and function-specifiers.
+/// \brief Captures information about "declaration specifiers".
+///
+/// "Declaration specifiers" encompasses storage-class-specifiers,
+/// type-specifiers, type-qualifiers, and function-specifiers.
class DeclSpec {
public:
- // storage-class-specifier
- // Note: The order of these enumerators is important for diagnostics.
+ /// \brief storage-class-specifier
+ /// \note The order of these enumerators is important for diagnostics.
enum SCS {
SCS_unspecified = 0,
SCS_typedef,
@@ -466,8 +476,7 @@ public:
SourceRange getTypeofParensRange() const { return TypeofParensRange; }
void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; }
- /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool"
- /// or "union".
+ /// \brief Turn a type-specifier-type into a string like "_Bool" or "union".
static const char *getSpecifierName(DeclSpec::TST T);
static const char *getSpecifierName(DeclSpec::TQ Q);
static const char *getSpecifierName(DeclSpec::TSS S);
@@ -510,7 +519,7 @@ public:
FS_explicitLoc = SourceLocation();
}
- /// hasTypeSpecifier - Return true if any type-specifier has been found.
+ /// \brief Return true if any type-specifier has been found.
bool hasTypeSpecifier() const {
return getTypeSpecType() != DeclSpec::TST_unspecified ||
getTypeSpecWidth() != DeclSpec::TSW_unspecified ||
@@ -518,9 +527,8 @@ public:
getTypeSpecSign() != DeclSpec::TSS_unspecified;
}
- /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
+ /// \brief Return a bitmask of which flavors of specifiers this
/// DeclSpec includes.
- ///
unsigned getParsedSpecifiers() const;
SCS getStorageClassSpecAsWritten() const {
@@ -590,7 +598,8 @@ public:
}
bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID, const LangOptions &Lang);
+ unsigned &DiagID, const LangOptions &Lang,
+ bool IsTypeSpec);
bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
@@ -624,17 +633,22 @@ public:
return Attrs.getPool();
}
- /// AddAttributes - contatenates two attribute lists.
+ /// \brief Concatenates two attribute lists.
+ ///
/// The GCC attribute syntax allows for the following:
///
+ /// \code
/// short __attribute__(( unused, deprecated ))
/// int __attribute__(( may_alias, aligned(16) )) var;
+ /// \endcode
///
/// This declares 4 attributes using 2 lists. The following syntax is
/// also allowed and equivalent to the previous declaration.
///
+ /// \code
/// short __attribute__((unused)) __attribute__((deprecated))
/// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
+ /// \endcode
///
void addAttributes(AttributeList *AL) {
Attrs.addAll(AL);
@@ -648,7 +662,7 @@ public:
ParsedAttributes &getAttributes() { return Attrs; }
const ParsedAttributes &getAttributes() const { return Attrs; }
- /// TakeAttributes - Return the current attribute list and remove them from
+ /// \brief Return the current attribute list and remove them from
/// the DeclSpec so that it doesn't own them.
ParsedAttributes takeAttributes() {
// The non-const "copy" constructor clears the operand automatically.
@@ -684,13 +698,14 @@ public:
ObjCDeclSpec *getObjCQualifiers() const { return ObjCQualifiers; }
void setObjCQualifiers(ObjCDeclSpec *quals) { ObjCQualifiers = quals; }
- /// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone,
- /// without a Declarator. Only tag declspecs can stand alone.
+ /// \brief Checks if this DeclSpec can stand alone, without a Declarator.
+ ///
+ /// Only tag declspecs can stand alone.
bool isMissingDeclaratorOk();
};
-/// ObjCDeclSpec - This class captures information about
-/// "declaration specifiers" specific to objective-c
+/// \brief Captures information about "declaration specifiers" specific to
+/// Objective-C.
class ObjCDeclSpec {
public:
/// ObjCDeclQualifier - Qualifier used on types in method
@@ -853,12 +868,14 @@ public:
assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers");
}
- /// \brief Destroy this unqualified-id.
- ~UnqualifiedId() { clear(); }
-
/// \brief Clear out this unqualified-id, setting it to default (invalid)
/// state.
- void clear();
+ void clear() {
+ Kind = IK_Identifier;
+ Identifier = 0;
+ StartLocation = SourceLocation();
+ EndLocation = SourceLocation();
+ }
/// \brief Determine whether this unqualified-id refers to a valid name.
bool isValid() const { return StartLocation.isValid(); }
@@ -979,12 +996,11 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return StartLocation; }
SourceLocation getLocEnd() const LLVM_READONLY { return EndLocation; }
};
-
-/// CachedTokens - A set of tokens that has been cached for later
-/// parsing.
+
+/// \brief A set of tokens that has been cached for later parsing.
typedef SmallVector<Token, 4> CachedTokens;
-/// DeclaratorChunk - One instance of this struct is used for each type in a
+/// \brief One instance of this struct is used for each type in a
/// declarator that is parsed.
///
/// This is intended to be a small value object.
@@ -1088,6 +1104,9 @@ struct DeclaratorChunk {
/// contains the location of the ellipsis.
unsigned isVariadic : 1;
+ /// Can this declaration be a constructor-style initializer?
+ unsigned isAmbiguous : 1;
+
/// \brief Whether the ref-qualifier (if any) is an lvalue reference.
/// Otherwise, it's an rvalue reference.
unsigned RefQualifierIsLValueRef : 1;
@@ -1102,6 +1121,10 @@ struct DeclaratorChunk {
/// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
unsigned DeleteArgInfo : 1;
+ /// HasTrailingReturnType - If this is true, a trailing return type was
+ /// specified.
+ unsigned HasTrailingReturnType : 1;
+
/// When isVariadic is true, the location of the ellipsis in the source.
unsigned EllipsisLoc;
@@ -1132,8 +1155,7 @@ struct DeclaratorChunk {
/// any.
unsigned MutableLoc;
- /// \brief When ExceptionSpecType isn't EST_None or EST_Delayed, the
- /// location of the keyword introducing the spec.
+ /// \brief The location of the keyword introducing the spec, if any.
unsigned ExceptionSpecLoc;
/// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
@@ -1152,13 +1174,13 @@ struct DeclaratorChunk {
Expr *NoexceptExpr;
};
- /// TrailingReturnType - If this isn't null, it's the trailing return type
- /// specified. This is actually a ParsedType, but stored as void* to
- /// allow union storage.
- void *TrailingReturnType;
+ /// \brief If HasTrailingReturnType is true, this is the trailing return
+ /// type specified.
+ UnionParsedType TrailingReturnType;
- /// freeArgs - reset the argument list to having zero arguments. This is
- /// used in various places for error recovery.
+ /// \brief Reset the argument list to having zero arguments.
+ ///
+ /// This is used in various places for error recovery.
void freeArgs() {
if (DeleteArgInfo) {
delete[] ArgInfo;
@@ -1220,6 +1242,13 @@ struct DeclaratorChunk {
ExceptionSpecificationType getExceptionSpecType() const {
return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
}
+
+ /// \brief Determine whether this function declarator had a
+ /// trailing-return-type.
+ bool hasTrailingReturnType() const { return HasTrailingReturnType; }
+
+ /// \brief Get the trailing-return-type for this function declarator.
+ ParsedType getTrailingReturnType() const { return TrailingReturnType; }
};
struct BlockPointerTypeInfo : TypeInfoCommon {
@@ -1273,7 +1302,7 @@ struct DeclaratorChunk {
}
}
- /// getAttrs - If there are attributes applied to this declaratorchunk, return
+ /// \brief If there are attributes applied to this declaratorchunk, return
/// them.
const AttributeList *getAttrs() const {
return Common.AttrList;
@@ -1283,8 +1312,7 @@ struct DeclaratorChunk {
return Common.AttrList;
}
- /// getPointer - Return a DeclaratorChunk for a pointer.
- ///
+ /// \brief Return a DeclaratorChunk for a pointer.
static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
SourceLocation ConstQualLoc,
SourceLocation VolatileQualLoc,
@@ -1300,8 +1328,7 @@ struct DeclaratorChunk {
return I;
}
- /// getReference - Return a DeclaratorChunk for a reference.
- ///
+ /// \brief Return a DeclaratorChunk for a reference.
static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc,
bool lvalue) {
DeclaratorChunk I;
@@ -1313,8 +1340,7 @@ struct DeclaratorChunk {
return I;
}
- /// getArray - Return a DeclaratorChunk for an array.
- ///
+ /// \brief Return a DeclaratorChunk for an array.
static DeclaratorChunk getArray(unsigned TypeQuals,
bool isStatic, bool isStar, Expr *NumElts,
SourceLocation LBLoc, SourceLocation RBLoc) {
@@ -1333,6 +1359,7 @@ struct DeclaratorChunk {
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
+ bool isAmbiguous,
SourceLocation EllipsisLoc,
ParamInfo *ArgInfo, unsigned NumArgs,
unsigned TypeQuals,
@@ -1350,11 +1377,10 @@ struct DeclaratorChunk {
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
- ParsedType TrailingReturnType =
- ParsedType());
+ TypeResult TrailingReturnType =
+ TypeResult());
- /// getBlockPointer - Return a DeclaratorChunk for a block.
- ///
+ /// \brief Return a DeclaratorChunk for a block.
static DeclaratorChunk getBlockPointer(unsigned TypeQuals,
SourceLocation Loc) {
DeclaratorChunk I;
@@ -1377,8 +1403,7 @@ struct DeclaratorChunk {
return I;
}
- /// getParen - Return a DeclaratorChunk for a paren.
- ///
+ /// \brief Return a DeclaratorChunk for a paren.
static DeclaratorChunk getParen(SourceLocation LParenLoc,
SourceLocation RParenLoc) {
DeclaratorChunk I;
@@ -1399,10 +1424,12 @@ enum FunctionDefinitionKind {
FDK_Defaulted,
FDK_Deleted
};
-
-/// Declarator - Information about one declarator, including the parsed type
-/// information and the identifier. When the declarator is fully formed, this
-/// is turned into the appropriate Decl object.
+
+/// \brief Information about one declarator, including the parsed type
+/// information and the identifier.
+///
+/// When the declarator is fully formed, this is turned into the appropriate
+/// Decl object.
///
/// Declarators come in two types: normal declarators and abstract declarators.
/// Abstract declarators are used when parsing types, and don't have an
@@ -1441,8 +1468,7 @@ private:
UnqualifiedId Name;
SourceRange Range;
- /// Context - Where we are parsing this declarator.
- ///
+ /// \brief Where we are parsing this declarator.
TheContext Context;
/// DeclTypeInfo - This holds each type that the declarator includes as it is
@@ -1463,13 +1489,13 @@ private:
/// Actually a FunctionDefinitionKind.
unsigned FunctionDefinition : 2;
- // Redeclaration - Is this Declarator is a redeclaration.
+ /// \brief Is this Declarator a redeclaration?
bool Redeclaration : 1;
/// Attrs - Attributes.
ParsedAttributes Attrs;
- /// AsmLabel - The asm label, if specified.
+ /// \brief The asm label, if specified.
Expr *AsmLabel;
/// InlineParams - This is a local array used for the first function decl
@@ -1478,7 +1504,7 @@ private:
DeclaratorChunk::ParamInfo InlineParams[16];
bool InlineParamsUsed;
- /// Extension - true if the declaration is preceded by __extension__.
+ /// \brief true if the declaration is preceded by \c __extension__.
bool Extension : 1;
/// \brief If this is the second or subsequent declarator in this declaration,
@@ -1536,7 +1562,7 @@ public:
Context == ObjCResultContext);
}
- /// getSourceRange - Get the source range that spans this declarator.
+ /// \brief Get the source range that spans this declarator.
const SourceRange &getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
@@ -1564,7 +1590,7 @@ public:
Range.setEnd(SR.getEnd());
}
- /// clear - Reset the contents of this Declarator.
+ /// \brief Reset the contents of this Declarator.
void clear() {
SS.clear();
Name.clear();
@@ -1730,13 +1756,12 @@ public:
SetRangeEnd(EndLoc);
}
- /// AddInnermostTypeInfo - Add a new innermost chunk to this declarator.
+ /// \brief Add a new innermost chunk to this declarator.
void AddInnermostTypeInfo(const DeclaratorChunk &TI) {
DeclTypeInfo.insert(DeclTypeInfo.begin(), TI);
}
- /// getNumTypeObjects() - Return the number of types applied to this
- /// declarator.
+ /// \brief Return the number of types applied to this declarator.
unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); }
/// Return the specified TypeInfo from this declarator. TypeInfo #0 is
@@ -1902,17 +1927,16 @@ public:
bool isRedeclaration() const { return Redeclaration; }
};
-/// FieldDeclarator - This little struct is used to capture information about
+/// \brief This little struct is used to capture information about
/// structure field declarators, which is basically just a bitfield size.
struct FieldDeclarator {
Declarator D;
Expr *BitfieldSize;
- explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) {
- BitfieldSize = 0;
- }
+ explicit FieldDeclarator(const DeclSpec &DS)
+ : D(DS, Declarator::MemberContext), BitfieldSize(0) { }
};
-/// VirtSpecifiers - Represents a C++0x virt-specifier-seq.
+/// \brief Represents a C++11 virt-specifier-seq.
class VirtSpecifiers {
public:
enum Specifier {
@@ -1945,7 +1969,7 @@ private:
SourceLocation LastLocation;
};
-/// LambdaCapture - An individual capture in a lambda introducer.
+/// \brief An individual capture in a lambda introducer.
struct LambdaCapture {
LambdaCaptureKind Kind;
SourceLocation Loc;
@@ -1959,7 +1983,7 @@ struct LambdaCapture {
{}
};
-/// LambdaIntroducer - Represents a complete lambda introducer.
+/// \brief Represents a complete lambda introducer.
struct LambdaIntroducer {
SourceRange Range;
SourceLocation DefaultLoc;
@@ -1969,7 +1993,7 @@ struct LambdaIntroducer {
LambdaIntroducer()
: Default(LCD_None) {}
- /// addCapture - Append a capture in a lambda introducer.
+ /// \brief Append a capture in a lambda introducer.
void addCapture(LambdaCaptureKind Kind,
SourceLocation Loc,
IdentifierInfo* Id = 0,
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
index 3320cd815a6b..c241266c9b8d 100644
--- a/include/clang/Sema/DelayedDiagnostic.h
+++ b/include/clang/Sema/DelayedDiagnostic.h
@@ -21,7 +21,7 @@
#ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
#define LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
-#include "clang/AST/DeclCXX.h"
+#include "clang/Sema/Sema.h"
namespace clang {
namespace sema {
@@ -40,17 +40,17 @@ public:
bool isMemberAccess() const { return IsMember; }
- AccessedEntity(ASTContext &Context,
+ AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator,
MemberNonce _,
CXXRecordDecl *NamingClass,
DeclAccessPair FoundDecl,
QualType BaseObjectType)
: Access(FoundDecl.getAccess()), IsMember(true),
Target(FoundDecl.getDecl()), NamingClass(NamingClass),
- BaseObjectType(BaseObjectType), Diag(0, Context.getDiagAllocator()) {
+ BaseObjectType(BaseObjectType), Diag(0, Allocator) {
}
- AccessedEntity(ASTContext &Context,
+ AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator,
BaseNonce _,
CXXRecordDecl *BaseClass,
CXXRecordDecl *DerivedClass,
@@ -58,7 +58,7 @@ public:
: Access(Access), IsMember(false),
Target(BaseClass),
NamingClass(DerivedClass),
- Diag(0, Context.getDiagAllocator()) {
+ Diag(0, Allocator) {
}
bool isQuiet() const { return Diag.getDiagID() == 0; }
@@ -214,7 +214,63 @@ private:
};
};
+/// DelayedDiagnosticPool - A collection of diagnostics which were
+/// delayed.
+class DelayedDiagnosticPool {
+ const DelayedDiagnosticPool *Parent;
+ llvm::SmallVector<DelayedDiagnostic, 4> Diagnostics;
+
+ // Do not implement.
+ DelayedDiagnosticPool(const DelayedDiagnosticPool &other);
+ DelayedDiagnosticPool &operator=(const DelayedDiagnosticPool &other);
+public:
+ DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {}
+ ~DelayedDiagnosticPool() {
+ for (llvm::SmallVectorImpl<DelayedDiagnostic>::iterator
+ i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i)
+ i->Destroy();
+ }
+
+ const DelayedDiagnosticPool *getParent() const { return Parent; }
+
+ /// Does this pool, or any of its ancestors, contain any diagnostics?
+ bool empty() const {
+ return (Diagnostics.empty() && (Parent == NULL || Parent->empty()));
+ }
+
+ /// Add a diagnostic to this pool.
+ void add(const DelayedDiagnostic &diag) {
+ Diagnostics.push_back(diag);
+ }
+
+ /// Steal the diagnostics from the given pool.
+ void steal(DelayedDiagnosticPool &pool) {
+ if (pool.Diagnostics.empty()) return;
+
+ if (Diagnostics.empty()) {
+ Diagnostics = llvm_move(pool.Diagnostics);
+ } else {
+ Diagnostics.append(pool.pool_begin(), pool.pool_end());
+ }
+ pool.Diagnostics.clear();
+ }
+
+ typedef llvm::SmallVectorImpl<DelayedDiagnostic>::const_iterator
+ pool_iterator;
+ pool_iterator pool_begin() const { return Diagnostics.begin(); }
+ pool_iterator pool_end() const { return Diagnostics.end(); }
+ bool pool_empty() const { return Diagnostics.empty(); }
+};
+
}
+
+/// Add a diagnostic to the current delay pool.
+inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) {
+ assert(shouldDelayDiagnostics() && "trying to delay without pool");
+ CurPool->add(diag);
+}
+
+
}
#endif
diff --git a/include/clang/Sema/Designator.h b/include/clang/Sema/Designator.h
index fe01f4d60149..55603fe2e2f9 100644
--- a/include/clang/Sema/Designator.h
+++ b/include/clang/Sema/Designator.h
@@ -179,18 +179,10 @@ public:
/// Designation - Represent a full designation, which is a sequence of
/// designators. This class is mostly a helper for InitListDesignations.
class Designation {
- /// InitIndex - The index of the initializer expression this is for. For
- /// example, if the initializer were "{ A, .foo=B, C }" a Designation would
- /// exist with InitIndex=1, because element #1 has a designation.
- unsigned InitIndex;
-
/// Designators - The actual designators for this initializer.
SmallVector<Designator, 2> Designators;
- Designation(unsigned Idx) : InitIndex(Idx) {}
public:
- Designation() : InitIndex(4000) {}
-
/// AddDesignator - Add a designator to the end of this list.
void AddDesignator(Designator D) {
Designators.push_back(D);
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 0dd68875a9ec..77659be1470f 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -15,6 +15,7 @@
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Overload.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/SourceLocation.h"
@@ -855,8 +856,8 @@ public:
///
/// \param BaseType the base type to which we will be casting.
///
- /// \param IsLValue true if the result of this cast will be treated as
- /// an lvalue.
+ /// \param Category Indicates whether the result will be treated as an
+ /// rvalue, an xvalue, or an lvalue.
void AddDerivedToBaseCastStep(QualType BaseType,
ExprValueKind Category);
@@ -865,9 +866,6 @@ public:
/// \param BindingTemporary True if we are binding a reference to a temporary
/// object (thereby extending its lifetime); false if we are binding to an
/// lvalue or an lvalue treated as an rvalue.
- ///
- /// \param UnnecessaryCopy True if we should check for a copy
- /// constructor for a completely unnecessary but
void AddReferenceBindingStep(QualType T, bool BindingTemporary);
/// \brief Add a new step that makes an extraneous copy of the input
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index d334447edc57..d2fc285c9e29 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -659,12 +659,25 @@ namespace clang {
/// A structure used to record information about a failed
/// template argument deduction.
struct DeductionFailureInfo {
- // A Sema::TemplateDeductionResult.
- unsigned Result;
+ /// A Sema::TemplateDeductionResult.
+ unsigned Result : 8;
+
+ /// \brief Indicates whether a diagnostic is stored in Diagnostic.
+ unsigned HasDiagnostic : 1;
/// \brief Opaque pointer containing additional data about
/// this deduction failure.
void *Data;
+
+ /// \brief A diagnostic indicating why deduction failed.
+ union {
+ void *Align;
+ char Diagnostic[sizeof(PartialDiagnosticAt)];
+ };
+
+ /// \brief Retrieve the diagnostic which caused this deduction failure,
+ /// if any.
+ PartialDiagnosticAt *getSFINAEDiagnostic();
/// \brief Retrieve the template parameter this deduction failure
/// refers to, if any.
@@ -740,11 +753,7 @@ namespace clang {
public:
OverloadCandidateSet(SourceLocation Loc) : Loc(Loc), NumInlineSequences(0){}
- ~OverloadCandidateSet() {
- for (iterator i = begin(), e = end(); i != e; ++i)
- for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
- i->Conversions[ii].~ImplicitConversionSequence();
- }
+ ~OverloadCandidateSet() { clear(); }
SourceLocation getLocation() const { return Loc; }
diff --git a/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h
index c1b471014b73..69080ad9b1d7 100644
--- a/include/clang/Sema/ParsedTemplate.h
+++ b/include/clang/Sema/ParsedTemplate.h
@@ -58,7 +58,7 @@ namespace clang {
SourceLocation TemplateLoc)
: Kind(ParsedTemplateArgument::Template),
Arg(Template.getAsOpaquePtr()),
- Loc(TemplateLoc), SS(SS), EllipsisLoc() { }
+ SS(SS), Loc(TemplateLoc), EllipsisLoc() { }
/// \brief Determine whether the given template argument is invalid.
bool isInvalid() const { return Arg == 0; }
@@ -118,13 +118,13 @@ namespace clang {
/// expression), or an ActionBase::TemplateTy (for a template).
void *Arg;
- /// \brief the location of the template argument.
- SourceLocation Loc;
-
/// \brief The nested-name-specifier that can accompany a template template
/// argument.
CXXScopeSpec SS;
-
+
+ /// \brief the location of the template argument.
+ SourceLocation Loc;
+
/// \brief The ellipsis location that can accompany a template template
/// argument (turning it into a template template argument expansion).
SourceLocation EllipsisLoc;
diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h
index 48f54179ec4a..b78556e65a6c 100644
--- a/include/clang/Sema/Scope.h
+++ b/include/clang/Sema/Scope.h
@@ -71,7 +71,7 @@ public:
FunctionPrototypeScope = 0x100,
/// AtCatchScope - This is a scope that corresponds to the Objective-C
- /// @catch statement.
+ /// \@catch statement.
AtCatchScope = 0x200,
/// ObjCMethodScope - This scope corresponds to an Objective-C method body.
@@ -270,7 +270,7 @@ public:
return getFlags() & Scope::FunctionPrototypeScope;
}
- /// isAtCatchScope - Return true if this scope is @catch.
+ /// isAtCatchScope - Return true if this scope is \@catch.
bool isAtCatchScope() const {
return getFlags() & Scope::AtCatchScope;
}
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index ceaf58669412..b4752f5dbb12 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -74,7 +74,7 @@ public:
///
ScopeKind Kind;
- /// \brief Whether this function contains a VLA, @try, try, C++
+ /// \brief Whether this function contains a VLA, \@try, try, C++
/// initializer, or anything else that can't be jumped past.
bool HasBranchProtectedScope;
@@ -84,6 +84,14 @@ public:
/// \brief Whether this function contains any indirect gotos.
bool HasIndirectGoto;
+ /// A flag that is set when parsing a -dealloc method and no [super dealloc]
+ /// call was found yet.
+ bool ObjCShouldCallSuperDealloc;
+
+ /// A flag that is set when parsing a -finalize method and no [super finalize]
+ /// call was found yet.
+ bool ObjCShouldCallSuperFinalize;
+
/// \brief Used to determine if errors occurred in this function or block.
DiagnosticErrorTrap ErrorTrap;
@@ -93,7 +101,7 @@ public:
/// \brief The list of return statements that occur within the function or
/// block, if there is any chance of applying the named return value
- /// optimization.
+ /// optimization, or if we need to infer a return type.
SmallVector<ReturnStmt*, 4> Returns;
/// \brief The stack of currently active compound stamement scopes in the
@@ -127,6 +135,8 @@ public:
HasBranchProtectedScope(false),
HasBranchIntoScope(false),
HasIndirectGoto(false),
+ ObjCShouldCallSuperDealloc(false),
+ ObjCShouldCallSuperFinalize(false),
ErrorTrap(Diag) { }
virtual ~FunctionScopeInfo();
@@ -344,6 +354,9 @@ public:
/// \brief Whether any of the capture expressions requires cleanups.
bool ExprNeedsCleanups;
+ /// \brief Whether the lambda contains an unexpanded parameter pack.
+ bool ContainsUnexpandedParameterPack;
+
/// \brief Variables used to index into by-copy array captures.
llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
@@ -355,7 +368,7 @@ public:
CXXMethodDecl *CallOperator)
: CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false),
- ExprNeedsCleanups(false)
+ ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false)
{
Kind = SK_Lambda;
}
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index c8767b6f9601..058e0d9d3920 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -28,6 +28,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/LambdaMangleContext.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/NSAPI.h"
#include "clang/Lex/ModuleLoader.h"
@@ -36,7 +37,9 @@
#include "clang/Basic/TypeTraits.h"
#include "clang/Basic/ExpressionTraits.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include <deque>
@@ -167,8 +170,10 @@ namespace clang {
namespace sema {
class AccessedEntity;
class BlockScopeInfo;
+ class CapturingScopeInfo;
class CompoundScopeInfo;
class DelayedDiagnostic;
+ class DelayedDiagnosticPool;
class FunctionScopeInfo;
class LambdaScopeInfo;
class PossiblyUnreachableDiag;
@@ -220,13 +225,13 @@ public:
/// This is used as part of a hack to omit that class from ADL results.
DeclarationName VAListTagName;
- /// PackContext - Manages the stack for #pragma pack. An alignment
+ /// PackContext - Manages the stack for \#pragma pack. An alignment
/// of 0 indicates default alignment.
void *PackContext; // Really a "PragmaPackStack*"
- bool MSStructPragmaOn; // True when #pragma ms_struct on
+ bool MSStructPragmaOn; // True when \#pragma ms_struct on
- /// VisContext - Manages the stack for #pragma GCC visibility.
+ /// VisContext - Manages the stack for \#pragma GCC visibility.
void *VisContext; // Really a "PragmaVisStack*"
/// ExprNeedsCleanups - True if the current evaluation context
@@ -262,10 +267,15 @@ public:
///
/// This set is used to suppress redundant diagnostics.
llvm::SmallPtrSet<NamedDecl *, 4> HiddenDefinitions;
-
+
/// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
OwningPtr<CXXFieldCollector> FieldCollector;
+ typedef llvm::SmallSetVector<const NamedDecl*, 16> NamedDeclSetType;
+
+ /// \brief Set containing all declared private fields that are not used.
+ NamedDeclSetType UnusedPrivateFields;
+
typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
/// PureVirtualClassDiagSet - a set of class declarations which we have
@@ -355,93 +365,63 @@ public:
class DelayedDiagnostics;
- class ParsingDeclState {
- unsigned SavedStackSize;
- friend class Sema::DelayedDiagnostics;
- };
-
- class ProcessingContextState {
- unsigned SavedParsingDepth;
- unsigned SavedActiveStackBase;
+ class DelayedDiagnosticsState {
+ sema::DelayedDiagnosticPool *SavedPool;
friend class Sema::DelayedDiagnostics;
};
+ typedef DelayedDiagnosticsState ParsingDeclState;
+ typedef DelayedDiagnosticsState ProcessingContextState;
/// A class which encapsulates the logic for delaying diagnostics
/// during parsing and other processing.
class DelayedDiagnostics {
- /// \brief The stack of diagnostics that were delayed due to being
- /// produced during the parsing of a declaration.
- sema::DelayedDiagnostic *Stack;
-
- /// \brief The number of objects on the delayed-diagnostics stack.
- unsigned StackSize;
-
- /// \brief The current capacity of the delayed-diagnostics stack.
- unsigned StackCapacity;
-
- /// \brief The index of the first "active" delayed diagnostic in
- /// the stack. When parsing class definitions, we ignore active
- /// delayed diagnostics from the surrounding context.
- unsigned ActiveStackBase;
-
- /// \brief The depth of the declarations we're currently parsing.
- /// This gets saved and reset whenever we enter a class definition.
- unsigned ParsingDepth;
+ /// \brief The current pool of diagnostics into which delayed
+ /// diagnostics should go.
+ sema::DelayedDiagnosticPool *CurPool;
public:
- DelayedDiagnostics() : Stack(0), StackSize(0), StackCapacity(0),
- ActiveStackBase(0), ParsingDepth(0) {}
-
- ~DelayedDiagnostics() {
- delete[] reinterpret_cast<char*>(Stack);
- }
+ DelayedDiagnostics() : CurPool(0) {}
/// Adds a delayed diagnostic.
- void add(const sema::DelayedDiagnostic &diag);
+ void add(const sema::DelayedDiagnostic &diag); // in DelayedDiagnostic.h
/// Determines whether diagnostics should be delayed.
- bool shouldDelayDiagnostics() { return ParsingDepth > 0; }
-
- /// Observe that we've started parsing a declaration. Access and
- /// deprecation diagnostics will be delayed; when the declaration
- /// is completed, all active delayed diagnostics will be evaluated
- /// in its context, and then active diagnostics stack will be
- /// popped down to the saved depth.
- ParsingDeclState pushParsingDecl() {
- ParsingDepth++;
-
- ParsingDeclState state;
- state.SavedStackSize = StackSize;
- return state;
- }
-
- /// Observe that we're completed parsing a declaration.
- static void popParsingDecl(Sema &S, ParsingDeclState state, Decl *decl);
+ bool shouldDelayDiagnostics() { return CurPool != 0; }
- /// Observe that we've started processing a different context, the
- /// contents of which are semantically separate from the
- /// declarations it may lexically appear in. This sets aside the
- /// current stack of active diagnostics and starts afresh.
- ProcessingContextState pushContext() {
- assert(StackSize >= ActiveStackBase);
+ /// Returns the current delayed-diagnostics pool.
+ sema::DelayedDiagnosticPool *getCurrentPool() const {
+ return CurPool;
+ }
- ProcessingContextState state;
- state.SavedParsingDepth = ParsingDepth;
- state.SavedActiveStackBase = ActiveStackBase;
+ /// Enter a new scope. Access and deprecation diagnostics will be
+ /// collected in this pool.
+ DelayedDiagnosticsState push(sema::DelayedDiagnosticPool &pool) {
+ DelayedDiagnosticsState state;
+ state.SavedPool = CurPool;
+ CurPool = &pool;
+ return state;
+ }
- ActiveStackBase = StackSize;
- ParsingDepth = 0;
+ /// Leave a delayed-diagnostic state that was previously pushed.
+ /// Do not emit any of the diagnostics. This is performed as part
+ /// of the bookkeeping of popping a pool "properly".
+ void popWithoutEmitting(DelayedDiagnosticsState state) {
+ CurPool = state.SavedPool;
+ }
+ /// Enter a new scope where access and deprecation diagnostics are
+ /// not delayed.
+ DelayedDiagnosticsState pushUndelayed() {
+ DelayedDiagnosticsState state;
+ state.SavedPool = CurPool;
+ CurPool = 0;
return state;
}
- /// Observe that we've stopped processing a context. This
- /// restores the previous stack of active diagnostics.
- void popContext(ProcessingContextState state) {
- assert(ActiveStackBase == StackSize);
- assert(ParsingDepth == 0);
- ActiveStackBase = state.SavedActiveStackBase;
- ParsingDepth = state.SavedParsingDepth;
+ /// Undo a previous pushUndelayed().
+ void popUndelayed(DelayedDiagnosticsState state) {
+ assert(CurPool == NULL);
+ CurPool = state.SavedPool;
}
} DelayedDiagnostics;
@@ -452,11 +432,11 @@ public:
DeclContext *SavedContext;
ProcessingContextState SavedContextState;
QualType SavedCXXThisTypeOverride;
-
+
public:
ContextRAII(Sema &S, DeclContext *ContextToPush)
: S(S), SavedContext(S.CurContext),
- SavedContextState(S.DelayedDiagnostics.pushContext()),
+ SavedContextState(S.DelayedDiagnostics.pushUndelayed()),
SavedCXXThisTypeOverride(S.CXXThisTypeOverride)
{
assert(ContextToPush && "pushing null context");
@@ -466,7 +446,7 @@ public:
void pop() {
if (!SavedContext) return;
S.CurContext = SavedContext;
- S.DelayedDiagnostics.popContext(SavedContextState);
+ S.DelayedDiagnostics.popUndelayed(SavedContextState);
S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
SavedContext = 0;
}
@@ -477,12 +457,12 @@ public:
};
/// WeakUndeclaredIdentifiers - Identifiers contained in
- /// #pragma weak before declared. rare. may alias another
+ /// \#pragma weak before declared. rare. may alias another
/// identifier, declared or undeclared
llvm::DenseMap<IdentifierInfo*,WeakInfo> WeakUndeclaredIdentifiers;
/// ExtnameUndeclaredIdentifiers - Identifiers contained in
- /// #pragma redefine_extname before declared. Used in Solaris system headers
+ /// \#pragma redefine_extname before declared. Used in Solaris system headers
/// to define functions that occur in multiple standards to call the version
/// in the currently selected standard.
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers;
@@ -492,7 +472,7 @@ public:
void LoadExternalWeakUndeclaredIdentifiers();
/// WeakTopLevelDecl - Translation-unit scoped declarations generated by
- /// #pragma weak during processing of other Decls.
+ /// \#pragma weak during processing of other Decls.
/// I couldn't figure out a clean way to generate these in-line, so
/// we store them here and handle separately -- which is a hack.
/// It would be best to refactor this.
@@ -513,10 +493,10 @@ public:
LazyDeclPtr StdBadAlloc;
/// \brief The C++ "std::initializer_list" template, which is defined in
- /// <initializer_list>.
+ /// \<initializer_list>.
ClassTemplateDecl *StdInitializerList;
- /// \brief The C++ "type_info" declaration, which is defined in <typeinfo>.
+ /// \brief The C++ "type_info" declaration, which is defined in \<typeinfo>.
RecordDecl *CXXTypeInfoDecl;
/// \brief The MSVC "_GUID" struct, which is defined in MSVC header files.
@@ -527,16 +507,28 @@ public:
/// \brief The declaration of the Objective-C NSNumber class.
ObjCInterfaceDecl *NSNumberDecl;
-
+
+ /// \brief Pointer to NSNumber type (NSNumber *).
+ QualType NSNumberPointer;
+
/// \brief The Objective-C NSNumber methods used to create NSNumber literals.
ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
-
+
+ /// \brief The declaration of the Objective-C NSString class.
+ ObjCInterfaceDecl *NSStringDecl;
+
+ /// \brief Pointer to NSString type (NSString *).
+ QualType NSStringPointer;
+
+ /// \brief The declaration of the stringWithUTF8String: method.
+ ObjCMethodDecl *StringWithUTF8StringMethod;
+
/// \brief The declaration of the Objective-C NSArray class.
ObjCInterfaceDecl *NSArrayDecl;
/// \brief The declaration of the arrayWithObjects:count: method.
ObjCMethodDecl *ArrayWithObjectsMethod;
-
+
/// \brief The declaration of the Objective-C NSDictionary class.
ObjCInterfaceDecl *NSDictionaryDecl;
@@ -550,13 +542,6 @@ public:
/// have been declared.
bool GlobalNewDeleteDeclared;
- /// A flag that is set when parsing a -dealloc method and no [super dealloc]
- /// call was found yet.
- bool ObjCShouldCallSuperDealloc;
- /// A flag that is set when parsing a -finalize method and no [super finalize]
- /// call was found yet.
- bool ObjCShouldCallSuperFinalize;
-
/// \brief Describes how the expressions currently being parsed are
/// evaluated at run-time, if at all.
enum ExpressionEvaluationContext {
@@ -611,10 +596,10 @@ public:
llvm::SmallVector<LambdaExpr *, 2> Lambdas;
/// \brief The declaration that provides context for the lambda expression
- /// if the normal declaration context does not suffice, e.g., in a
+ /// if the normal declaration context does not suffice, e.g., in a
/// default function argument.
Decl *LambdaContextDecl;
-
+
/// \brief The context information used to mangle lambda expressions
/// within this context.
///
@@ -629,7 +614,7 @@ public:
/// \brief If we are processing a decltype type, a set of temporary binding
/// expressions for which we have deferred checking the destructor.
llvm::SmallVector<CXXBindTemporaryExpr*, 8> DelayedDecltypeBinds;
-
+
ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
unsigned NumCleanupObjects,
bool ParentNeedsCleanups,
@@ -638,11 +623,11 @@ public:
: Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects),
LambdaContextDecl(LambdaContextDecl), LambdaMangle() { }
-
+
~ExpressionEvaluationContextRecord() {
delete LambdaMangle;
}
-
+
/// \brief Retrieve the mangling context for lambdas.
LambdaMangleContext &getLambdaMangleContext() {
assert(LambdaContextDecl && "Need to have a lambda context declaration");
@@ -654,17 +639,12 @@ public:
/// A stack of expression evaluation contexts.
SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
-
+
/// SpecialMemberOverloadResult - The overloading result for a special member
/// function.
///
/// This is basically a wrapper around PointerIntPair. The lowest bits of the
- /// integer are used to determine whether overload resolution succeeded, and
- /// whether, when looking up a copy constructor or assignment operator, we
- /// found a potential copy constructor/assignment operator whose first
- /// parameter is const-qualified. This is used for determining parameter types
- /// of other objects and is utterly meaningless on other types of special
- /// members.
+ /// integer are used to determine whether overload resolution succeeded.
class SpecialMemberOverloadResult : public llvm::FastFoldingSetNode {
public:
enum Kind {
@@ -735,7 +715,7 @@ public:
/// of selectors are "overloaded").
GlobalMethodPool MethodPool;
- /// Method selectors used in a @selector expression. Used for implementation
+ /// Method selectors used in a \@selector expression. Used for implementation
/// of -Wselector.
llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors;
@@ -826,7 +806,8 @@ public:
bool findMacroSpelling(SourceLocation &loc, StringRef name);
/// \brief Get a string to suggest for zero-initialization of a type.
- const char *getFixItZeroInitializerForType(QualType T) const;
+ std::string getFixItZeroInitializerForType(QualType T) const;
+ std::string getFixItZeroLiteralForType(QualType T) const;
ExprResult Owned(Expr* E) { return E; }
ExprResult Owned(ExprResult R) { return R; }
@@ -861,9 +842,11 @@ public:
/// \brief Retrieve the current lambda expression, if any.
sema::LambdaScopeInfo *getCurLambda();
- /// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls
+ /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+ void ActOnComment(SourceRange Comment);
+
//===--------------------------------------------------------------------===//
// Type Analysis / Processing: SemaType.cpp.
//
@@ -899,7 +882,7 @@ public:
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo);
-
+
/// \brief Package the given type and TSI into a ParsedType.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
DeclarationNameInfo GetNameForDeclarator(Declarator &D);
@@ -936,19 +919,168 @@ public:
/// in an Objective-C message declaration. Return the appropriate type.
ParsedType ActOnObjCInstanceType(SourceLocation Loc);
+ /// \brief Abstract class used to diagnose incomplete types.
+ struct TypeDiagnoser {
+ bool Suppressed;
+
+ TypeDiagnoser(bool Suppressed = false) : Suppressed(Suppressed) { }
+
+ virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
+ virtual ~TypeDiagnoser() {}
+ };
+
+ static int getPrintable(int I) { return I; }
+ static unsigned getPrintable(unsigned I) { return I; }
+ static bool getPrintable(bool B) { return B; }
+ static const char * getPrintable(const char *S) { return S; }
+ static StringRef getPrintable(StringRef S) { return S; }
+ static const std::string &getPrintable(const std::string &S) { return S; }
+ static const IdentifierInfo *getPrintable(const IdentifierInfo *II) {
+ return II;
+ }
+ static DeclarationName getPrintable(DeclarationName N) { return N; }
+ static QualType getPrintable(QualType T) { return T; }
+ static SourceRange getPrintable(SourceRange R) { return R; }
+ static SourceRange getPrintable(SourceLocation L) { return L; }
+ static SourceRange getPrintable(Expr *E) { return E->getSourceRange(); }
+ static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange();}
+
+ template<typename T1>
+ class BoundTypeDiagnoser1 : public TypeDiagnoser {
+ unsigned DiagID;
+ const T1 &Arg1;
+
+ public:
+ BoundTypeDiagnoser1(unsigned DiagID, const T1 &Arg1)
+ : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1) { }
+ virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ if (Suppressed) return;
+ S.Diag(Loc, DiagID) << getPrintable(Arg1) << T;
+ }
+
+ virtual ~BoundTypeDiagnoser1() { }
+ };
+
+ template<typename T1, typename T2>
+ class BoundTypeDiagnoser2 : public TypeDiagnoser {
+ unsigned DiagID;
+ const T1 &Arg1;
+ const T2 &Arg2;
+
+ public:
+ BoundTypeDiagnoser2(unsigned DiagID, const T1 &Arg1,
+ const T2 &Arg2)
+ : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1),
+ Arg2(Arg2) { }
+
+ virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ if (Suppressed) return;
+ S.Diag(Loc, DiagID) << getPrintable(Arg1) << getPrintable(Arg2) << T;
+ }
+
+ virtual ~BoundTypeDiagnoser2() { }
+ };
+
+ template<typename T1, typename T2, typename T3>
+ class BoundTypeDiagnoser3 : public TypeDiagnoser {
+ unsigned DiagID;
+ const T1 &Arg1;
+ const T2 &Arg2;
+ const T3 &Arg3;
+
+ public:
+ BoundTypeDiagnoser3(unsigned DiagID, const T1 &Arg1,
+ const T2 &Arg2, const T3 &Arg3)
+ : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1),
+ Arg2(Arg2), Arg3(Arg3) { }
+
+ virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ if (Suppressed) return;
+ S.Diag(Loc, DiagID)
+ << getPrintable(Arg1) << getPrintable(Arg2) << getPrintable(Arg3) << T;
+ }
+
+ virtual ~BoundTypeDiagnoser3() { }
+ };
+
bool RequireCompleteType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD,
- std::pair<SourceLocation, PartialDiagnostic> Note);
- bool RequireCompleteType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD);
+ TypeDiagnoser &Diagnoser);
bool RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID);
- bool RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
- std::pair<SourceLocation,
- PartialDiagnostic> Note);
+
+ template<typename T1>
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ unsigned DiagID, const T1 &Arg1) {
+ BoundTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1);
+ return RequireCompleteType(Loc, T, Diagnoser);
+ }
+
+ template<typename T1, typename T2>
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ unsigned DiagID, const T1 &Arg1, const T2 &Arg2) {
+ BoundTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2);
+ return RequireCompleteType(Loc, T, Diagnoser);
+ }
+
+ template<typename T1, typename T2, typename T3>
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ unsigned DiagID, const T1 &Arg1, const T2 &Arg2,
+ const T3 &Arg3) {
+ BoundTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2,
+ Arg3);
+ return RequireCompleteType(Loc, T, Diagnoser);
+ }
+
+ bool RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser);
+ bool RequireCompleteExprType(Expr *E, unsigned DiagID);
+
+ template<typename T1>
+ bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1) {
+ BoundTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1);
+ return RequireCompleteExprType(E, Diagnoser);
+ }
+
+ template<typename T1, typename T2>
+ bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1,
+ const T2 &Arg2) {
+ BoundTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2);
+ return RequireCompleteExprType(E, Diagnoser);
+ }
+
+ template<typename T1, typename T2, typename T3>
+ bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1,
+ const T2 &Arg2, const T3 &Arg3) {
+ BoundTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2,
+ Arg3);
+ return RequireCompleteExprType(E, Diagnoser);
+ }
bool RequireLiteralType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD);
+ TypeDiagnoser &Diagnoser);
+ bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID);
+
+ template<typename T1>
+ bool RequireLiteralType(SourceLocation Loc, QualType T,
+ unsigned DiagID, const T1 &Arg1) {
+ BoundTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1);
+ return RequireLiteralType(Loc, T, Diagnoser);
+ }
+
+ template<typename T1, typename T2>
+ bool RequireLiteralType(SourceLocation Loc, QualType T,
+ unsigned DiagID, const T1 &Arg1, const T2 &Arg2) {
+ BoundTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2);
+ return RequireLiteralType(Loc, T, Diagnoser);
+ }
+
+ template<typename T1, typename T2, typename T3>
+ bool RequireLiteralType(SourceLocation Loc, QualType T,
+ unsigned DiagID, const T1 &Arg1, const T2 &Arg2,
+ const T3 &Arg3) {
+ BoundTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2,
+ Arg3);
+ return RequireLiteralType(Loc, T, Diagnoser);
+ }
QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
const CXXScopeSpec &SS, QualType T);
@@ -978,6 +1110,8 @@ public:
void DiagnoseUseOfUnimplementedSelectors();
+ bool isSimpleTypeSpecifier(tok::TokenKind Kind) const;
+
ParsedType getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec *SS = 0,
bool isClassName = false,
@@ -988,7 +1122,7 @@ public:
IdentifierInfo **CorrectedII = 0);
TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S);
- bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
+ bool DiagnoseUnknownTypeName(IdentifierInfo *&II,
SourceLocation IILoc,
Scope *S,
CXXScopeSpec *SS,
@@ -1173,12 +1307,21 @@ public:
unsigned NumDecls);
DeclGroupPtrTy BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
bool TypeMayContainAuto = true);
+
+ /// Should be called on all declarations that might have attached
+ /// documentation comments.
+ void ActOnDocumentableDecl(Decl *D);
+ void ActOnDocumentableDecls(Decl **Group, unsigned NumDecls);
+
void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
SourceLocation LocAfterDecls);
void CheckForFunctionRedefinition(FunctionDecl *FD);
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
+ bool isObjCMethodDecl(Decl *D) {
+ return D && isa<ObjCMethodDecl>(D);
+ }
void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope);
Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body);
@@ -1213,7 +1356,7 @@ public:
/// \param ImportLoc The location of the 'import' keyword.
///
/// \param Path The module access path.
- DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc,
+ DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc,
ModuleIdPath Path);
/// \brief Retrieve a suitable printing policy.
@@ -1286,13 +1429,15 @@ public:
Declarator &D, Expr *BitfieldWidth);
FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
- Declarator &D, Expr *BitfieldWidth, bool HasInit,
+ Declarator &D, Expr *BitfieldWidth,
+ InClassInitStyle InitStyle,
AccessSpecifier AS);
FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
TypeSourceInfo *TInfo,
RecordDecl *Record, SourceLocation Loc,
- bool Mutable, Expr *BitfieldWidth, bool HasInit,
+ bool Mutable, Expr *BitfieldWidth,
+ InClassInitStyle InitStyle,
SourceLocation TSSL,
AccessSpecifier AS, NamedDecl *PrevDecl,
Declarator *D = 0);
@@ -1432,6 +1577,24 @@ public:
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
TypeSourceInfo *TInfo);
bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New);
+
+ /// Attribute merging methods. Return true if a new attribute was added.
+ AvailabilityAttr *mergeAvailabilityAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Platform,
+ VersionTuple Introduced,
+ VersionTuple Deprecated,
+ VersionTuple Obsoleted,
+ bool IsUnavailable,
+ StringRef Message);
+ VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range,
+ VisibilityAttr::VisibilityType Vis);
+ DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range);
+ DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range);
+ FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format,
+ int FormatIdx, int FirstArg);
+ SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name);
+ bool mergeDeclAttribute(Decl *New, InheritableAttr *Attr);
+
void mergeDeclAttributes(Decl *New, Decl *Old, bool MergeDeprecation = true);
void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S);
@@ -1558,16 +1721,59 @@ public:
ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
llvm::APSInt &Value, CCEKind CCE);
+ /// \brief Abstract base class used to diagnose problems that occur while
+ /// trying to convert an expression to integral or enumeration type.
+ class ICEConvertDiagnoser {
+ public:
+ bool Suppress;
+ bool SuppressConversion;
+
+ ICEConvertDiagnoser(bool Suppress = false,
+ bool SuppressConversion = false)
+ : Suppress(Suppress), SuppressConversion(SuppressConversion) { }
+
+ /// \brief Emits a diagnostic complaining that the expression does not have
+ /// integral or enumeration type.
+ virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) = 0;
+
+ /// \brief Emits a diagnostic when the expression has incomplete class type.
+ virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
+ QualType T) = 0;
+
+ /// \brief Emits a diagnostic when the only matching conversion function
+ /// is explicit.
+ virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) = 0;
+
+ /// \brief Emits a note for the explicit conversion function.
+ virtual DiagnosticBuilder
+ noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
+
+ /// \brief Emits a diagnostic when there are multiple possible conversion
+ /// functions.
+ virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+ QualType T) = 0;
+
+ /// \brief Emits a note for one of the candidate conversions.
+ virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
+ QualType ConvTy) = 0;
+
+ /// \brief Emits a diagnostic when we picked a conversion function
+ /// (for cases when we are not allowed to pick a conversion function).
+ virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) = 0;
+
+ virtual ~ICEConvertDiagnoser() {}
+ };
+
ExprResult
ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE,
- const PartialDiagnostic &NotIntDiag,
- const PartialDiagnostic &IncompleteDiag,
- const PartialDiagnostic &ExplicitConvDiag,
- const PartialDiagnostic &ExplicitConvNote,
- const PartialDiagnostic &AmbigDiag,
- const PartialDiagnostic &AmbigNote,
- const PartialDiagnostic &ConvDiag,
+ ICEConvertDiagnoser &Diagnoser,
bool AllowScopedEnumerations);
+
enum ObjCSubscriptKind {
OS_Array,
OS_Dictionary,
@@ -1910,14 +2116,16 @@ public:
unsigned Quals);
CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals,
bool RValueThis, unsigned ThisQuals);
- CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class);
- CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, bool RValueThis,
- unsigned ThisQuals);
+ CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class,
+ unsigned Quals);
+ CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals,
+ bool RValueThis, unsigned ThisQuals);
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R,
ArrayRef<QualType> ArgTys,
bool AllowRawAndTemplate);
+ bool isKnownName(StringRef name);
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
SourceLocation Loc,
@@ -2000,13 +2208,11 @@ public:
bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
ObjCInterfaceDecl *IDecl);
- typedef llvm::DenseSet<Selector, llvm::DenseMapInfo<Selector> > SelectorSet;
+ typedef llvm::SmallPtrSet<Selector, 8> SelectorSet;
typedef llvm::DenseMap<Selector, ObjCMethodDecl*> ProtocolsMethodsMap;
/// CheckProtocolMethodDefs - This routine checks unimplemented
/// methods declared in protocol, and those referenced by it.
- /// \param IDecl - Used for checking for methods which may have been
- /// inherited.
void CheckProtocolMethodDefs(SourceLocation ImpLoc,
ObjCProtocolDecl *PDecl,
bool& IncompleteImpl,
@@ -2021,7 +2227,7 @@ public:
SourceLocation Loc);
/// ImplMethodsVsClassMethods - This is main routine to warn if any method
- /// remains unimplemented in the class or category @implementation.
+ /// remains unimplemented in the class or category \@implementation.
void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
ObjCContainerDecl* IDecl,
bool IncompleteImpl = false);
@@ -2033,7 +2239,7 @@ public:
const SelectorSet &InsMap);
/// DefaultSynthesizeProperties - This routine default synthesizes all
- /// properties which must be synthesized in class's @implementation.
+ /// properties which must be synthesized in the class's \@implementation.
void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
ObjCInterfaceDecl *IDecl);
void DefaultSynthesizeProperties(Scope *S, Decl *D);
@@ -2050,8 +2256,8 @@ public:
ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl,
IdentifierInfo *II);
- /// Called by ActOnProperty to handle @property declarations in
- //// class extensions.
+ /// Called by ActOnProperty to handle \@property declarations in
+ /// class extensions.
Decl *HandlePropertyInClassExtension(Scope *S,
SourceLocation AtLoc,
SourceLocation LParenLoc,
@@ -2067,7 +2273,7 @@ public:
tok::ObjCKeywordKind MethodImplKind);
/// Called by ActOnProperty and HandlePropertyInClassExtension to
- /// handle creating the ObjcPropertyDecl for a category or @interface.
+ /// handle creating the ObjcPropertyDecl for a category or \@interface.
ObjCPropertyDecl *CreatePropertyDecl(Scope *S,
ObjCContainerDecl *CDecl,
SourceLocation AtLoc,
@@ -2123,7 +2329,7 @@ public:
/// \brief Add the given method to the list of globally-known methods.
void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
-
+
private:
/// AddMethodToGlobalPool - Add an instance or factory method to the global
/// pool. See descriptoin of AddInstanceMethodToGlobalPool.
@@ -2213,7 +2419,10 @@ public:
};
FullExprArg MakeFullExpr(Expr *Arg) {
- return FullExprArg(ActOnFinishFullExpr(Arg).release());
+ return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation());
+ }
+ FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) {
+ return FullExprArg(ActOnFinishFullExpr(Arg, CC).release());
}
StmtResult ActOnExprStmt(FullExprArg Expr);
@@ -2258,7 +2467,8 @@ public:
StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
SourceLocation ColonLoc, Stmt *SubStmt);
- StmtResult ActOnAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
+ StmtResult ActOnAttributedStmt(SourceLocation AttrLoc,
+ ArrayRef<const Attr*> Attrs,
Stmt *SubStmt);
StmtResult ActOnIfStmt(SourceLocation IfLoc,
@@ -2285,12 +2495,14 @@ public:
FullExprArg Third,
SourceLocation RParenLoc,
Stmt *Body);
- ExprResult ActOnObjCForCollectionOperand(SourceLocation forLoc,
+ ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc,
Expr *collection);
StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
SourceLocation LParenLoc,
- Stmt *First, Expr *Second,
- SourceLocation RParenLoc, Stmt *Body);
+ Stmt *First, Expr *collection,
+ SourceLocation RParenLoc);
+ StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body);
+
StmtResult ActOnCXXForRangeStmt(SourceLocation ForLoc,
SourceLocation LParenLoc, Stmt *LoopVar,
SourceLocation ColonLoc, Expr *Collection,
@@ -2329,6 +2541,10 @@ public:
SourceLocation RParenLoc,
bool MSAsm = false);
+ StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc,
+ ArrayRef<Token> AsmToks,
+ ArrayRef<unsigned> LineEnds,
+ SourceLocation EndLoc);
VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
SourceLocation StartLoc,
@@ -2408,21 +2624,21 @@ public:
void DiagnoseEmptyLoopBody(const Stmt *S,
const Stmt *PossibleBody);
- ParsingDeclState PushParsingDeclaration() {
- return DelayedDiagnostics.pushParsingDecl();
- }
- void PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
- DelayedDiagnostics::popParsingDecl(*this, state, decl);
+ ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
+ return DelayedDiagnostics.push(pool);
}
+ void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
typedef ProcessingContextState ParsingClassState;
ParsingClassState PushParsingClass() {
- return DelayedDiagnostics.pushContext();
+ return DelayedDiagnostics.pushUndelayed();
}
void PopParsingClass(ParsingClassState state) {
- DelayedDiagnostics.popContext(state);
+ DelayedDiagnostics.popUndelayed(state);
}
+ void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
+
void EmitDeprecationWarning(NamedDecl *D, StringRef Message,
SourceLocation Loc,
const ObjCInterfaceDecl *UnknownObjCClass=0);
@@ -2484,13 +2700,13 @@ public:
///
/// \param Loc The location at which the capture occurs.
///
- /// \param Kind The kind of capture, which may be implicit (for either a
+ /// \param Kind The kind of capture, which may be implicit (for either a
/// block or a lambda), or explicit by-value or by-reference (for a lambda).
///
/// \param EllipsisLoc The location of the ellipsis, if one is provided in
/// an explicit lambda capture.
///
- /// \param BuildAndDiagnose Whether we are actually supposed to add the
+ /// \param BuildAndDiagnose Whether we are actually supposed to add the
/// captures or diagnose errors. If false, this routine merely check whether
/// the capture can occur without performing the capture itself or complaining
/// if the variable cannot be captured.
@@ -2499,14 +2715,14 @@ public:
/// this variable in the innermost block or lambda. Only valid when the
/// variable can be captured.
///
- /// \param DeclRefType Will be set to the type of a refernce to the capture
- /// from within the current scope. Only valid when the variable can be
+ /// \param DeclRefType Will be set to the type of a reference to the capture
+ /// from within the current scope. Only valid when the variable can be
/// captured.
///
/// \returns true if an error occurred (i.e., the variable cannot be
/// captured) and false if the capture succeeded.
bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind,
- SourceLocation EllipsisLoc, bool BuildAndDiagnose,
+ SourceLocation EllipsisLoc, bool BuildAndDiagnose,
QualType &CaptureType,
QualType &DeclRefType);
@@ -2514,13 +2730,13 @@ public:
bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
TryCaptureKind Kind = TryCapture_Implicit,
SourceLocation EllipsisLoc = SourceLocation());
-
+
/// \brief Given a variable, determine the type that a reference to that
/// variable will have in the given scope.
QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc);
-
+
void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
- void MarkDeclarationsReferencedInExpr(Expr *E,
+ void MarkDeclarationsReferencedInExpr(Expr *E,
bool SkipLocalVariables = false);
/// \brief Try to recover by turning the given expression into a
@@ -2537,10 +2753,10 @@ public:
/// \brief Conditionally issue a diagnostic based on the current
/// evaluation context.
///
- /// \param stmt - If stmt is non-null, delay reporting the diagnostic until
- /// the function body is parsed, and then do a basic reachability analysis to
- /// determine if the statement is reachable. If it is unreachable, the
- /// diagnostic will not be emitted.
+ /// \param Statement If Statement is non-null, delay reporting the
+ /// diagnostic until the function body is parsed, and then do a basic
+ /// reachability analysis to determine if the statement is reachable.
+ /// If it is unreachable, the diagnostic will not be emitted.
bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
const PartialDiagnostic &PD);
@@ -2696,6 +2912,18 @@ public:
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
+ // This struct is for use by ActOnMemberAccess to allow
+ // BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after
+ // changing the access operator from a '.' to a '->' (to see if that is the
+ // change needed to fix an error about an unknown member, e.g. when the class
+ // defines a custom operator->).
+ struct ActOnMemberAccessExtraArgs {
+ Scope *S;
+ UnqualifiedId &Id;
+ Decl *ObjCImpDecl;
+ bool HasTrailingLParen;
+ };
+
ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
SourceLocation OpLoc, bool IsArrow,
const CXXScopeSpec &SS,
@@ -2703,7 +2931,8 @@ public:
NamedDecl *FirstQualifierInScope,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
- bool SuppressQualifierCheck = false);
+ bool SuppressQualifierCheck = false,
+ ActOnMemberAccessExtraArgs *ExtraArgs = 0);
ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
ExprResult LookupMemberExpr(LookupResult &R, ExprResult &Base,
@@ -2901,7 +3130,8 @@ public:
/// ActOnBlockArguments - This callback allows processing of block arguments.
/// If there are no arguments, this is still invoked.
- void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope);
+ void ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
+ Scope *CurScope);
/// ActOnBlockError - If there is an error parsing a block, this callback
/// is invoked to pop the information about the block from the action impl.
@@ -3010,7 +3240,7 @@ public:
TypeResult Type);
/// InitializeVarWithConstructor - Creates an CXXConstructExpr
- /// and sets it as the initializer for the the passed in VarDecl.
+ /// and sets it as the initializer for the passed in VarDecl.
bool InitializeVarWithConstructor(VarDecl *VD,
CXXConstructorDecl *Constructor,
MultiExprArg Exprs,
@@ -3075,7 +3305,7 @@ public:
public:
explicit ImplicitExceptionSpecification(Sema &Self)
: Self(&Self), ComputedEST(EST_BasicNoexcept) {
- if (!Self.Context.getLangOpts().CPlusPlus0x)
+ if (!Self.getLangOpts().CPlusPlus0x)
ComputedEST = EST_DynamicNone;
}
@@ -3098,17 +3328,16 @@ public:
/// \brief Integrate an invoked expression into the collected data.
void CalledExpr(Expr *E);
- /// \brief Specify that the exception specification can't be detemined yet.
- void SetDelayed() {
- ClearExceptions();
- ComputedEST = EST_Delayed;
- }
-
- FunctionProtoType::ExtProtoInfo getEPI() const {
- FunctionProtoType::ExtProtoInfo EPI;
+ /// \brief Overwrite an EPI's exception specification with this
+ /// computed exception specification.
+ void getEPI(FunctionProtoType::ExtProtoInfo &EPI) const {
EPI.ExceptionSpecType = getExceptionSpecType();
EPI.NumExceptions = size();
EPI.Exceptions = data();
+ }
+ FunctionProtoType::ExtProtoInfo getEPI() const {
+ FunctionProtoType::ExtProtoInfo EPI;
+ getEPI(EPI);
return EPI;
}
};
@@ -3116,34 +3345,39 @@ public:
/// \brief Determine what sort of exception specification a defaulted
/// copy constructor of a class will have.
ImplicitExceptionSpecification
- ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl);
+ ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
+ CXXMethodDecl *MD);
/// \brief Determine what sort of exception specification a defaulted
/// default constructor of a class will have, and whether the parameter
/// will be const.
- std::pair<ImplicitExceptionSpecification, bool>
- ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl);
+ ImplicitExceptionSpecification
+ ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD);
/// \brief Determine what sort of exception specification a defautled
/// copy assignment operator of a class will have, and whether the
/// parameter will be const.
- std::pair<ImplicitExceptionSpecification, bool>
- ComputeDefaultedCopyAssignmentExceptionSpecAndConst(CXXRecordDecl *ClassDecl);
+ ImplicitExceptionSpecification
+ ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD);
/// \brief Determine what sort of exception specification a defaulted move
/// constructor of a class will have.
ImplicitExceptionSpecification
- ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl);
+ ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD);
/// \brief Determine what sort of exception specification a defaulted move
/// assignment operator of a class will have.
ImplicitExceptionSpecification
- ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl);
+ ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD);
/// \brief Determine what sort of exception specification a defaulted
/// destructor of a class will have.
ImplicitExceptionSpecification
- ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl);
+ ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD);
+
+ /// \brief Evaluate the implicit exception specification for a defaulted
+ /// special member function.
+ void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD);
/// \brief Check the given exception-specification and update the
/// extended prototype information with the results.
@@ -3191,8 +3425,7 @@ public:
/// C++11 says that user-defined destructors with no exception spec get one
/// that looks as if the destructor was implicitly declared.
void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
- CXXDestructorDecl *Destructor,
- bool WasDelayed = false);
+ CXXDestructorDecl *Destructor);
/// \brief Declare all inherited constructors for the given class.
///
@@ -3259,7 +3492,7 @@ public:
/// \brief Determine whether the given function is an implicitly-deleted
/// special member function.
bool isImplicitlyDeleted(FunctionDecl *FD);
-
+
/// \brief Check whether 'this' shows up in the type of a static member
/// function after the (naturally empty) cv-qualifier-seq would be.
///
@@ -3275,7 +3508,7 @@ public:
///
/// \returns true if an error occurred.
bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
-
+
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
/// it simply returns the passed in expression.
@@ -3352,34 +3585,32 @@ public:
/// \brief Try to retrieve the type of the 'this' pointer.
///
- /// \param Capture If true, capture 'this' in this context.
- ///
/// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
QualType getCurrentThisType();
- /// \brief When non-NULL, the C++ 'this' expression is allowed despite the
+ /// \brief When non-NULL, the C++ 'this' expression is allowed despite the
/// current context not being a non-static member function. In such cases,
/// this provides the type used for 'this'.
QualType CXXThisTypeOverride;
-
+
/// \brief RAII object used to temporarily allow the C++ 'this' expression
/// to be used, with the given qualifiers on the current class type.
class CXXThisScopeRAII {
Sema &S;
QualType OldCXXThisTypeOverride;
bool Enabled;
-
+
public:
/// \brief Introduce a new scope where 'this' may be allowed (when enabled),
- /// using the given declaration (which is either a class template or a
+ /// using the given declaration (which is either a class template or a
/// class) along with the given qualifiers.
/// along with the qualifiers placed on '*this'.
- CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals,
+ CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals,
bool Enabled = true);
-
+
~CXXThisScopeRAII();
};
-
+
/// \brief Make sure the value of 'this' is actually available in the current
/// context, if it is a potentially evaluated context.
///
@@ -3390,14 +3621,14 @@ public:
void CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false);
/// \brief Determine whether the given type is the type of *this that is used
- /// outside of the body of a member function for a type that is currently
+ /// outside of the body of a member function for a type that is currently
/// being defined.
bool isThisOutsideMemberFunctionBody(QualType BaseType);
-
+
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
-
-
+
+
/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
@@ -3513,7 +3744,7 @@ public:
ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc);
-
+
/// ActOnArrayTypeTrait - Parsed one of the bianry type trait support
/// pseudo-functions.
ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT,
@@ -3572,7 +3803,7 @@ public:
ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
- SourceLocation TildeLoc,
+ SourceLocation TildeLoc,
const DeclSpec& DS,
bool HasTrailingLParen);
@@ -3583,7 +3814,11 @@ public:
Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt);
ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr);
- ExprResult ActOnFinishFullExpr(Expr *Expr);
+ ExprResult ActOnFinishFullExpr(Expr *Expr) {
+ return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc()
+ : SourceLocation());
+ }
+ ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC);
StmtResult ActOnFinishFullStmt(Stmt *Stmt);
// Marks SS invalid if it represents an incomplete type.
@@ -3660,7 +3895,7 @@ public:
ExprResult ActOnDecltypeExpression(Expr *E);
bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
- const DeclSpec &DS,
+ const DeclSpec &DS,
SourceLocation ColonColonLoc);
bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
@@ -3681,7 +3916,7 @@ public:
/// including this new type).
///
/// \param TemplateKWLoc the location of the 'template' keyword, if any.
- /// \param TemplateName The template name.
+ /// \param TemplateName the template name.
/// \param TemplateNameLoc The location of the template name.
/// \param LAngleLoc The location of the opening angle bracket ('<').
/// \param TemplateArgs The template arguments.
@@ -3696,7 +3931,7 @@ public:
bool ActOnCXXNestedNameSpecifier(Scope *S,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
- TemplateTy Template,
+ TemplateTy TemplateName,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
@@ -3759,17 +3994,14 @@ public:
/// \brief Create a new lambda closure type.
CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
bool KnownDependent = false);
-
+
/// \brief Start the definition of a lambda expression.
CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
SourceRange IntroducerRange,
TypeSourceInfo *MethodType,
SourceLocation EndLoc,
- llvm::ArrayRef<ParmVarDecl *> Params,
- llvm::Optional<unsigned> ManglingNumber
- = llvm::Optional<unsigned>(),
- Decl *ContextDecl = 0);
-
+ llvm::ArrayRef<ParmVarDecl *> Params);
+
/// \brief Introduce the scope for a lambda expression.
sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
@@ -3777,16 +4009,20 @@ public:
bool ExplicitParams,
bool ExplicitResultType,
bool Mutable);
-
+
/// \brief Note that we have finished the explicit captures for the
/// given lambda.
void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
-
+
/// \brief Introduce the lambda parameters into scope.
void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope);
-
+
+ /// \brief Deduce a block or lambda's return type based on the return
+ /// statements present in the body.
+ void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
+
/// ActOnStartOfLambdaDefinition - This is called just before we start
- /// parsing the body of a lambda; it analyzes the explicit captures and
+ /// parsing the body of a lambda; it analyzes the explicit captures and
/// arguments, and sets up various data-structures for the body of the
/// lambda.
void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
@@ -3800,10 +4036,10 @@ public:
/// ActOnLambdaExpr - This is called when the body of a lambda expression
/// was successfully completed.
ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
- Scope *CurScope,
+ Scope *CurScope,
bool IsInstantiation = false);
- /// \brief Define the "body" of the conversion from a lambda object to a
+ /// \brief Define the "body" of the conversion from a lambda object to a
/// function pointer.
///
/// This routine doesn't actually define a sensible body; rather, it fills
@@ -3813,7 +4049,7 @@ public:
void DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLoc, CXXConversionDecl *Conv);
- /// \brief Define the "body" of the conversion from a lambda object to a
+ /// \brief Define the "body" of the conversion from a lambda object to a
/// block pointer.
///
/// This routine doesn't actually define a sensible body; rather, it fills
@@ -3832,26 +4068,33 @@ public:
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
Expr **Strings,
unsigned NumStrings);
-
+
ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
-
- /// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the
+
+ /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
/// numeric literal expression. Type of the expression will be "NSNumber *"
/// or "id" if NSNumber is unavailable.
ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number);
ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc,
bool Value);
ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements);
-
+
+ /// BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the
+ /// '@' prefixed parenthesized expression. The type of the expression will
+ /// either be "NSNumber *" or "NSString *" depending on the type of
+ /// ValueType, which is allowed to be a built-in numeric type or
+ /// "char *" or "const char *".
+ ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr);
+
ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
Expr *IndexExpr,
ObjCMethodDecl *getterMethod,
ObjCMethodDecl *setterMethod);
-
- ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
+
+ ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
ObjCDictionaryElement *Elements,
unsigned NumElements);
-
+
ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
TypeSourceInfo *EncodedTypeInfo,
SourceLocation RParenLoc);
@@ -3865,18 +4108,19 @@ public:
ParsedType Ty,
SourceLocation RParenLoc);
- // ParseObjCSelectorExpression - Build selector expression for @selector
+ /// ParseObjCSelectorExpression - Build selector expression for \@selector
ExprResult ParseObjCSelectorExpression(Selector Sel,
SourceLocation AtLoc,
SourceLocation SelLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc);
- // ParseObjCProtocolExpression - Build protocol expression for @protocol
+ /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
SourceLocation AtLoc,
SourceLocation ProtoLoc,
SourceLocation LParenLoc,
+ SourceLocation ProtoIdLoc,
SourceLocation RParenLoc);
//===--------------------------------------------------------------------===//
@@ -3907,7 +4151,7 @@ public:
Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
Expr *BitfieldWidth, const VirtSpecifiers &VS,
- bool HasDeferredInit);
+ InClassInitStyle InitStyle);
void ActOnCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc,
Expr *Init);
@@ -4004,6 +4248,11 @@ public:
void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
bool DefinitionRequired = false);
+ /// \brief Mark the exception specifications of all virtual member functions
+ /// in the given class as needed.
+ void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
+ const CXXRecordDecl *RD);
+
/// MarkVirtualMembersReferenced - Will mark all members of the given
/// CXXRecordDecl referenced.
void MarkVirtualMembersReferenced(SourceLocation Loc,
@@ -4047,6 +4296,11 @@ public:
Expr *AssertExpr,
Expr *AssertMessageExpr,
SourceLocation RParenLoc);
+ Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
+ Expr *AssertExpr,
+ StringLiteral *AssertMessageExpr,
+ SourceLocation RParenLoc,
+ bool Failed);
FriendDecl *CheckFriendTypeDecl(SourceLocation Loc,
SourceLocation FriendLoc,
@@ -4067,12 +4321,7 @@ public:
Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
void CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record);
- void CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *Ctor);
- void CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *Ctor);
- void CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *Method);
- void CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *Ctor);
- void CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *Method);
- void CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *Dtor);
+ void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD);
//===--------------------------------------------------------------------===//
// C++ Derived Classes
@@ -4130,12 +4379,12 @@ public:
bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
- /// CheckOverrideControl - Check C++0x override control semantics.
- void CheckOverrideControl(const Decl *D);
+ /// CheckOverrideControl - Check C++11 override control semantics.
+ void CheckOverrideControl(Decl *D);
/// CheckForFunctionMarkedFinal - Checks whether a virtual member function
/// overrides a virtual member function marked 'final', according to
- /// C++0x [class.virtual]p3.
+ /// C++11 [class.virtual]p4.
bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
const CXXMethodDecl *Old);
@@ -4178,9 +4427,7 @@ public:
CXXDestructorDecl *Dtor,
const PartialDiagnostic &PDiag,
QualType objectType = QualType());
- AccessResult CheckDirectMemberAccess(SourceLocation Loc,
- NamedDecl *D,
- const PartialDiagnostic &PDiag);
+ AccessResult CheckFriendAccess(NamedDecl *D);
AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
Expr *ObjectExpr,
Expr *ArgExpr,
@@ -4206,36 +4453,10 @@ public:
void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
- /// A flag to suppress access checking.
- bool SuppressAccessChecking;
-
/// \brief When true, access checking violations are treated as SFINAE
/// failures rather than hard errors.
bool AccessCheckingSFINAE;
- /// \brief RAII object used to temporarily suppress access checking.
- class SuppressAccessChecksRAII {
- Sema &S;
- bool SuppressingAccess;
-
- public:
- SuppressAccessChecksRAII(Sema &S, bool Suppress)
- : S(S), SuppressingAccess(Suppress) {
- if (Suppress) S.ActOnStartSuppressingAccessChecks();
- }
- ~SuppressAccessChecksRAII() {
- done();
- }
- void done() {
- if (!SuppressingAccess) return;
- S.ActOnStopSuppressingAccessChecks();
- SuppressingAccess = false;
- }
- };
-
- void ActOnStartSuppressingAccessChecks();
- void ActOnStopSuppressingAccessChecks();
-
enum AbstractDiagSelID {
AbstractNone = -1,
AbstractReturnType,
@@ -4246,7 +4467,31 @@ public:
};
bool RequireNonAbstractType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD);
+ TypeDiagnoser &Diagnoser);
+ template<typename T1>
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T,
+ unsigned DiagID,
+ const T1 &Arg1) {
+ BoundTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1);
+ return RequireNonAbstractType(Loc, T, Diagnoser);
+ }
+
+ template<typename T1, typename T2>
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T,
+ unsigned DiagID,
+ const T1 &Arg1, const T2 &Arg2) {
+ BoundTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2);
+ return RequireNonAbstractType(Loc, T, Diagnoser);
+ }
+
+ template<typename T1, typename T2, typename T3>
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T,
+ unsigned DiagID,
+ const T1 &Arg1, const T2 &Arg2, const T3 &Arg3) {
+ BoundTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2, Arg3);
+ return RequireNonAbstractType(Loc, T, Diagnoser);
+ }
+
void DiagnoseAbstractType(const CXXRecordDecl *RD);
bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
@@ -4263,9 +4508,9 @@ public:
//===--------------------------------------------------------------------===//
// C++ Templates [C++ 14]
//
- void FilterAcceptableTemplateNames(LookupResult &R,
+ void FilterAcceptableTemplateNames(LookupResult &R,
bool AllowFunctionTemplates = true);
- bool hasAnyAcceptableTemplateNames(LookupResult &R,
+ bool hasAnyAcceptableTemplateNames(LookupResult &R,
bool AllowFunctionTemplates = true);
void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
@@ -4638,7 +4883,7 @@ public:
ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
const CXXScopeSpec &SS,
SourceLocation TemplateLoc,
- TemplateTy Template,
+ TemplateTy TemplateName,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
@@ -4730,7 +4975,13 @@ public:
UPPC_IfExists,
/// \brief Microsoft __if_not_exists.
- UPPC_IfNotExists
+ UPPC_IfNotExists,
+
+ /// \brief Lambda expression.
+ UPPC_Lambda,
+
+ /// \brief Block expression,
+ UPPC_Block
};
/// \brief Diagnose unexpanded parameter packs.
@@ -4741,7 +4992,9 @@ public:
/// parameter packs.
///
/// \param Unexpanded the set of unexpanded parameter packs.
- void DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
UnexpandedParameterPackContext UPPC,
ArrayRef<UnexpandedParameterPack> Unexpanded);
@@ -4922,9 +5175,6 @@ public:
/// \param Unexpanded The set of unexpanded parameter packs within the
/// pattern.
///
- /// \param NumUnexpanded The number of unexpanded parameter packs in
- /// \p Unexpanded.
- ///
/// \param ShouldExpand Will be set to \c true if the transformer should
/// expand the corresponding pack expansions into separate arguments. When
/// set, \c NumExpansions must also be set.
@@ -4957,10 +5207,11 @@ public:
/// \brief Determine the number of arguments in the given pack expansion
/// type.
///
- /// This routine already assumes that the pack expansion type can be
- /// expanded and that the number of arguments in the expansion is
+ /// This routine assumes that the number of arguments in the expansion is
/// consistent across all of the unexpanded parameter packs in its pattern.
- unsigned getNumArgumentsInExpansion(QualType T,
+ ///
+ /// Returns an empty Optional if the type can't be expanded.
+ llvm::Optional<unsigned> getNumArgumentsInExpansion(QualType T,
const MultiLevelTemplateArgumentList &TemplateArgs);
/// \brief Determine whether the given declarator contains any unexpanded
@@ -5366,16 +5617,14 @@ public:
/// template-id.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
TemplateDecl *Template,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
+ ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange = SourceRange());
/// \brief Note that we are instantiating a default argument in a
/// template-id.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
FunctionTemplateDecl *FunctionTemplate,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
+ ArrayRef<TemplateArgument> TemplateArgs,
ActiveTemplateInstantiation::InstantiationKind Kind,
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
@@ -5385,15 +5634,13 @@ public:
/// specialization.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ClassTemplatePartialSpecializationDecl *PartialSpec,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
+ ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ParmVarDecl *Param,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
+ ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange = SourceRange());
/// \brief Note that we are substituting prior template arguments into a
@@ -5401,15 +5648,13 @@ public:
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
NamedDecl *Template,
NonTypeTemplateParmDecl *Param,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
+ ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
NamedDecl *Template,
TemplateTemplateParmDecl *Param,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
+ ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
/// \brief Note that we are checking the default template argument
@@ -5417,8 +5662,7 @@ public:
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
TemplateDecl *Template,
NamedDecl *Param,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
+ ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
@@ -5456,6 +5700,14 @@ public:
/// diagnostics that will be suppressed.
llvm::Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const;
+ /// \brief Determines whether we are currently in a context that
+ /// is not evaluated as per C++ [expr] p5.
+ bool isUnevaluatedContext() const {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ return ExprEvalContexts.back().Context == Sema::Unevaluated;
+ }
+
/// \brief RAII class used to determine whether SFINAE has
/// trapped any errors that occur during template argument
/// deduction.`
@@ -5705,7 +5957,7 @@ public:
SourceLocation EndProtoLoc,
AttributeList *AttrList);
- Decl *ActOnCompatiblityAlias(
+ Decl *ActOnCompatibilityAlias(
SourceLocation AtCompatibilityAliasLoc,
IdentifierInfo *AliasName, SourceLocation AliasLocation,
IdentifierInfo *ClassName, SourceLocation ClassLocation);
@@ -5768,28 +6020,27 @@ public:
/// be modified to be consistent with \arg PropertyTy.
void CheckObjCPropertyAttributes(Decl *PropertyPtrTy,
SourceLocation Loc,
- unsigned &Attributes);
+ unsigned &Attributes,
+ bool propertyInPrimaryClass);
/// Process the specified property declaration and create decls for the
/// setters and getters as needed.
/// \param property The property declaration being processed
- /// \param DC The semantic container for the property
+ /// \param CD The semantic container for the property
/// \param redeclaredProperty Declaration for property if redeclared
/// in class extension.
/// \param lexicalDC Container for redeclaredProperty.
void ProcessPropertyDecl(ObjCPropertyDecl *property,
- ObjCContainerDecl *DC,
+ ObjCContainerDecl *CD,
ObjCPropertyDecl *redeclaredProperty = 0,
ObjCContainerDecl *lexicalDC = 0);
+
void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
ObjCPropertyDecl *SuperProperty,
const IdentifierInfo *Name);
void ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl);
- void CompareMethodParamsInBaseAndSuper(Decl *IDecl,
- ObjCMethodDecl *MethodDecl,
- bool IsInstance);
void CompareProperties(Decl *CDecl, Decl *MergeProtocols);
@@ -5855,14 +6106,6 @@ public:
AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind,
bool isVariadic, bool MethodDefinition);
- // Helper method for ActOnClassMethod/ActOnInstanceMethod.
- // Will search "local" class/category implementations for a method decl.
- // Will also search in class's root looking for instance method.
- // Returns 0 if no method is found.
- ObjCMethodDecl *LookupPrivateClassMethod(Selector Sel,
- ObjCInterfaceDecl *CDecl);
- ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel,
- ObjCInterfaceDecl *ClassDecl);
ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel,
const ObjCObjectPointerType *OPT,
bool IsInstance);
@@ -5988,9 +6231,16 @@ public:
const ObjCMethodDecl *Overridden,
bool IsImplementation);
- /// \brief Check whether the given method overrides any methods in its class,
- /// calling \c CheckObjCMethodOverride for each overridden method.
- bool CheckObjCMethodOverrides(ObjCMethodDecl *NewMethod, DeclContext *DC);
+ /// \brief Describes the compatibility of a result type with its method.
+ enum ResultTypeCompatibilityKind {
+ RTC_Compatible,
+ RTC_Incompatible,
+ RTC_Unknown
+ };
+
+ void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
+ ObjCInterfaceDecl *CurrentClass,
+ ResultTypeCompatibilityKind RTC);
enum PragmaOptionsAlignKind {
POAK_Native, // #pragma options align=native
@@ -6001,7 +6251,7 @@ public:
POAK_Reset // #pragma options align=reset
};
- /// ActOnPragmaOptionsAlign - Called on well formed #pragma options align.
+ /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
SourceLocation PragmaLoc,
SourceLocation KindLoc);
@@ -6018,7 +6268,7 @@ public:
PMSST_ON // #pragms ms_struct on
};
- /// ActOnPragmaPack - Called on well formed #pragma pack(...).
+ /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
void ActOnPragmaPack(PragmaPackKind Kind,
IdentifierInfo *Name,
Expr *Alignment,
@@ -6026,15 +6276,15 @@ public:
SourceLocation LParenLoc,
SourceLocation RParenLoc);
- /// ActOnPragmaMSStruct - Called on well formed #pragms ms_struct [on|off].
+ /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
- /// ActOnPragmaUnused - Called on well-formed '#pragma unused'.
+ /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
void ActOnPragmaUnused(const Token &Identifier,
Scope *curScope,
SourceLocation PragmaLoc);
- /// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... .
+ /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... .
void ActOnPragmaVisibility(const IdentifierInfo* VisType,
SourceLocation PragmaLoc);
@@ -6042,20 +6292,20 @@ public:
SourceLocation Loc);
void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W);
- /// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
+ /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident.
void ActOnPragmaWeakID(IdentifierInfo* WeakName,
SourceLocation PragmaLoc,
SourceLocation WeakNameLoc);
- /// ActOnPragmaRedefineExtname - Called on well formed
- /// #pragma redefine_extname oldname newname.
+ /// ActOnPragmaRedefineExtname - Called on well formed
+ /// \#pragma redefine_extname oldname newname.
void ActOnPragmaRedefineExtname(IdentifierInfo* WeakName,
IdentifierInfo* AliasName,
SourceLocation PragmaLoc,
SourceLocation WeakNameLoc,
SourceLocation AliasNameLoc);
- /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident.
+ /// ActOnPragmaWeakAlias - Called on well formed \#pragma weak ident = ident.
void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
IdentifierInfo* AliasName,
SourceLocation PragmaLoc,
@@ -6063,11 +6313,11 @@ public:
SourceLocation AliasNameLoc);
/// ActOnPragmaFPContract - Called on well formed
- /// #pragma {STDC,OPENCL} FP_CONTRACT
+ /// \#pragma {STDC,OPENCL} FP_CONTRACT
void ActOnPragmaFPContract(tok::OnOffSwitch OOS);
/// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
- /// a the record decl, to handle '#pragma pack' and '#pragma options align'.
+ /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
void AddAlignmentAttributesForRecord(RecordDecl *RD);
/// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record.
@@ -6081,25 +6331,27 @@ public:
void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
SourceLocation Loc);
- /// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used,
+ /// AddPushedVisibilityAttribute - If '\#pragma GCC visibility' was used,
/// add an appropriate visibility attribute.
void AddPushedVisibilityAttribute(Decl *RD);
/// PopPragmaVisibility - Pop the top element of the visibility stack; used
- /// for '#pragma GCC visibility' and visibility attributes on namespaces.
+ /// for '\#pragma GCC visibility' and visibility attributes on namespaces.
void PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc);
/// FreeVisContext - Deallocate and null out VisContext.
void FreeVisContext();
/// AddCFAuditedAttribute - Check whether we're currently within
- /// '#pragma clang arc_cf_code_audited' and, if so, consider adding
+ /// '\#pragma clang arc_cf_code_audited' and, if so, consider adding
/// the appropriate attribute.
void AddCFAuditedAttribute(Decl *D);
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
- void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E);
- void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T);
+ void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
+ bool isDeclSpec);
+ void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T,
+ bool isDeclSpec);
/// \brief The kind of conversion being performed.
enum CheckedConversionKind {
@@ -6164,6 +6416,21 @@ public:
VariadicDoesNotApply
};
+ VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ Expr *Fn);
+
+ // Used for determining in which context a type is allowed to be passed to a
+ // vararg function.
+ enum VarArgKind {
+ VAK_Valid,
+ VAK_ValidInCXX11,
+ VAK_Invalid
+ };
+
+ // Determines which VarArgKind fits an expression.
+ VarArgKind isValidVarArgType(const QualType &Ty);
+
/// GatherArgumentsForCall - Collector argument expressions for various
/// form of call prototypes.
bool GatherArgumentsForCall(SourceLocation CallLoc,
@@ -6176,10 +6443,14 @@ public:
bool AllowExplicit = false);
// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
- // will warn if the resulting type is not a POD type.
+ // will create a runtime trap if the resulting type is not a POD type.
ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
FunctionDecl *FDecl);
+ /// Checks to see if the given expression is a valid argument to a variadic
+ /// function, issuing a diagnostic and returning NULL if not.
+ bool variadicArgumentPODCheck(const Expr *E, VariadicCallType CT);
+
// UsualArithmeticConversions - performs the UsualUnaryConversions on it's
// operands and then handles various conversions that are common to binary
// operators (C99 6.3.1.8). If both operands aren't arithmetic, this
@@ -6269,6 +6540,11 @@ public:
Expr *SrcExpr, AssignmentAction Action,
bool *Complained = 0);
+ /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant
+ /// integer not in the range of enum values.
+ void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
+ Expr *SrcExpr);
+
/// CheckAssignmentConstraints - Perform type checking for assignment,
/// argument passing, variable initialization, and function return values.
/// C99 6.5.16.
@@ -6434,7 +6710,7 @@ public:
/// \brief Force an expression with unknown-type to an expression of the
/// given type.
ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
-
+
// CheckVectorCast - check type constraints for vectors.
// Since vectors are an extension, there are no C standard reference for this.
// We allow casting between vectors and integer datatypes of the same size.
@@ -6540,20 +6816,29 @@ public:
/// in the global scope.
bool CheckObjCDeclScope(Decl *D);
+ /// \brief Abstract base class used for diagnosing integer constant
+ /// expression violations.
+ class VerifyICEDiagnoser {
+ public:
+ bool Suppress;
+
+ VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { }
+
+ virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) =0;
+ virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR);
+ virtual ~VerifyICEDiagnoser() { }
+ };
+
/// VerifyIntegerConstantExpression - Verifies that an expression is an ICE,
/// and reports the appropriate diagnostics. Returns false on success.
/// Can optionally return the value of the expression.
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
- const PartialDiagnostic &Diag,
- bool AllowFold,
- const PartialDiagnostic &FoldDiag);
+ VerifyICEDiagnoser &Diagnoser,
+ bool AllowFold = true);
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
- const PartialDiagnostic &Diag,
- bool AllowFold = true) {
- return VerifyIntegerConstantExpression(E, Result, Diag, AllowFold,
- PDiag(0));
- }
- ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result = 0);
+ unsigned DiagID,
+ bool AllowFold = true);
+ ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result=0);
/// VerifyBitField - verifies that a bit field expression is an ICE and has
/// the correct width, and that the field type is valid.
@@ -6745,15 +7030,39 @@ private:
const ArraySubscriptExpr *ASE=0,
bool AllowOnePastEnd=true, bool IndexNegated=false);
void CheckArrayAccess(const Expr *E);
- bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
- bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
+ // Used to grab the relevant information from a FormatAttr and a
+ // FunctionDeclaration.
+ struct FormatStringInfo {
+ unsigned FormatIdx;
+ unsigned FirstDataArg;
+ bool HasVAListArg;
+ };
+
+ bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
+ FormatStringInfo *FSI);
+ bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
+ const FunctionProtoType *Proto);
+ bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
Expr **Args, unsigned NumArgs);
- bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
+ bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall,
+ const FunctionProtoType *Proto);
+ void CheckConstructorCall(FunctionDecl *FDecl,
+ Expr **Args,
+ unsigned NumArgs,
+ const FunctionProtoType *Proto,
+ SourceLocation Loc);
+
+ void checkCall(NamedDecl *FDecl, Expr **Args, unsigned NumArgs,
+ unsigned NumProtoArgs, bool IsMemberFunction,
+ SourceLocation Loc, SourceRange Range,
+ VariadicCallType CallType);
+
bool CheckObjCString(Expr *Arg);
ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool SemaBuiltinVAStart(CallExpr *TheCall);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
@@ -6783,23 +7092,36 @@ private:
FST_Unknown
};
static FormatStringType GetFormatStringType(const FormatAttr *Format);
- bool SemaCheckStringLiteral(const Expr *E, Expr **Args, unsigned NumArgs,
- bool HasVAListArg, unsigned format_idx,
- unsigned firstDataArg, FormatStringType Type,
- bool inFunctionCall = true);
+
+ enum StringLiteralCheckType {
+ SLCT_NotALiteral,
+ SLCT_UncheckedLiteral,
+ SLCT_CheckedLiteral
+ };
+
+ StringLiteralCheckType checkFormatStringExpr(const Expr *E,
+ Expr **Args, unsigned NumArgs,
+ bool HasVAListArg,
+ unsigned format_idx,
+ unsigned firstDataArg,
+ FormatStringType Type,
+ VariadicCallType CallType,
+ bool inFunctionCall = true);
void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr,
Expr **Args, unsigned NumArgs, bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg,
- FormatStringType Type, bool inFunctionCall);
+ FormatStringType Type, bool inFunctionCall,
+ VariadicCallType CallType);
- void CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall);
- void CheckFormatArguments(const FormatAttr *Format, Expr **Args,
+ bool CheckFormatArguments(const FormatAttr *Format, Expr **Args,
unsigned NumArgs, bool IsCXXMember,
+ VariadicCallType CallType,
SourceLocation Loc, SourceRange Range);
- void CheckFormatArguments(Expr **Args, unsigned NumArgs,
+ bool CheckFormatArguments(Expr **Args, unsigned NumArgs,
bool HasVAListArg, unsigned format_idx,
unsigned firstDataArg, FormatStringType Type,
+ VariadicCallType CallType,
SourceLocation Loc, SourceRange range);
void CheckNonNullArguments(const NonNullAttr *NonNull,
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h
index c16823a6a14b..273374dfd8b0 100644
--- a/include/clang/Sema/Template.h
+++ b/include/clang/Sema/Template.h
@@ -152,10 +152,11 @@ namespace clang {
/// \brief Construct an integral non-type template argument that
/// has been deduced, possibly from an array bound.
- DeducedTemplateArgument(const llvm::APSInt &Value,
+ DeducedTemplateArgument(ASTContext &Ctx,
+ const llvm::APSInt &Value,
QualType ValueType,
bool DeducedFromArrayBound)
- : TemplateArgument(Value, ValueType),
+ : TemplateArgument(Ctx, Value, ValueType),
DeducedFromArrayBound(DeducedFromArrayBound) { }
/// \brief For a non-type template argument, determine whether the
@@ -371,8 +372,10 @@ namespace clang {
public:
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs)
- : SemaRef(SemaRef), SubstIndex(SemaRef, -1), Owner(Owner),
- TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0) { }
+ : SemaRef(SemaRef),
+ SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
+ Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0)
+ { }
// FIXME: Once we get closer to completion, replace these manually-written
// declarations with automatically-generated ones from
diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h
index 100d56ed3317..4c2d876d1f87 100644
--- a/include/clang/Sema/TemplateDeduction.h
+++ b/include/clang/Sema/TemplateDeduction.h
@@ -39,6 +39,9 @@ class TemplateDeductionInfo {
/// deduction is occurring.
SourceLocation Loc;
+ /// \brief Have we suppressed an error during deduction?
+ bool HasSFINAEDiagnostic;
+
/// \brief Warnings (and follow-on notes) that were suppressed due to
/// SFINAE while performing template argument deduction.
SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
@@ -49,7 +52,7 @@ class TemplateDeductionInfo {
public:
TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc)
- : Context(Context), Deduced(0), Loc(Loc) { }
+ : Context(Context), Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false) { }
~TemplateDeductionInfo() {
// FIXME: if (Deduced) Deduced->Destroy(Context);
@@ -68,6 +71,15 @@ public:
return Result;
}
+ /// \brief Take ownership of the SFINAE diagnostic.
+ void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) {
+ assert(HasSFINAEDiagnostic);
+ PD.first = SuppressedDiagnostics.front().first;
+ PD.second.swap(SuppressedDiagnostics.front().second);
+ SuppressedDiagnostics.clear();
+ HasSFINAEDiagnostic = false;
+ }
+
/// \brief Provide a new template argument list that contains the
/// results of template argument deduction.
void reset(TemplateArgumentList *NewDeduced) {
@@ -75,10 +87,31 @@ public:
Deduced = NewDeduced;
}
+ /// \brief Is a SFINAE diagnostic available?
+ bool hasSFINAEDiagnostic() const {
+ return HasSFINAEDiagnostic;
+ }
+
+ /// \brief Set the diagnostic which caused the SFINAE failure.
+ void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) {
+ // Only collect the first diagnostic.
+ if (HasSFINAEDiagnostic)
+ return;
+ SuppressedDiagnostics.clear();
+ SuppressedDiagnostics.push_back(
+ std::make_pair(Loc, PartialDiagnostic::NullDiagnostic()));
+ SuppressedDiagnostics.back().second.swap(PD);
+ HasSFINAEDiagnostic = true;
+ }
+
/// \brief Add a new diagnostic to the set of diagnostics
void addSuppressedDiagnostic(SourceLocation Loc,
- const PartialDiagnostic &PD) {
- SuppressedDiagnostics.push_back(std::make_pair(Loc, PD));
+ PartialDiagnostic PD) {
+ if (HasSFINAEDiagnostic)
+ return;
+ SuppressedDiagnostics.push_back(
+ std::make_pair(Loc, PartialDiagnostic::NullDiagnostic()));
+ SuppressedDiagnostics.back().second.swap(PD);
}
/// \brief Iterator over the set of suppressed diagnostics.
diff --git a/include/clang/Sema/Weak.h b/include/clang/Sema/Weak.h
index d36b97089364..6d1b64bd3016 100644
--- a/include/clang/Sema/Weak.h
+++ b/include/clang/Sema/Weak.h
@@ -21,7 +21,7 @@ namespace clang {
class IdentifierInfo;
-/// \brief Captures information about a #pragma weak directive.
+/// \brief Captures information about a \#pragma weak directive.
class WeakInfo {
IdentifierInfo *alias; // alias (optional)
SourceLocation loc; // for diagnostics
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index f9bb8928a362..dbe6e5a31440 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -207,7 +207,10 @@ namespace clang {
PREPROCESSOR_DETAIL_BLOCK_ID,
/// \brief The block containing the submodule structure.
- SUBMODULE_BLOCK_ID
+ SUBMODULE_BLOCK_ID,
+
+ /// \brief The block containing comments.
+ COMMENTS_BLOCK_ID
};
/// \brief Record types that occur within the AST block itself.
@@ -405,7 +408,7 @@ namespace clang {
/// sets.
CXX_BASE_SPECIFIER_OFFSETS = 37,
- /// \brief Record code for #pragma diagnostic mappings.
+ /// \brief Record code for \#pragma diagnostic mappings.
DIAG_PRAGMA_MAPPINGS = 38,
/// \brief Record code for special CUDA declarations.
@@ -417,7 +420,7 @@ namespace clang {
/// \brief The directory that the PCH was originally created in.
ORIGINAL_PCH_DIR = 41,
- /// \brief Record code for floating point #pragma options.
+ /// \brief Record code for floating point \#pragma options.
FP_PRAGMA_OPTIONS = 42,
/// \brief Record code for enabled OpenCL extensions.
@@ -441,7 +444,7 @@ namespace clang {
MODULE_OFFSET_MAP = 47,
/// \brief Record code for the source manager line table information,
- /// which stores information about #line directives.
+ /// which stores information about \#line directives.
SOURCE_MANAGER_LINE_TABLE = 48,
/// \brief Record code for map of Objective-C class definition IDs to the
@@ -469,7 +472,7 @@ namespace clang {
///
/// This array can only be interpreted properly using the Objective-C
/// categories map.
- OBJC_CATEGORIES
+ OBJC_CATEGORIES = 54
};
/// \brief Record types used within a source manager block.
@@ -500,8 +503,8 @@ namespace clang {
PP_MACRO_OBJECT_LIKE = 1,
/// \brief A function-like macro definition.
- /// [PP_MACRO_FUNCTION_LIKE, <ObjectLikeStuff>, IsC99Varargs, IsGNUVarars,
- /// NumArgs, ArgIdentInfoID* ]
+ /// [PP_MACRO_FUNCTION_LIKE, \<ObjectLikeStuff>, IsC99Varargs,
+ /// IsGNUVarars, NumArgs, ArgIdentInfoID* ]
PP_MACRO_FUNCTION_LIKE = 2,
/// \brief Describes one token.
@@ -545,7 +548,12 @@ namespace clang {
/// \brief Specifies a required feature.
SUBMODULE_REQUIRES = 7
};
-
+
+ /// \brief Record types used within a comments block.
+ enum CommentRecordTypes {
+ COMMENTS_RAW_COMMENT = 0
+ };
+
/// \defgroup ASTAST AST file AST constants
///
/// The constants in this group describe various components of the
@@ -557,7 +565,7 @@ namespace clang {
///
/// These type IDs correspond to predefined types in the AST
/// context, such as built-in types (int) and special place-holder
- /// types (the <overload> and <dependent> type markers). Such
+ /// types (the \<overload> and \<dependent> type markers). Such
/// types are never actually serialized, since they will be built
/// by the AST context when it is created.
enum PredefinedTypeIDs {
@@ -632,7 +640,9 @@ namespace clang {
/// \brief ARC's unbridged-cast placeholder type.
PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
/// \brief The pseudo-object placeholder type.
- PREDEF_TYPE_PSEUDO_OBJECT = 35
+ PREDEF_TYPE_PSEUDO_OBJECT = 35,
+ /// \brief The __va_list_tag placeholder type.
+ PREDEF_TYPE_VA_LIST_TAG = 36
};
/// \brief The number of predefined type IDs that are reserved for
@@ -738,28 +748,26 @@ namespace clang {
/// The constants in this enumeration are indices into the
/// SPECIAL_TYPES record.
enum SpecialTypeIDs {
- /// \brief __builtin_va_list
- SPECIAL_TYPE_BUILTIN_VA_LIST = 0,
/// \brief CFConstantString type
- SPECIAL_TYPE_CF_CONSTANT_STRING = 1,
+ SPECIAL_TYPE_CF_CONSTANT_STRING = 0,
/// \brief C FILE typedef type
- SPECIAL_TYPE_FILE = 2,
+ SPECIAL_TYPE_FILE = 1,
/// \brief C jmp_buf typedef type
- SPECIAL_TYPE_JMP_BUF = 3,
+ SPECIAL_TYPE_JMP_BUF = 2,
/// \brief C sigjmp_buf typedef type
- SPECIAL_TYPE_SIGJMP_BUF = 4,
+ SPECIAL_TYPE_SIGJMP_BUF = 3,
/// \brief Objective-C "id" redefinition type
- SPECIAL_TYPE_OBJC_ID_REDEFINITION = 5,
+ SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4,
/// \brief Objective-C "Class" redefinition type
- SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 6,
+ SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5,
/// \brief Objective-C "SEL" redefinition type
- SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 7,
+ SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6,
/// \brief C ucontext_t typedef type
- SPECIAL_TYPE_UCONTEXT_T = 8
+ SPECIAL_TYPE_UCONTEXT_T = 7
};
/// \brief The number of special type IDs.
- const unsigned NumSpecialTypeIDs = 9;
+ const unsigned NumSpecialTypeIDs = 8;
/// \brief Predefined declaration IDs.
///
@@ -793,14 +801,17 @@ namespace clang {
PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
/// \brief The internal 'instancetype' typedef.
- PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8
+ PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
+
+ /// \brief The internal '__builtin_va_list' typedef.
+ PREDEF_DECL_BUILTIN_VA_LIST_ID = 9
};
/// \brief The number of declaration IDs that are predefined.
///
/// For more information about predefined declarations, see the
/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
- const unsigned int NUM_PREDEF_DECL_IDS = 9;
+ const unsigned int NUM_PREDEF_DECL_IDS = 10;
/// \brief Record codes for each kind of declaration.
///
@@ -862,7 +873,7 @@ namespace clang {
/// in the order in which those declarations were added to the
/// declaration context. This data is used when iterating over
/// the contents of a DeclContext, e.g., via
- /// DeclContext::decls_begin()/DeclContext::decls_end().
+ /// DeclContext::decls_begin() and DeclContext::decls_end().
DECL_CONTEXT_LEXICAL,
/// \brief A record that stores the set of declarations that are
/// visible from a given DeclContext.
@@ -1066,7 +1077,7 @@ namespace clang {
/// \brief An ObjCStringLiteral record.
EXPR_OBJC_STRING_LITERAL,
- EXPR_OBJC_NUMERIC_LITERAL,
+ EXPR_OBJC_BOXED_EXPRESSION,
EXPR_OBJC_ARRAY_LITERAL,
EXPR_OBJC_DICTIONARY_LITERAL,
@@ -1089,7 +1100,7 @@ namespace clang {
EXPR_OBJC_MESSAGE_EXPR,
/// \brief An ObjCIsa Expr record.
EXPR_OBJC_ISA,
- /// \breif An ObjCIndirectCopyRestoreExpr record.
+ /// \brief An ObjCIndirectCopyRestoreExpr record.
EXPR_OBJC_INDIRECT_COPY_RESTORE,
/// \brief An ObjCForCollectionStmt record.
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index a9d0fc3f1e86..f0b727531a57 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -199,6 +199,8 @@ class ASTReader
public ExternalSLocEntrySource
{
public:
+ typedef SmallVector<uint64_t, 64> RecordData;
+
enum ASTReadResult { Success, Failure, IgnorePCH };
/// \brief Types of AST files.
friend class PCHValidator;
@@ -454,7 +456,7 @@ private:
/// consumer eagerly.
SmallVector<uint64_t, 16> ExternalDefinitions;
- /// \brief The IDs of all tentative definitions stored in the the chain.
+ /// \brief The IDs of all tentative definitions stored in the chain.
///
/// Sema keeps track of all tentative definitions in a TU because it has to
/// complete them and pass them on to CodeGen. Thus, tentative definitions in
@@ -591,11 +593,14 @@ private:
/// indicates how many separate module file load operations have occurred.
unsigned CurrentGeneration;
+ typedef llvm::DenseMap<unsigned, SwitchCase *> SwitchCaseMapTy;
/// \brief Mapping from switch-case IDs in the chain to switch-case statements
///
/// Statements usually don't have IDs, but switch cases need them, so that the
/// switch statement can refer to them.
- std::map<unsigned, SwitchCase *> SwitchCaseStmts;
+ SwitchCaseMapTy SwitchCaseStmts;
+
+ SwitchCaseMapTy *CurrSwitchCaseStmts;
/// \brief The number of stat() calls that hit/missed the stat
/// cache.
@@ -798,7 +803,7 @@ private:
llvm::BitstreamCursor &SLocCursorForID(int ID);
SourceLocation getImportLocation(ModuleFile *F);
ASTReadResult ReadSubmoduleBlock(ModuleFile &F);
- bool ParseLanguageOptions(const SmallVectorImpl<uint64_t> &Record);
+ bool ParseLanguageOptions(const RecordData &Record);
struct RecordLocation {
RecordLocation(ModuleFile *M, uint64_t O)
@@ -821,19 +826,19 @@ private:
RecordLocation getLocalBitOffset(uint64_t GlobalOffset);
uint64_t getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset);
- /// \brief Returns the first preprocessed entity ID that ends after \arg BLoc.
+ /// \brief Returns the first preprocessed entity ID that ends after BLoc.
serialization::PreprocessedEntityID
findBeginPreprocessedEntity(SourceLocation BLoc) const;
- /// \brief Returns the first preprocessed entity ID that begins after \arg
- /// ELoc.
+ /// \brief Returns the first preprocessed entity ID that begins after ELoc.
serialization::PreprocessedEntityID
findEndPreprocessedEntity(SourceLocation ELoc) const;
- /// \brief \arg SLocMapI points at a chunk of a module that contains no
- /// preprocessed entities or the entities it contains are not the ones we are
- /// looking for. Find the next module that contains entities and return the ID
+ /// \brief Find the next module that contains entities and return the ID
/// of the first entry.
+ /// \arg SLocMapI points at a chunk of a module that contains no
+ /// preprocessed entities or the entities it contains are not the
+ /// ones we are looking for.
serialization::PreprocessedEntityID
findNextPreprocessedEntity(
GlobalSLocOffsetMapType::const_iterator SLocMapI) const;
@@ -859,8 +864,6 @@ private:
ASTReader(const ASTReader&); // do not implement
ASTReader &operator=(const ASTReader &); // do not implement
public:
- typedef SmallVector<uint64_t, 64> RecordData;
-
/// \brief Load the AST file and validate its contents against the given
/// Preprocessor.
///
@@ -907,8 +910,8 @@ public:
///
/// \param Mod The module whose names should be made visible.
///
- /// \param Visibility The level of visibility to give the names in the module.
- /// Visibility can only be increased over time.
+ /// \param NameVisibility The level of visibility to give the names in the
+ /// module. Visibility can only be increased over time.
void makeModuleVisible(Module *Mod,
Module::NameVisibilityKind NameVisibility);
@@ -1498,6 +1501,13 @@ public:
SwitchCase *getSwitchCaseWithID(unsigned ID);
void ClearSwitchCaseIDs();
+
+ /// \brief Cursors for comments blocks.
+ SmallVector<std::pair<llvm::BitstreamCursor,
+ serialization::ModuleFile *>, 8> CommentsCursors;
+
+ /// \brief Loads comments ranges.
+ void ReadComments();
};
/// \brief Helper class that saves the current stream position and
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index e693f17593f9..d038d58aed8b 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -110,6 +110,10 @@ private:
/// serialization, rather than just queueing updates.
bool WritingAST;
+ /// \brief Indicates that we are done serializing the collection of decls
+ /// and types to emit.
+ bool DoneWritingDeclsAndTypes;
+
/// \brief Indicates that the AST contained compiler errors.
bool ASTHasCompilerErrors;
@@ -296,6 +300,10 @@ private:
/// it.
llvm::SmallPtrSet<const DeclContext *, 16> UpdatedDeclContexts;
+ /// \brief Keeps track of visible decls that were added in DeclContexts
+ /// coming from another AST file.
+ SmallVector<const Decl *, 16> UpdatingVisibleDecls;
+
typedef llvm::SmallPtrSet<const Decl *, 16> DeclsToRewriteTy;
/// \brief Decls that will be replaced in the current dependent AST file.
DeclsToRewriteTy DeclsToRewrite;
@@ -337,7 +345,7 @@ private:
SmallVector<Stmt *, 16> *CollectedStmts;
/// \brief Mapping from SwitchCase statements to IDs.
- std::map<SwitchCase *, unsigned> SwitchCaseIDs;
+ llvm::DenseMap<SwitchCase *, unsigned> SwitchCaseIDs;
/// \brief The number of statements written to the AST file.
unsigned NumStatements;
@@ -414,11 +422,12 @@ private:
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
void WriteTypeDeclOffsets();
void WriteFileDeclIDsMap();
+ void WriteComments();
void WriteSelectors(Sema &SemaRef);
void WriteReferencedSelectorsPool(Sema &SemaRef);
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
bool IsModule);
- void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record);
+ void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record);
void ResolveDeclUpdatesBlocks();
void WriteDeclUpdatesBlocks();
void WriteDeclReplacementsBlock();
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 2b699a85f8ef..5ee52cc61589 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -101,20 +101,27 @@ protected:
/// Used for clients to tell if the report's configuration has changed
/// since the last time they checked.
unsigned ConfigurationChangeToken;
+
+ /// When set, this flag disables all callstack pruning from a diagnostic
+ /// path. This is useful for some reports that want maximum fidelty
+ /// when reporting an issue.
+ bool DoNotPrunePath;
public:
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
: BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode),
- ConfigurationChangeToken(0) {}
+ ConfigurationChangeToken(0), DoNotPrunePath(false) {}
BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
const ExplodedNode *errornode)
: BT(bt), DeclWithIssue(0), ShortDescription(shortDesc), Description(desc),
- ErrorNode(errornode), ConfigurationChangeToken(0) {}
+ ErrorNode(errornode), ConfigurationChangeToken(0),
+ DoNotPrunePath(false) {}
BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l)
: BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0),
- ConfigurationChangeToken(0) {}
+ ConfigurationChangeToken(0),
+ DoNotPrunePath(false) {}
/// \brief Create a BugReport with a custom uniqueing location.
///
@@ -142,6 +149,13 @@ public:
return ShortDescription.empty() ? Description : ShortDescription;
}
+ /// Indicates whether or not any path pruning should take place
+ /// when generating a PathDiagnostic from this BugReport.
+ bool shouldPrunePath() const { return !DoNotPrunePath; }
+
+ /// Disable all path pruning when generating a PathDiagnostic.
+ void disablePathPruning() { DoNotPrunePath = true; }
+
void markInteresting(SymbolRef sym);
void markInteresting(const MemRegion *R);
void markInteresting(SVal V);
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
index 7e665ceda54b..f53c15f117c9 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
@@ -226,13 +226,11 @@ public:
namespace bugreporter {
-BugReporterVisitor *getTrackNullOrUndefValueVisitor(const ExplodedNode *N,
- const Stmt *S,
- BugReport *R);
+void addTrackNullOrUndefValueVisitor(const ExplodedNode *N, const Stmt *S,
+ BugReport *R);
const Stmt *GetDerefExpr(const ExplodedNode *N);
const Stmt *GetDenomExpr(const ExplodedNode *N);
-const Stmt *GetCalleeExpr(const ExplodedNode *N);
const Stmt *GetRetValExpr(const ExplodedNode *N);
} // end namespace clang
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index 5a8a1c78ca7d..2e7abfa5cc3b 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -148,6 +148,15 @@ public:
assert(Range.isValid());
}
+ /// Create a location at an explicit offset in the source.
+ ///
+ /// This should only be used if there are no more appropriate constructors.
+ PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
+ : K(SingleLocK), S(0), D(0), SM(&sm), Loc(loc, sm), Range(genRange()) {
+ assert(Loc.isValid());
+ assert(Range.isValid());
+ }
+
/// Create a location corresponding to the given declaration.
static PathDiagnosticLocation create(const Decl *D,
const SourceManager &SM) {
@@ -163,6 +172,14 @@ public:
const SourceManager &SM,
const LocationOrAnalysisDeclContext LAC);
+ /// Create a location for the end of the statement.
+ ///
+ /// If the statement is a CompoundStatement, the location will point to the
+ /// closing brace instead of following it.
+ static PathDiagnosticLocation createEnd(const Stmt *S,
+ const SourceManager &SM,
+ const LocationOrAnalysisDeclContext LAC);
+
/// Create the location for the operator of the binary expression.
/// Assumes the statement has a valid location.
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO,
@@ -333,10 +350,17 @@ public:
};
-class PathPieces :
- public std::deque<IntrusiveRefCntPtr<PathDiagnosticPiece> > {
+class PathPieces : public std::deque<IntrusiveRefCntPtr<PathDiagnosticPiece> > {
+ void flattenTo(PathPieces &Primary, PathPieces &Current,
+ bool ShouldFlattenMacros) const;
public:
- ~PathPieces();
+ ~PathPieces();
+
+ PathPieces flatten(bool ShouldFlattenMacros) const {
+ PathPieces Result;
+ flattenTo(Result, Result, ShouldFlattenMacros);
+ return Result;
+ }
};
class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
@@ -362,7 +386,7 @@ public:
/// \brief Interface for classes constructing Stack hints.
///
/// If a PathDiagnosticEvent occurs in a different frame than the final
-/// diagnostic the hints can be used to summarise the effect of the call.
+/// diagnostic the hints can be used to summarize the effect of the call.
class StackHintGenerator {
public:
virtual ~StackHintGenerator() = 0;
@@ -510,7 +534,7 @@ public:
}
static PathDiagnosticCallPiece *construct(const ExplodedNode *N,
- const CallExit &CE,
+ const CallExitEnd &CE,
const SourceManager &SM);
static PathDiagnosticCallPiece *construct(PathPieces &pieces,
@@ -637,6 +661,8 @@ public:
void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
+
+ bool isWithinCall() const { return !pathStack.empty(); }
// PathDiagnostic();
PathDiagnostic(const Decl *DeclWithIssue,
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index 76d8c15f75cb..3214d96c5398 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -122,7 +122,7 @@ public:
class PreObjCMessage {
template <typename CHECKER>
- static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
+ static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
CheckerContext &C) {
((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
}
@@ -137,7 +137,7 @@ public:
class PostObjCMessage {
template <typename CHECKER>
- static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
+ static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
CheckerContext &C) {
((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
}
@@ -150,6 +150,36 @@ public:
}
};
+class PreCall {
+ template <typename CHECKER>
+ static void _checkCall(void *checker, const CallEvent &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPreCall(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPreCall(
+ CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
+ }
+};
+
+class PostCall {
+ template <typename CHECKER>
+ static void _checkCall(void *checker, const CallEvent &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPostCall(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPostCall(
+ CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
+ }
+};
+
class Location {
template <typename CHECKER>
static void _checkLocation(void *checker,
@@ -266,7 +296,7 @@ class RegionChanges {
const StoreManager::InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> Explicits,
ArrayRef<const MemRegion *> Regions,
- const CallOrObjCMessage *Call) {
+ const CallEvent *Call) {
return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
Explicits, Regions, Call);
}
@@ -372,16 +402,14 @@ template <typename CHECK1, typename CHECK2=check::_VoidCheck,
typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck,
- typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck>
+ typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck,
+ typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck,
+ typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck,
+ typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck>
class Checker;
template <>
-class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
- check::_VoidCheck, check::_VoidCheck, check::_VoidCheck>
+class Checker<check::_VoidCheck>
: public CheckerBase
{
virtual void anchor();
@@ -393,19 +421,22 @@ template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
- typename CHECK17,typename CHECK18>
+ typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20,
+ typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24>
class Checker
: public CHECK1,
- public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
- CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
- CHECK16,CHECK17,CHECK18> {
+ public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
+ CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
+ CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
+ CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> {
public:
template <typename CHECKER>
static void _register(CHECKER *checker, CheckerManager &mgr) {
CHECK1::_register(checker, mgr);
- Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
- CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
- CHECK16,CHECK17,CHECK18>::_register(checker, mgr);
+ Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
+ CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
+ CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
+ CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr);
}
};
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index d215f992e68e..e11b6d518a4e 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -33,7 +33,8 @@ namespace ento {
class AnalysisManager;
class BugReporter;
class CheckerContext;
- class ObjCMessage;
+ class SimpleCall;
+ class ObjCMethodCall;
class SVal;
class ExplodedNode;
class ExplodedNodeSet;
@@ -44,12 +45,6 @@ namespace ento {
class MemRegion;
class SymbolReaper;
-class GraphExpander {
-public:
- virtual ~GraphExpander();
- virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0;
-};
-
template <typename T> class CheckerFn;
template <typename RET, typename P1, typename P2, typename P3, typename P4,
@@ -207,7 +202,7 @@ public:
/// \brief Run checkers for pre-visiting obj-c messages.
void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
- const ObjCMessage &msg,
+ const ObjCMethodCall &msg,
ExprEngine &Eng) {
runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
}
@@ -215,16 +210,39 @@ public:
/// \brief Run checkers for post-visiting obj-c messages.
void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
- const ObjCMessage &msg,
- ExprEngine &Eng) {
- runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng);
+ const ObjCMethodCall &msg,
+ ExprEngine &Eng,
+ bool wasInlined = false) {
+ runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng,
+ wasInlined);
}
/// \brief Run checkers for visiting obj-c messages.
void runCheckersForObjCMessage(bool isPreVisit,
ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
- const ObjCMessage &msg, ExprEngine &Eng);
+ const ObjCMethodCall &msg, ExprEngine &Eng,
+ bool wasInlined = false);
+
+ /// \brief Run checkers for pre-visiting obj-c messages.
+ void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
+ const CallEvent &Call, ExprEngine &Eng) {
+ runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
+ }
+
+ /// \brief Run checkers for post-visiting obj-c messages.
+ void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
+ const CallEvent &Call, ExprEngine &Eng,
+ bool wasInlined = false) {
+ runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
+ wasInlined);
+ }
+
+ /// \brief Run checkers for visiting obj-c messages.
+ void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const CallEvent &Call, ExprEngine &Eng,
+ bool wasInlined = false);
/// \brief Run checkers for load/store of a location.
void runCheckersForLocation(ExplodedNodeSet &Dst,
@@ -272,7 +290,8 @@ public:
void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
SymbolReaper &SymReaper, const Stmt *S,
- ExprEngine &Eng);
+ ExprEngine &Eng,
+ ProgramPoint::Kind K);
/// \brief True if at least one checker wants to check region changes.
bool wantsRegionChangeUpdate(ProgramStateRef state);
@@ -286,24 +305,25 @@ public:
/// For example, in the case of a function call, these would be arguments.
/// \param Regions The transitive closure of accessible regions,
/// i.e. all regions that may have been touched by this change.
- /// \param The call expression wrapper if the regions are invalidated by a
- /// call.
- ProgramStateRef
+ /// \param Call The call expression wrapper if the regions are invalidated
+ /// by a call.
+ ProgramStateRef
runCheckersForRegionChanges(ProgramStateRef state,
const StoreManager::InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
- const CallOrObjCMessage *Call);
+ const CallEvent *Call);
/// \brief Run checkers for handling assumptions on symbolic values.
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
SVal Cond, bool Assumption);
/// \brief Run checkers for evaluating a call.
+ ///
+ /// Warning: Currently, the CallEvent MUST come from a CallExpr!
void runCheckersForEvalCall(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
- const CallExpr *CE, ExprEngine &Eng,
- GraphExpander *defaultEval = 0);
+ const CallEvent &CE, ExprEngine &Eng);
/// \brief Run checkers for the entire Translation Unit.
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
@@ -342,8 +362,11 @@ public:
typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
- typedef CheckerFn<void (const ObjCMessage &, CheckerContext &)>
+ typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
CheckObjCMessageFunc;
+
+ typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
+ CheckCallFunc;
typedef CheckerFn<void (const SVal &location, bool isLoad,
const Stmt *S,
@@ -372,7 +395,7 @@ public:
const StoreManager::InvalidatedSymbols *symbols,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
- const CallOrObjCMessage *Call)>
+ const CallEvent *Call)>
CheckRegionChangesFunc;
typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
@@ -402,6 +425,9 @@ public:
void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
+ void _registerForPreCall(CheckCallFunc checkfn);
+ void _registerForPostCall(CheckCallFunc checkfn);
+
void _registerForLocation(CheckLocationFunc checkfn);
void _registerForBind(CheckBindFunc checkfn);
@@ -523,6 +549,9 @@ private:
std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
+ std::vector<CheckCallFunc> PreCallCheckers;
+ std::vector<CheckCallFunc> PostCallCheckers;
+
std::vector<CheckLocationFunc> LocationCheckers;
std::vector<CheckBindFunc> BindCheckers;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
new file mode 100644
index 000000000000..e1ff17b361aa
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
@@ -0,0 +1,106 @@
+//== APSIntType.h - Simple record of the type of APSInts --------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CORE_APSINTTYPE_H
+#define LLVM_CLANG_SA_CORE_APSINTTYPE_H
+
+#include "llvm/ADT/APSInt.h"
+
+namespace clang {
+namespace ento {
+
+/// \brief A record of the "type" of an APSInt, used for conversions.
+class APSIntType {
+ uint32_t BitWidth;
+ bool IsUnsigned;
+
+public:
+ APSIntType(uint32_t Width, bool Unsigned)
+ : BitWidth(Width), IsUnsigned(Unsigned) {}
+
+ /* implicit */ APSIntType(const llvm::APSInt &Value)
+ : BitWidth(Value.getBitWidth()), IsUnsigned(Value.isUnsigned()) {}
+
+ uint32_t getBitWidth() const { return BitWidth; }
+ bool isUnsigned() const { return IsUnsigned; }
+
+ /// \brief Convert a given APSInt, in place, to match this type.
+ ///
+ /// This behaves like a C cast: converting 255u8 (0xFF) to s16 gives
+ /// 255 (0x00FF), and converting -1s8 (0xFF) to u16 gives 65535 (0xFFFF).
+ void apply(llvm::APSInt &Value) const {
+ // Note the order here. We extend first to preserve the sign, if this value
+ // is signed, /then/ match the signedness of the result type.
+ Value = Value.extOrTrunc(BitWidth);
+ Value.setIsUnsigned(IsUnsigned);
+ }
+
+ /// Convert and return a new APSInt with the given value, but this
+ /// type's bit width and signedness.
+ ///
+ /// \see apply
+ llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY {
+ llvm::APSInt Result(Value, Value.isUnsigned());
+ apply(Result);
+ return Result;
+ }
+
+ /// Returns an all-zero value for this type.
+ llvm::APSInt getZeroValue() const LLVM_READONLY {
+ return llvm::APSInt(BitWidth, IsUnsigned);
+ }
+
+ /// Returns the minimum value for this type.
+ llvm::APSInt getMinValue() const LLVM_READONLY {
+ return llvm::APSInt::getMinValue(BitWidth, IsUnsigned);
+ }
+
+ /// Returns the maximum value for this type.
+ llvm::APSInt getMaxValue() const LLVM_READONLY {
+ return llvm::APSInt::getMaxValue(BitWidth, IsUnsigned);
+ }
+
+ /// Used to classify whether a value is representable using this type.
+ ///
+ /// \see testInRange
+ enum RangeTestResultKind {
+ RTR_Below = -1, ///< Value is less than the minimum representable value.
+ RTR_Within = 0, ///< Value is representable using this type.
+ RTR_Above = 1 ///< Value is greater than the maximum representable value.
+ };
+
+ /// Tests whether a given value is losslessly representable using this type.
+ ///
+ /// Note that signedness conversions will be rejected, even with the same bit
+ /// pattern. For example, -1s8 is not in range for 'unsigned char' (u8).
+ RangeTestResultKind testInRange(const llvm::APSInt &Val) const LLVM_READONLY;
+
+ bool operator==(const APSIntType &Other) const {
+ return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned;
+ }
+
+ /// \brief Provide an ordering for finding a common conversion type.
+ ///
+ /// Unsigned integers are considered to be better conversion types than
+ /// signed integers of the same width.
+ bool operator<(const APSIntType &Other) const {
+ if (BitWidth < Other.BitWidth)
+ return true;
+ if (BitWidth > Other.BitWidth)
+ return false;
+ if (!IsUnsigned && Other.IsUnsigned)
+ return true;
+ return false;
+ }
+};
+
+} // end ento namespace
+} // end clang namespace
+
+#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index d01644ba0eb5..1cc53d4423da 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -41,8 +41,6 @@ class AnalysisManager : public BugReporterData {
CheckerManager *CheckerMgr;
- enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
-
/// \brief The maximum number of exploded nodes the analyzer will generate.
unsigned MaxNodes;
@@ -93,7 +91,7 @@ public:
bool vizdot, bool vizubi, AnalysisPurgeMode purge,
bool eager, bool trim,
bool useUnoptimizedCFG,
- bool addImplicitDtors, bool addInitializers,
+ bool addImplicitDtors,
bool eagerlyTrimEGraph,
AnalysisIPAMode ipa,
unsigned inlineMaxStack,
@@ -171,7 +169,7 @@ public:
bool shouldEagerlyAssume() const { return EagerlyAssume; }
- bool shouldInlineCall() const { return (IPAMode == Inlining); }
+ bool shouldInlineCall() const { return (IPAMode != None); }
CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG();
@@ -190,10 +188,6 @@ public:
return AnaCtxMgr.getContext(D);
}
- AnalysisDeclContext *getAnalysisDeclContext(const Decl *D, idx::TranslationUnit *TU) {
- return AnaCtxMgr.getContext(D, TU);
- }
-
};
} // enAnaCtxMgrspace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index 9a699f9b7c9c..b4a9de76f4d1 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -16,6 +16,7 @@
#ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H
#define LLVM_CLANG_GR_BASICVALUEFACTORY_H
+#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
@@ -86,28 +87,30 @@ public:
const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
const llvm::APSInt& getValue(uint64_t X, QualType T);
+ /// Returns the type of the APSInt used to store values of the given QualType.
+ APSIntType getAPSIntType(QualType T) const {
+ assert(T->isIntegerType() || Loc::isLocType(T));
+ return APSIntType(Ctx.getTypeSize(T),
+ !T->isSignedIntegerOrEnumerationType());
+ }
+
/// Convert - Create a new persistent APSInt with the same value as 'From'
/// but with the bitwidth and signedness of 'To'.
const llvm::APSInt &Convert(const llvm::APSInt& To,
const llvm::APSInt& From) {
-
- if (To.isUnsigned() == From.isUnsigned() &&
- To.getBitWidth() == From.getBitWidth())
+ APSIntType TargetType(To);
+ if (TargetType == APSIntType(From))
return From;
- return getValue(From.getSExtValue(), To.getBitWidth(), To.isUnsigned());
+ return getValue(TargetType.convert(From));
}
const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
- assert(T->isIntegerType() || Loc::isLocType(T));
- unsigned bitwidth = Ctx.getTypeSize(T);
- bool isUnsigned
- = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
-
- if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth())
+ APSIntType TargetType = getAPSIntType(T);
+ if (TargetType == APSIntType(From))
return From;
- return getValue(From.getSExtValue(), bitwidth, isUnsigned);
+ return getValue(TargetType.convert(From));
}
const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
@@ -116,25 +119,19 @@ public:
}
inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) {
- return getValue(llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned()));
+ return getValue(APSIntType(v).getMaxValue());
}
inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) {
- return getValue(llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned()));
+ return getValue(APSIntType(v).getMinValue());
}
inline const llvm::APSInt& getMaxValue(QualType T) {
- assert(T->isIntegerType() || Loc::isLocType(T));
- bool isUnsigned
- = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
- return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned));
+ return getValue(getAPSIntType(T).getMaxValue());
}
inline const llvm::APSInt& getMinValue(QualType T) {
- assert(T->isIntegerType() || Loc::isLocType(T));
- bool isUnsigned
- = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
- return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned));
+ return getValue(getAPSIntType(T).getMinValue());
}
inline const llvm::APSInt& Add1(const llvm::APSInt& V) {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
new file mode 100644
index 000000000000..47edfe9fca91
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -0,0 +1,962 @@
+//===- CallEvent.h - Wrapper for all function and method calls ----*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file defines CallEvent and its subclasses, which represent path-
+/// sensitive instances of different kinds of function and method calls
+/// (C, C++, and Objective-C).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL
+#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace clang {
+class ProgramPoint;
+class ProgramPointTag;
+
+namespace ento {
+
+enum CallEventKind {
+ CE_Function,
+ CE_Block,
+ CE_BEG_SIMPLE_CALLS = CE_Function,
+ CE_END_SIMPLE_CALLS = CE_Block,
+ CE_CXXMember,
+ CE_CXXMemberOperator,
+ CE_CXXDestructor,
+ CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember,
+ CE_END_CXX_INSTANCE_CALLS = CE_CXXDestructor,
+ CE_CXXConstructor,
+ CE_CXXAllocator,
+ CE_BEG_FUNCTION_CALLS = CE_Function,
+ CE_END_FUNCTION_CALLS = CE_CXXAllocator,
+ CE_ObjCMessage
+};
+
+class CallEvent;
+class CallEventManager;
+
+template<typename T = CallEvent>
+class CallEventRef : public IntrusiveRefCntPtr<const T> {
+public:
+ CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {}
+ CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr<const T>(Orig) {}
+
+ CallEventRef<T> cloneWithState(ProgramStateRef State) const {
+ return this->getPtr()->template cloneWithState<T>(State);
+ }
+
+ // Allow implicit conversions to a superclass type, since CallEventRef
+ // behaves like a pointer-to-const.
+ template <typename SuperT>
+ operator CallEventRef<SuperT> () const {
+ return this->getPtr();
+ }
+};
+
+/// \brief Defines the runtime definition of the called function.
+class RuntimeDefinition {
+ /// The Declaration of the function which will be called at runtime.
+ /// 0 if not available.
+ const Decl *D;
+
+ /// The region representing an object (ObjC/C++) on which the method is
+ /// called. With dynamic dispatch, the method definition depends on the
+ /// runtime type of this object. 0 when there is no dynamic dispatch.
+ const MemRegion *R;
+
+public:
+ RuntimeDefinition(): D(0), R(0) {}
+ RuntimeDefinition(const Decl *InD): D(InD), R(0) {}
+ RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {}
+ const Decl *getDecl() { return D; }
+ const MemRegion *getDispatchRegion() { return R; }
+ bool mayHaveOtherDefinitions() { return R != 0; }
+};
+
+/// \brief Represents an abstract call to a function or method along a
+/// particular path.
+///
+/// CallEvents are created through the factory methods of CallEventManager.
+///
+/// CallEvents should always be cheap to create and destroy. In order for
+/// CallEventManager to be able to re-use CallEvent-sized memory blocks,
+/// subclasses of CallEvent may not add any data members to the base class.
+/// Use the "Data" and "Location" fields instead.
+class CallEvent {
+public:
+ typedef CallEventKind Kind;
+
+private:
+ ProgramStateRef State;
+ const LocationContext *LCtx;
+ llvm::PointerUnion<const Expr *, const Decl *> Origin;
+
+ // DO NOT IMPLEMENT
+ CallEvent &operator=(const CallEvent &);
+
+protected:
+ // This is user data for subclasses.
+ const void *Data;
+
+ // This is user data for subclasses.
+ // This should come right before RefCount, so that the two fields can be
+ // packed together on LP64 platforms.
+ SourceLocation Location;
+
+private:
+ mutable unsigned RefCount;
+
+ template <typename T> friend struct llvm::IntrusiveRefCntPtrInfo;
+ void Retain() const { ++RefCount; }
+ void Release() const;
+
+protected:
+ friend class CallEventManager;
+
+ CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx)
+ : State(state), LCtx(lctx), Origin(E), RefCount(0) {}
+
+ CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx)
+ : State(state), LCtx(lctx), Origin(D), RefCount(0) {}
+
+ // DO NOT MAKE PUBLIC
+ CallEvent(const CallEvent &Original)
+ : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin),
+ Data(Original.Data), Location(Original.Location), RefCount(0) {}
+
+
+ ProgramStateRef getState() const {
+ return State;
+ }
+
+ const LocationContext *getLocationContext() const {
+ return LCtx;
+ }
+
+
+ /// Copies this CallEvent, with vtable intact, into a new block of memory.
+ virtual void cloneTo(void *Dest) const = 0;
+
+ /// \brief Get the value of arbitrary expressions at this point in the path.
+ SVal getSVal(const Stmt *S) const {
+ return getState()->getSVal(S, getLocationContext());
+ }
+
+
+ typedef SmallVectorImpl<const MemRegion *> RegionList;
+
+ /// \brief Used to specify non-argument regions that will be invalidated as a
+ /// result of this call.
+ virtual void getExtraInvalidatedRegions(RegionList &Regions) const {}
+
+ virtual QualType getDeclaredResultType() const = 0;
+
+public:
+ virtual ~CallEvent() {}
+
+ /// \brief Returns the kind of call this is.
+ virtual Kind getKind() const = 0;
+
+ /// \brief Returns the declaration of the function or method that will be
+ /// called. May be null.
+ virtual const Decl *getDecl() const {
+ return Origin.dyn_cast<const Decl *>();
+ }
+
+ /// \brief Returns the definition of the function or method that will be
+ /// called.
+ virtual RuntimeDefinition getRuntimeDefinition() const = 0;
+
+ /// \brief Returns the expression whose value will be the result of this call.
+ /// May be null.
+ const Expr *getOriginExpr() const {
+ return Origin.dyn_cast<const Expr *>();
+ }
+
+ /// \brief Returns the number of arguments (explicit and implicit).
+ ///
+ /// Note that this may be greater than the number of parameters in the
+ /// callee's declaration, and that it may include arguments not written in
+ /// the source.
+ virtual unsigned getNumArgs() const = 0;
+
+ /// \brief Returns true if the callee is known to be from a system header.
+ bool isInSystemHeader() const {
+ const Decl *D = getDecl();
+ if (!D)
+ return false;
+
+ SourceLocation Loc = D->getLocation();
+ if (Loc.isValid()) {
+ const SourceManager &SM =
+ getState()->getStateManager().getContext().getSourceManager();
+ return SM.isInSystemHeader(D->getLocation());
+ }
+
+ // Special case for implicitly-declared global operator new/delete.
+ // These should be considered system functions.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return FD->isOverloadedOperator() && FD->isImplicit() && FD->isGlobal();
+
+ return false;
+ }
+
+ /// \brief Returns a source range for the entire call, suitable for
+ /// outputting in diagnostics.
+ virtual SourceRange getSourceRange() const {
+ return getOriginExpr()->getSourceRange();
+ }
+
+ /// \brief Returns the value of a given argument at the time of the call.
+ virtual SVal getArgSVal(unsigned Index) const;
+
+ /// \brief Returns the expression associated with a given argument.
+ /// May be null if this expression does not appear in the source.
+ virtual const Expr *getArgExpr(unsigned Index) const { return 0; }
+
+ /// \brief Returns the source range for errors associated with this argument.
+ ///
+ /// May be invalid if the argument is not written in the source.
+ virtual SourceRange getArgSourceRange(unsigned Index) const;
+
+ /// \brief Returns the result type, adjusted for references.
+ QualType getResultType() const;
+
+ /// \brief Returns true if any of the arguments appear to represent callbacks.
+ bool hasNonZeroCallbackArg() const;
+
+ /// \brief Returns true if any of the arguments are known to escape to long-
+ /// term storage, even if this method will not modify them.
+ // NOTE: The exact semantics of this are still being defined!
+ // We don't really want a list of hardcoded exceptions in the long run,
+ // but we don't want duplicated lists of known APIs in the short term either.
+ virtual bool argumentsMayEscape() const {
+ return hasNonZeroCallbackArg();
+ }
+
+ /// \brief Returns an appropriate ProgramPoint for this call.
+ ProgramPoint getProgramPoint(bool IsPreVisit = false,
+ const ProgramPointTag *Tag = 0) const;
+
+ /// \brief Returns a new state with all argument regions invalidated.
+ ///
+ /// This accepts an alternate state in case some processing has already
+ /// occurred.
+ ProgramStateRef invalidateRegions(unsigned BlockCount,
+ ProgramStateRef Orig = 0) const;
+
+ typedef std::pair<Loc, SVal> FrameBindingTy;
+ typedef SmallVectorImpl<FrameBindingTy> BindingsTy;
+
+ /// Populates the given SmallVector with the bindings in the callee's stack
+ /// frame at the start of this call.
+ virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const = 0;
+
+ /// Returns a copy of this CallEvent, but using the given state.
+ template <typename T>
+ CallEventRef<T> cloneWithState(ProgramStateRef NewState) const;
+
+ /// Returns a copy of this CallEvent, but using the given state.
+ CallEventRef<> cloneWithState(ProgramStateRef NewState) const {
+ return cloneWithState<CallEvent>(NewState);
+ }
+
+ /// \brief Returns true if this is a statement that can be considered for
+ /// inlining.
+ ///
+ /// FIXME: This should go away once CallEvents are cheap and easy to
+ /// construct from ExplodedNodes.
+ static bool mayBeInlined(const Stmt *S);
+
+ // Iterator access to formal parameters and their types.
+private:
+ typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun;
+
+public:
+ typedef const ParmVarDecl * const *param_iterator;
+
+ /// Returns an iterator over the call's formal parameters.
+ ///
+ /// If UseDefinitionParams is set, this will return the parameter decls
+ /// used in the callee's definition (suitable for inlining). Most of the
+ /// time it is better to use the decl found by name lookup, which likely
+ /// carries more annotations.
+ ///
+ /// Remember that the number of formal parameters may not match the number
+ /// of arguments for all calls. However, the first parameter will always
+ /// correspond with the argument value returned by \c getArgSVal(0).
+ ///
+ /// If the call has no accessible declaration (or definition, if
+ /// \p UseDefinitionParams is set), \c param_begin() will be equal to
+ /// \c param_end().
+ virtual param_iterator param_begin() const =0;
+ /// \sa param_begin()
+ virtual param_iterator param_end() const = 0;
+
+ typedef llvm::mapped_iterator<param_iterator, get_type_fun>
+ param_type_iterator;
+
+ /// Returns an iterator over the types of the call's formal parameters.
+ ///
+ /// This uses the callee decl found by default name lookup rather than the
+ /// definition because it represents a public interface, and probably has
+ /// more annotations.
+ param_type_iterator param_type_begin() const {
+ return llvm::map_iterator(param_begin(),
+ get_type_fun(&ParmVarDecl::getType));
+ }
+ /// \sa param_type_begin()
+ param_type_iterator param_type_end() const {
+ return llvm::map_iterator(param_end(), get_type_fun(&ParmVarDecl::getType));
+ }
+
+ // For debugging purposes only
+ void dump(raw_ostream &Out) const;
+ LLVM_ATTRIBUTE_USED void dump() const { dump(llvm::errs()); }
+
+ static bool classof(const CallEvent *) { return true; }
+};
+
+
+/// \brief Represents a call to any sort of function that might have a
+/// FunctionDecl.
+class AnyFunctionCall : public CallEvent {
+protected:
+ AnyFunctionCall(const Expr *E, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CallEvent(E, St, LCtx) {}
+ AnyFunctionCall(const Decl *D, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CallEvent(D, St, LCtx) {}
+ AnyFunctionCall(const AnyFunctionCall &Other) : CallEvent(Other) {}
+
+ virtual QualType getDeclaredResultType() const;
+
+public:
+ // This function is overridden by subclasses, but they must return
+ // a FunctionDecl.
+ virtual const FunctionDecl *getDecl() const {
+ return cast<FunctionDecl>(CallEvent::getDecl());
+ }
+
+ virtual RuntimeDefinition getRuntimeDefinition() const {
+ const FunctionDecl *FD = getDecl();
+ // Note that hasBody() will fill FD with the definition FunctionDecl.
+ if (FD && FD->hasBody(FD))
+ return RuntimeDefinition(FD);
+ return RuntimeDefinition();
+ }
+
+ virtual bool argumentsMayEscape() const;
+
+ virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const;
+
+ virtual param_iterator param_begin() const;
+ virtual param_iterator param_end() const;
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() >= CE_BEG_FUNCTION_CALLS &&
+ CA->getKind() <= CE_END_FUNCTION_CALLS;
+ }
+};
+
+/// \brief Represents a call to a non-C++ function, written as a CallExpr.
+class SimpleCall : public AnyFunctionCall {
+protected:
+ SimpleCall(const CallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : AnyFunctionCall(CE, St, LCtx) {}
+ SimpleCall(const SimpleCall &Other) : AnyFunctionCall(Other) {}
+
+public:
+ virtual const CallExpr *getOriginExpr() const {
+ return cast<CallExpr>(AnyFunctionCall::getOriginExpr());
+ }
+
+ virtual const FunctionDecl *getDecl() const;
+
+ virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); }
+
+ virtual const Expr *getArgExpr(unsigned Index) const {
+ return getOriginExpr()->getArg(Index);
+ }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() >= CE_BEG_SIMPLE_CALLS &&
+ CA->getKind() <= CE_END_SIMPLE_CALLS;
+ }
+};
+
+/// \brief Represents a C function or static C++ member function call.
+///
+/// Example: \c fun()
+class FunctionCall : public SimpleCall {
+ friend class CallEventManager;
+
+protected:
+ FunctionCall(const CallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : SimpleCall(CE, St, LCtx) {}
+
+ FunctionCall(const FunctionCall &Other) : SimpleCall(Other) {}
+ virtual void cloneTo(void *Dest) const { new (Dest) FunctionCall(*this); }
+
+public:
+ virtual Kind getKind() const { return CE_Function; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_Function;
+ }
+};
+
+/// \brief Represents a call to a block.
+///
+/// Example: <tt>^{ /* ... */ }()</tt>
+class BlockCall : public SimpleCall {
+ friend class CallEventManager;
+
+protected:
+ BlockCall(const CallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : SimpleCall(CE, St, LCtx) {}
+
+ BlockCall(const BlockCall &Other) : SimpleCall(Other) {}
+ virtual void cloneTo(void *Dest) const { new (Dest) BlockCall(*this); }
+
+ virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+
+ virtual QualType getDeclaredResultType() const;
+
+public:
+ /// \brief Returns the region associated with this instance of the block.
+ ///
+ /// This may be NULL if the block's origin is unknown.
+ const BlockDataRegion *getBlockRegion() const;
+
+ /// \brief Gets the declaration of the block.
+ ///
+ /// This is not an override of getDecl() because AnyFunctionCall has already
+ /// assumed that it's a FunctionDecl.
+ const BlockDecl *getBlockDecl() const {
+ const BlockDataRegion *BR = getBlockRegion();
+ if (!BR)
+ return 0;
+ return BR->getDecl();
+ }
+
+ virtual RuntimeDefinition getRuntimeDefinition() const {
+ return RuntimeDefinition(getBlockDecl());
+ }
+
+ virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const;
+
+ virtual param_iterator param_begin() const;
+ virtual param_iterator param_end() const;
+
+ virtual Kind getKind() const { return CE_Block; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_Block;
+ }
+};
+
+/// \brief Represents a non-static C++ member function call, no matter how
+/// it is written.
+class CXXInstanceCall : public AnyFunctionCall {
+protected:
+ virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+
+ CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : AnyFunctionCall(CE, St, LCtx) {}
+ CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : AnyFunctionCall(D, St, LCtx) {}
+
+
+ CXXInstanceCall(const CXXInstanceCall &Other) : AnyFunctionCall(Other) {}
+
+public:
+ /// \brief Returns the expression representing the implicit 'this' object.
+ virtual const Expr *getCXXThisExpr() const { return 0; }
+
+ /// \brief Returns the value of the implicit 'this' object.
+ virtual SVal getCXXThisVal() const {
+ const Expr *Base = getCXXThisExpr();
+ // FIXME: This doesn't handle an overloaded ->* operator.
+ if (!Base)
+ return UnknownVal();
+ return getSVal(Base);
+ }
+
+ virtual const FunctionDecl *getDecl() const;
+
+ virtual RuntimeDefinition getRuntimeDefinition() const;
+
+ virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const;
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS &&
+ CA->getKind() <= CE_END_CXX_INSTANCE_CALLS;
+ }
+};
+
+/// \brief Represents a non-static C++ member function call.
+///
+/// Example: \c obj.fun()
+class CXXMemberCall : public CXXInstanceCall {
+ friend class CallEventManager;
+
+protected:
+ CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CXXInstanceCall(CE, St, LCtx) {}
+
+ CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {}
+ virtual void cloneTo(void *Dest) const { new (Dest) CXXMemberCall(*this); }
+
+public:
+ virtual const CXXMemberCallExpr *getOriginExpr() const {
+ return cast<CXXMemberCallExpr>(CXXInstanceCall::getOriginExpr());
+ }
+
+ virtual unsigned getNumArgs() const {
+ if (const CallExpr *CE = getOriginExpr())
+ return CE->getNumArgs();
+ return 0;
+ }
+
+ virtual const Expr *getArgExpr(unsigned Index) const {
+ return getOriginExpr()->getArg(Index);
+ }
+
+ virtual const Expr *getCXXThisExpr() const;
+
+ virtual Kind getKind() const { return CE_CXXMember; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_CXXMember;
+ }
+};
+
+/// \brief Represents a C++ overloaded operator call where the operator is
+/// implemented as a non-static member function.
+///
+/// Example: <tt>iter + 1</tt>
+class CXXMemberOperatorCall : public CXXInstanceCall {
+ friend class CallEventManager;
+
+protected:
+ CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CXXInstanceCall(CE, St, LCtx) {}
+
+ CXXMemberOperatorCall(const CXXMemberOperatorCall &Other)
+ : CXXInstanceCall(Other) {}
+ virtual void cloneTo(void *Dest) const {
+ new (Dest) CXXMemberOperatorCall(*this);
+ }
+
+public:
+ virtual const CXXOperatorCallExpr *getOriginExpr() const {
+ return cast<CXXOperatorCallExpr>(CXXInstanceCall::getOriginExpr());
+ }
+
+ virtual unsigned getNumArgs() const {
+ return getOriginExpr()->getNumArgs() - 1;
+ }
+ virtual const Expr *getArgExpr(unsigned Index) const {
+ return getOriginExpr()->getArg(Index + 1);
+ }
+
+ virtual const Expr *getCXXThisExpr() const;
+
+ virtual Kind getKind() const { return CE_CXXMemberOperator; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_CXXMemberOperator;
+ }
+};
+
+/// \brief Represents an implicit call to a C++ destructor.
+///
+/// This can occur at the end of a scope (for automatic objects), at the end
+/// of a full-expression (for temporaries), or as part of a delete.
+class CXXDestructorCall : public CXXInstanceCall {
+ friend class CallEventManager;
+
+protected:
+ /// Creates an implicit destructor.
+ ///
+ /// \param DD The destructor that will be called.
+ /// \param Trigger The statement whose completion causes this destructor call.
+ /// \param Target The object region to be destructed.
+ /// \param St The path-sensitive state at this point in the program.
+ /// \param LCtx The location context at this point in the program.
+ CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
+ const MemRegion *Target, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CXXInstanceCall(DD, St, LCtx) {
+ Data = Target;
+ Location = Trigger->getLocEnd();
+ }
+
+ CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {}
+ virtual void cloneTo(void *Dest) const { new (Dest) CXXDestructorCall(*this); }
+
+public:
+ virtual SourceRange getSourceRange() const { return Location; }
+ virtual unsigned getNumArgs() const { return 0; }
+
+ /// \brief Returns the value of the implicit 'this' object.
+ virtual SVal getCXXThisVal() const;
+
+ virtual Kind getKind() const { return CE_CXXDestructor; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_CXXDestructor;
+ }
+};
+
+/// \brief Represents a call to a C++ constructor.
+///
+/// Example: \c T(1)
+class CXXConstructorCall : public AnyFunctionCall {
+ friend class CallEventManager;
+
+protected:
+ /// Creates a constructor call.
+ ///
+ /// \param CE The constructor expression as written in the source.
+ /// \param Target The region where the object should be constructed. If NULL,
+ /// a new symbolic region will be used.
+ /// \param St The path-sensitive state at this point in the program.
+ /// \param LCtx The location context at this point in the program.
+ CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *target,
+ ProgramStateRef St, const LocationContext *LCtx)
+ : AnyFunctionCall(CE, St, LCtx) {
+ Data = target;
+ }
+
+ CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
+ virtual void cloneTo(void *Dest) const { new (Dest) CXXConstructorCall(*this); }
+
+ virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+
+public:
+ virtual const CXXConstructExpr *getOriginExpr() const {
+ return cast<CXXConstructExpr>(AnyFunctionCall::getOriginExpr());
+ }
+
+ virtual const CXXConstructorDecl *getDecl() const {
+ return getOriginExpr()->getConstructor();
+ }
+
+ virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); }
+
+ virtual const Expr *getArgExpr(unsigned Index) const {
+ return getOriginExpr()->getArg(Index);
+ }
+
+ /// \brief Returns the value of the implicit 'this' object.
+ SVal getCXXThisVal() const;
+
+ virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const;
+
+ virtual Kind getKind() const { return CE_CXXConstructor; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_CXXConstructor;
+ }
+};
+
+/// \brief Represents the memory allocation call in a C++ new-expression.
+///
+/// This is a call to "operator new".
+class CXXAllocatorCall : public AnyFunctionCall {
+ friend class CallEventManager;
+
+protected:
+ CXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : AnyFunctionCall(E, St, LCtx) {}
+
+ CXXAllocatorCall(const CXXAllocatorCall &Other) : AnyFunctionCall(Other) {}
+ virtual void cloneTo(void *Dest) const { new (Dest) CXXAllocatorCall(*this); }
+
+public:
+ virtual const CXXNewExpr *getOriginExpr() const {
+ return cast<CXXNewExpr>(AnyFunctionCall::getOriginExpr());
+ }
+
+ virtual const FunctionDecl *getDecl() const {
+ return getOriginExpr()->getOperatorNew();
+ }
+
+ virtual unsigned getNumArgs() const {
+ return getOriginExpr()->getNumPlacementArgs() + 1;
+ }
+
+ virtual const Expr *getArgExpr(unsigned Index) const {
+ // The first argument of an allocator call is the size of the allocation.
+ if (Index == 0)
+ return 0;
+ return getOriginExpr()->getPlacementArg(Index - 1);
+ }
+
+ virtual Kind getKind() const { return CE_CXXAllocator; }
+
+ static bool classof(const CallEvent *CE) {
+ return CE->getKind() == CE_CXXAllocator;
+ }
+};
+
+/// \brief Represents the ways an Objective-C message send can occur.
+//
+// Note to maintainers: OCM_Message should always be last, since it does not
+// need to fit in the Data field's low bits.
+enum ObjCMessageKind {
+ OCM_PropertyAccess,
+ OCM_Subscript,
+ OCM_Message
+};
+
+/// \brief Represents any expression that calls an Objective-C method.
+///
+/// This includes all of the kinds listed in ObjCMessageKind.
+class ObjCMethodCall : public CallEvent {
+ friend class CallEventManager;
+
+ const PseudoObjectExpr *getContainingPseudoObjectExpr() const;
+
+protected:
+ ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CallEvent(Msg, St, LCtx) {
+ Data = 0;
+ }
+
+ ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {}
+ virtual void cloneTo(void *Dest) const { new (Dest) ObjCMethodCall(*this); }
+
+ virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+
+ virtual QualType getDeclaredResultType() const;
+
+ /// Check if the selector may have multiple definitions (may have overrides).
+ virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
+ Selector Sel) const;
+
+public:
+ virtual const ObjCMessageExpr *getOriginExpr() const {
+ return cast<ObjCMessageExpr>(CallEvent::getOriginExpr());
+ }
+ virtual const ObjCMethodDecl *getDecl() const {
+ return getOriginExpr()->getMethodDecl();
+ }
+ virtual unsigned getNumArgs() const {
+ return getOriginExpr()->getNumArgs();
+ }
+ virtual const Expr *getArgExpr(unsigned Index) const {
+ return getOriginExpr()->getArg(Index);
+ }
+
+ bool isInstanceMessage() const {
+ return getOriginExpr()->isInstanceMessage();
+ }
+ ObjCMethodFamily getMethodFamily() const {
+ return getOriginExpr()->getMethodFamily();
+ }
+ Selector getSelector() const {
+ return getOriginExpr()->getSelector();
+ }
+
+ virtual SourceRange getSourceRange() const;
+
+ /// \brief Returns the value of the receiver at the time of this call.
+ SVal getReceiverSVal() const;
+
+ /// \brief Get the interface for the receiver.
+ ///
+ /// This works whether this is an instance message or a class message.
+ /// However, it currently just uses the static type of the receiver.
+ const ObjCInterfaceDecl *getReceiverInterface() const {
+ return getOriginExpr()->getReceiverInterface();
+ }
+
+ ObjCMessageKind getMessageKind() const;
+
+ bool isSetter() const {
+ switch (getMessageKind()) {
+ case OCM_Message:
+ llvm_unreachable("This is not a pseudo-object access!");
+ case OCM_PropertyAccess:
+ return getNumArgs() > 0;
+ case OCM_Subscript:
+ return getNumArgs() > 1;
+ }
+ llvm_unreachable("Unknown message kind");
+ }
+
+ virtual RuntimeDefinition getRuntimeDefinition() const;
+
+ virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const;
+
+ virtual param_iterator param_begin() const;
+ virtual param_iterator param_end() const;
+
+ virtual Kind getKind() const { return CE_ObjCMessage; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_ObjCMessage;
+ }
+};
+
+
+/// \brief Manages the lifetime of CallEvent objects.
+///
+/// CallEventManager provides a way to create arbitrary CallEvents "on the
+/// stack" as if they were value objects by keeping a cache of CallEvent-sized
+/// memory blocks. The CallEvents created by CallEventManager are only valid
+/// for the lifetime of the OwnedCallEvent that holds them; right now these
+/// objects cannot be copied and ownership cannot be transferred.
+class CallEventManager {
+ friend class CallEvent;
+
+ llvm::BumpPtrAllocator &Alloc;
+ SmallVector<void *, 8> Cache;
+
+ void reclaim(const void *Memory) {
+ Cache.push_back(const_cast<void *>(Memory));
+ }
+
+ /// Returns memory that can be initialized as a CallEvent.
+ void *allocate() {
+ if (Cache.empty())
+ return Alloc.Allocate<FunctionCall>();
+ else
+ return Cache.pop_back_val();
+ }
+
+ template <typename T, typename Arg>
+ T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) {
+ return new (allocate()) T(A, St, LCtx);
+ }
+
+ template <typename T, typename Arg1, typename Arg2>
+ T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx) {
+ return new (allocate()) T(A1, A2, St, LCtx);
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3>
+ T *create(Arg1 A1, Arg2 A2, Arg3 A3, ProgramStateRef St,
+ const LocationContext *LCtx) {
+ return new (allocate()) T(A1, A2, A3, St, LCtx);
+ }
+
+public:
+ CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {}
+
+
+ CallEventRef<>
+ getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State);
+
+
+ CallEventRef<>
+ getSimpleCall(const CallExpr *E, ProgramStateRef State,
+ const LocationContext *LCtx);
+
+ CallEventRef<ObjCMethodCall>
+ getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State,
+ const LocationContext *LCtx) {
+ return create<ObjCMethodCall>(E, State, LCtx);
+ }
+
+ CallEventRef<CXXConstructorCall>
+ getCXXConstructorCall(const CXXConstructExpr *E, const MemRegion *Target,
+ ProgramStateRef State, const LocationContext *LCtx) {
+ return create<CXXConstructorCall>(E, Target, State, LCtx);
+ }
+
+ CallEventRef<CXXDestructorCall>
+ getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
+ const MemRegion *Target, ProgramStateRef State,
+ const LocationContext *LCtx) {
+ return create<CXXDestructorCall>(DD, Trigger, Target, State, LCtx);
+ }
+
+ CallEventRef<CXXAllocatorCall>
+ getCXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef State,
+ const LocationContext *LCtx) {
+ return create<CXXAllocatorCall>(E, State, LCtx);
+ }
+};
+
+
+template <typename T>
+CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const {
+ assert(isa<T>(*this) && "Cloning to unrelated type");
+ assert(sizeof(T) == sizeof(CallEvent) && "Subclasses may not add fields");
+
+ if (NewState == State)
+ return cast<T>(this);
+
+ CallEventManager &Mgr = State->getStateManager().getCallEventManager();
+ T *Copy = static_cast<T *>(Mgr.allocate());
+ cloneTo(Copy);
+ assert(Copy->getKind() == this->getKind() && "Bad copy");
+
+ Copy->State = NewState;
+ return Copy;
+}
+
+inline void CallEvent::Release() const {
+ assert(RefCount > 0 && "Reference count is already zero.");
+ --RefCount;
+
+ if (RefCount > 0)
+ return;
+
+ CallEventManager &Mgr = State->getStateManager().getCallEventManager();
+ Mgr.reclaim(this);
+
+ this->~CallEvent();
+}
+
+} // end namespace ento
+} // end namespace clang
+
+namespace llvm {
+ // Support isa<>, cast<>, and dyn_cast<> for CallEventRef.
+ template<class T> struct simplify_type< clang::ento::CallEventRef<T> > {
+ typedef const T *SimpleType;
+
+ static SimpleType
+ getSimplifiedValue(const clang::ento::CallEventRef<T>& Val) {
+ return Val.getPtr();
+ }
+ };
+}
+
+#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index b051d33cbd84..8c8e82ce20dd 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -92,6 +92,10 @@ public:
return Pred->getLocationContext();
}
+ const StackFrameContext *getStackFrame() const {
+ return Pred->getStackFrame();
+ }
+
BugReporter &getBugReporter() {
return Eng.getBugReporter();
}
@@ -132,6 +136,11 @@ public:
return 0;
}
+ /// \brief Get the value of arbitrary expressions at this point in the path.
+ SVal getSVal(const Stmt *S) const {
+ return getState()->getSVal(S, getLocationContext());
+ }
+
/// \brief Generates a new transition in the program state graph
/// (ExplodedGraph). Uses the default CheckerContext predecessor node.
///
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 59136fc314ae..e75cdd87596b 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -65,7 +65,7 @@ private:
/// WList - A set of queued nodes that need to be processed by the
/// worklist algorithm. It is up to the implementation of WList to decide
/// the order that nodes are processed.
- WorkList* WList;
+ OwningPtr<WorkList> WList;
/// BCounterFactory - A factory object for created BlockCounter objects.
/// These are used to record for key nodes in the ExplodedGraph the
@@ -104,23 +104,18 @@ private:
CoreEngine(const CoreEngine&); // Do not implement.
CoreEngine& operator=(const CoreEngine&);
- ExplodedNode *generateCallExitNode(ExplodedNode *N);
+ ExplodedNode *generateCallExitBeginNode(ExplodedNode *N);
public:
- /// Construct a CoreEngine object to analyze the provided CFG using
- /// a DFS exploration of the exploded graph.
+ /// Construct a CoreEngine object to analyze the provided CFG.
CoreEngine(SubEngine& subengine, SetOfConstDecls *VisitedCallees,
FunctionSummariesTy *FS)
: SubEng(subengine), G(new ExplodedGraph()),
- WList(WorkList::makeBFS()),
+ WList(WorkList::makeDFS()),
BCounterFactory(G->getAllocator()),
AnalyzedCallees(VisitedCallees),
FunctionSummaries(FS){}
- ~CoreEngine() {
- delete WList;
- }
-
/// getGraph - Returns the exploded graph.
ExplodedGraph& getGraph() { return *G.get(); }
@@ -156,7 +151,7 @@ public:
blocksAborted.push_back(std::make_pair(block, node));
}
- WorkList *getWorkList() const { return WList; }
+ WorkList *getWorkList() const { return WList.get(); }
BlocksExhausted::const_iterator blocks_exhausted_begin() const {
return blocksExhausted.begin();
@@ -188,10 +183,10 @@ public:
// TODO: Turn into a calss.
struct NodeBuilderContext {
- CoreEngine &Eng;
+ const CoreEngine &Eng;
const CFGBlock *Block;
ExplodedNode *Pred;
- NodeBuilderContext(CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
+ NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
: Eng(E), Block(B), Pred(N) { assert(B); assert(!N->isSink()); }
ExplodedNode *getPred() const { return Pred; }
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 46fbb88212e3..1052d9491a96 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -133,6 +133,10 @@ public:
return getLocation().getLocationContext();
}
+ const StackFrameContext *getStackFrame() const {
+ return getLocationContext()->getCurrentStackFrame();
+ }
+
const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
CFG &getCFG() const { return *getLocationContext()->getCFG(); }
@@ -151,7 +155,7 @@ public:
static void Profile(llvm::FoldingSetNodeID &ID,
const ProgramPoint &Loc,
- ProgramStateRef state,
+ const ProgramStateRef &state,
bool IsSink) {
ID.Add(Loc);
ID.AddPointer(state.getPtr());
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 2a21a03e9a2d..4addb9d4ec49 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -41,8 +41,8 @@ class ObjCForCollectionStmt;
namespace ento {
class AnalysisManager;
-class CallOrObjCMessage;
-class ObjCMessage;
+class CallEvent;
+class SimpleCall;
class ExprEngine : public SubEngine {
AnalysisManager &AMgr;
@@ -151,6 +151,25 @@ public:
ExplodedGraph& getGraph() { return G; }
const ExplodedGraph& getGraph() const { return G; }
+ /// \brief Run the analyzer's garbage collection - remove dead symbols and
+ /// bindings.
+ ///
+ /// \param Node - The predecessor node, from which the processing should
+ /// start.
+ /// \param Out - The returned set of output nodes.
+ /// \param ReferenceStmt - Run garbage collection using the symbols,
+ /// which are live before the given statement.
+ /// \param LC - The location context of the ReferenceStmt.
+ /// \param DiagnosticStmt - the statement used to associate the diagnostic
+ /// message, if any warnings should occur while removing the dead (leaks
+ /// are usually reported here).
+ /// \param K - In some cases it is possible to use PreStmt kind. (Do
+ /// not use it unless you know what you are doing.)
+ void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
+ const Stmt *ReferenceStmt, const LocationContext *LC,
+ const Stmt *DiagnosticStmt,
+ ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
+
/// processCFGElement - Called by CoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a CFG element.
void processCFGElement(const CFGElement E, ExplodedNode *Pred,
@@ -199,7 +218,8 @@ public:
/// Generate the entry node of the callee.
void processCallEnter(CallEnter CE, ExplodedNode *Pred);
- /// Generate the first post callsite node.
+ /// Generate the sequence of nodes that simulate the call exit and the post
+ /// visit for CallExpr.
void processCallExit(ExplodedNode *Pred);
/// Called by CoreEngine when the analysis worklist has terminated.
@@ -220,7 +240,7 @@ public:
const StoreManager::InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
- const CallOrObjCMessage *Call);
+ const CallEvent *Call);
/// printState - Called by ProgramStateManager to print checker-specific data.
void printState(raw_ostream &Out, ProgramStateRef State,
@@ -265,6 +285,10 @@ public:
/// VisitAsmStmt - Transfer function logic for inline asm.
void VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ /// VisitMSAsmStmt - Transfer function logic for MS inline asm.
+ void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
/// VisitBlockExpr - Transfer function logic for BlockExprs.
void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
@@ -323,7 +347,7 @@ public:
void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
- void VisitObjCMessage(const ObjCMessage &msg, ExplodedNode *Pred,
+ void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// VisitReturnStmt - Transfer function logic for return statements.
@@ -353,13 +377,10 @@ public:
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
- void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
- void VisitCXXDestructor(const CXXDestructorDecl *DD,
+ void VisitCXXDestructor(QualType ObjectType,
const MemRegion *Dest, const Stmt *S,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
@@ -373,13 +394,6 @@ public:
void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
ExplodedNode *Pred,
ExplodedNodeSet &Dst);
-
- /// Synthesize CXXThisRegion.
- const CXXThisRegion *getCXXThisRegion(const CXXRecordDecl *RD,
- const StackFrameContext *SFC);
-
- const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *decl,
- const StackFrameContext *frameCtx);
/// evalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
@@ -416,19 +430,6 @@ public:
}
protected:
- void evalObjCMessage(StmtNodeBuilder &Bldr, const ObjCMessage &msg,
- ExplodedNode *Pred, ProgramStateRef state,
- bool GenSink);
-
- ProgramStateRef invalidateArguments(ProgramStateRef State,
- const CallOrObjCMessage &Call,
- const LocationContext *LC);
-
- ProgramStateRef MarkBranch(ProgramStateRef state,
- const Stmt *Terminator,
- const LocationContext *LCtx,
- bool branchTaken);
-
/// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore, VisitDeclStmt, and others.
void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
@@ -455,6 +456,21 @@ public:
void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE,
ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val,
const ProgramPointTag *tag = 0);
+
+ /// \brief Create a new state in which the call return value is binded to the
+ /// call origin expression.
+ ProgramStateRef bindReturnValue(const CallEvent &Call,
+ const LocationContext *LCtx,
+ ProgramStateRef State);
+
+ /// Evaluate a call, running pre- and post-call checks and allowing checkers
+ /// to be responsible for handling the evaluation of the call itself.
+ void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
+ const CallEvent &Call);
+
+ /// \brief Default implementation of call evaluation.
+ void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred,
+ const CallEvent &Call);
private:
void evalLoadCommon(ExplodedNodeSet &Dst,
const Expr *NodeEx, /* Eventually will be a CFGStmt */
@@ -474,8 +490,20 @@ private:
ProgramStateRef St, SVal location,
const ProgramPointTag *tag, bool isLoad);
- bool shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred);
- bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
+ bool shouldInlineDecl(const Decl *D, ExplodedNode *Pred);
+ bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
+ ExplodedNode *Pred, ProgramStateRef State);
+
+ /// \brief Conservatively evaluate call by invalidating regions and binding
+ /// a conjured return value.
+ void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
+ ExplodedNode *Pred, ProgramStateRef State);
+
+ /// \brief Either inline or process the call conservatively (or both), based
+ /// on DynamicDispatchBifurcation data.
+ void BifurcateCall(const MemRegion *BifurReg,
+ const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
+ ExplodedNode *Pred);
bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
index 42adff3e2b94..cf4a6929a3aa 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
@@ -14,15 +14,16 @@
#ifndef LLVM_CLANG_GR_FUNCTIONSUMMARY_H
#define LLVM_CLANG_GR_FUNCTIONSUMMARY_H
+#include <deque>
#include "clang/AST/Decl.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/BitVector.h"
namespace clang {
namespace ento {
-typedef llvm::SmallPtrSet<Decl*, 24> SetOfDecls;
-typedef llvm::SmallPtrSet<const Decl*, 24> SetOfConstDecls;
+typedef std::deque<Decl*> SetOfDecls;
+typedef llvm::DenseSet<const Decl*> SetOfConstDecls;
class FunctionSummariesTy {
struct FunctionSummary {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 87bc0df0908f..01218effff90 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -16,6 +16,7 @@
#ifndef LLVM_CLANG_GR_MEMREGION_H
#define LLVM_CLANG_GR_MEMREGION_H
+#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/ExprObjC.h"
@@ -51,11 +52,21 @@ class RegionOffset {
int64_t Offset;
public:
- RegionOffset(const MemRegion *r) : R(r), Offset(0) {}
+ enum { Symbolic = INT64_MAX };
+
+ RegionOffset() : R(0) {}
RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
const MemRegion *getRegion() const { return R; }
- int64_t getOffset() const { return Offset; }
+
+ bool hasSymbolicOffset() const { return Offset == Symbolic; }
+
+ int64_t getOffset() const {
+ assert(!hasSymbolicOffset());
+ return Offset;
+ }
+
+ bool isValid() const { return R; }
};
//===----------------------------------------------------------------------===//
@@ -127,7 +138,7 @@ public:
const MemRegion *getBaseRegion() const;
- const MemRegion *StripCasts() const;
+ const MemRegion *StripCasts(bool StripBaseCasts = true) const;
bool hasGlobalsOrParametersStorage() const;
@@ -147,8 +158,11 @@ public:
void dump() const;
+ /// \brief Returns true if this region can be printed in a user-friendly way.
+ virtual bool canPrintPretty() const;
+
/// \brief Print the region for use in diagnostics.
- virtual void dumpPretty(raw_ostream &os) const;
+ virtual void printPretty(raw_ostream &os) const;
Kind getKind() const { return kind; }
@@ -197,8 +211,9 @@ public:
}
};
-/// \class The region of the static variables within the current CodeTextRegion
+/// \brief The region of the static variables within the current CodeTextRegion
/// scope.
+///
/// Currently, only the static locals are placed there, so we know that these
/// variables do not get invalidated by calls to other functions.
class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
@@ -221,7 +236,7 @@ public:
}
};
-/// \class The region for all the non-static global variables.
+/// \brief The region for all the non-static global variables.
///
/// This class is further split into subclasses for efficient implementation of
/// invalidating a set of related global values as is done in
@@ -236,8 +251,6 @@ protected:
public:
- void dumpToStream(raw_ostream &os) const;
-
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES &&
@@ -245,7 +258,7 @@ public:
}
};
-/// \class The region containing globals which are defined in system/external
+/// \brief The region containing globals which are defined in system/external
/// headers and are considered modifiable by system calls (ex: errno).
class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
friend class MemRegionManager;
@@ -262,7 +275,7 @@ public:
}
};
-/// \class The region containing globals which are considered not to be modified
+/// \brief The region containing globals which are considered not to be modified
/// or point to data which could be modified as a result of a function call
/// (system or internal). Ex: Const global scalars would be modeled as part of
/// this region. This region also includes most system globals since they have
@@ -282,7 +295,7 @@ public:
}
};
-/// \class The region containing globals which can be modified by calls to
+/// \brief The region containing globals which can be modified by calls to
/// "internally" defined functions - (for now just) functions other then system
/// calls.
class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
@@ -307,6 +320,9 @@ class HeapSpaceRegion : public MemSpaceRegion {
HeapSpaceRegion(MemRegionManager *mgr)
: MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
public:
+
+ void dumpToStream(raw_ostream &os) const;
+
static bool classof(const MemRegion *R) {
return R->getKind() == HeapSpaceRegionKind;
}
@@ -318,6 +334,9 @@ class UnknownSpaceRegion : public MemSpaceRegion {
UnknownSpaceRegion(MemRegionManager *mgr)
: MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
public:
+
+ void dumpToStream(raw_ostream &os) const;
+
static bool classof(const MemRegion *R) {
return R->getKind() == UnknownSpaceRegionKind;
}
@@ -351,6 +370,9 @@ class StackLocalsSpaceRegion : public StackSpaceRegion {
StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
public:
+
+ void dumpToStream(raw_ostream &os) const;
+
static bool classof(const MemRegion *R) {
return R->getKind() == StackLocalsSpaceRegionKind;
}
@@ -363,6 +385,9 @@ private:
StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
public:
+
+ void dumpToStream(raw_ostream &os) const;
+
static bool classof(const MemRegion *R) {
return R->getKind() == StackArgumentsSpaceRegionKind;
}
@@ -478,6 +503,8 @@ public:
return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
}
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k >= BEG_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
@@ -579,25 +606,37 @@ class BlockDataRegion : public SubRegion {
const BlockTextRegion *BC;
const LocationContext *LC; // Can be null */
void *ReferencedVars;
+ void *OriginalVars;
BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
const MemRegion *sreg)
- : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {}
+ : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
+ ReferencedVars(0), OriginalVars(0) {}
-public:
+public:
const BlockTextRegion *getCodeRegion() const { return BC; }
const BlockDecl *getDecl() const { return BC->getDecl(); }
class referenced_vars_iterator {
const MemRegion * const *R;
+ const MemRegion * const *OriginalR;
public:
- explicit referenced_vars_iterator(const MemRegion * const *r) : R(r) {}
+ explicit referenced_vars_iterator(const MemRegion * const *r,
+ const MemRegion * const *originalR)
+ : R(r), OriginalR(originalR) {}
operator const MemRegion * const *() const {
return R;
}
-
+
+ const MemRegion *getCapturedRegion() const {
+ return *R;
+ }
+ const MemRegion *getOriginalRegion() const {
+ return *OriginalR;
+ }
+
const VarRegion* operator*() const {
return cast<VarRegion>(*R);
}
@@ -610,6 +649,7 @@ public:
}
referenced_vars_iterator &operator++() {
++R;
+ ++OriginalR;
return *this;
}
};
@@ -781,8 +821,6 @@ public:
const Decl *getDecl() const { return D; }
void Profile(llvm::FoldingSetNodeID& ID) const;
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
-
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS;
@@ -819,7 +857,8 @@ public:
return R->getKind() == VarRegionKind;
}
- void dumpPretty(raw_ostream &os) const;
+ bool canPrintPretty() const;
+ void printPretty(raw_ostream &os) const;
};
/// CXXThisRegion - Represents the region for the implicit 'this' parameter
@@ -878,7 +917,9 @@ public:
}
void dumpToStream(raw_ostream &os) const;
- void dumpPretty(raw_ostream &os) const;
+
+ bool canPrintPretty() const;
+ void printPretty(raw_ostream &os) const;
};
class ObjCIvarRegion : public DeclRegion {
@@ -1106,8 +1147,11 @@ public:
const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
const LocationContext *LC);
- /// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
- const SymbolicRegion* getSymbolicRegion(SymbolRef sym);
+ /// \brief Retrieve or create a "symbolic" memory region.
+ const SymbolicRegion* getSymbolicRegion(SymbolRef Sym);
+
+ /// \brief Return a unique symbolic region belonging to heap memory space.
+ const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym);
const StringRegion *getStringRegion(const StringLiteral* Str);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
deleted file mode 100644
index d8aec0991d9a..000000000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
+++ /dev/null
@@ -1,293 +0,0 @@
-//===- ObjCMessage.h - Wrapper for ObjC messages and dot syntax ---*- 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 ObjCMessage which serves as a common wrapper for ObjC
-// message expressions or implicit messages for loading/storing ObjC properties.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
-#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/Basic/SourceManager.h"
-#include "llvm/ADT/PointerUnion.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Compiler.h"
-
-namespace clang {
-namespace ento {
-using llvm::StrInStrNoCase;
-
-/// \brief Represents both explicit ObjC message expressions and implicit
-/// messages that are sent for handling properties in dot syntax.
-class ObjCMessage {
- const ObjCMessageExpr *Msg;
- const ObjCPropertyRefExpr *PE;
- const bool IsPropSetter;
-public:
- ObjCMessage() : Msg(0), PE(0), IsPropSetter(false) {}
-
- ObjCMessage(const ObjCMessageExpr *E, const ObjCPropertyRefExpr *pe = 0,
- bool isSetter = false)
- : Msg(E), PE(pe), IsPropSetter(isSetter) {
- assert(E && "should not be initialized with null expression");
- }
-
- bool isValid() const { return Msg; }
-
- bool isPureMessageExpr() const { return !PE; }
-
- bool isPropertyGetter() const { return PE && !IsPropSetter; }
-
- bool isPropertySetter() const {
- return IsPropSetter;
- }
-
- const Expr *getMessageExpr() const {
- return Msg;
- }
-
- QualType getType(ASTContext &ctx) const {
- return Msg->getType();
- }
-
- QualType getResultType(ASTContext &ctx) const {
- if (const ObjCMethodDecl *MD = Msg->getMethodDecl())
- return MD->getResultType();
- return getType(ctx);
- }
-
- ObjCMethodFamily getMethodFamily() const {
- return Msg->getMethodFamily();
- }
-
- Selector getSelector() const {
- return Msg->getSelector();
- }
-
- const Expr *getInstanceReceiver() const {
- return Msg->getInstanceReceiver();
- }
-
- SVal getInstanceReceiverSVal(ProgramStateRef State,
- const LocationContext *LC) const {
- if (!isInstanceMessage())
- return UndefinedVal();
- if (const Expr *Ex = getInstanceReceiver())
- return State->getSValAsScalarOrLoc(Ex, LC);
-
- // An instance message with no expression means we are sending to super.
- // In this case the object reference is the same as 'self'.
- const ImplicitParamDecl *SelfDecl = LC->getSelfDecl();
- assert(SelfDecl && "No message receiver Expr, but not in an ObjC method");
- return State->getSVal(State->getRegion(SelfDecl, LC));
- }
-
- bool isInstanceMessage() const {
- return Msg->isInstanceMessage();
- }
-
- const ObjCMethodDecl *getMethodDecl() const {
- return Msg->getMethodDecl();
- }
-
- const ObjCInterfaceDecl *getReceiverInterface() const {
- return Msg->getReceiverInterface();
- }
-
- SourceLocation getSuperLoc() const {
- if (PE)
- return PE->getReceiverLocation();
- return Msg->getSuperLoc();
- }
-
- SourceRange getSourceRange() const LLVM_READONLY {
- if (PE)
- return PE->getSourceRange();
- return Msg->getSourceRange();
- }
-
- unsigned getNumArgs() const {
- return Msg->getNumArgs();
- }
-
- SVal getArgSVal(unsigned i,
- const LocationContext *LCtx,
- ProgramStateRef state) const {
- assert(i < getNumArgs() && "Invalid index for argument");
- return state->getSVal(Msg->getArg(i), LCtx);
- }
-
- QualType getArgType(unsigned i) const {
- assert(i < getNumArgs() && "Invalid index for argument");
- return Msg->getArg(i)->getType();
- }
-
- const Expr *getArgExpr(unsigned i) const {
- assert(i < getNumArgs() && "Invalid index for argument");
- return Msg->getArg(i);
- }
-
- SourceRange getArgSourceRange(unsigned i) const {
- const Expr *argE = getArgExpr(i);
- return argE->getSourceRange();
- }
-
- SourceRange getReceiverSourceRange() const {
- if (PE) {
- if (PE->isObjectReceiver())
- return PE->getBase()->getSourceRange();
- }
- else {
- return Msg->getReceiverRange();
- }
-
- // FIXME: This isn't a range.
- return PE->getReceiverLocation();
- }
-};
-
-/// \brief Common wrapper for a call expression, ObjC message, or C++
-/// constructor, mainly to provide a common interface for their arguments.
-class CallOrObjCMessage {
- llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE;
- ObjCMessage Msg;
- ProgramStateRef State;
- const LocationContext *LCtx;
-public:
- CallOrObjCMessage(const CallExpr *callE, ProgramStateRef state,
- const LocationContext *lctx)
- : CallE(callE), State(state), LCtx(lctx) {}
- CallOrObjCMessage(const CXXConstructExpr *consE, ProgramStateRef state,
- const LocationContext *lctx)
- : CallE(consE), State(state), LCtx(lctx) {}
- CallOrObjCMessage(const ObjCMessage &msg, ProgramStateRef state,
- const LocationContext *lctx)
- : CallE((CallExpr *)0), Msg(msg), State(state), LCtx(lctx) {}
-
- QualType getResultType(ASTContext &ctx) const;
-
- bool isFunctionCall() const {
- return CallE && CallE.is<const CallExpr *>();
- }
-
- bool isCXXConstructExpr() const {
- return CallE && CallE.is<const CXXConstructExpr *>();
- }
-
- bool isObjCMessage() const {
- return !CallE;
- }
-
- bool isCXXCall() const {
- const CallExpr *ActualCallE = CallE.dyn_cast<const CallExpr *>();
- return ActualCallE && isa<CXXMemberCallExpr>(ActualCallE);
- }
-
- /// Check if the callee is declared in the system header.
- bool isInSystemHeader() const {
- if (const Decl *FD = getDecl()) {
- const SourceManager &SM =
- State->getStateManager().getContext().getSourceManager();
- return SM.isInSystemHeader(FD->getLocation());
- }
- return false;
- }
-
- const Expr *getOriginExpr() const {
- if (!CallE)
- return Msg.getMessageExpr();
- if (const CXXConstructExpr *Ctor =
- CallE.dyn_cast<const CXXConstructExpr *>())
- return Ctor;
- return CallE.get<const CallExpr *>();
- }
-
- SVal getFunctionCallee() const;
- SVal getCXXCallee() const;
- SVal getInstanceMessageReceiver(const LocationContext *LC) const;
-
- /// Get the declaration of the function or method.
- const Decl *getDecl() const;
-
- unsigned getNumArgs() const {
- if (!CallE)
- return Msg.getNumArgs();
- if (const CXXConstructExpr *Ctor =
- CallE.dyn_cast<const CXXConstructExpr *>())
- return Ctor->getNumArgs();
- return CallE.get<const CallExpr *>()->getNumArgs();
- }
-
- SVal getArgSVal(unsigned i) const {
- assert(i < getNumArgs());
- if (!CallE)
- return Msg.getArgSVal(i, LCtx, State);
- return State->getSVal(getArg(i), LCtx);
- }
-
- const Expr *getArg(unsigned i) const {
- assert(i < getNumArgs());
- if (!CallE)
- return Msg.getArgExpr(i);
- if (const CXXConstructExpr *Ctor =
- CallE.dyn_cast<const CXXConstructExpr *>())
- return Ctor->getArg(i);
- return CallE.get<const CallExpr *>()->getArg(i);
- }
-
- SourceRange getArgSourceRange(unsigned i) const {
- assert(i < getNumArgs());
- if (CallE)
- return getArg(i)->getSourceRange();
- return Msg.getArgSourceRange(i);
- }
-
- SourceRange getReceiverSourceRange() const {
- assert(isObjCMessage());
- return Msg.getReceiverSourceRange();
- }
-
- /// \brief Check if the name corresponds to a CoreFoundation or CoreGraphics
- /// function that allows objects to escape.
- ///
- /// Many methods allow a tracked object to escape. For example:
- ///
- /// CFMutableDictionaryRef x = CFDictionaryCreateMutable(..., customDeallocator);
- /// CFDictionaryAddValue(y, key, x);
- ///
- /// We handle this and similar cases with the following heuristic. If the
- /// function name contains "InsertValue", "SetValue", "AddValue",
- /// "AppendValue", or "SetAttribute", then we assume that arguments may
- /// escape.
- //
- // TODO: To reduce false negatives here, we should track the container
- // allocation site and check if a proper deallocator was set there.
- static bool isCFCGAllowingEscape(StringRef FName) {
- if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G'))
- if (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
- StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
- StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
- StrInStrNoCase(FName, "WithData") != StringRef::npos ||
- StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
- StrInStrNoCase(FName, "SetAttribute") != StringRef::npos) {
- return true;
- }
- return false;
- }
-};
-
-}
-}
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 360d6486f966..d36aa1bd1bcb 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -35,7 +35,8 @@ class ASTContext;
namespace ento {
-class CallOrObjCMessage;
+class CallEvent;
+class CallEventManager;
typedef ConstraintManager* (*ConstraintManagerCreator)(ProgramStateManager&,
SubEngine&);
@@ -49,13 +50,34 @@ template <typename T> struct ProgramStatePartialTrait;
template <typename T> struct ProgramStateTrait {
typedef typename T::data_type data_type;
- static inline void *GDMIndex() { return &T::TagInt; }
static inline void *MakeVoidPtr(data_type D) { return (void*) D; }
static inline data_type MakeData(void *const* P) {
return P ? (data_type) *P : (data_type) 0;
}
};
+/// \class Stores the dynamic type information.
+/// Information about type of an object at runtime. This is used by dynamic
+/// dispatch implementation.
+class DynamicTypeInfo {
+ QualType T;
+ bool CanBeASubClass;
+
+public:
+ DynamicTypeInfo() : T(QualType()) {}
+ DynamicTypeInfo(QualType WithType, bool CanBeSub = true):
+ T(WithType), CanBeASubClass(CanBeSub) {}
+ QualType getType() { return T; }
+ bool canBeASubClass() { return CanBeASubClass; }
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ T.Profile(ID);
+ ID.AddInteger((unsigned)CanBeASubClass);
+ }
+ bool operator==(const DynamicTypeInfo &X) const {
+ return T == X.T && CanBeASubClass == X.CanBeASubClass;
+ }
+};
+
/// \class ProgramState
/// ProgramState - This class encapsulates:
///
@@ -220,12 +242,12 @@ public:
const Expr *E, unsigned BlockCount,
const LocationContext *LCtx,
StoreManager::InvalidatedSymbols *IS = 0,
- const CallOrObjCMessage *Call = 0) const;
+ const CallEvent *Call = 0) const;
/// enterStackFrame - Returns the state for entry to the given stack frame,
/// preserving the current state.
- ProgramStateRef enterStackFrame(const LocationContext *callerCtx,
- const StackFrameContext *calleeCtx) const;
+ ProgramStateRef enterStackFrame(const CallEvent &Call,
+ const StackFrameContext *CalleeCtx) const;
/// Get the lvalue for a variable reference.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
@@ -239,6 +261,9 @@ public:
/// Get the lvalue for a field reference.
SVal getLValue(const FieldDecl *decl, SVal Base) const;
+ /// Get the lvalue for an indirect field reference.
+ SVal getLValue(const IndirectFieldDecl *decl, SVal Base) const;
+
/// Get the lvalue for an array index.
SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
@@ -310,6 +335,20 @@ public:
bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const;
bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const;
+ /// \brief Get dynamic type information for a region.
+ DynamicTypeInfo getDynamicTypeInfo(const MemRegion *Reg) const;
+
+ /// \brief Set dynamic type information of the region; return the new state.
+ ProgramStateRef setDynamicTypeInfo(const MemRegion *Reg,
+ DynamicTypeInfo NewTy) const;
+
+ /// \brief Set dynamic type information of the region; return the new state.
+ ProgramStateRef setDynamicTypeInfo(const MemRegion *Reg,
+ QualType NewTy,
+ bool CanBeSubClassed = true) const {
+ return setDynamicTypeInfo(Reg, DynamicTypeInfo(NewTy, CanBeSubClassed));
+ }
+
//==---------------------------------------------------------------------==//
// Accessing the Generic Data Map (GDM).
//==---------------------------------------------------------------------==//
@@ -382,7 +421,7 @@ private:
const Expr *E, unsigned BlockCount,
const LocationContext *LCtx,
StoreManager::InvalidatedSymbols &IS,
- const CallOrObjCMessage *Call) const;
+ const CallEvent *Call) const;
};
//===----------------------------------------------------------------------===//
@@ -412,6 +451,9 @@ private:
/// Object that manages the data for all created SVals.
OwningPtr<SValBuilder> svalBuilder;
+ /// Manages memory for created CallEvents.
+ OwningPtr<CallEventManager> CallEventMgr;
+
/// A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator &Alloc;
@@ -423,28 +465,7 @@ public:
StoreManagerCreator CreateStoreManager,
ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc,
- SubEngine &subeng)
- : Eng(&subeng),
- EnvMgr(alloc),
- GDMFactory(alloc),
- svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
- Alloc(alloc) {
- StoreMgr.reset((*CreateStoreManager)(*this));
- ConstraintMgr.reset((*CreateConstraintManager)(*this, subeng));
- }
-
- ProgramStateManager(ASTContext &Ctx,
- StoreManagerCreator CreateStoreManager,
- ConstraintManager* ConstraintManagerPtr,
- llvm::BumpPtrAllocator& alloc)
- : Eng(0),
- EnvMgr(alloc),
- GDMFactory(alloc),
- svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
- Alloc(alloc) {
- StoreMgr.reset((*CreateStoreManager)(*this));
- ConstraintMgr.reset(ConstraintManagerPtr);
- }
+ SubEngine &subeng);
~ProgramStateManager();
@@ -480,6 +501,8 @@ public:
return svalBuilder->getRegionManager();
}
+ CallEventManager &getCallEventManager() { return *CallEventMgr; }
+
StoreManager& getStoreManager() { return *StoreMgr; }
ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
SubEngine* getOwningEngine() { return Eng; }
@@ -650,6 +673,18 @@ inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const {
return getStateManager().StoreMgr->getLValueField(D, Base);
}
+inline SVal ProgramState::getLValue(const IndirectFieldDecl *D,
+ SVal Base) const {
+ StoreManager &SM = *getStateManager().StoreMgr;
+ for (IndirectFieldDecl::chain_iterator I = D->chain_begin(),
+ E = D->chain_end();
+ I != E; ++I) {
+ Base = SM.getLValueField(cast<FieldDecl>(*I), Base);
+ }
+
+ return Base;
+}
+
inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
if (NonLoc *N = dyn_cast<NonLoc>(&Idx))
return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
@@ -672,7 +707,7 @@ ProgramState::getSValAsScalarOrLoc(const Stmt *S,
const LocationContext *LCtx) const {
if (const Expr *Ex = dyn_cast<Expr>(S)) {
QualType T = Ex->getType();
- if (Ex->isLValue() || Loc::isLocType(T) || T->isIntegerType())
+ if (Ex->isGLValue() || Loc::isLocType(T) || T->isIntegerType())
return getSVal(S, LCtx);
}
@@ -765,14 +800,12 @@ CB ProgramState::scanReachableSymbols(const MemRegion * const *beg,
/// \class ScanReachableSymbols
/// A Utility class that allows to visit the reachable symbols using a custom
/// SymbolVisitor.
-class ScanReachableSymbols : public SubRegionMap::Visitor {
- virtual void anchor();
+class ScanReachableSymbols {
typedef llvm::DenseMap<const void*, unsigned> VisitedItems;
VisitedItems visited;
ProgramStateRef state;
SymbolVisitor &visitor;
- OwningPtr<SubRegionMap> SRM;
public:
ScanReachableSymbols(ProgramStateRef st, SymbolVisitor& v)
@@ -782,11 +815,6 @@ public:
bool scan(SVal val);
bool scan(const MemRegion *R);
bool scan(const SymExpr *sym);
-
- // From SubRegionMap::Visitor.
- bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) {
- return scan(SubRegion);
- }
};
} // end GR namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 4ad36f9dbb1d..83c3a5634586 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_GR_SVALBUILDER
#define LLVM_CLANG_GR_SVALBUILDER
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -78,7 +79,7 @@ public:
// FIXME: Remove the second disjunct when we support symbolic
// truncation/extension.
return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) ||
- (Ty2->isIntegerType() && Ty2->isIntegerType()));
+ (Ty1->isIntegerType() && Ty2->isIntegerType()));
}
SVal evalCast(SVal val, QualType castTy, QualType originalType);
@@ -107,12 +108,9 @@ public:
/// that value is returned. Otherwise, returns NULL.
virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal val) = 0;
- /// Handles generation of the value in case the builder is not smart enough to
- /// handle the given binary expression. Depending on the state, decides to
- /// either keep the expression or forget the history and generate an
- /// UnknownVal.
- SVal makeGenericVal(ProgramStateRef state, BinaryOperator::Opcode op,
- NonLoc lhs, NonLoc rhs, QualType resultTy);
+ /// Constructs a symbolic expression for two non-location values.
+ SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op,
+ NonLoc lhs, NonLoc rhs, QualType resultTy);
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
SVal lhs, SVal rhs, QualType type);
@@ -185,6 +183,12 @@ public:
const LocationContext *LCtx,
QualType type,
unsigned visitCount);
+ /// \brief Conjure a symbol representing heap allocated memory region.
+ ///
+ /// Note, the expression should represent a location.
+ DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E,
+ const LocationContext *LCtx,
+ unsigned Count);
DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(
SymbolRef parentSymbol, const TypedValueRegion *region);
@@ -307,6 +311,13 @@ public:
return loc::ConcreteInt(BasicVals.getValue(integer));
}
+ /// Return a memory region for the 'this' object reference.
+ loc::MemRegionVal getCXXThis(const CXXMethodDecl *D,
+ const StackFrameContext *SFC);
+
+ /// Return a memory region for the 'this' object reference.
+ loc::MemRegionVal getCXXThis(const CXXRecordDecl *D,
+ const StackFrameContext *SFC);
};
SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index ce3eb1db8365..e0b5f64b900b 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -68,7 +68,6 @@ protected:
public:
explicit SVal() : Data(0), Kind(0) {}
- ~SVal() {}
/// BufferTy - A temporary buffer to hold a set of SVals.
typedef SmallVector<SVal,5> BufferTy;
@@ -164,13 +163,10 @@ public:
class UndefinedVal : public SVal {
public:
UndefinedVal() : SVal(UndefinedKind) {}
- UndefinedVal(const void *D) : SVal(UndefinedKind, D) {}
static inline bool classof(const SVal* V) {
return V->getBaseKind() == UndefinedKind;
}
-
- const void *getData() const { return Data; }
};
class DefinedOrUnknownSVal : public SVal {
@@ -326,16 +322,22 @@ class LocAsInteger : public NonLoc {
public:
Loc getLoc() const {
- return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first);
+ const std::pair<SVal, uintptr_t> *D =
+ static_cast<const std::pair<SVal, uintptr_t> *>(Data);
+ return cast<Loc>(D->first);
}
const Loc& getPersistentLoc() const {
- const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first;
+ const std::pair<SVal, uintptr_t> *D =
+ static_cast<const std::pair<SVal, uintptr_t> *>(Data);
+ const SVal& V = D->first;
return cast<Loc>(V);
}
unsigned getNumBits() const {
- return ((std::pair<SVal, unsigned>*) Data)->second;
+ const std::pair<SVal, uintptr_t> *D =
+ static_cast<const std::pair<SVal, uintptr_t> *>(Data);
+ return D->second;
}
// Implement isa<T> support.
@@ -401,7 +403,7 @@ public:
namespace loc {
-enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
+enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
class GotoLabel : public Loc {
public:
@@ -431,7 +433,7 @@ public:
}
/// \brief Get the underlining region and strip casts.
- const MemRegion* stripCasts() const;
+ const MemRegion* stripCasts(bool StripBaseCasts = true) const;
template <typename REGION>
const REGION* getRegionAs() const {
@@ -480,28 +482,6 @@ public:
}
};
-/// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or
-/// "store" of an ObjC property for the dot syntax.
-class ObjCPropRef : public Loc {
-public:
- explicit ObjCPropRef(const ObjCPropertyRefExpr *E)
- : Loc(ObjCPropRefKind, E) {}
-
- const ObjCPropertyRefExpr *getPropRefExpr() const {
- return static_cast<const ObjCPropertyRefExpr *>(Data);
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == LocKind &&
- V->getSubKind() == ObjCPropRefKind;
- }
-
- static inline bool classof(const Loc* V) {
- return V->getSubKind() == ObjCPropRefKind;
- }
-};
-
} // end ento::loc namespace
} // end GR namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 5315f4b7420a..138a590b1b24 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -29,10 +29,10 @@ class StackFrameContext;
namespace ento {
-class CallOrObjCMessage;
+class CallEvent;
class ProgramState;
class ProgramStateManager;
-class SubRegionMap;
+class ScanReachableSymbols;
class StoreManager {
protected:
@@ -49,7 +49,7 @@ public:
virtual ~StoreManager() {}
/// Return the value bound to specified location in a given state.
- /// \param[in] state The analysis state.
+ /// \param[in] store The analysis state.
/// \param[in] loc The symbolic memory location.
/// \param[in] T An optional type that provides a hint indicating the
/// expected type of the returned value. This is used if the value is
@@ -58,12 +58,12 @@ public:
virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0;
/// Return a state with the specified value bound to the given location.
- /// \param[in] state The analysis state.
+ /// \param[in] store The analysis state.
/// \param[in] loc The symbolic memory location.
/// \param[in] val The value to bind to location \c loc.
- /// \return A pointer to a ProgramState object that contains the same bindings as
- /// \c state with the addition of having the value specified by \c val bound
- /// to the location given for \c loc.
+ /// \return A pointer to a ProgramState object that contains the same
+ /// bindings as \c state with the addition of having the value specified
+ /// by \c val bound to the location given for \c loc.
virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
virtual StoreRef BindDefault(Store store, const MemRegion *R, SVal V);
@@ -85,11 +85,6 @@ public:
/// used to query and manipulate MemRegion objects.
MemRegionManager& getRegionManager() { return MRMgr; }
- /// getSubRegionMap - Returns an opaque map object that clients can query
- /// to get the subregions of a given MemRegion object. It is the
- // caller's responsibility to 'delete' the returned map.
- virtual SubRegionMap *getSubRegionMap(Store store) = 0;
-
virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
}
@@ -120,7 +115,10 @@ public:
virtual SVal ArrayToPointer(Loc Array) = 0;
/// Evaluates DerivedToBase casts.
- virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType) = 0;
+ SVal evalDerivedToBase(SVal derived, const CastExpr *Cast);
+
+ /// Evaluates a derived-to-base cast through a single level of derivation.
+ virtual SVal evalDerivedToBase(SVal derived, QualType derivedPtrType) = 0;
/// \brief Evaluates C++ dynamic_cast cast.
/// The callback may result in the following 3 scenarios:
@@ -133,15 +131,6 @@ public:
virtual SVal evalDynamicCast(SVal base, QualType derivedPtrType,
bool &Failed) = 0;
- class CastResult {
- ProgramStateRef state;
- const MemRegion *region;
- public:
- ProgramStateRef getState() const { return state; }
- const MemRegion* getRegion() const { return region; }
- CastResult(ProgramStateRef s, const MemRegion* r = 0) : state(s), region(r){}
- };
-
const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T);
/// castRegion - Used by ExprEngine::VisitCast to handle casts from
@@ -176,8 +165,7 @@ public:
/// invalidate additional regions that may have changed based on accessing
/// the given regions. Optionally, invalidates non-static globals as well.
/// \param[in] store The initial store
- /// \param[in] Begin A pointer to the first region to invalidate.
- /// \param[in] End A pointer just past the last region to invalidate.
+ /// \param[in] Regions The regions to invalidate.
/// \param[in] E The current statement being evaluated. Used to conjure
/// symbols to mark the values of invalidated regions.
/// \param[in] Count The current block count. Used to conjure
@@ -186,7 +174,7 @@ public:
/// accessible. Pass \c NULL if this information will not be used.
/// \param[in] Call The call expression which will be used to determine which
/// globals should get invalidated.
- /// \param[in,out] Regions A vector to fill with any regions being
+ /// \param[in,out] Invalidated A vector to fill with any regions being
/// invalidated. This should include any regions explicitly invalidated
/// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used.
@@ -195,14 +183,20 @@ public:
const Expr *E, unsigned Count,
const LocationContext *LCtx,
InvalidatedSymbols &IS,
- const CallOrObjCMessage *Call,
+ const CallEvent *Call,
InvalidatedRegions *Invalidated) = 0;
/// enterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
- virtual StoreRef enterStackFrame(ProgramStateRef state,
- const LocationContext *callerCtx,
- const StackFrameContext *calleeCtx);
+ StoreRef enterStackFrame(Store store,
+ const CallEvent &Call,
+ const StackFrameContext *CalleeCtx);
+
+ /// Finds the transitive closure of symbols within the given region.
+ ///
+ /// Returns false if the visitor aborted the scan.
+ virtual bool scanReachableSymbols(Store S, const MemRegion *R,
+ ScanReachableSymbols &Visitor) = 0;
virtual void print(Store store, raw_ostream &Out,
const char* nl, const char *sep) = 0;
@@ -275,24 +269,6 @@ inline StoreRef &StoreRef::operator=(StoreRef const &newStore) {
return *this;
}
-// FIXME: Do we still need this?
-/// SubRegionMap - An abstract interface that represents a queryable map
-/// between MemRegion objects and their subregions.
-class SubRegionMap {
- virtual void anchor();
-public:
- virtual ~SubRegionMap() {}
-
- class Visitor {
- virtual void anchor();
- public:
- virtual ~Visitor() {}
- virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0;
- };
-
- virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0;
-};
-
// FIXME: Do we need to pass ProgramStateManager anymore?
StoreManager *CreateRegionStoreManager(ProgramStateManager& StMgr);
StoreManager *CreateFieldsOnlyRegionStoreManager(ProgramStateManager& StMgr);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index baf57d49060c..68b81f19a4fd 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -105,7 +105,7 @@ public:
const StoreManager::InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
- const CallOrObjCMessage *Call) = 0;
+ const CallEvent *Call) = 0;
inline ProgramStateRef
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index c7de7eff8df2..5d27f8654eb0 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -94,6 +94,8 @@ public:
return symbol_iterator(this);
}
static symbol_iterator symbol_end() { return symbol_iterator(); }
+
+ unsigned computeComplexity() const;
};
typedef const SymExpr* SymbolRef;
@@ -553,6 +555,7 @@ public:
BasicValueFactory &getBasicVals() { return BV; }
};
+/// \brief A class responsible for cleaning up unused symbols.
class SymbolReaper {
enum SymbolStatus {
NotProcessed,
@@ -569,21 +572,26 @@ class SymbolReaper {
RegionSetTy RegionRoots;
- const LocationContext *LCtx;
+ const StackFrameContext *LCtx;
const Stmt *Loc;
SymbolManager& SymMgr;
StoreRef reapedStore;
llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
public:
+ /// \brief Construct a reaper object, which removes everything which is not
+ /// live before we execute statement s in the given location context.
+ ///
+ /// If the statement is NULL, everything is this and parent contexts is
+ /// considered live.
SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr,
StoreManager &storeMgr)
- : LCtx(ctx), Loc(s), SymMgr(symmgr), reapedStore(0, storeMgr) {}
+ : LCtx(ctx->getCurrentStackFrame()), Loc(s), SymMgr(symmgr),
+ reapedStore(0, storeMgr) {}
~SymbolReaper() {}
const LocationContext *getLocationContext() const { return LCtx; }
- const Stmt *getCurrentStatement() const { return Loc; }
bool isLive(SymbolRef sym);
bool isLiveRegion(const MemRegion *region);
diff --git a/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h
new file mode 100644
index 000000000000..492ddd2b0078
--- /dev/null
+++ b/include/clang/Tooling/ArgumentsAdjusters.h
@@ -0,0 +1,59 @@
+//===--- ArgumentsAdjusters.h - Command line arguments adjuster -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares base abstract class ArgumentsAdjuster and its descendants.
+// These classes are intended to modify command line arguments obtained from
+// a compilation database before they are used to run a frontend action.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+#define LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+namespace tooling {
+
+/// \brief A sequence of command line arguments.
+typedef std::vector<std::string> CommandLineArguments;
+
+/// \brief Abstract interface for a command line adjusters.
+///
+/// This abstract interface describes a command line argument adjuster,
+/// which is responsible for command line arguments modification before
+/// the arguments are used to run a frontend action.
+class ArgumentsAdjuster {
+ virtual void anchor();
+public:
+ /// \brief Returns adjusted command line arguments.
+ ///
+ /// \param Args Input sequence of command line arguments.
+ ///
+ /// \returns Modified sequence of command line arguments.
+ virtual CommandLineArguments Adjust(const CommandLineArguments &Args) = 0;
+ virtual ~ArgumentsAdjuster() {
+ }
+};
+
+/// \brief Syntax check only command line adjuster.
+///
+/// This class implements ArgumentsAdjuster interface and converts input
+/// command line arguments to the "syntax check only" variant.
+class ClangSyntaxOnlyAdjuster : public ArgumentsAdjuster {
+ virtual CommandLineArguments Adjust(const CommandLineArguments &Args);
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+
diff --git a/include/clang/Tooling/CommandLineClangTool.h b/include/clang/Tooling/CommandLineClangTool.h
new file mode 100644
index 000000000000..c29c30236416
--- /dev/null
+++ b/include/clang/Tooling/CommandLineClangTool.h
@@ -0,0 +1,80 @@
+//===- CommandLineClangTool.h - command-line clang tools driver -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the CommandLineClangTool class used to run clang
+// tools as separate command-line applications with a consistent common
+// interface for handling compilation database and input files.
+//
+// It provides a common subset of command-line options, common algorithm
+// for locating a compilation database and source files, and help messages
+// for the basic command-line interface.
+//
+// It creates a CompilationDatabase, initializes a ClangTool and runs a
+// user-specified FrontendAction over all TUs in which the given files are
+// compiled.
+//
+// This class uses the Clang Tooling infrastructure, see
+// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+// for details on setting it up with LLVM source tree.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMANDLINECLANGTOOL_H
+#define LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMANDLINECLANGTOOL_H
+
+#include "llvm/Support/CommandLine.h"
+#include "clang/Tooling/CompilationDatabase.h"
+
+namespace clang {
+
+namespace tooling {
+
+class CompilationDatabase;
+class FrontendActionFactory;
+
+/// \brief A common driver for command-line Clang tools.
+///
+/// Parses a common subset of command-line arguments, locates and loads a
+/// compilation commands database, runs a tool with user-specified action. It
+/// also contains a help message for the common command-line options.
+/// An example of usage:
+/// @code
+/// int main(int argc, const char **argv) {
+/// CommandLineClangTool Tool;
+/// cl::extrahelp MoreHelp("\nMore help text...");
+/// Tool.initialize(argc, argv);
+/// return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>());
+/// }
+/// @endcode
+///
+class CommandLineClangTool {
+public:
+ /// Sets up command-line options and help messages.
+ /// Add your own help messages after constructing this tool.
+ CommandLineClangTool();
+
+ /// Parses command-line, initializes a compilation database.
+ /// This method exits program in case of error.
+ void initialize(int argc, const char **argv);
+
+ /// Runs a clang tool with an action created by \c ActionFactory.
+ int run(FrontendActionFactory *ActionFactory);
+
+private:
+ llvm::OwningPtr<CompilationDatabase> Compilations;
+ llvm::cl::opt<std::string> BuildPath;
+ llvm::cl::list<std::string> SourcePaths;
+ llvm::cl::extrahelp MoreHelp;
+};
+
+} // namespace tooling
+
+} // namespace clang
+
+#endif // LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMANDLINECLANGTOOL_H
diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h
index 625c8eced4b8..f78ffaed284c 100644
--- a/include/clang/Tooling/CompilationDatabase.h
+++ b/include/clang/Tooling/CompilationDatabase.h
@@ -81,6 +81,20 @@ public:
static CompilationDatabase *loadFromDirectory(StringRef BuildDirectory,
std::string &ErrorMessage);
+ /// \brief Tries to detect a compilation database location and load it.
+ ///
+ /// Looks for a compilation database in all parent paths of file 'SourceFile'
+ /// by calling loadFromDirectory.
+ static CompilationDatabase *autoDetectFromSource(StringRef SourceFile,
+ std::string &ErrorMessage);
+
+ /// \brief Tries to detect a compilation database location and load it.
+ ///
+ /// Looks for a compilation database in directory 'SourceDir' and all
+ /// its parent paths by calling loadFromDirectory.
+ static CompilationDatabase *autoDetectFromDirectory(StringRef SourceDir,
+ std::string &ErrorMessage);
+
/// \brief Returns all compile commands in which the specified file was
/// compiled.
///
@@ -92,6 +106,9 @@ public:
/// lines for a.cc and b.cc and only the first command line for t.cc.
virtual std::vector<CompileCommand> getCompileCommands(
StringRef FilePath) const = 0;
+
+ /// \brief Returns the list of all files available in the compilation database.
+ virtual std::vector<std::string> getAllFiles() const = 0;
};
/// \brief A compilation database that returns a single compile command line.
@@ -141,6 +158,11 @@ public:
virtual std::vector<CompileCommand> getCompileCommands(
StringRef FilePath) const;
+ /// \brief Returns the list of all files available in the compilation database.
+ ///
+ /// Note: This is always an empty list for the fixed compilation database.
+ virtual std::vector<std::string> getAllFiles() const;
+
private:
/// This is built up to contain a single entry vector to be returned from
/// getCompileCommands after adding the positional argument.
@@ -187,6 +209,11 @@ public:
virtual std::vector<CompileCommand> getCompileCommands(
StringRef FilePath) const;
+ /// \brief Returns the list of all files available in the compilation database.
+ ///
+ /// These are the 'file' entries of the JSON objects.
+ virtual std::vector<std::string> getAllFiles() const;
+
private:
/// \brief Constructs a JSON compilation database on a memory buffer.
JSONCompilationDatabase(llvm::MemoryBuffer *Database)
@@ -215,4 +242,3 @@ private:
} // end namespace clang
#endif // LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H
-
diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h
new file mode 100644
index 000000000000..0e42a0ec64fc
--- /dev/null
+++ b/include/clang/Tooling/Refactoring.h
@@ -0,0 +1,151 @@
+//===--- Refactoring.h - Framework for clang refactoring tools --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Interfaces supporting refactorings that span multiple translation units.
+// While single translation unit refactorings are supported via the Rewriter,
+// when refactoring multiple translation units changes must be stored in a
+// SourceManager independent form, duplicate changes need to be removed, and
+// all changes must be applied at once at the end of the refactoring so that
+// the code is always parseable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_H
+#define LLVM_CLANG_TOOLING_REFACTORING_H
+
+#include "llvm/ADT/StringRef.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Tooling/Tooling.h"
+#include <set>
+#include <string>
+
+namespace clang {
+
+class Rewriter;
+class SourceLocation;
+
+namespace tooling {
+
+/// \brief A text replacement.
+///
+/// Represents a SourceManager independent replacement of a range of text in a
+/// specific file.
+class Replacement {
+public:
+ /// \brief Creates an invalid (not applicable) replacement.
+ Replacement();
+
+ /// \brief Creates a replacement of the range [Offset, Offset+Length) in
+ /// FilePath with ReplacementText.
+ ///
+ /// \param FilePath A source file accessible via a SourceManager.
+ /// \param Offset The byte offset of the start of the range in the file.
+ /// \param Length The length of the range in bytes.
+ Replacement(llvm::StringRef FilePath, unsigned Offset,
+ unsigned Length, llvm::StringRef ReplacementText);
+
+ /// \brief Creates a Replacement of the range [Start, Start+Length) with
+ /// ReplacementText.
+ Replacement(SourceManager &Sources, SourceLocation Start, unsigned Length,
+ llvm::StringRef ReplacementText);
+
+ /// \brief Creates a Replacement of the given range with ReplacementText.
+ Replacement(SourceManager &Sources, const CharSourceRange &Range,
+ llvm::StringRef ReplacementText);
+
+ /// \brief Creates a Replacement of the node with ReplacementText.
+ template <typename Node>
+ Replacement(SourceManager &Sources, const Node &NodeToReplace,
+ llvm::StringRef ReplacementText);
+
+ /// \brief Returns whether this replacement can be applied to a file.
+ ///
+ /// Only replacements that are in a valid file can be applied.
+ bool isApplicable() const;
+
+ /// \brief Accessors.
+ /// @{
+ StringRef getFilePath() const { return FilePath; }
+ unsigned getOffset() const { return Offset; }
+ unsigned getLength() const { return Length; }
+ /// @}
+
+ /// \brief Applies the replacement on the Rewriter.
+ bool apply(Rewriter &Rewrite) const;
+
+ /// \brief Returns a human readable string representation.
+ std::string toString() const;
+
+ /// \brief Comparator to be able to use Replacement in std::set for uniquing.
+ class Less {
+ public:
+ bool operator()(const Replacement &R1, const Replacement &R2) const;
+ };
+
+ private:
+ void setFromSourceLocation(SourceManager &Sources, SourceLocation Start,
+ unsigned Length, llvm::StringRef ReplacementText);
+ void setFromSourceRange(SourceManager &Sources, const CharSourceRange &Range,
+ llvm::StringRef ReplacementText);
+
+ std::string FilePath;
+ unsigned Offset;
+ unsigned Length;
+ std::string ReplacementText;
+};
+
+/// \brief A set of Replacements.
+/// FIXME: Change to a vector and deduplicate in the RefactoringTool.
+typedef std::set<Replacement, Replacement::Less> Replacements;
+
+/// \brief Apply all replacements on the Rewriter.
+///
+/// If at least one Apply returns false, ApplyAll returns false. Every
+/// Apply will be executed independently of the result of other
+/// Apply operations.
+bool applyAllReplacements(Replacements &Replaces, Rewriter &Rewrite);
+
+/// \brief A tool to run refactorings.
+///
+/// This is a refactoring specific version of \see ClangTool.
+/// All text replacements added to getReplacements() during the run of the
+/// tool will be applied and saved after all translation units have been
+/// processed.
+class RefactoringTool {
+public:
+ /// \see ClangTool::ClangTool.
+ RefactoringTool(const CompilationDatabase &Compilations,
+ ArrayRef<std::string> SourcePaths);
+
+ /// \brief Returns a set of replacements. All replacements added during the
+ /// run of the tool will be applied after all translation units have been
+ /// processed.
+ Replacements &getReplacements();
+
+ /// \see ClangTool::run.
+ int run(FrontendActionFactory *ActionFactory);
+
+private:
+ ClangTool Tool;
+ Replacements Replace;
+};
+
+template <typename Node>
+Replacement::Replacement(SourceManager &Sources, const Node &NodeToReplace,
+ llvm::StringRef ReplacementText) {
+ const CharSourceRange Range =
+ CharSourceRange::getTokenRange(NodeToReplace->getSourceRange());
+ setFromSourceRange(Sources, Range, ReplacementText);
+}
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // end namespace LLVM_CLANG_TOOLING_REFACTORING_H
+
diff --git a/include/clang/Tooling/RefactoringCallbacks.h b/include/clang/Tooling/RefactoringCallbacks.h
new file mode 100644
index 000000000000..c500f356a4d2
--- /dev/null
+++ b/include/clang/Tooling/RefactoringCallbacks.h
@@ -0,0 +1,90 @@
+//===--- RefactoringCallbacks.h - Structural query framework ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides callbacks to make common kinds of refactorings easy.
+//
+// The general idea is to construct a matcher expression that describes a
+// subtree match on the AST and then replace the corresponding source code
+// either by some specific text or some other AST node.
+//
+// Example:
+// int main(int argc, char **argv) {
+// ClangTool Tool(argc, argv);
+// MatchFinder Finder;
+// ReplaceStmtWithText Callback("integer", "42");
+// Finder.AddMatcher(id("integer", expression(integerLiteral())), Callback);
+// return Tool.run(newFrontendActionFactory(&Finder));
+// }
+//
+// This will replace all integer literals with "42".
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_CALLBACKS_H
+#define LLVM_CLANG_TOOLING_REFACTORING_CALLBACKS_H
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Refactoring.h"
+
+namespace clang {
+namespace tooling {
+
+/// \brief Base class for RefactoringCallbacks.
+///
+/// Collects \c tooling::Replacements while running.
+class RefactoringCallback : public ast_matchers::MatchFinder::MatchCallback {
+public:
+ RefactoringCallback();
+ Replacements &getReplacements();
+
+protected:
+ Replacements Replace;
+};
+
+/// \brief Replace the text of the statement bound to \c FromId with the text in
+/// \c ToText.
+class ReplaceStmtWithText : public RefactoringCallback {
+public:
+ ReplaceStmtWithText(StringRef FromId, StringRef ToText);
+ virtual void run(const ast_matchers::MatchFinder::MatchResult &Result);
+
+private:
+ std::string FromId;
+ std::string ToText;
+};
+
+/// \brief Replace the text of the statement bound to \c FromId with the text of
+/// the statement bound to \c ToId.
+class ReplaceStmtWithStmt : public RefactoringCallback {
+public:
+ ReplaceStmtWithStmt(StringRef FromId, StringRef ToId);
+ virtual void run(const ast_matchers::MatchFinder::MatchResult &Result);
+
+private:
+ std::string FromId;
+ std::string ToId;
+};
+
+/// \brief Replace an if-statement bound to \c Id with the outdented text of its
+/// body, choosing the consequent or the alternative based on whether
+/// \c PickTrueBranch is true.
+class ReplaceIfStmtWithItsBody : public RefactoringCallback {
+public:
+ ReplaceIfStmtWithItsBody(StringRef Id, bool PickTrueBranch);
+ virtual void run(const ast_matchers::MatchFinder::MatchResult &Result);
+
+private:
+ std::string Id;
+ const bool PickTrueBranch;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTORING_CALLBACKS_H
diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
index 868eae306899..e06705f0279b 100644
--- a/include/clang/Tooling/Tooling.h
+++ b/include/clang/Tooling/Tooling.h
@@ -15,7 +15,7 @@
// all TUs in which the given files are compiled.
//
// It is also possible to run a FrontendAction over a snippet of code by
-// calling runSyntaxOnlyToolOnCode, which is useful for unit testing.
+// calling runToolOnCode, which is useful for unit testing.
//
// Applications that need more fine grained control over how to run
// multiple FrontendActions over code can use ToolInvocation.
@@ -35,6 +35,9 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Util.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/ArgumentsAdjusters.h"
+#include "clang/Tooling/CompilationDatabase.h"
#include <string>
#include <vector>
@@ -50,8 +53,6 @@ class FrontendAction;
namespace tooling {
-class CompilationDatabase;
-
/// \brief Interface to generate clang::FrontendActions.
class FrontendActionFactory {
public:
@@ -74,18 +75,19 @@ template <typename T>
FrontendActionFactory *newFrontendActionFactory();
/// \brief Returns a new FrontendActionFactory for any type that provides an
-/// implementation of newFrontendAction().
+/// implementation of newASTConsumer().
///
-/// FactoryT must implement: FrontendAction *newFrontendAction().
+/// FactoryT must implement: ASTConsumer *newASTConsumer().
///
/// Example:
-/// struct ProvidesFrontendActions {
-/// FrontendAction *newFrontendAction();
+/// struct ProvidesASTConsumers {
+/// clang::ASTConsumer *newASTConsumer();
/// } Factory;
/// FrontendActionFactory *FactoryAdapter =
/// newFrontendActionFactory(&Factory);
template <typename FactoryT>
-FrontendActionFactory *newFrontendActionFactory(FactoryT *ActionFactory);
+inline FrontendActionFactory *newFrontendActionFactory(
+ FactoryT *ConsumerFactory);
/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
///
@@ -102,7 +104,10 @@ class ToolInvocation {
public:
/// \brief Create a tool invocation.
///
- /// \param CommandLine The command line arguments to clang.
+ /// \param CommandLine The command line arguments to clang. Note that clang
+ /// uses its binary name (CommandLine[0]) to locate its builtin headers.
+ /// Callers have to ensure that they are installed in a compatible location
+ /// (see clang driver implementation) or mapped in via mapVirtualFile.
/// \param ToolAction The action to be executed. Class takes ownership.
/// \param Files The FileManager used for the execution. Class does not take
/// ownership.
@@ -126,8 +131,7 @@ class ToolInvocation {
bool runInvocation(const char *BinaryName,
clang::driver::Compilation *Compilation,
clang::CompilerInvocation *Invocation,
- const clang::driver::ArgStringList &CC1Args,
- clang::FrontendAction *ToolAction);
+ const clang::driver::ArgStringList &CC1Args);
std::vector<std::string> CommandLine;
llvm::OwningPtr<FrontendAction> ToolAction;
@@ -139,6 +143,10 @@ class ToolInvocation {
/// \brief Utility to run a FrontendAction over a set of files.
///
/// This class is written to be usable for command line utilities.
+/// By default the class uses ClangSyntaxOnlyAdjuster to modify
+/// command line arguments before the arguments are used to run
+/// a frontend action. One could install another command line
+/// arguments adjuster by call setArgumentsAdjuster() method.
class ClangTool {
public:
/// \brief Constructs a clang tool to run over a list of files.
@@ -156,6 +164,11 @@ class ClangTool {
/// \param Content A null terminated buffer of the file's content.
void mapVirtualFile(StringRef FilePath, StringRef Content);
+ /// \brief Install command line arguments adjuster.
+ ///
+ /// \param Adjuster Command line arguments adjuster.
+ void setArgumentsAdjuster(ArgumentsAdjuster *Adjuster);
+
/// Runs a frontend action over all files specified in the command line.
///
/// \param ActionFactory Factory generating the frontend actions. The function
@@ -169,13 +182,14 @@ class ClangTool {
FileManager &getFiles() { return Files; }
private:
- // We store command lines as pair (file name, command line).
- typedef std::pair< std::string, std::vector<std::string> > CommandLine;
- std::vector<CommandLine> CommandLines;
+ // We store compile commands as pair (file name, compile command).
+ std::vector< std::pair<std::string, CompileCommand> > CompileCommands;
FileManager Files;
// Contains a list of pairs (<file name>, <file content>).
std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
+
+ llvm::OwningPtr<ArgumentsAdjuster> ArgsAdjuster;
};
template <typename T>
@@ -189,25 +203,54 @@ FrontendActionFactory *newFrontendActionFactory() {
}
template <typename FactoryT>
-FrontendActionFactory *newFrontendActionFactory(FactoryT *ActionFactory) {
+inline FrontendActionFactory *newFrontendActionFactory(
+ FactoryT *ConsumerFactory) {
class FrontendActionFactoryAdapter : public FrontendActionFactory {
public:
- explicit FrontendActionFactoryAdapter(FactoryT *ActionFactory)
- : ActionFactory(ActionFactory) {}
+ explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory)
+ : ConsumerFactory(ConsumerFactory) {}
virtual clang::FrontendAction *create() {
- return ActionFactory->newFrontendAction();
+ return new ConsumerFactoryAdaptor(ConsumerFactory);
}
private:
- FactoryT *ActionFactory;
+ class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
+ public:
+ ConsumerFactoryAdaptor(FactoryT *ConsumerFactory)
+ : ConsumerFactory(ConsumerFactory) {}
+
+ clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &,
+ llvm::StringRef) {
+ return ConsumerFactory->newASTConsumer();
+ }
+
+ private:
+ FactoryT *ConsumerFactory;
+ };
+ FactoryT *ConsumerFactory;
};
- return new FrontendActionFactoryAdapter(ActionFactory);
+ return new FrontendActionFactoryAdapter(ConsumerFactory);
}
+/// \brief Returns the absolute path of \c File, by prepending it with
+/// the current directory if \c File is not absolute.
+///
+/// Otherwise returns \c File.
+/// If 'File' starts with "./", the returned path will not contain the "./".
+/// Otherwise, the returned path will contain the literal path-concatenation of
+/// the current directory and \c File.
+///
+/// The difference to llvm::sys::fs::make_absolute is that we prefer
+/// ::getenv("PWD") if available.
+/// FIXME: Make this functionality available from llvm::sys::fs and delete
+/// this function.
+///
+/// \param File Either an absolute or relative path.
+std::string getAbsolutePath(StringRef File);
+
} // end namespace tooling
} // end namespace clang
#endif // LLVM_CLANG_TOOLING_TOOLING_H
-