diff options
author | dim <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 |
commit | 6148c19c738a92f344008aa3f88f4e008bada0ee (patch) | |
tree | d4426858455f04d0d8c25a2f9eb9ea5582ffe1b6 /contrib/llvm/tools/clang/include | |
parent | 2c8643c6396b0a3db33430cf9380e70bbb9efce0 (diff) | |
parent | 173a4f43a911175643bda81ee675e8d9269056ea (diff) | |
download | FreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.zip FreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.tar.gz |
Merge clang 3.5.0 release from ^/vendor/clang/dist, resolve conflicts,
and preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/tools/clang/include')
307 files changed, 25619 insertions, 10258 deletions
diff --git a/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h b/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h new file mode 100644 index 0000000..ed3e8d9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h @@ -0,0 +1,148 @@ +/*==-- clang-c/BuildSystem.h - Utilities for use by build systems -*- 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 various utilities for use by build systems. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef CLANG_C_BUILD_SYSTEM_H +#define CLANG_C_BUILD_SYSTEM_H + +#include "clang-c/Platform.h" +#include "clang-c/CXErrorCode.h" +#include "clang-c/CXString.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup BUILD_SYSTEM Build system utilities + * @{ + */ + +/** + * \brief Return the timestamp for use with Clang's + * \c -fbuild-session-timestamp= option. + */ +CINDEX_LINKAGE unsigned long long clang_getBuildSessionTimestamp(void); + +/** + * \brief Object encapsulating information about overlaying virtual + * file/directories over the real file system. + */ +typedef struct CXVirtualFileOverlayImpl *CXVirtualFileOverlay; + +/** + * \brief Create a \c CXVirtualFileOverlay object. + * Must be disposed with \c clang_VirtualFileOverlay_dispose(). + * + * \param options is reserved, always pass 0. + */ +CINDEX_LINKAGE CXVirtualFileOverlay +clang_VirtualFileOverlay_create(unsigned options); + +/** + * \brief Map an absolute virtual file path to an absolute real one. + * The virtual path must be canonicalized (not contain "."/".."). + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_VirtualFileOverlay_addFileMapping(CXVirtualFileOverlay, + const char *virtualPath, + const char *realPath); + +/** + * \brief Set the case sensitivity for the \c CXVirtualFileOverlay object. + * The \c CXVirtualFileOverlay object is case-sensitive by default, this + * option can be used to override the default. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_VirtualFileOverlay_setCaseSensitivity(CXVirtualFileOverlay, + int caseSensitive); + +/** + * \brief Write out the \c CXVirtualFileOverlay object to a char buffer. + * + * \param options is reserved, always pass 0. + * \param out_buffer_ptr pointer to receive the buffer pointer, which should be + * disposed using \c free(). + * \param out_buffer_size pointer to receive the buffer size. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay, unsigned options, + char **out_buffer_ptr, + unsigned *out_buffer_size); + +/** + * \brief Dispose a \c CXVirtualFileOverlay object. + */ +CINDEX_LINKAGE void clang_VirtualFileOverlay_dispose(CXVirtualFileOverlay); + +/** + * \brief Object encapsulating information about a module.map file. + */ +typedef struct CXModuleMapDescriptorImpl *CXModuleMapDescriptor; + +/** + * \brief Create a \c CXModuleMapDescriptor object. + * Must be disposed with \c clang_ModuleMapDescriptor_dispose(). + * + * \param options is reserved, always pass 0. + */ +CINDEX_LINKAGE CXModuleMapDescriptor +clang_ModuleMapDescriptor_create(unsigned options); + +/** + * \brief Sets the framework module name that the module.map describes. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_ModuleMapDescriptor_setFrameworkModuleName(CXModuleMapDescriptor, + const char *name); + +/** + * \brief Sets the umbrealla header name that the module.map describes. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_ModuleMapDescriptor_setUmbrellaHeader(CXModuleMapDescriptor, + const char *name); + +/** + * \brief Write out the \c CXModuleMapDescriptor object to a char buffer. + * + * \param options is reserved, always pass 0. + * \param out_buffer_ptr pointer to receive the buffer pointer, which should be + * disposed using \c free(). + * \param out_buffer_size pointer to receive the buffer size. + * \returns 0 for success, non-zero to indicate an error. + */ +CINDEX_LINKAGE enum CXErrorCode +clang_ModuleMapDescriptor_writeToBuffer(CXModuleMapDescriptor, unsigned options, + char **out_buffer_ptr, + unsigned *out_buffer_size); + +/** + * \brief Dispose a \c CXModuleMapDescriptor object. + */ +CINDEX_LINKAGE void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* CLANG_C_BUILD_SYSTEM_H */ + diff --git a/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h b/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h new file mode 100644 index 0000000..a026c95 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h @@ -0,0 +1,64 @@ +/*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- 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 CXErrorCode enumerators. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef CLANG_C_CXERRORCODE_H +#define CLANG_C_CXERRORCODE_H + +#include "clang-c/Platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Error codes returned by libclang routines. + * + * Zero (\c CXError_Success) is the only error code indicating success. Other + * error codes, including not yet assigned non-zero values, indicate errors. + */ +enum CXErrorCode { + /** + * \brief No error. + */ + CXError_Success = 0, + + /** + * \brief A generic error code, no further details are available. + * + * Errors of this kind can get their own specific error codes in future + * libclang versions. + */ + CXError_Failure = 1, + + /** + * \brief libclang crashed while performing the requested operation. + */ + CXError_Crashed = 2, + + /** + * \brief The function detected that the arguments violate the function + * contract. + */ + CXError_InvalidArguments = 3, + + /** + * \brief An AST deserialization error has occurred. + */ + CXError_ASTReadError = 4 +}; + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/contrib/llvm/tools/clang/include/clang-c/CXString.h b/contrib/llvm/tools/clang/include/clang-c/CXString.h index 592c4dc..cf198cb 100644 --- a/contrib/llvm/tools/clang/include/clang-c/CXString.h +++ b/contrib/llvm/tools/clang/include/clang-c/CXString.h @@ -31,7 +31,7 @@ extern "C" { * \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. + * the ownership of that string might differ 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. */ diff --git a/contrib/llvm/tools/clang/include/clang-c/Documentation.h b/contrib/llvm/tools/clang/include/clang-c/Documentation.h new file mode 100644 index 0000000..ad2da07 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang-c/Documentation.h @@ -0,0 +1,554 @@ +/*==-- clang-c/Documentation.h - Utilities for comment processing -*- 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 supplementary interface for inspecting *| +|* documentation comments. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef CLANG_C_DOCUMENTATION_H +#define CLANG_C_DOCUMENTATION_H + +#include "clang-c/Index.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup CINDEX_COMMENT Comment introspection + * + * The routines in this group provide access to information in documentation + * comments. These facilities are distinct from the core and may be subject to + * their own schedule of stability and deprecation. + * + * @{ + */ + +/** + * \brief A parsed comment. + */ +typedef struct { + const void *ASTNode; + CXTranslationUnit TranslationUnit; +} CXComment; + +/** + * \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); + +/** + * \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). + * + * For example: \\param [in] ParamName description. + */ + CXComment_ParamCommand = 7, + + /** + * \brief A \\tparam command that describes a template parameter (name and + * description). + * + * 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 ChildIdx child 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, <br />). + */ +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 Comment a \c CXComment_FullComment AST node. + * + * \returns string containing an XML document. + */ +CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment); + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* CLANG_C_DOCUMENTATION_H */ + diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h index 95d54c2..f69f567 100644 --- a/contrib/llvm/tools/clang/include/clang-c/Index.h +++ b/contrib/llvm/tools/clang/include/clang-c/Index.h @@ -19,7 +19,9 @@ #include <time.h> #include "clang-c/Platform.h" +#include "clang-c/CXErrorCode.h" #include "clang-c/CXString.h" +#include "clang-c/BuildSystem.h" /** * \brief The version constants for the libclang API. @@ -30,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 20 +#define CINDEX_VERSION_MINOR 27 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -599,6 +601,32 @@ CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range); CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range); /** + * \brief Identifies an array of ranges. + */ +typedef struct { + /** \brief The number of ranges in the \c ranges array. */ + unsigned count; + /** + * \brief An array of \c CXSourceRanges. + */ + CXSourceRange *ranges; +} CXSourceRangeList; + +/** + * \brief Retrieve all ranges that were skipped by the preprocessor. + * + * The preprocessor will skip lines when they are surrounded by an + * if/ifdef/ifndef directive whose condition does not evaluate to true. + */ +CINDEX_LINKAGE CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit tu, + CXFile file); + +/** + * \brief Destroy the given \c CXSourceRangeList. + */ +CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges); + +/** * @} */ @@ -1050,10 +1078,27 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( struct CXUnsavedFile *unsaved_files); /** - * \brief Create a translation unit from an AST file (-emit-ast). + * \brief Same as \c clang_createTranslationUnit2, but returns + * the \c CXTranslationUnit instead of an error code. In case of an error this + * routine returns a \c NULL \c CXTranslationUnit, without further detailed + * error codes. */ -CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, - const char *ast_filename); +CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit( + CXIndex CIdx, + const char *ast_filename); + +/** + * \brief Create a translation unit from an AST file (\c -emit-ast). + * + * \param[out] out_TU A non-NULL pointer to store the created + * \c CXTranslationUnit. + * + * \returns Zero on success, otherwise returns an error code. + */ +CINDEX_LINKAGE enum CXErrorCode clang_createTranslationUnit2( + CXIndex CIdx, + const char *ast_filename, + CXTranslationUnit *out_TU); /** * \brief Flags that control the creation of translation units. @@ -1167,7 +1212,22 @@ enum CXTranslationUnit_Flags { * set of optimizations enabled may change from one version to the next. */ CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void); - + +/** + * \brief Same as \c clang_parseTranslationUnit2, but returns + * the \c CXTranslationUnit instead of an error code. In case of an error this + * routine returns a \c NULL \c CXTranslationUnit, without further detailed + * error codes. + */ +CINDEX_LINKAGE CXTranslationUnit +clang_parseTranslationUnit(CXIndex CIdx, + const char *source_filename, + const char *const *command_line_args, + int num_command_line_args, + struct CXUnsavedFile *unsaved_files, + unsigned num_unsaved_files, + unsigned options); + /** * \brief Parse the given source file and the translation unit corresponding * to that file. @@ -1182,7 +1242,7 @@ CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void); * associated. * * \param source_filename The name of the source file to load, or NULL if the - * source file is included in \p command_line_args. + * source file is included in \c command_line_args. * * \param command_line_args The command-line arguments that would be * passed to the \c clang executable if it were being invoked out-of-process. @@ -1191,7 +1251,7 @@ CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void); * '-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. + * \c command_line_args. * * \param unsaved_files the files that have not yet been saved to disk * but may be required for parsing, including the contents of @@ -1206,18 +1266,22 @@ CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void); * is managed but not its compilation. This should be a bitwise OR of the * CXTranslationUnit_XXX flags. * - * \returns A new translation unit describing the parsed code and containing - * any diagnostics produced by the compiler. If there is a failure from which - * the compiler cannot recover, returns NULL. + * \param[out] out_TU A non-NULL pointer to store the created + * \c CXTranslationUnit, describing the parsed code and containing any + * diagnostics produced by the compiler. + * + * \returns Zero on success, otherwise returns an error code. */ -CINDEX_LINKAGE CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx, - const char *source_filename, - const char * const *command_line_args, - int num_command_line_args, - struct CXUnsavedFile *unsaved_files, - unsigned num_unsaved_files, - unsigned options); - +CINDEX_LINKAGE enum CXErrorCode +clang_parseTranslationUnit2(CXIndex CIdx, + const char *source_filename, + const char *const *command_line_args, + int num_command_line_args, + struct CXUnsavedFile *unsaved_files, + unsigned num_unsaved_files, + unsigned options, + CXTranslationUnit *out_TU); + /** * \brief Flags that control how translation units are saved. * @@ -1369,10 +1433,11 @@ CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU); * The function \c clang_defaultReparseOptions() produces a default set of * options recommended for most uses, based on the translation unit. * - * \returns 0 if the sources could be reparsed. A non-zero value will be + * \returns 0 if the sources could be reparsed. A non-zero error code will be * returned if reparsing was impossible, such that the translation unit is - * invalid. In such cases, the only valid call for \p TU is - * \c clang_disposeTranslationUnit(TU). + * invalid. In such cases, the only valid call for \c TU is + * \c clang_disposeTranslationUnit(TU). The error codes returned by this + * routine are described by the \c CXErrorCode enum. */ CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU, unsigned num_unsaved_files, @@ -1669,7 +1734,7 @@ enum CXCursorKind { /** * \brief An expression that refers to some value declaration, such - * as a function, varible, or enumerator. + * as a function, variable, or enumerator. */ CXCursor_DeclRefExpr = 101, @@ -1907,7 +1972,7 @@ enum CXCursorKind { */ CXCursor_ObjCBoolLiteralExpr = 145, - /** \brief Represents the "self" expression in a ObjC method. + /** \brief Represents the "self" expression in an Objective-C method. */ CXCursor_ObjCSelfExpr = 146, @@ -2070,7 +2135,67 @@ enum CXCursorKind { */ CXCursor_OMPParallelDirective = 232, - CXCursor_LastStmt = CXCursor_OMPParallelDirective, + /** \brief OpenMP simd directive. + */ + CXCursor_OMPSimdDirective = 233, + + /** \brief OpenMP for directive. + */ + CXCursor_OMPForDirective = 234, + + /** \brief OpenMP sections directive. + */ + CXCursor_OMPSectionsDirective = 235, + + /** \brief OpenMP section directive. + */ + CXCursor_OMPSectionDirective = 236, + + /** \brief OpenMP single directive. + */ + CXCursor_OMPSingleDirective = 237, + + /** \brief OpenMP parallel for directive. + */ + CXCursor_OMPParallelForDirective = 238, + + /** \brief OpenMP parallel sections directive. + */ + CXCursor_OMPParallelSectionsDirective = 239, + + /** \brief OpenMP task directive. + */ + CXCursor_OMPTaskDirective = 240, + + /** \brief OpenMP master directive. + */ + CXCursor_OMPMasterDirective = 241, + + /** \brief OpenMP critical directive. + */ + CXCursor_OMPCriticalDirective = 242, + + /** \brief OpenMP taskyield directive. + */ + CXCursor_OMPTaskyieldDirective = 243, + + /** \brief OpenMP barrier directive. + */ + CXCursor_OMPBarrierDirective = 244, + + /** \brief OpenMP taskwait directive. + */ + CXCursor_OMPTaskwaitDirective = 245, + + /** \brief OpenMP flush directive. + */ + CXCursor_OMPFlushDirective = 246, + + /** \brief Windows Structured Exception Handling's leave statement. + */ + CXCursor_SEHLeaveStmt = 247, + + CXCursor_LastStmt = CXCursor_SEHLeaveStmt, /** * \brief Cursor that represents the translation unit itself. @@ -2096,8 +2221,15 @@ enum CXCursorKind { CXCursor_AnnotateAttr = 406, CXCursor_AsmLabelAttr = 407, CXCursor_PackedAttr = 408, - CXCursor_LastAttr = CXCursor_PackedAttr, - + CXCursor_PureAttr = 409, + CXCursor_ConstAttr = 410, + CXCursor_NoDuplicateAttr = 411, + CXCursor_CUDAConstantAttr = 412, + CXCursor_CUDADeviceAttr = 413, + CXCursor_CUDAGlobalAttr = 414, + CXCursor_CUDAHostAttr = 415, + CXCursor_LastAttr = CXCursor_CUDAHostAttr, + /* Preprocessing */ CXCursor_PreprocessingDirective = 500, CXCursor_MacroDefinition = 501, @@ -2141,14 +2273,6 @@ typedef struct { } CXCursor; /** - * \brief A comment AST node. - */ -typedef struct { - const void *ASTNode; - CXTranslationUnit TranslationUnit; -} CXComment; - -/** * \defgroup CINDEX_CURSOR_MANIP Cursor manipulations * * @{ @@ -2369,7 +2493,7 @@ clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability); /** * \brief Describe the "language" of the entity referred to by a cursor. */ -CINDEX_LINKAGE enum CXLanguageKind { +enum CXLanguageKind { CXLanguage_Invalid = 0, CXLanguage_C, CXLanguage_ObjC, @@ -2435,10 +2559,10 @@ CINDEX_LINKAGE unsigned clang_CXCursorSet_insert(CXCursorSet cset, * void C::f() { } * \endcode * - * In the out-of-line definition of \c C::f, the semantic parent is the + * In the out-of-line definition of \c C::f, the semantic parent is * the class \c C, of which this function is a member. The lexical parent is * the place where the declaration actually occurs in the source code; in this - * case, the definition occurs in the translation unit. In general, the + * case, the definition occurs in the translation unit. In general, the * lexical parent for a given entity can change without affecting the semantics * of the program, and the lexical parent of different declarations of the * same entity may be different. Changing the semantic parent of a declaration, @@ -2470,10 +2594,10 @@ CINDEX_LINKAGE CXCursor clang_getCursorSemanticParent(CXCursor cursor); * void C::f() { } * \endcode * - * In the out-of-line definition of \c C::f, the semantic parent is the + * In the out-of-line definition of \c C::f, the semantic parent is * the class \c C, of which this function is a member. The lexical parent is * the place where the declaration actually occurs in the source code; in this - * case, the definition occurs in the translation unit. In general, the + * case, the definition occurs in the translation unit. In general, the * lexical parent for a given entity can change without affecting the semantics * of the program, and the lexical parent of different declarations of the * same entity may be different. Changing the semantic parent of a declaration, @@ -2598,7 +2722,7 @@ CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor); * * The extent of a cursor starts with the file/line/column pointing at the * first character within the source construct that the cursor refers to and - * ends with the last character withinin that source construct. For a + * ends with the last character within that source construct. For a * declaration, the extent covers the declaration itself. For a reference, * the extent covers the location of the reference (e.g., where the referenced * entity was actually used). @@ -2620,7 +2744,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor); */ enum CXTypeKind { /** - * \brief Reprents an invalid type (e.g., where no type is available). + * \brief Represents an invalid type (e.g., where no type is available). */ CXType_Invalid = 0, @@ -2854,14 +2978,14 @@ CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K); CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T); /** - * \brief Retrieve the result type associated with a function type. + * \brief Retrieve the return type associated with a function type. * * If a non-function type is passed in, an invalid type is returned. */ CINDEX_LINKAGE CXType clang_getResultType(CXType T); /** - * \brief Retrieve the number of non-variadic arguments associated with a + * \brief Retrieve the number of non-variadic parameters associated with a * function type. * * If a non-function type is passed in, -1 is returned. @@ -2869,7 +2993,7 @@ CINDEX_LINKAGE CXType clang_getResultType(CXType T); CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); /** - * \brief Retrieve the type of an argument of a function type. + * \brief Retrieve the type of a parameter 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. @@ -2882,7 +3006,7 @@ CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i); CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T); /** - * \brief Retrieve the result type associated with a given cursor. + * \brief Retrieve the return type associated with a given cursor. * * This only returns a valid type if the cursor refers to a function or method. */ @@ -3012,6 +3136,24 @@ enum CXRefQualifierKind { }; /** + * \brief Returns the number of template arguments for given class template + * specialization, or -1 if type \c T is not a class template specialization. + * + * Variadic argument packs count as only one argument, and can not be inspected + * further. + */ +CINDEX_LINKAGE int clang_Type_getNumTemplateArguments(CXType T); + +/** + * \brief Returns the type template argument of a template class specialization + * at given index. + * + * This function only returns template type arguments and does not handle + * template template arguments or variadic packs. + */ +CINDEX_LINKAGE CXType clang_Type_getTemplateArgumentAsType(CXType T, unsigned i); + +/** * \brief Retrieve the ref-qualifier kind of a function or method. * * The ref-qualifier is returned for C++ functions or methods. For other types @@ -3274,8 +3416,8 @@ CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor); /** * \brief Retrieve a range for a piece that forms the cursors spelling name. * Most of the times there is only one range for the complete spelling but for - * objc methods and objc message expressions, there are multiple pieces for each - * selector identifier. + * Objective-C methods and Objective-C message expressions, there are multiple + * pieces for each selector identifier. * * \param pieceIndex the index of the spelling name piece. If this is greater * than the actual number of pieces, it will return a NULL (invalid) range. @@ -3371,25 +3513,25 @@ 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. + * \brief If the cursor points to a selector identifier in an Objective-C + * method or message expression, this returns the selector index. * * 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 + * \returns The selector index if the cursor is an Objective-C method or message * expression and the cursor is pointing to a selector identifier, or -1 * otherwise. */ 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: + * \brief Given a cursor pointing to a C++ method call or an Objective-C + * 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. + * For an Objective-C 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. @@ -3397,8 +3539,8 @@ CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor); CINDEX_LINKAGE int clang_Cursor_isDynamicCall(CXCursor C); /** - * \brief Given a cursor pointing to an ObjC message, returns the CXType of the - * receiver. + * \brief Given a cursor pointing to an Objective-C message, returns the CXType + * of the receiver. */ CINDEX_LINKAGE CXType clang_Cursor_getReceiverType(CXCursor C); @@ -3433,7 +3575,7 @@ CINDEX_LINKAGE unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C, /** * \brief 'Qualifiers' written next to the return and parameter types in - * ObjC method declarations. + * Objective-C method declarations. */ typedef enum { CXObjCDeclQualifier_None = 0x0, @@ -3446,15 +3588,16 @@ typedef enum { } CXObjCDeclQualifierKind; /** - * \brief Given a cursor that represents an ObjC method or parameter - * declaration, return the associated ObjC qualifiers for the return type or the - * parameter respectively. The bits are formed from CXObjCDeclQualifierKind. + * \brief Given a cursor that represents an Objective-C method or parameter + * declaration, return the associated Objective-C qualifiers for the return + * type or the parameter respectively. The bits are formed from + * CXObjCDeclQualifierKind. */ CINDEX_LINKAGE unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C); /** - * \brief Given a cursor that represents an ObjC method or property declaration, - * return non-zero if the declaration was affected by "@optional". + * \brief Given a cursor that represents an Objective-C method or property + * declaration, return non-zero if the declaration was affected by "@optional". * Returns zero if the cursor is not such a declaration or it is "@required". */ CINDEX_LINKAGE unsigned clang_Cursor_isObjCOptional(CXCursor C); @@ -3485,13 +3628,6 @@ CINDEX_LINKAGE CXString clang_Cursor_getRawCommentText(CXCursor C); 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); - -/** * @} */ @@ -3511,6 +3647,12 @@ typedef void *CXModule; CINDEX_LINKAGE CXModule clang_Cursor_getModule(CXCursor C); /** + * \brief Given a CXFile header file, return the module that contains it, if one + * exists. + */ +CINDEX_LINKAGE CXModule clang_getModuleForFile(CXTranslationUnit, CXFile); + +/** * \param Module a module object. * * \returns the module file where the provided module object came from. @@ -3543,6 +3685,13 @@ CINDEX_LINKAGE CXString clang_Module_getFullName(CXModule Module); /** * \param Module a module object. * + * \returns non-zero if the module is a system one. + */ +CINDEX_LINKAGE int clang_Module_isSystem(CXModule Module); + +/** + * \param Module a module object. + * * \returns the number of top level headers associated with this module. */ CINDEX_LINKAGE unsigned clang_Module_getNumTopLevelHeaders(CXTranslationUnit, @@ -3564,514 +3713,6 @@ CXFile clang_Module_getTopLevelHeader(CXTranslationUnit, */ /** - * \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). - * - * For example: \\param [in] ParamName description. - */ - CXComment_ParamCommand = 7, - - /** - * \brief A \\tparam command that describes a template parameter (name and - * description). - * - * 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 ChildIdx child 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, <br />). - */ -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 Comment a \c CXComment_FullComment AST node. - * - * \returns string containing an XML document. - */ -CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment); - -/** - * @} - */ - -/** * \defgroup CINDEX_CPP C++ AST introspection * * The routines in this group provide access information in the ASTs specific @@ -4100,6 +3741,12 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C); CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C); /** + * \brief Determine if a C++ member function or member function template is + * declared 'const'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(CXCursor C); + +/** * \brief Given a cursor that represents a template, determine * the cursor kind of the specializations would be generated by instantiating * the template. @@ -4189,7 +3836,7 @@ enum CXNameRefFlags { * Non-contiguous names occur in Objective-C when a selector with two or more * parameters is used, or in C++ when using an operator: * \code - * [object doSomething:here withValue:there]; // ObjC + * [object doSomething:here withValue:there]; // Objective-C * return some_vector[1]; // C++ * \endcode */ @@ -5022,7 +4669,7 @@ CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results, unsigned Index); /** - * \brief Determines what compeltions are appropriate for the context + * \brief Determines what completions are appropriate for the context * the given code completion. * * \param Results the code completion results to query @@ -5472,7 +5119,7 @@ typedef struct { const CXIdxContainerInfo *declAsContainer; /** * \brief Whether the declaration exists in code or was created implicitly - * by the compiler, e.g. implicit objc methods for properties. + * by the compiler, e.g. implicit Objective-C methods for properties. */ int isImplicit; const CXIdxAttrInfo *const *attributes; @@ -5545,8 +5192,8 @@ typedef enum { */ CXIdxEntityRef_Direct = 1, /** - * \brief An implicit reference, e.g. a reference of an ObjC method via the - * dot syntax. + * \brief An implicit reference, e.g. a reference of an Objective-C method + * via the dot syntax. */ CXIdxEntityRef_Implicit = 2 } CXIdxEntityRefKind; @@ -5740,7 +5387,7 @@ typedef enum { /** * \brief Skip a function/method body that was already parsed during an - * indexing session assosiated with a \c CXIndexAction object. + * indexing session associated with a \c CXIndexAction object. * Bodies in system headers are always skipped. */ CXIndexOpt_SkipParsedBodiesInSession = 0x10 @@ -5763,11 +5410,12 @@ typedef enum { * \param index_options A bitmask of options that affects how indexing is * performed. This should be a bitwise OR of the CXIndexOpt_XXX flags. * - * \param out_TU [out] pointer to store a CXTranslationUnit that can be reused - * after indexing is finished. Set to NULL if you do not require it. + * \param[out] out_TU pointer to store a \c CXTranslationUnit that can be + * reused after indexing is finished. Set to \c NULL if you do not require it. * - * \returns If there is a failure from which the there is no recovery, returns - * non-zero, otherwise returns 0. + * \returns 0 on success or if there were errors from which the compiler could + * recover. If there is a failure from which the there is no recovery, returns + * a non-zero \c CXErrorCode. * * The rest of the parameters are the same as #clang_parseTranslationUnit. */ @@ -5836,6 +5484,9 @@ CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc loc); * @} */ +/* Include the comment API for compatibility. This will eventually go away. */ +#include "clang-c/Documentation.h" + #ifdef __cplusplus } #endif diff --git a/contrib/llvm/tools/clang/include/clang-c/module.modulemap b/contrib/llvm/tools/clang/include/clang-c/module.modulemap new file mode 100644 index 0000000..95a59d6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang-c/module.modulemap @@ -0,0 +1,4 @@ +module Clang_C { + umbrella "." + module * { export * } +} diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h index 196f6c0..ad4f23c 100644 --- a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h +++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h @@ -113,7 +113,7 @@ public: virtual void remove(CharSourceRange range) { } }; - bool applyTransform(TransformFn trans, RewriteListener *listener = 0); + bool applyTransform(TransformFn trans, RewriteListener *listener = nullptr); FileRemapper &getRemapper() { return Remapper; } }; diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h index 45c8b4e..b3e74b9 100644 --- a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h +++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h @@ -12,14 +12,14 @@ #include "clang/ARCMigrate/FileRemapper.h" #include "clang/Frontend/FrontendAction.h" -#include "llvm/ADT/OwningPtr.h" +#include <memory> namespace clang { namespace arcmt { class CheckAction : public WrapperFrontendAction { protected: - virtual bool BeginInvocation(CompilerInstance &CI); + bool BeginInvocation(CompilerInstance &CI) override; public: CheckAction(FrontendAction *WrappedAction); @@ -27,7 +27,7 @@ public: class ModifyAction : public WrapperFrontendAction { protected: - virtual bool BeginInvocation(CompilerInstance &CI); + bool BeginInvocation(CompilerInstance &CI) override; public: ModifyAction(FrontendAction *WrappedAction); @@ -36,9 +36,9 @@ public: class MigrateSourceAction : public ASTFrontendAction { FileRemapper Remapper; protected: - virtual bool BeginInvocation(CompilerInstance &CI); - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + bool BeginInvocation(CompilerInstance &CI) override; + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class MigrateAction : public WrapperFrontendAction { @@ -46,7 +46,7 @@ class MigrateAction : public WrapperFrontendAction { std::string PlistOut; bool EmitPremigrationARCErros; protected: - virtual bool BeginInvocation(CompilerInstance &CI); + bool BeginInvocation(CompilerInstance &CI) override; public: MigrateAction(FrontendAction *WrappedAction, StringRef migrateDir, @@ -65,8 +65,9 @@ public: unsigned migrateAction); protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,StringRef InFile); - virtual bool BeginInvocation(CompilerInstance &CI); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + bool BeginInvocation(CompilerInstance &CI) override; }; } diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h index f7677cc..e094301 100644 --- a/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h +++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h @@ -12,9 +12,9 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" +#include <memory> namespace llvm { class MemoryBuffer; @@ -30,7 +30,7 @@ namespace arcmt { class FileRemapper { // FIXME: Reuse the same FileManager for multiple ASTContexts. - OwningPtr<FileManager> FileMgr; + std::unique_ptr<FileManager> FileMgr; typedef llvm::PointerUnion<const FileEntry *, llvm::MemoryBuffer *> Target; typedef llvm::DenseMap<const FileEntry *, Target> MappingsTy; @@ -56,8 +56,6 @@ public: void applyMappings(PreprocessorOptions &PPOpts) const; - void transferMappingsAndClear(PreprocessorOptions &PPOpts); - void clear(StringRef outputDir = StringRef()); private: diff --git a/contrib/llvm/tools/clang/include/clang/AST/APValue.h b/contrib/llvm/tools/clang/include/clang/AST/APValue.h index b4fd2af..e58c219 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/APValue.h +++ b/contrib/llvm/tools/clang/include/clang/AST/APValue.h @@ -80,7 +80,7 @@ private: struct Vec { APValue *Elts; unsigned NumElts; - Vec() : Elts(0), NumElts(0) {} + Vec() : Elts(nullptr), NumElts(0) {} ~Vec() { delete[] Elts; } }; struct Arr { @@ -108,34 +108,33 @@ private: }; struct MemberPointerData; - enum { - MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? - sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat)) - }; + // We ensure elsewhere that Data is big enough for LV and MemberPointerData. + typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, + ComplexAPFloat, Vec, Arr, StructData, + UnionData, AddrLabelDiffData> DataType; + static const size_t DataSize = sizeof(DataType); - union { - void *Aligner; - char Data[MaxSize]; - }; + DataType Data; public: APValue() : Kind(Uninitialized) {} - explicit APValue(const APSInt &I) : Kind(Uninitialized) { - MakeInt(); setInt(I); + explicit APValue(APSInt I) : Kind(Uninitialized) { + MakeInt(); setInt(std::move(I)); } - explicit APValue(const APFloat &F) : Kind(Uninitialized) { - MakeFloat(); setFloat(F); + explicit APValue(APFloat F) : Kind(Uninitialized) { + MakeFloat(); setFloat(std::move(F)); } explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { MakeVector(); setVector(E, N); } - APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) { - MakeComplexInt(); setComplexInt(R, I); + APValue(APSInt R, APSInt I) : Kind(Uninitialized) { + MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { - MakeComplexFloat(); setComplexFloat(R, I); + APValue(APFloat R, APFloat I) : Kind(Uninitialized) { + MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); + APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); } APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex) : Kind(Uninitialized) { MakeLValue(); setLValue(B, O, N, CallIndex); @@ -200,7 +199,7 @@ public: APSInt &getInt() { assert(isInt() && "Invalid accessor"); - return *(APSInt*)(char*)Data; + return *(APSInt*)(char*)Data.buffer; } const APSInt &getInt() const { return const_cast<APValue*>(this)->getInt(); @@ -208,7 +207,7 @@ public: APFloat &getFloat() { assert(isFloat() && "Invalid accessor"); - return *(APFloat*)(char*)Data; + return *(APFloat*)(char*)Data.buffer; } const APFloat &getFloat() const { return const_cast<APValue*>(this)->getFloat(); @@ -216,7 +215,7 @@ public: APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data)->Real; + return ((ComplexAPSInt*)(char*)Data.buffer)->Real; } const APSInt &getComplexIntReal() const { return const_cast<APValue*>(this)->getComplexIntReal(); @@ -224,7 +223,7 @@ public: APSInt &getComplexIntImag() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data)->Imag; + return ((ComplexAPSInt*)(char*)Data.buffer)->Imag; } const APSInt &getComplexIntImag() const { return const_cast<APValue*>(this)->getComplexIntImag(); @@ -232,7 +231,7 @@ public: APFloat &getComplexFloatReal() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data)->Real; + return ((ComplexAPFloat*)(char*)Data.buffer)->Real; } const APFloat &getComplexFloatReal() const { return const_cast<APValue*>(this)->getComplexFloatReal(); @@ -240,7 +239,7 @@ public: APFloat &getComplexFloatImag() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data)->Imag; + return ((ComplexAPFloat*)(char*)Data.buffer)->Imag; } const APFloat &getComplexFloatImag() const { return const_cast<APValue*>(this)->getComplexFloatImag(); @@ -259,20 +258,20 @@ public: APValue &getVectorElt(unsigned I) { assert(isVector() && "Invalid accessor"); assert(I < getVectorLength() && "Index out of range"); - return ((Vec*)(char*)Data)->Elts[I]; + return ((Vec*)(char*)Data.buffer)->Elts[I]; } const APValue &getVectorElt(unsigned I) const { return const_cast<APValue*>(this)->getVectorElt(I); } unsigned getVectorLength() const { assert(isVector() && "Invalid accessor"); - return ((const Vec*)(const void *)Data)->NumElts; + return ((const Vec*)(const void *)Data.buffer)->NumElts; } APValue &getArrayInitializedElt(unsigned I) { assert(isArray() && "Invalid accessor"); assert(I < getArrayInitializedElts() && "Index out of range"); - return ((Arr*)(char*)Data)->Elts[I]; + return ((Arr*)(char*)Data.buffer)->Elts[I]; } const APValue &getArrayInitializedElt(unsigned I) const { return const_cast<APValue*>(this)->getArrayInitializedElt(I); @@ -283,35 +282,35 @@ public: APValue &getArrayFiller() { assert(isArray() && "Invalid accessor"); assert(hasArrayFiller() && "No array filler"); - return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()]; + return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()]; } const APValue &getArrayFiller() const { return const_cast<APValue*>(this)->getArrayFiller(); } unsigned getArrayInitializedElts() const { assert(isArray() && "Invalid accessor"); - return ((const Arr*)(const void *)Data)->NumElts; + return ((const Arr*)(const void *)Data.buffer)->NumElts; } unsigned getArraySize() const { assert(isArray() && "Invalid accessor"); - return ((const Arr*)(const void *)Data)->ArrSize; + return ((const Arr*)(const void *)Data.buffer)->ArrSize; } unsigned getStructNumBases() const { assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data)->NumBases; + return ((const StructData*)(const char*)Data.buffer)->NumBases; } unsigned getStructNumFields() const { assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data)->NumFields; + return ((const StructData*)(const char*)Data.buffer)->NumFields; } APValue &getStructBase(unsigned i) { assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data)->Elts[i]; + return ((StructData*)(char*)Data.buffer)->Elts[i]; } APValue &getStructField(unsigned i) { assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i]; + return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i]; } const APValue &getStructBase(unsigned i) const { return const_cast<APValue*>(this)->getStructBase(i); @@ -322,11 +321,11 @@ public: const FieldDecl *getUnionField() const { assert(isUnion() && "Invalid accessor"); - return ((const UnionData*)(const char*)Data)->Field; + return ((const UnionData*)(const char*)Data.buffer)->Field; } APValue &getUnionValue() { assert(isUnion() && "Invalid accessor"); - return *((UnionData*)(char*)Data)->Value; + return *((UnionData*)(char*)Data.buffer)->Value; } const APValue &getUnionValue() const { return const_cast<APValue*>(this)->getUnionValue(); @@ -338,41 +337,41 @@ public: const AddrLabelExpr* getAddrLabelDiffLHS() const { assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data)->LHSExpr; + return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr; } const AddrLabelExpr* getAddrLabelDiffRHS() const { assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data)->RHSExpr; + return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr; } - void setInt(const APSInt &I) { + void setInt(APSInt I) { assert(isInt() && "Invalid accessor"); - *(APSInt*)(char*)Data = I; + *(APSInt *)(char *)Data.buffer = std::move(I); } - void setFloat(const APFloat &F) { + void setFloat(APFloat F) { assert(isFloat() && "Invalid accessor"); - *(APFloat*)(char*)Data = F; + *(APFloat *)(char *)Data.buffer = std::move(F); } void setVector(const APValue *E, unsigned N) { assert(isVector() && "Invalid accessor"); - ((Vec*)(char*)Data)->Elts = new APValue[N]; - ((Vec*)(char*)Data)->NumElts = N; + ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; + ((Vec*)(char*)Data.buffer)->NumElts = N; for (unsigned i = 0; i != N; ++i) - ((Vec*)(char*)Data)->Elts[i] = E[i]; + ((Vec*)(char*)Data.buffer)->Elts[i] = E[i]; } - void setComplexInt(const APSInt &R, const APSInt &I) { + void setComplexInt(APSInt R, APSInt I) { assert(R.getBitWidth() == I.getBitWidth() && "Invalid complex int (type mismatch)."); assert(isComplexInt() && "Invalid accessor"); - ((ComplexAPSInt*)(char*)Data)->Real = R; - ((ComplexAPSInt*)(char*)Data)->Imag = I; + ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R); + ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I); } - void setComplexFloat(const APFloat &R, const APFloat &I) { + void setComplexFloat(APFloat R, APFloat I) { assert(&R.getSemantics() == &I.getSemantics() && "Invalid complex float (type mismatch)."); assert(isComplexFloat() && "Invalid accessor"); - ((ComplexAPFloat*)(char*)Data)->Real = R; - ((ComplexAPFloat*)(char*)Data)->Imag = I; + ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R); + ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); } void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, unsigned CallIndex); @@ -381,13 +380,13 @@ public: unsigned CallIndex); void setUnion(const FieldDecl *Field, const APValue &Value) { assert(isUnion() && "Invalid accessor"); - ((UnionData*)(char*)Data)->Field = Field; - *((UnionData*)(char*)Data)->Value = Value; + ((UnionData*)(char*)Data.buffer)->Field = Field; + *((UnionData*)(char*)Data.buffer)->Value = Value; } void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) { - ((AddrLabelDiffData*)(char*)Data)->LHSExpr = LHSExpr; - ((AddrLabelDiffData*)(char*)Data)->RHSExpr = RHSExpr; + ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; + ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr; } /// Assign by swapping from a copy of the RHS. @@ -404,46 +403,46 @@ private: } void MakeInt() { assert(isUninit() && "Bad state change"); - new ((void*)Data) APSInt(1); + new ((void*)Data.buffer) APSInt(1); Kind = Int; } void MakeFloat() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) APFloat(0.0); + new ((void*)(char*)Data.buffer) APFloat(0.0); Kind = Float; } void MakeVector() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) Vec(); + new ((void*)(char*)Data.buffer) Vec(); Kind = Vector; } void MakeComplexInt() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) ComplexAPSInt(); + new ((void*)(char*)Data.buffer) ComplexAPSInt(); Kind = ComplexInt; } void MakeComplexFloat() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) ComplexAPFloat(); + new ((void*)(char*)Data.buffer) ComplexAPFloat(); Kind = ComplexFloat; } void MakeLValue(); void MakeArray(unsigned InitElts, unsigned Size); void MakeStruct(unsigned B, unsigned M) { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) StructData(B, M); + new ((void*)(char*)Data.buffer) StructData(B, M); Kind = Struct; } void MakeUnion() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) UnionData(); + new ((void*)(char*)Data.buffer) UnionData(); Kind = Union; } void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, ArrayRef<const CXXRecordDecl*> Path); void MakeAddrLabelDiff() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) AddrLabelDiffData(); + new ((void*)(char*)Data.buffer) AddrLabelDiffData(); Kind = AddrLabelDiff; } }; diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h index 7b6fa94..736a10b 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h @@ -18,10 +18,10 @@ namespace clang { class ASTContext; + class CXXMethodDecl; class CXXRecordDecl; class Decl; class DeclGroupRef; - class HandleTagDeclDefinition; class ASTMutationListener; class ASTDeserializationListener; // layering violation because void* is ugly class SemaConsumer; // layering violation required for safe SemaConsumer @@ -50,13 +50,15 @@ public: virtual void Initialize(ASTContext &Context) {} /// HandleTopLevelDecl - Handle the specified top-level declaration. This is - /// called by the parser to process every top-level Decl*. Note that D can be - /// the head of a chain of Decls (e.g. for `int a, b` the chain will have two - /// elements). Use Decl::getNextDeclarator() to walk the chain. + /// called by the parser to process every top-level Decl*. /// /// \returns true to continue parsing, or false to abort parsing. virtual bool HandleTopLevelDecl(DeclGroupRef D); + /// \brief This callback is invoked each time an inline method definition is + /// completed. + virtual void HandleInlineMethodDefinition(CXXMethodDecl *D) {} + /// HandleInterestingDecl - Handle the specified interesting declaration. This /// is called by the AST reader when deserializing things that might interest /// the consumer. The default implementation forwards to HandleTopLevelDecl. @@ -136,12 +138,12 @@ public: /// \brief If the consumer is interested in entities getting modified after /// their initial creation, it should return a pointer to /// an ASTMutationListener here. - virtual ASTMutationListener *GetASTMutationListener() { return 0; } + virtual ASTMutationListener *GetASTMutationListener() { return nullptr; } /// \brief If the consumer is interested in entities being deserialized from /// AST files, it should return a pointer to a ASTDeserializationListener here virtual ASTDeserializationListener *GetASTDeserializationListener() { - return 0; + return nullptr; } /// PrintStats - If desired, print any statistics. diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h index f420e85..8134f6b 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h @@ -19,6 +19,7 @@ #include "clang/AST/CanonicalType.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/Decl.h" +#include "clang/AST/ExternalASTSource.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/RawCommentList.h" @@ -33,10 +34,10 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/Allocator.h" +#include <memory> #include <vector> namespace llvm { @@ -51,7 +52,6 @@ namespace clang { class CharUnits; class DiagnosticsEngine; class Expr; - class ExternalASTSource; class ASTMutationListener; class IdentifierTable; class MaterializeTemporaryExpr; @@ -66,6 +66,7 @@ namespace clang { class UnresolvedSetIterator; class UsingDecl; class UsingShadowDecl; + class VTableContextBase; namespace Builtin { class Context; } @@ -82,7 +83,7 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<ExtQuals> ExtQualNodes; mutable llvm::FoldingSet<ComplexType> ComplexTypes; mutable llvm::FoldingSet<PointerType> PointerTypes; - mutable llvm::FoldingSet<DecayedType> DecayedTypes; + mutable llvm::FoldingSet<AdjustedType> AdjustedTypes; mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes; mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes; mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes; @@ -364,6 +365,7 @@ private: /// \brief Side-table of mangling numbers for declarations which rarely /// need them (like static local vars). llvm::DenseMap<const NamedDecl *, unsigned> MangleNumbers; + llvm::DenseMap<const VarDecl *, unsigned> StaticLocalNumbers; /// \brief Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. @@ -392,7 +394,7 @@ private: PartialDiagnostic::StorageAllocator DiagAllocator; /// \brief The current C++ ABI. - OwningPtr<CXXABI> ABI; + std::unique_ptr<CXXABI> ABI; CXXABI *createCXXABI(const TargetInfo &T); /// \brief The logical -> physical address space map. @@ -415,14 +417,16 @@ public: SelectorTable &Selectors; Builtin::Context &BuiltinInfo; mutable DeclarationNameTable DeclarationNames; - OwningPtr<ExternalASTSource> ExternalSource; + IntrusiveRefCntPtr<ExternalASTSource> ExternalSource; ASTMutationListener *Listener; /// \brief Contains parents of a node. - typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 1> ParentVector; + typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector; /// \brief Maps from a node to its parents. - typedef llvm::DenseMap<const void *, ParentVector> ParentMap; + typedef llvm::DenseMap<const void *, + llvm::PointerUnion<ast_type_traits::DynTypedNode *, + ParentVector *>> ParentMap; /// \brief Returns the parents of the given node. /// @@ -601,9 +605,9 @@ public: /// /// \param OriginalDecl if not NULL, is set to declaration AST node that had /// the comment, if the comment we found comes from a redeclaration. - const RawComment *getRawCommentForAnyRedecl( - const Decl *D, - const Decl **OriginalDecl = NULL) const; + const RawComment * + getRawCommentForAnyRedecl(const Decl *D, + const Decl **OriginalDecl = nullptr) const; /// Return parsed documentation comment attached to a given declaration. /// Returns NULL if no comment is attached. @@ -624,6 +628,43 @@ public: private: mutable comments::CommandTraits CommentCommandTraits; + /// \brief Iterator that visits import declarations. + class import_iterator { + ImportDecl *Import; + + public: + typedef ImportDecl *value_type; + typedef ImportDecl *reference; + typedef ImportDecl *pointer; + typedef int difference_type; + typedef std::forward_iterator_tag iterator_category; + + import_iterator() : Import() {} + explicit import_iterator(ImportDecl *Import) : Import(Import) {} + + reference operator*() const { return Import; } + pointer operator->() const { return Import; } + + import_iterator &operator++() { + Import = ASTContext::getNextLocalImport(Import); + return *this; + } + + import_iterator operator++(int) { + import_iterator Other(*this); + ++(*this); + return Other; + } + + friend bool operator==(import_iterator X, import_iterator Y) { + return X.Import == Y.Import; + } + + friend bool operator!=(import_iterator X, import_iterator Y) { + return X.Import != Y.Import; + } + }; + public: comments::CommandTraits &getCommentCommandTraits() const { return CommentCommandTraits; @@ -710,47 +751,10 @@ public: return Import->NextLocalImport; } - /// \brief Iterator that visits import declarations. - class import_iterator { - ImportDecl *Import; - - public: - typedef ImportDecl *value_type; - typedef ImportDecl *reference; - typedef ImportDecl *pointer; - typedef int difference_type; - typedef std::forward_iterator_tag iterator_category; - - import_iterator() : Import() { } - explicit import_iterator(ImportDecl *Import) : Import(Import) { } - - reference operator*() const { return Import; } - pointer operator->() const { return Import; } - - import_iterator &operator++() { - Import = ASTContext::getNextLocalImport(Import); - return *this; - } - - import_iterator operator++(int) { - import_iterator Other(*this); - ++(*this); - return Other; - } - - friend bool operator==(import_iterator X, import_iterator Y) { - return X.Import == Y.Import; - } - - friend bool operator!=(import_iterator X, import_iterator Y) { - return X.Import != Y.Import; - } - }; - - import_iterator local_import_begin() const { - return import_iterator(FirstLocalImport); + typedef llvm::iterator_range<import_iterator> import_range; + import_range local_imports() const { + return import_range(import_iterator(FirstLocalImport), import_iterator()); } - import_iterator local_import_end() const { return import_iterator(); } Decl *getPrimaryMergedDecl(Decl *D) { Decl *Result = MergedDecls.lookup(D); @@ -797,11 +801,8 @@ public: // 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, - unsigned size_reserve, - bool DelayInitialization = false); + ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, + SelectorTable &sels, Builtin::Context &builtins); ~ASTContext(); @@ -810,11 +811,13 @@ public: /// The external AST source provides the ability to load parts of /// the abstract syntax tree as needed from some external storage, /// e.g., a precompiled header. - void setExternalSource(OwningPtr<ExternalASTSource> &Source); + void setExternalSource(IntrusiveRefCntPtr<ExternalASTSource> Source); /// \brief Retrieve a pointer to the external AST source associated /// with this AST context, if any. - ExternalASTSource *getExternalSource() const { return ExternalSource.get(); } + ExternalASTSource *getExternalSource() const { + return ExternalSource.get(); + } /// \brief Attach an AST mutation listener to the AST context. /// @@ -832,6 +835,14 @@ public: void PrintStats() const; const SmallVectorImpl<Type *>& getTypes() const { return Types; } + /// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl + /// declaration. + RecordDecl *buildImplicitRecord(StringRef Name, + RecordDecl::TagKind TK = TTK_Struct) const; + + /// \brief Create a new implicit TU-level typedef declaration. + TypedefDecl *buildImplicitTypedef(QualType T, StringRef Name) const; + /// \brief Retrieve the declaration for the 128-bit signed integer type. TypedefDecl *getInt128Decl() const; @@ -840,7 +851,7 @@ public: /// \brief Retrieve the declaration for a 128-bit float stub type. TypeDecl *getFloat128StubType() const; - + //===--------------------------------------------------------------------===// // Type Constructors //===--------------------------------------------------------------------===// @@ -915,6 +926,14 @@ public: return CanQualType::CreateUnsafe(getPointerType((QualType) T)); } + /// \brief Return the uniqued reference to a type adjusted from the original + /// type to a new type. + QualType getAdjustedType(QualType Orig, QualType New) const; + CanQualType getAdjustedType(CanQualType Orig, CanQualType New) const { + return CanQualType::CreateUnsafe( + getAdjustedType((QualType)Orig, (QualType)New)); + } + /// \brief Return the uniqued reference to the decayed version of the given /// type. Can only be called on array and function types which decay to /// pointer types. @@ -1041,7 +1060,7 @@ public: /// \brief Return the unique reference to the type for the specified type /// declaration. QualType getTypeDeclType(const TypeDecl *Decl, - const TypeDecl *PrevDecl = 0) const { + const TypeDecl *PrevDecl = nullptr) const { assert(Decl && "Passed null for Decl param"); if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); @@ -1075,9 +1094,10 @@ public: const TemplateTypeParmType *Replaced, const TemplateArgument &ArgPack); - QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, - bool ParameterPack, - TemplateTypeParmDecl *ParmDecl = 0) const; + QualType + getTemplateTypeParmType(unsigned Depth, unsigned Index, + bool ParameterPack, + TemplateTypeParmDecl *ParmDecl = nullptr) const; QualType getTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, @@ -1121,11 +1141,18 @@ public: Optional<unsigned> NumExpansions); QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, - ObjCInterfaceDecl *PrevDecl = 0) const; + ObjCInterfaceDecl *PrevDecl = nullptr) const; QualType getObjCObjectType(QualType Base, ObjCProtocolDecl * const *Protocols, unsigned NumProtocols) const; + + bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl); + /// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in + /// QT's qualified-id protocol list adopt all protocols in IDecl's list + /// of protocols. + bool QIdProtocolsAdoptObjCObjectProtocols(QualType QT, + ObjCInterfaceDecl *IDecl); /// \brief Return a ObjCObjectPointerType type for the given ObjCObjectType. QualType getObjCObjectPointerType(QualType OIT) const; @@ -1344,7 +1371,11 @@ public: /// /// If \p Field is specified then record field names are also encoded. void getObjCEncodingForType(QualType T, std::string &S, - const FieldDecl *Field=0) const; + const FieldDecl *Field=nullptr) const; + + /// \brief Emit the Objective-C property type encoding for the given + /// type \p T into \p S. + void getObjCEncodingForPropertyType(QualType T, std::string &S) const; void getLegacyIntegralTypeEncoding(QualType &t) const; @@ -1382,6 +1413,10 @@ public: bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, ObjCProtocolDecl *rProto) const; + + ObjCPropertyImplDecl *getObjCPropertyImplDeclForPropertyDecl( + const ObjCPropertyDecl *PD, + const Decl *Container) const; /// \brief Return the size of type \p T for Objective-C encoding purpose, /// in characters. @@ -1542,7 +1577,7 @@ public: /// arguments to the builtin that are required to be integer constant /// expressions. QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, - unsigned *IntegerConstantArgs = 0) const; + unsigned *IntegerConstantArgs = nullptr) const; private: CanQualType getFromTargetType(unsigned Type) const; @@ -1704,6 +1739,8 @@ public: bool isNearlyEmpty(const CXXRecordDecl *RD) const; + VTableContextBase *getVTableContext(); + MangleContext *createMangleContext(); void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, @@ -1745,6 +1782,10 @@ public: return getCanonicalType(T1) == getCanonicalType(T2); } + bool hasSameType(const Type *T1, const Type *T2) const { + return getCanonicalType(T1) == getCanonicalType(T2); + } + /// \brief Return this type as a completely-unqualified array type, /// capturing the qualifiers in \p Quals. /// @@ -1994,9 +2035,9 @@ public: bool Unqualified = false, bool BlockReturnType = false); QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified = false); - QualType mergeFunctionArgumentTypes(QualType, QualType, - bool OfBlockPointer=false, - bool Unqualified = false); + QualType mergeFunctionParameterTypes(QualType, QualType, + bool OfBlockPointer = false, + bool Unqualified = false); QualType mergeTransparentUnionType(QualType, QualType, bool OfBlockPointer=false, bool Unqualified = false); @@ -2008,7 +2049,7 @@ public: const FunctionProtoType *ToFunctionType); void ResetObjCLayout(const ObjCContainerDecl *CD) { - ObjCLayouts[CD] = 0; + ObjCLayouts[CD] = nullptr; } //===--------------------------------------------------------------------===// @@ -2027,14 +2068,12 @@ public: //===--------------------------------------------------------------------===// // Type Iterators. //===--------------------------------------------------------------------===// + typedef llvm::iterator_range<SmallVectorImpl<Type *>::const_iterator> + type_const_range; - typedef SmallVectorImpl<Type *>::iterator type_iterator; - typedef SmallVectorImpl<Type *>::const_iterator const_type_iterator; - - type_iterator types_begin() { return Types.begin(); } - type_iterator types_end() { return Types.end(); } - const_type_iterator types_begin() const { return Types.begin(); } - const_type_iterator types_end() const { return Types.end(); } + type_const_range types() const { + return type_const_range(Types.begin(), Types.end()); + } //===--------------------------------------------------------------------===// // Integer Values @@ -2125,7 +2164,7 @@ public: /// when it is called. void AddDeallocation(void (*Callback)(void*), void *Data); - GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD); + GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const; GVALinkage GetGVALinkageForVariable(const VarDecl *VD); /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH @@ -2139,6 +2178,9 @@ public: void setManglingNumber(const NamedDecl *ND, unsigned Number); unsigned getManglingNumber(const NamedDecl *ND) const; + void setStaticLocalNumber(const VarDecl *VD, unsigned Number); + unsigned getStaticLocalNumber(const VarDecl *VD) const; + /// \brief Retrieve the context for computing mangling numbers in the given /// DeclContext. MangleNumberingContext &getManglingNumberContext(const DeclContext *DC); @@ -2212,9 +2254,7 @@ public: /// \brief Initialize built-in types. /// /// This routine may only be invoked once for a given ASTContext object. - /// It is normally invoked by the ASTContext constructor. However, the - /// constructor can be asked to delay initialization, which places the burden - /// of calling this function on the user of that object. + /// It is normally invoked after ASTContext construction. /// /// \param Target The target void InitBuiltinTypes(const TargetInfo &Target); @@ -2238,17 +2278,21 @@ private: void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S, const FieldDecl *Field, bool includeVBases = true) const; - +public: // Adds the encoding of a method parameter or return type. void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, QualType T, std::string& S, bool Extended) const; + /// \brief Returns true if this is an inline-initialized static data member + /// which is treated as a definition for MSVC compatibility. + bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const; + +private: const ASTRecordLayout & getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl) const; -private: /// \brief A set of deallocations that should be performed when the /// ASTContext is destroyed. typedef llvm::SmallDenseMap<void(*)(void*), llvm::SmallVector<void*, 16> > @@ -2263,8 +2307,11 @@ private: friend class DeclContext; friend class DeclarationNameTable; void ReleaseDeclContextMaps(); + void ReleaseParentMapEntries(); - llvm::OwningPtr<ParentMap> AllParents; + std::unique_ptr<ParentMap> AllParents; + + std::unique_ptr<VTableContextBase> VTContext; }; /// \brief Utility function for constructing a nullary selector. @@ -2363,4 +2410,18 @@ inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t) { C.Deallocate(Ptr); } +/// \brief Create the representation of a LazyGenerationalUpdatePtr. +template <typename Owner, typename T, + void (clang::ExternalASTSource::*Update)(Owner)> +typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType + clang::LazyGenerationalUpdatePtr<Owner, T, Update>::makeValue( + const clang::ASTContext &Ctx, T Value) { + // Note, this is implemented here so that ExternalASTSource.h doesn't need to + // include ASTContext.h. We explicitly instantiate it for all relevant types + // in ASTContext.cpp. + if (auto *Source = Ctx.getExternalSource()) + return new (Ctx) LazyData(Source, Value); + return Value; +} + #endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h index 1635511..484ca4c 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h @@ -36,12 +36,9 @@ namespace clang { void FormatASTNodeDiagnosticArgument( DiagnosticsEngine::ArgumentKind Kind, intptr_t Val, - const char *Modifier, - unsigned ModLen, - const char *Argument, - unsigned ArgLen, - const DiagnosticsEngine::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, + StringRef Modifier, + StringRef Argument, + ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, SmallVectorImpl<char> &Output, void *Cookie, ArrayRef<intptr_t> QualTypeVals); diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h index b74c8ee..a335f98 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h @@ -278,7 +278,7 @@ namespace clang { /// happens especially for anonymous structs. If the original of the second /// RecordDecl can be found, we can complete it without the need for /// importation, eliminating this loop. - virtual Decl *GetOriginalDecl(Decl *To) { return NULL; } + virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; } /// \brief Determine whether the given types are structurally /// equivalent. diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h b/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h index 358ac71..9af016b 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h @@ -36,9 +36,9 @@ inline bool isLambdaCallOperator(const DeclContext *DC) { return isLambdaCallOperator(cast<CXXMethodDecl>(DC)); } -inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) { +inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) { if (!MD) return false; - CXXRecordDecl *LambdaClass = MD->getParent(); + const CXXRecordDecl *LambdaClass = MD->getParent(); if (LambdaClass && LambdaClass->isGenericLambda()) return isLambdaCallOperator(MD) && MD->isFunctionTemplateSpecialization(); diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h index 6d12a92..a89bfed 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h @@ -65,6 +65,10 @@ public: virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, const FunctionDecl *D) {} + /// \brief A function's exception specification has been evaluated or + /// instantiated. + virtual void ResolvedExceptionSpec(const FunctionDecl *FD) {} + /// \brief A function's return type has been deduced. virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType); @@ -74,6 +78,9 @@ public: /// \brief A static data member was implicitly instantiated. virtual void StaticDataMemberInstantiated(const VarDecl *D) {} + /// \brief A function template's definition was instantiated. + virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {} + /// \brief A new objc category class was added for an interface. virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) {} diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h b/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h index 087ad56..0e06e26 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h @@ -57,11 +57,18 @@ public: bool isSame(ASTNodeKind Other) const; /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. - bool isBaseOf(ASTNodeKind Other) const; + /// \param Distance If non-null, used to return the distance between \c this + /// and \c Other in the class hierarchy. + bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; /// \brief String representation of the kind. StringRef asStringRef() const; + /// \brief Strict weak ordering for ASTNodeKind. + bool operator<(const ASTNodeKind &Other) const { + return KindId < Other.KindId; + } + private: /// \brief Kind ids. /// @@ -91,7 +98,9 @@ private: /// \brief Returns \c true if \c Base is a base kind of (or same as) \c /// Derived. - static bool isBaseOf(NodeKindId Base, NodeKindId Derived); + /// \param Distance If non-null, used to return the distance between \c Base + /// and \c Derived in the class hierarchy. + static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance); /// \brief Helper meta-function to convert a kind T to its enum value. /// @@ -133,6 +142,11 @@ KIND_TO_KIND_ID(Type) #include "clang/AST/TypeNodes.def" #undef KIND_TO_KIND_ID +inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { + OS << K.asStringRef(); + return OS; +} + /// \brief A dynamically typed AST node container. /// /// Stores an AST node in a type safe way. This allows writing code that @@ -198,8 +212,8 @@ public: return getMemoizationData() < Other.getMemoizationData(); } bool operator==(const DynTypedNode &Other) const { - // Nodes with different types cannot be equal. - if (!NodeKind.isSame(Other.NodeKind)) + if (!NodeKind.isBaseOf(Other.NodeKind) && + !Other.NodeKind.isBaseOf(NodeKind)) return false; // FIXME: Implement for other types. @@ -223,7 +237,7 @@ private: static const T *get(ASTNodeKind NodeKind, const char Storage[]) { if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind)) return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); - return NULL; + return nullptr; } static DynTypedNode create(const BaseT &Node) { DynTypedNode Result; @@ -238,7 +252,7 @@ private: static const T *get(ASTNodeKind NodeKind, const char Storage[]) { if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) return *reinterpret_cast<T *const *>(Storage); - return NULL; + return nullptr; } static DynTypedNode create(const T &Node) { DynTypedNode Result; @@ -253,7 +267,7 @@ private: static const T *get(ASTNodeKind NodeKind, const char Storage[]) { if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) return reinterpret_cast<const T *>(Storage); - return NULL; + return nullptr; } static DynTypedNode create(const T &Node) { DynTypedNode Result; @@ -283,18 +297,18 @@ private: template <typename T> struct DynTypedNode::BaseConverter< - T, typename llvm::enable_if<llvm::is_base_of< - Decl, T> >::type> : public DynCastPtrConverter<T, Decl> {}; + T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type> + : public DynCastPtrConverter<T, Decl> {}; template <typename T> struct DynTypedNode::BaseConverter< - T, typename llvm::enable_if<llvm::is_base_of< - Stmt, T> >::type> : public DynCastPtrConverter<T, Stmt> {}; + T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type> + : public DynCastPtrConverter<T, Stmt> {}; template <typename T> struct DynTypedNode::BaseConverter< - T, typename llvm::enable_if<llvm::is_base_of< - Type, T> >::type> : public DynCastPtrConverter<T, Type> {}; + T, typename std::enable_if<std::is_base_of<Type, T>::value>::type> + : public DynCastPtrConverter<T, Type> {}; template <> struct DynTypedNode::BaseConverter< @@ -341,7 +355,7 @@ inline const void *DynTypedNode::getMemoizationData() const { } else if (ASTNodeKind::getFromNodeKind<NestedNameSpecifier>().isBaseOf(NodeKind)) { return BaseConverter<NestedNameSpecifier>::get(NodeKind, Storage.buffer); } - return NULL; + return nullptr; } } // end namespace ast_type_traits diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h b/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h index e8be670..84b0842 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h @@ -32,9 +32,6 @@ class ASTUnresolvedSet { DeclsTy Decls; - ASTUnresolvedSet(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION; - void operator=(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION; - friend class LazyASTUnresolvedSet; public: diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h b/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h index 6db918e..d92167e 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h @@ -26,30 +26,6 @@ #include <cstring> #include <memory> -#ifdef _MSC_VER -namespace std { -#if _MSC_VER <= 1310 - // Work around flawed VC++ implementation of std::uninitialized_copy. Define - // additional overloads so that elements with pointer types are recognized as - // scalars and not objects, causing bizarre type conversion errors. - template<class T1, class T2> - inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { - _Scalar_ptr_iterator_tag _Cat; - return _Cat; - } - - template<class T1, class T2> - inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { - _Scalar_ptr_iterator_tag _Cat; - return _Cat; - } -#else - // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear - // is that the above hack won't work if it wasn't fixed. -#endif -} -#endif - namespace clang { class ASTContext; @@ -69,15 +45,30 @@ protected: public: // Default ctor - Initialize to empty. - ASTVector() : Begin(0), End(0), Capacity(0, false) {} + ASTVector() : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {} + + ASTVector(ASTVector &&O) : Begin(O.Begin), End(O.End), Capacity(O.Capacity) { + O.Begin = O.End = nullptr; + O.Capacity.setPointer(nullptr); + O.Capacity.setInt(false); + } ASTVector(const ASTContext &C, unsigned N) - : Begin(0), End(0), Capacity(0, false) { + : Begin(nullptr), End(nullptr), Capacity(nullptr, false) { reserve(C, N); } + ASTVector &operator=(ASTVector &&RHS) { + ASTVector O(std::move(RHS)); + using std::swap; + swap(Begin, O.Begin); + swap(End, O.End); + swap(Capacity, O.Capacity); + return *this; + } + ~ASTVector() { - if (llvm::is_class<T>::value) { + if (std::is_class<T>::value) { // Destroy the constructed elements in the vector. destroy_range(Begin, End); } @@ -147,7 +138,7 @@ public: } void clear() { - if (llvm::is_class<T>::value) { + if (std::is_class<T>::value) { destroy_range(Begin, End); } End = Begin; @@ -392,7 +383,7 @@ void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) { T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity]; // Copy the elements over. - if (llvm::is_class<T>::value) { + if (std::is_class<T>::value) { std::uninitialized_copy(Begin, End, NewElts); // Destroy the original elements. destroy_range(Begin, End); diff --git a/contrib/llvm/tools/clang/include/clang/AST/Attr.h b/contrib/llvm/tools/clang/include/clang/AST/Attr.h index 7dbf413..fc48816 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Attr.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Attr.h @@ -26,8 +26,8 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> #include <cassert> -#include <cstring> namespace clang { class ASTContext; @@ -48,10 +48,9 @@ protected: /// An index into the spelling list of an /// attribute defined in Attr.td file. unsigned SpellingListIndex : 4; - bool Inherited : 1; - bool IsPackExpansion : 1; + bool Implicit : 1; virtual ~Attr(); @@ -76,7 +75,7 @@ public: protected: Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0) : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex), - Inherited(false), IsPackExpansion(false) {} + Inherited(false), IsPackExpansion(false), Implicit(false) {} public: @@ -85,6 +84,7 @@ public: } unsigned getSpellingListIndex() const { return SpellingListIndex; } + virtual const char *getSpelling() const = 0; SourceLocation getLocation() const { return Range.getBegin(); } SourceRange getRange() const { return Range; } @@ -92,6 +92,11 @@ public: bool isInherited() const { return Inherited; } + /// \brief Returns true if the attribute has been implicitly created instead + /// of explicitly written by the user. + bool isImplicit() const { return Implicit; } + void setImplicit(bool I) { Implicit = I; } + void setPackExpansion(bool PE) { IsPackExpansion = PE; } bool isPackExpansion() const { return IsPackExpansion; } @@ -103,6 +108,11 @@ public: // Pretty print this attribute. virtual void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const = 0; + + /// \brief By default, attributes cannot be duplicated when being merged; + /// however, an attribute can override this. Returns true if the attribute + /// can be duplicated when merging. + virtual bool duplicatesAllowed() const { return false; } }; class InheritableAttr : public Attr { @@ -121,7 +131,7 @@ public: }; class InheritableParamAttr : public InheritableAttr { - virtual void anchor(); + void anchor() override; protected: InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0) @@ -136,23 +146,21 @@ public: } }; -class MSInheritanceAttr : public InheritableAttr { - virtual void anchor(); -protected: - MSInheritanceAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0) - : InheritableAttr(AK, R, SpellingListIndex) {} - -public: - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - // Relies on relative order of enum emission with respect to param attrs. - return (A->getKind() <= attr::LAST_MS_INHERITANCE && - A->getKind() > attr::LAST_INHERITABLE_PARAM); - } -}; - #include "clang/AST/Attrs.inc" +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const Attr *At) { + DB.AddTaggedVal(reinterpret_cast<intptr_t>(At), + DiagnosticsEngine::ak_attr); + return DB; +} + +inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + const Attr *At) { + PD.AddTaggedVal(reinterpret_cast<intptr_t>(At), + DiagnosticsEngine::ak_attr); + return PD; +} } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h b/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h index 8bd8fbe..39ee81f 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h +++ b/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h @@ -43,7 +43,7 @@ typedef SmallVector<Attr*, 2> AttrVec; typedef SmallVector<const Attr*, 2> ConstAttrVec; /// specific_attr_iterator - Iterates over a subrange of an AttrVec, only -/// providing attributes that are of a specifc type. +/// providing attributes that are of a specific type. template <typename SpecificAttr, typename Container = AttrVec> class specific_attr_iterator { typedef typename Container::const_iterator Iterator; @@ -53,7 +53,7 @@ class specific_attr_iterator { /// specifically requested, we don't necessarily advance this all the /// way. Instead, we advance it when an operation is requested; if the /// operation is acting on what should be a past-the-end iterator, - /// then we offer no guarantees, but this way we do not dererence a + /// then we offer no guarantees, but this way we do not dereference a /// past-the-end iterator when we move to a past-the-end position. mutable Iterator Current; @@ -98,7 +98,7 @@ public: friend bool operator==(specific_attr_iterator Left, specific_attr_iterator Right) { - assert((Left.Current == 0) == (Right.Current == 0)); + assert((Left.Current == nullptr) == (Right.Current == nullptr)); if (Left.Current < Right.Current) Left.AdvanceToNext(Right.Current); else @@ -134,7 +134,7 @@ inline SpecificAttr *getSpecificAttr(const Container& container) { if (i != specific_attr_end<SpecificAttr>(container)) return *i; else - return 0; + return nullptr; } } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h index dbe4ad0..37f6748 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h +++ b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h @@ -177,8 +177,8 @@ public: bool RecordPaths = true, bool DetectVirtual = true) : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), - DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0), - NumDeclsFound(0) { } + DetectVirtual(DetectVirtual), DetectedVirtual(nullptr), + DeclsFound(nullptr), NumDeclsFound(0) { } ~CXXBasePaths() { delete [] DeclsFound; } @@ -190,8 +190,8 @@ public: CXXBasePath& front() { return Paths.front(); } const CXXBasePath& front() const { return Paths.front(); } - decl_iterator found_decls_begin(); - decl_iterator found_decls_end(); + typedef llvm::iterator_range<decl_iterator> decl_range; + decl_range found_decls(); /// \brief Determine whether the path from the most-derived type to the /// given base type is ambiguous (i.e., it refers to multiple subobjects of @@ -232,7 +232,8 @@ public: /// \brief Uniquely identifies a virtual method within a class /// hierarchy by the method itself and a class subobject number. struct UniqueVirtualMethod { - UniqueVirtualMethod() : Method(0), Subobject(0), InVirtualSubobject(0) { } + UniqueVirtualMethod() + : Method(nullptr), Subobject(0), InVirtualSubobject(nullptr) { } UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject, const CXXRecordDecl *InVirtualSubobject) diff --git a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h index 9c699b7..7cccef6 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h +++ b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h @@ -17,7 +17,6 @@ #include "clang/AST/Type.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/type_traits.h" #include <iterator> namespace clang { @@ -60,9 +59,9 @@ public: /// \brief Converting constructor that permits implicit upcasting of /// canonical type pointers. - template<typename U> - CanQual(const CanQual<U>& Other, - typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0); + template <typename U> + CanQual(const CanQual<U> &Other, + typename std::enable_if<std::is_base_of<T, U>::value, int>::type = 0); /// \brief Retrieve the underlying type pointer, which refers to a /// canonical type. @@ -541,39 +540,39 @@ struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { template<> struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) }; template<> struct CanProxyAdaptor<FunctionNoProtoType> : public CanProxyBase<FunctionNoProtoType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) }; template<> struct CanProxyAdaptor<FunctionProtoType> : public CanProxyBase<FunctionProtoType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs) - CanQualType getArgType(unsigned i) const { - return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i)); + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams) + CanQualType getParamType(unsigned i) const { + return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i)); } LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals) - typedef CanTypeIterator<FunctionProtoType::arg_type_iterator> - arg_type_iterator; + typedef CanTypeIterator<FunctionProtoType::param_type_iterator> + param_type_iterator; - arg_type_iterator arg_type_begin() const { - return arg_type_iterator(this->getTypePtr()->arg_type_begin()); + param_type_iterator param_type_begin() const { + return param_type_iterator(this->getTypePtr()->param_type_begin()); } - arg_type_iterator arg_type_end() const { - return arg_type_iterator(this->getTypePtr()->arg_type_end()); + param_type_iterator param_type_end() const { + return param_type_iterator(this->getTypePtr()->param_type_end()); } // Note: canonical function types never have exception specifications diff --git a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h index 09ff682..72ca9f5 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h +++ b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h @@ -165,7 +165,7 @@ namespace clang { /// RoundUpToAlignment - Returns the next integer (mod 2**64) that is /// greater than or equal to this quantity and is a multiple of \p Align. /// Align must be non-zero. - CharUnits RoundUpToAlignment(const CharUnits &Align) { + CharUnits RoundUpToAlignment(const CharUnits &Align) const { return CharUnits(llvm::RoundUpToAlignment(Quantity, Align.Quantity)); } @@ -173,12 +173,7 @@ namespace clang { /// Given that this is a non-zero alignment value, what is the /// alignment at the given offset? CharUnits alignmentAtOffset(CharUnits offset) { - // alignment: 0010000 - // offset: 1011100 - // lowBits: 0001011 - // result: 0000100 - QuantityType lowBits = (Quantity-1) & (offset.Quantity-1); - return CharUnits((lowBits + 1) & ~lowBits); + return CharUnits(llvm::MinAlign(Quantity, offset.Quantity)); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/Comment.h b/contrib/llvm/tools/clang/include/clang/AST/Comment.h index 28849f5..e18fe9a 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Comment.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Comment.h @@ -100,16 +100,26 @@ protected: }; enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 }; + class HTMLTagCommentBitfields { + friend class HTMLTagComment; + + unsigned : NumInlineContentCommentBits; + + /// True if we found that this tag is malformed in some way. + unsigned IsMalformed : 1; + }; + enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 }; + class HTMLStartTagCommentBitfields { friend class HTMLStartTagComment; - unsigned : NumInlineContentCommentBits; + unsigned : NumHTMLTagCommentBits; /// 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 }; + enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 }; class ParagraphCommentBitfields { friend class ParagraphComment; @@ -155,6 +165,7 @@ protected: InlineContentCommentBitfields InlineContentCommentBits; TextCommentBitfields TextCommentBits; InlineCommandCommentBitfields InlineCommandCommentBits; + HTMLTagCommentBitfields HTMLTagCommentBits; HTMLStartTagCommentBitfields HTMLStartTagCommentBits; ParagraphCommentBitfields ParagraphCommentBits; BlockCommandCommentBitfields BlockCommandCommentBits; @@ -194,9 +205,9 @@ public: const char *getCommentKindName() const; - LLVM_ATTRIBUTE_USED void dump() const; - LLVM_ATTRIBUTE_USED void dumpColor() const; - LLVM_ATTRIBUTE_USED void dump(const ASTContext &Context) const; + void dump() const; + void dumpColor() const; + void dump(const ASTContext &Context) const; void dump(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) const; @@ -267,9 +278,9 @@ public: return C->getCommentKind() == TextCommentKind; } - child_iterator child_begin() const { return NULL; } + child_iterator child_begin() const { return nullptr; } - child_iterator child_end() const { return NULL; } + child_iterator child_end() const { return nullptr; } StringRef getText() const LLVM_READONLY { return Text; } @@ -325,9 +336,9 @@ public: return C->getCommentKind() == InlineCommandCommentKind; } - child_iterator child_begin() const { return NULL; } + child_iterator child_begin() const { return nullptr; } - child_iterator child_end() const { return NULL; } + child_iterator child_end() const { return nullptr; } unsigned getCommandID() const { return InlineCommandCommentBits.CommandID; @@ -360,8 +371,7 @@ public: }; /// 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. +/// treated as inline content (regardless HTML semantics). class HTMLTagComment : public InlineContentComment { protected: StringRef TagName; @@ -377,6 +387,7 @@ protected: TagName(TagName), TagNameRange(TagNameBegin, TagNameEnd) { setLocation(TagNameBegin); + HTMLTagCommentBits.IsMalformed = 0; } public: @@ -392,6 +403,14 @@ public: return SourceRange(L.getLocWithOffset(1), L.getLocWithOffset(1 + TagName.size())); } + + bool isMalformed() const { + return HTMLTagCommentBits.IsMalformed; + } + + void setIsMalformed() { + HTMLTagCommentBits.IsMalformed = 1; + } }; /// An opening HTML tag with attributes. @@ -450,9 +469,9 @@ public: return C->getCommentKind() == HTMLStartTagCommentKind; } - child_iterator child_begin() const { return NULL; } + child_iterator child_begin() const { return nullptr; } - child_iterator child_end() const { return NULL; } + child_iterator child_end() const { return nullptr; } unsigned getNumAttrs() const { return Attributes.size(); @@ -505,9 +524,9 @@ public: return C->getCommentKind() == HTMLEndTagCommentKind; } - child_iterator child_begin() const { return NULL; } + child_iterator child_begin() const { return nullptr; } - child_iterator child_end() const { return NULL; } + child_iterator child_end() const { return nullptr; } }; /// Block content (contains inline content). @@ -601,7 +620,7 @@ protected: unsigned CommandID, CommandMarkerKind CommandMarker) : BlockContentComment(K, LocBegin, LocEnd), - Paragraph(NULL) { + Paragraph(nullptr) { setLocation(getCommandNameBeginLoc()); BlockCommandCommentBits.CommandID = CommandID; BlockCommandCommentBits.CommandMarker = CommandMarker; @@ -613,7 +632,7 @@ public: unsigned CommandID, CommandMarkerKind CommandMarker) : BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), - Paragraph(NULL) { + Paragraph(nullptr) { setLocation(getCommandNameBeginLoc()); BlockCommandCommentBits.CommandID = CommandID; BlockCommandCommentBits.CommandMarker = CommandMarker; @@ -699,7 +718,7 @@ private: unsigned ParamIndex; public: - enum LLVM_ENUM_INT_TYPE(unsigned) { + enum : unsigned { InvalidParamIndex = ~0U, VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U }; @@ -861,9 +880,9 @@ public: return C->getCommentKind() == VerbatimBlockLineCommentKind; } - child_iterator child_begin() const { return NULL; } + child_iterator child_begin() const { return nullptr; } - child_iterator child_end() const { return NULL; } + child_iterator child_end() const { return nullptr; } StringRef getText() const LLVM_READONLY { return Text; @@ -948,9 +967,9 @@ public: return C->getCommentKind() == VerbatimLineCommentKind; } - child_iterator child_begin() const { return NULL; } + child_iterator child_begin() const { return nullptr; } - child_iterator child_end() const { return NULL; } + child_iterator child_end() const { return nullptr; } StringRef getText() const { return Text; @@ -981,9 +1000,9 @@ struct DeclInfo { /// that we consider a "function". ArrayRef<const ParmVarDecl *> ParamVars; - /// Function result type if \c CommentDecl is something that we consider + /// Function return type if \c CommentDecl is something that we consider /// a "function". - QualType ResultType; + QualType ReturnType; /// Template parameters that can be referenced by \\tparam if \c CommentDecl is /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentCommands.td b/contrib/llvm/tools/clang/include/clang/AST/CommentCommands.td index ed323da..958ee03 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CommentCommands.td +++ b/contrib/llvm/tools/clang/include/clang/AST/CommentCommands.td @@ -146,7 +146,7 @@ def Todo : BlockCommand<"todo">; def Version : BlockCommand<"version">; def Warning : BlockCommand<"warning">; // HeaderDoc commands -def Abstract : BlockCommand<"abstract">; +def Abstract : BlockCommand<"abstract"> { let IsBriefCommand = 1; } def ClassDesign : RecordLikeDetailCommand<"classdesign">; def CoClass : RecordLikeDetailCommand<"coclass">; def Dependency : RecordLikeDetailCommand<"dependency">; diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLTags.td b/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLTags.td index f98e32d..2514900 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLTags.td +++ b/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLTags.td @@ -52,3 +52,16 @@ def Tr : Tag<"tr"> { let EndTagOptional = 1; } def Th : Tag<"th"> { let EndTagOptional = 1; } def Td : Tag<"td"> { let EndTagOptional = 1; } +// Define a blacklist of attributes that are not safe to pass through to HTML +// output if the input is untrusted. +// +// FIXME: this should be a whitelist. When changing this to a whitelist, don't +// forget to change the default in the TableGen backend. +class Attribute<string spelling> { + string Spelling = spelling; + bit IsSafeToPassThrough = 1; +} +class EventHandlerContentAttribute<string spelling> : Attribute<spelling> { + let IsSafeToPassThrough = 0; +} + diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h b/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h index f152c77..a6e3ed8 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h +++ b/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h @@ -14,8 +14,8 @@ #ifndef LLVM_CLANG_AST_COMMENT_LEXER_H #define LLVM_CLANG_AST_COMMENT_LEXER_H -#include "clang/Basic/SourceManager.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -293,17 +293,7 @@ private: 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.TextPtr = "<UNSET>"; - Result.IntVal = 7; -#endif - BufferPtr = TokEnd; - } + tok::TokenKind Kind); void formTextToken(Token &Result, const char *TokEnd) { StringRef Text(BufferPtr, TokEnd - BufferPtr); @@ -362,7 +352,7 @@ public: StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr, - bool *Invalid = NULL) const; + bool *Invalid = nullptr) const; }; } // end namespace comments diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h b/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h index 3910960..027c3b9 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h +++ b/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h @@ -84,8 +84,8 @@ public: 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); + } + return ArrayRef<T>(); } ParagraphComment *actOnParagraphComment( diff --git a/contrib/llvm/tools/clang/include/clang/AST/DataRecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/DataRecursiveASTVisitor.h new file mode 100644 index 0000000..9ef0087 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -0,0 +1,2519 @@ +//===--- DataRecursiveASTVisitor.h - Data-Recursive AST Visitor -*- 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 DataRecursiveASTVisitor interface, which recursively +// traverses the entire AST, using data recursion for Stmts/Exprs. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_H +#define LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_H + +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" + +// The following three macros are used for meta programming. The code +// using them is responsible for defining macro OPERATOR(). + +// All unary operators. +#define UNARYOP_LIST() \ + OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \ + OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \ + OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \ + OPERATOR(Extension) + +// All binary operators (excluding compound assign operators). +#define BINOP_LIST() \ + OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \ + OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \ + OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \ + OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) OPERATOR(LAnd) \ + OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma) + +// All compound assign operators. +#define CAO_LIST() \ + OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \ + OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) + +namespace clang { + +// Reduce the diff between RecursiveASTVisitor / DataRecursiveASTVisitor to +// make it easier to track changes and keep the two in sync. +#define RecursiveASTVisitor DataRecursiveASTVisitor + +// A helper macro to implement short-circuiting when recursing. It +// invokes CALL_EXPR, which must be a method call, on the derived +// object (s.t. a user of RecursiveASTVisitor can override the method +// in CALL_EXPR). +#define TRY_TO(CALL_EXPR) \ + do { \ + if (!getDerived().CALL_EXPR) \ + return false; \ + } while (0) + +/// \brief A class that does preorder depth-first traversal on the +/// entire Clang AST and visits each node. +/// +/// This class performs three distinct tasks: +/// 1. traverse the AST (i.e. go to each node); +/// 2. at a given node, walk up the class hierarchy, starting from +/// the node's dynamic type, until the top-most class (e.g. Stmt, +/// Decl, or Type) is reached. +/// 3. given a (node, class) combination, where 'class' is some base +/// class of the dynamic type of 'node', call a user-overridable +/// function to actually visit the node. +/// +/// These tasks are done by three groups of methods, respectively: +/// 1. TraverseDecl(Decl *x) does task #1. It is the entry point +/// for traversing an AST rooted at x. This method simply +/// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo +/// is the dynamic type of *x, which calls WalkUpFromFoo(x) and +/// then recursively visits the child nodes of x. +/// TraverseStmt(Stmt *x) and TraverseType(QualType x) work +/// similarly. +/// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit +/// any child node of x. Instead, it first calls WalkUpFromBar(x) +/// where Bar is the direct parent class of Foo (unless Foo has +/// no parent), and then calls VisitFoo(x) (see the next list item). +/// 3. VisitFoo(Foo *x) does task #3. +/// +/// These three method groups are tiered (Traverse* > WalkUpFrom* > +/// Visit*). A method (e.g. Traverse*) may call methods from the same +/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*). +/// It may not call methods from a higher tier. +/// +/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar +/// is Foo's super class) before calling VisitFoo(), the result is +/// that the Visit*() methods for a given node are called in the +/// top-down order (e.g. for a node of type NamespaceDecl, the order will +/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). +/// +/// This scheme guarantees that all Visit*() calls for the same AST +/// node are grouped together. In other words, Visit*() methods for +/// different nodes are never interleaved. +/// +/// Stmts are traversed internally using a data queue to avoid a stack overflow +/// with hugely nested ASTs. +/// +/// Clients of this visitor should subclass the visitor (providing +/// themselves as the template argument, using the curiously recurring +/// template pattern) and override any of the Traverse*, WalkUpFrom*, +/// and Visit* methods for declarations, types, statements, +/// expressions, or other AST nodes where the visitor should customize +/// behavior. Most users only need to override Visit*. Advanced +/// users may override Traverse* and WalkUpFrom* to implement custom +/// traversal strategies. Returning false from one of these overridden +/// functions will abort the entire traversal. +/// +/// By default, this visitor tries to visit every part of the explicit +/// source code exactly once. The default policy towards templates +/// is to descend into the 'pattern' class or function body, not any +/// explicit or implicit instantiations. Explicit specializations +/// are still visited, and the patterns of partial specializations +/// are visited separately. This behavior can be changed by +/// overriding shouldVisitTemplateInstantiations() in the derived class +/// to return true, in which case all known implicit and explicit +/// instantiations will be visited at the same time as the pattern +/// from which they were produced. +template <typename Derived> class RecursiveASTVisitor { +public: + /// \brief Return a reference to the derived class. + Derived &getDerived() { return *static_cast<Derived *>(this); } + + /// \brief Return whether this visitor should recurse into + /// template instantiations. + bool shouldVisitTemplateInstantiations() const { return false; } + + /// \brief Return whether this visitor should recurse into the types of + /// TypeLocs. + bool shouldWalkTypesOfTypeLocs() const { return true; } + + /// \brief Recursively visit a statement or expression, by + /// dispatching to Traverse*() based on the argument's dynamic type. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is NULL). + bool TraverseStmt(Stmt *S); + + /// \brief Recursively visit a type, by dispatching to + /// Traverse*Type() based on the argument's getTypeClass() property. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is a Null type). + bool TraverseType(QualType T); + + /// \brief Recursively visit a type with location, by dispatching to + /// Traverse*TypeLoc() based on the argument type's getTypeClass() property. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is a Null type location). + bool TraverseTypeLoc(TypeLoc TL); + + /// \brief Recursively visit an attribute, by dispatching to + /// Traverse*Attr() based on the argument's dynamic type. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is a Null type location). + bool TraverseAttr(Attr *At); + + /// \brief Recursively visit a declaration, by dispatching to + /// Traverse*Decl() based on the argument's dynamic type. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is NULL). + bool TraverseDecl(Decl *D); + + /// \brief Recursively visit a C++ nested-name-specifier. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); + + /// \brief Recursively visit a C++ nested-name-specifier with location + /// information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); + + /// \brief Recursively visit a name with its location information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); + + /// \brief Recursively visit a template name and dispatch to the + /// appropriate method. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseTemplateName(TemplateName Template); + + /// \brief Recursively visit a template argument and dispatch to the + /// appropriate method for the argument type. + /// + /// \returns false if the visitation was terminated early, true otherwise. + // FIXME: migrate callers to TemplateArgumentLoc instead. + bool TraverseTemplateArgument(const TemplateArgument &Arg); + + /// \brief Recursively visit a template argument location and dispatch to the + /// appropriate method for the argument type. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); + + /// \brief Recursively visit a set of template arguments. + /// This can be overridden by a subclass, but it's not expected that + /// will be needed -- this visitor always dispatches to another. + /// + /// \returns false if the visitation was terminated early, true otherwise. + // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. + bool TraverseTemplateArguments(const TemplateArgument *Args, + unsigned NumArgs); + + /// \brief Recursively visit a constructor initializer. This + /// automatically dispatches to another visitor for the initializer + /// expression, but not for the name of the initializer, so may + /// be overridden for clients that need access to the name. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseConstructorInitializer(CXXCtorInitializer *Init); + + /// \brief Recursively visit a lambda capture. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C); + + /// \brief Recursively visit the body of a lambda expression. + /// + /// This provides a hook for visitors that need more context when visiting + /// \c LE->getBody(). + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseLambdaBody(LambdaExpr *LE); + + // ---- Methods on Attrs ---- + + // \brief Visit an attribute. + bool VisitAttr(Attr *A) { return true; } + +// Declare Traverse* and empty Visit* for all Attr classes. +#define ATTR_VISITOR_DECLS_ONLY +#include "clang/AST/AttrVisitor.inc" +#undef ATTR_VISITOR_DECLS_ONLY + +// ---- Methods on Stmts ---- + +// Declare Traverse*() for all concrete Stmt classes. +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S); +#include "clang/AST/StmtNodes.inc" + // The above header #undefs ABSTRACT_STMT and STMT upon exit. + + // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. + bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } + bool VisitStmt(Stmt *S) { return true; } +#define STMT(CLASS, PARENT) \ + bool WalkUpFrom##CLASS(CLASS *S) { \ + TRY_TO(WalkUpFrom##PARENT(S)); \ + TRY_TO(Visit##CLASS(S)); \ + return true; \ + } \ + bool Visit##CLASS(CLASS *S) { return true; } +#include "clang/AST/StmtNodes.inc" + +// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary +// operator methods. Unary operators are not classes in themselves +// (they're all opcodes in UnaryOperator) but do have visitors. +#define OPERATOR(NAME) \ + bool TraverseUnary##NAME(UnaryOperator *S) { \ + TRY_TO(WalkUpFromUnary##NAME(S)); \ + StmtQueueAction StmtQueue(*this); \ + StmtQueue.queue(S->getSubExpr()); \ + return true; \ + } \ + bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ + TRY_TO(WalkUpFromUnaryOperator(S)); \ + TRY_TO(VisitUnary##NAME(S)); \ + return true; \ + } \ + bool VisitUnary##NAME(UnaryOperator *S) { return true; } + + UNARYOP_LIST() +#undef OPERATOR + +// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary +// operator methods. Binary operators are not classes in themselves +// (they're all opcodes in BinaryOperator) but do have visitors. +#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ + bool TraverseBin##NAME(BINOP_TYPE *S) { \ + TRY_TO(WalkUpFromBin##NAME(S)); \ + StmtQueueAction StmtQueue(*this); \ + StmtQueue.queue(S->getLHS()); \ + StmtQueue.queue(S->getRHS()); \ + return true; \ + } \ + bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ + TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \ + TRY_TO(VisitBin##NAME(S)); \ + return true; \ + } \ + bool VisitBin##NAME(BINOP_TYPE *S) { return true; } + +#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator) + BINOP_LIST() +#undef OPERATOR + +// Define Traverse*(), WalkUpFrom*(), and Visit*() for compound +// assignment methods. Compound assignment operators are not +// classes in themselves (they're all opcodes in +// CompoundAssignOperator) but do have visitors. +#define OPERATOR(NAME) \ + GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator) + + CAO_LIST() +#undef OPERATOR +#undef GENERAL_BINOP_FALLBACK + +// ---- Methods on Types ---- +// FIXME: revamp to take TypeLoc's rather than Types. + +// Declare Traverse*() for all concrete Type classes. +#define ABSTRACT_TYPE(CLASS, BASE) +#define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T); +#include "clang/AST/TypeNodes.def" + // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. + + // Define WalkUpFrom*() and empty Visit*() for all Type classes. + bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); } + bool VisitType(Type *T) { return true; } +#define TYPE(CLASS, BASE) \ + bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ + TRY_TO(WalkUpFrom##BASE(T)); \ + TRY_TO(Visit##CLASS##Type(T)); \ + return true; \ + } \ + bool Visit##CLASS##Type(CLASS##Type *T) { return true; } +#include "clang/AST/TypeNodes.def" + +// ---- Methods on TypeLocs ---- +// FIXME: this currently just calls the matching Type methods + +// Declare Traverse*() for all concrete TypeLoc classes. +#define ABSTRACT_TYPELOC(CLASS, BASE) +#define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); +#include "clang/AST/TypeLocNodes.def" + // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit. + + // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes. + bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); } + bool VisitTypeLoc(TypeLoc TL) { return true; } + + // QualifiedTypeLoc and UnqualTypeLoc are not declared in + // TypeNodes.def and thus need to be handled specially. + bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) { + return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); + } + bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; } + bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) { + return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); + } + bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; } + +// Note that BASE includes trailing 'Type' which CLASS doesn't. +#define TYPE(CLASS, BASE) \ + bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ + TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ + TRY_TO(Visit##CLASS##TypeLoc(TL)); \ + return true; \ + } \ + bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } +#include "clang/AST/TypeNodes.def" + +// ---- Methods on Decls ---- + +// Declare Traverse*() for all concrete Decl classes. +#define ABSTRACT_DECL(DECL) +#define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D); +#include "clang/AST/DeclNodes.inc" + // The above header #undefs ABSTRACT_DECL and DECL upon exit. + + // Define WalkUpFrom*() and empty Visit*() for all Decl classes. + bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } + bool VisitDecl(Decl *D) { return true; } +#define DECL(CLASS, BASE) \ + bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ + TRY_TO(WalkUpFrom##BASE(D)); \ + TRY_TO(Visit##CLASS##Decl(D)); \ + return true; \ + } \ + bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } +#include "clang/AST/DeclNodes.inc" + +private: + // These are helper methods used by more than one Traverse* method. + bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); + bool TraverseClassInstantiations(ClassTemplateDecl *D); + bool TraverseVariableInstantiations(VarTemplateDecl *D); + bool TraverseFunctionInstantiations(FunctionTemplateDecl *D); + bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, + unsigned Count); + bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); + bool TraverseRecordHelper(RecordDecl *D); + bool TraverseCXXRecordHelper(CXXRecordDecl *D); + bool TraverseDeclaratorHelper(DeclaratorDecl *D); + bool TraverseDeclContextHelper(DeclContext *DC); + bool TraverseFunctionHelper(FunctionDecl *D); + bool TraverseVarHelper(VarDecl *D); + bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); + bool TraverseOMPClause(OMPClause *C); +#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C); +#include "clang/Basic/OpenMPKinds.def" + /// \brief Process clauses with list of variables. + template <typename T> bool VisitOMPClauseList(T *Node); + + typedef SmallVector<Stmt *, 16> StmtsTy; + typedef SmallVector<StmtsTy *, 4> QueuesTy; + + QueuesTy Queues; + + class NewQueueRAII { + RecursiveASTVisitor &RAV; + + public: + NewQueueRAII(StmtsTy &queue, RecursiveASTVisitor &RAV) : RAV(RAV) { + RAV.Queues.push_back(&queue); + } + ~NewQueueRAII() { RAV.Queues.pop_back(); } + }; + + StmtsTy &getCurrentQueue() { + assert(!Queues.empty() && "base TraverseStmt was never called?"); + return *Queues.back(); + } + +public: + class StmtQueueAction { + StmtsTy &CurrQueue; + + public: + explicit StmtQueueAction(RecursiveASTVisitor &RAV) + : CurrQueue(RAV.getCurrentQueue()) {} + + void queue(Stmt *S) { CurrQueue.push_back(S); } + }; +}; + +#define DISPATCH(NAME, CLASS, VAR) \ + return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)) + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { + if (!S) + return true; + + StmtsTy Queue, StmtsToEnqueue; + Queue.push_back(S); + NewQueueRAII NQ(StmtsToEnqueue, *this); + + while (!Queue.empty()) { + S = Queue.pop_back_val(); + if (!S) + continue; + + StmtsToEnqueue.clear(); + +#define DISPATCH_STMT(NAME, CLASS, VAR) \ + TRY_TO(Traverse##NAME(static_cast<CLASS *>(VAR))); \ + break + + // If we have a binary expr, dispatch to the subcode of the binop. A smart + // optimizer (e.g. LLVM) will fold this comparison into the switch stmt + // below. + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { + switch (BinOp->getOpcode()) { +#define OPERATOR(NAME) \ + case BO_##NAME: \ + DISPATCH_STMT(Bin##NAME, BinaryOperator, S); + + BINOP_LIST() +#undef OPERATOR +#undef BINOP_LIST + +#define OPERATOR(NAME) \ + case BO_##NAME##Assign: \ + DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); + + CAO_LIST() +#undef OPERATOR +#undef CAO_LIST + } + } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { + switch (UnOp->getOpcode()) { +#define OPERATOR(NAME) \ + case UO_##NAME: \ + DISPATCH_STMT(Unary##NAME, UnaryOperator, S); + + UNARYOP_LIST() +#undef OPERATOR +#undef UNARYOP_LIST + } + } else { + + // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. + switch (S->getStmtClass()) { + case Stmt::NoStmtClass: + break; +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS##Class: \ + DISPATCH_STMT(CLASS, CLASS, S); +#include "clang/AST/StmtNodes.inc" + } + } + + for (SmallVectorImpl<Stmt *>::reverse_iterator RI = StmtsToEnqueue.rbegin(), + RE = StmtsToEnqueue.rend(); + RI != RE; ++RI) + Queue.push_back(*RI); + } + + return true; +} + +#undef DISPATCH_STMT + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { + if (T.isNull()) + return true; + + switch (T->getTypeClass()) { +#define ABSTRACT_TYPE(CLASS, BASE) +#define TYPE(CLASS, BASE) \ + case Type::CLASS: \ + DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr())); +#include "clang/AST/TypeNodes.def" + } + + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { + if (TL.isNull()) + return true; + + switch (TL.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, BASE) +#define TYPELOC(CLASS, BASE) \ + case TypeLoc::CLASS: \ + return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>()); +#include "clang/AST/TypeLocNodes.def" + } + + return true; +} + +// Define the Traverse*Attr(Attr* A) methods +#define VISITORCLASS RecursiveASTVisitor +#include "clang/AST/AttrVisitor.inc" +#undef VISITORCLASS + +template <typename Derived> +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()) + return true; + + switch (D->getKind()) { +#define ABSTRACT_DECL(DECL) +#define DECL(CLASS, BASE) \ + case Decl::CLASS: \ + if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \ + return false; \ + break; +#include "clang/AST/DeclNodes.inc" + } + + // Visit any attributes attached to this declaration. + for (auto *I : D->attrs()) { + if (!getDerived().TraverseAttr(I)) + return false; + } + return true; +} + +#undef DISPATCH + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( + NestedNameSpecifier *NNS) { + if (!NNS) + return true; + + if (NNS->getPrefix()) + TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix())); + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Global: + return true; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); + } + + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS) { + if (!NNS) + return true; + + if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) + TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); + + switch (NNS.getNestedNameSpecifier()->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Global: + return true; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); + break; + } + + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( + DeclarationNameInfo NameInfo) { + switch (NameInfo.getName().getNameKind()) { + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) + TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc())); + + break; + + case DeclarationName::Identifier: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXUsingDirective: + break; + } + + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier())); + + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( + const TemplateArgument &Arg) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + case TemplateArgument::NullPtr: + return true; + + case TemplateArgument::Type: + return getDerived().TraverseType(Arg.getAsType()); + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + return getDerived().TraverseTemplateName( + Arg.getAsTemplateOrTemplatePattern()); + + case TemplateArgument::Expression: + return getDerived().TraverseStmt(Arg.getAsExpr()); + + case TemplateArgument::Pack: + return getDerived().TraverseTemplateArguments(Arg.pack_begin(), + Arg.pack_size()); + } + + return true; +} + +// FIXME: no template name location? +// FIXME: no source locations for a template argument pack? +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( + const TemplateArgumentLoc &ArgLoc) { + const TemplateArgument &Arg = ArgLoc.getArgument(); + + switch (Arg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + case TemplateArgument::NullPtr: + return true; + + case TemplateArgument::Type: { + // FIXME: how can TSI ever be NULL? + if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) + return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); + else + return getDerived().TraverseType(Arg.getAsType()); + } + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + if (ArgLoc.getTemplateQualifierLoc()) + TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( + ArgLoc.getTemplateQualifierLoc())); + return getDerived().TraverseTemplateName( + Arg.getAsTemplateOrTemplatePattern()); + + case TemplateArgument::Expression: + return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); + + case TemplateArgument::Pack: + return getDerived().TraverseTemplateArguments(Arg.pack_begin(), + Arg.pack_size()); + } + + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( + const TemplateArgument *Args, unsigned NumArgs) { + for (unsigned I = 0; I != NumArgs; ++I) { + TRY_TO(TraverseTemplateArgument(Args[I])); + } + + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( + CXXCtorInitializer *Init) { + if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); + + if (Init->isWritten()) + TRY_TO(TraverseStmt(Init->getInit())); + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE, + const LambdaCapture *C) { + if (C->isInitCapture()) + TRY_TO(TraverseDecl(C->getCapturedVar())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) { + StmtQueueAction StmtQueue(*this); + StmtQueue.queue(LE->getBody()); + return true; +} + +// ----------------- Type traversal ----------------- + +// This macro makes available a variable T, the passed-in type. +#define DEF_TRAVERSE_TYPE(TYPE, CODE) \ + template <typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \ + TRY_TO(WalkUpFrom##TYPE(T)); \ + { CODE; } \ + return true; \ + } + +DEF_TRAVERSE_TYPE(BuiltinType, {}) + +DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); }) + +DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) + +DEF_TRAVERSE_TYPE(BlockPointerType, + { TRY_TO(TraverseType(T->getPointeeType())); }) + +DEF_TRAVERSE_TYPE(LValueReferenceType, + { TRY_TO(TraverseType(T->getPointeeType())); }) + +DEF_TRAVERSE_TYPE(RValueReferenceType, + { TRY_TO(TraverseType(T->getPointeeType())); }) + +DEF_TRAVERSE_TYPE(MemberPointerType, { + TRY_TO(TraverseType(QualType(T->getClass(), 0))); + TRY_TO(TraverseType(T->getPointeeType())); +}) + +DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); }) + +DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); }) + +DEF_TRAVERSE_TYPE(ConstantArrayType, + { TRY_TO(TraverseType(T->getElementType())); }) + +DEF_TRAVERSE_TYPE(IncompleteArrayType, + { TRY_TO(TraverseType(T->getElementType())); }) + +DEF_TRAVERSE_TYPE(VariableArrayType, { + TRY_TO(TraverseType(T->getElementType())); + TRY_TO(TraverseStmt(T->getSizeExpr())); +}) + +DEF_TRAVERSE_TYPE(DependentSizedArrayType, { + TRY_TO(TraverseType(T->getElementType())); + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); +}) + +DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); + TRY_TO(TraverseType(T->getElementType())); +}) + +DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); }) + +DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); }) + +DEF_TRAVERSE_TYPE(FunctionNoProtoType, + { TRY_TO(TraverseType(T->getReturnType())); }) + +DEF_TRAVERSE_TYPE(FunctionProtoType, { + TRY_TO(TraverseType(T->getReturnType())); + + for (const auto &A : T->param_types()) { + TRY_TO(TraverseType(A)); + } + + for (const auto &E : T->exceptions()) { + TRY_TO(TraverseType(E)); + } +}) + +DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) +DEF_TRAVERSE_TYPE(TypedefType, {}) + +DEF_TRAVERSE_TYPE(TypeOfExprType, + { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) + +DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); }) + +DEF_TRAVERSE_TYPE(DecltypeType, + { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) + +DEF_TRAVERSE_TYPE(UnaryTransformType, { + TRY_TO(TraverseType(T->getBaseType())); + TRY_TO(TraverseType(T->getUnderlyingType())); +}) + +DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); }) + +DEF_TRAVERSE_TYPE(RecordType, {}) +DEF_TRAVERSE_TYPE(EnumType, {}) +DEF_TRAVERSE_TYPE(TemplateTypeParmType, {}) +DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {}) +DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {}) + +DEF_TRAVERSE_TYPE(TemplateSpecializationType, { + TRY_TO(TraverseTemplateName(T->getTemplateName())); + TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); +}) + +DEF_TRAVERSE_TYPE(InjectedClassNameType, {}) + +DEF_TRAVERSE_TYPE(AttributedType, + { TRY_TO(TraverseType(T->getModifiedType())); }) + +DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); }) + +DEF_TRAVERSE_TYPE(ElaboratedType, { + if (T->getQualifier()) { + TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); + } + TRY_TO(TraverseType(T->getNamedType())); +}) + +DEF_TRAVERSE_TYPE(DependentNameType, + { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); }) + +DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { + TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); + TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); +}) + +DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) + +DEF_TRAVERSE_TYPE(ObjCInterfaceType, {}) + +DEF_TRAVERSE_TYPE(ObjCObjectType, { + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (T->getBaseType().getTypePtr() != T) + TRY_TO(TraverseType(T->getBaseType())); +}) + +DEF_TRAVERSE_TYPE(ObjCObjectPointerType, + { TRY_TO(TraverseType(T->getPointeeType())); }) + +DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) + +#undef DEF_TRAVERSE_TYPE + +// ----------------- TypeLoc traversal ----------------- + +// This macro makes available a variable TL, the passed-in TypeLoc. +// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc, +// in addition to WalkUpFrom* for the TypeLoc itself, such that existing +// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods +// continue to work. +#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ + template <typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ + if (getDerived().shouldWalkTypesOfTypeLocs()) \ + TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ + TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ + { CODE; } \ + return true; \ + } + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { + // Move this over to the 'main' typeloc tree. Note that this is a + // move -- we pretend that we were really looking at the unqualified + // typeloc all along -- rather than a recursion, so we don't follow + // the normal CRTP plan of going through + // getDerived().TraverseTypeLoc. If we did, we'd be traversing + // twice for the same type (once as a QualifiedTypeLoc version of + // the type, once as an UnqualifiedTypeLoc version of the type), + // which in effect means we'd call VisitTypeLoc twice with the + // 'same' type. This solves that problem, at the cost of never + // seeing the qualified version of the type (unless the client + // subclasses TraverseQualifiedTypeLoc themselves). It's not a + // perfect solution. A perfect solution probably requires making + // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a + // wrapper around Type* -- rather than being its own class in the + // type hierarchy. + return TraverseTypeLoc(TL.getUnqualifiedLoc()); +} + +DEF_TRAVERSE_TYPELOC(BuiltinType, {}) + +// FIXME: ComplexTypeLoc is unfinished +DEF_TRAVERSE_TYPELOC(ComplexType, { + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + +DEF_TRAVERSE_TYPELOC(PointerType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) + +DEF_TRAVERSE_TYPELOC(BlockPointerType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) + +DEF_TRAVERSE_TYPELOC(LValueReferenceType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) + +DEF_TRAVERSE_TYPELOC(RValueReferenceType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) + +// FIXME: location of base class? +// We traverse this in the type case as well, but how is it not reached through +// the pointee type? +DEF_TRAVERSE_TYPELOC(MemberPointerType, { + TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); + TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); +}) + +DEF_TRAVERSE_TYPELOC(AdjustedType, + { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) + +DEF_TRAVERSE_TYPELOC(DecayedType, + { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { + // This isn't available for ArrayType, but is for the ArrayTypeLoc. + TRY_TO(TraverseStmt(TL.getSizeExpr())); + return true; +} + +DEF_TRAVERSE_TYPELOC(ConstantArrayType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); +}) + +DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); +}) + +DEF_TRAVERSE_TYPELOC(VariableArrayType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); +}) + +DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); +}) + +// FIXME: order? why not size expr first? +// FIXME: base VectorTypeLoc is unfinished +DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { + if (TL.getTypePtr()->getSizeExpr()) + TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + +// FIXME: VectorTypeLoc is unfinished +DEF_TRAVERSE_TYPELOC(VectorType, { + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + +// FIXME: size and attributes +// FIXME: base VectorTypeLoc is unfinished +DEF_TRAVERSE_TYPELOC(ExtVectorType, { + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + +DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, + { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); }) + +// FIXME: location of exception specifications (attributes?) +DEF_TRAVERSE_TYPELOC(FunctionProtoType, { + TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); + + const FunctionProtoType *T = TL.getTypePtr(); + + for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) { + if (TL.getParam(I)) { + TRY_TO(TraverseDecl(TL.getParam(I))); + } else if (I < T->getNumParams()) { + TRY_TO(TraverseType(T->getParamType(I))); + } + } + + for (const auto &E : T->exceptions()) { + TRY_TO(TraverseType(E)); + } +}) + +DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) +DEF_TRAVERSE_TYPELOC(TypedefType, {}) + +DEF_TRAVERSE_TYPELOC(TypeOfExprType, + { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) + +DEF_TRAVERSE_TYPELOC(TypeOfType, { + TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); +}) + +// FIXME: location of underlying expr +DEF_TRAVERSE_TYPELOC(DecltypeType, { + TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); +}) + +DEF_TRAVERSE_TYPELOC(UnaryTransformType, { + TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_TYPELOC(AutoType, { + TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); +}) + +DEF_TRAVERSE_TYPELOC(RecordType, {}) +DEF_TRAVERSE_TYPELOC(EnumType, {}) +DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {}) +DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {}) +DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {}) + +// FIXME: use the loc for the template name? +DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { + TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); + } +}) + +DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {}) + +DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) + +DEF_TRAVERSE_TYPELOC(AttributedType, + { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) + +DEF_TRAVERSE_TYPELOC(ElaboratedType, { + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); + } + TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); +}) + +DEF_TRAVERSE_TYPELOC(DependentNameType, { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); +}) + +DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); + } + + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); + } +}) + +DEF_TRAVERSE_TYPELOC(PackExpansionType, + { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) + +DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) + +DEF_TRAVERSE_TYPELOC(ObjCObjectType, { + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) + TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); +}) + +DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) + +DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) + +#undef DEF_TRAVERSE_TYPELOC + +// ----------------- Decl traversal ----------------- +// +// For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing +// the children that come from the DeclContext associated with it. +// Therefore each Traverse* only needs to worry about children other +// than those. + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { + if (!DC) + return true; + + for (auto *Child : DC->decls()) { + // BlockDecls and CapturedDecls are traversed through BlockExprs and + // CapturedStmts respectively. + if (!isa<BlockDecl>(Child) && !isa<CapturedDecl>(Child)) + TRY_TO(TraverseDecl(Child)); + } + + return true; +} + +// This macro makes available a variable D, the passed-in decl. +#define DEF_TRAVERSE_DECL(DECL, CODE) \ + template <typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \ + TRY_TO(WalkUpFrom##DECL(D)); \ + { CODE; } \ + TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ + return true; \ + } + +DEF_TRAVERSE_DECL(AccessSpecDecl, {}) + +DEF_TRAVERSE_DECL(BlockDecl, { + if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); + TRY_TO(TraverseStmt(D->getBody())); + for (const auto &I : D->captures()) { + if (I.hasCopyExpr()) { + TRY_TO(TraverseStmt(I.getCopyExpr())); + } + } + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; +}) + +DEF_TRAVERSE_DECL(CapturedDecl, { + TRY_TO(TraverseStmt(D->getBody())); + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; +}) + +DEF_TRAVERSE_DECL(EmptyDecl, {}) + +DEF_TRAVERSE_DECL(FileScopeAsmDecl, + { TRY_TO(TraverseStmt(D->getAsmString())); }) + +DEF_TRAVERSE_DECL(ImportDecl, {}) + +DEF_TRAVERSE_DECL(FriendDecl, { + // Friend is either decl or a type. + if (D->getFriendType()) + TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); + else + TRY_TO(TraverseDecl(D->getFriendDecl())); +}) + +DEF_TRAVERSE_DECL(FriendTemplateDecl, { + if (D->getFriendType()) + TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); + else + TRY_TO(TraverseDecl(D->getFriendDecl())); + for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { + TemplateParameterList *TPL = D->getTemplateParameterList(I); + for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = TPL->end(); + ITPL != ETPL; ++ITPL) { + TRY_TO(TraverseDecl(*ITPL)); + } + } +}) + +DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, + { TRY_TO(TraverseDecl(D->getSpecialization())); }) + +DEF_TRAVERSE_DECL(LinkageSpecDecl, {}) + +DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this + }) + +DEF_TRAVERSE_DECL(StaticAssertDecl, { + TRY_TO(TraverseStmt(D->getAssertExpr())); + TRY_TO(TraverseStmt(D->getMessage())); +}) + +DEF_TRAVERSE_DECL( + TranslationUnitDecl, + {// Code in an unnamed namespace shows up automatically in + // decls_begin()/decls_end(). Thus we don't need to recurse on + // D->getAnonymousNamespace(). + }) + +DEF_TRAVERSE_DECL(NamespaceAliasDecl, { + // We shouldn't traverse an aliased namespace, since it will be + // defined (and, therefore, traversed) somewhere else. + // + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; +}) + +DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl. + }) + +DEF_TRAVERSE_DECL( + NamespaceDecl, + {// Code in an unnamed namespace shows up automatically in + // decls_begin()/decls_end(). Thus we don't need to recurse on + // D->getAnonymousNamespace(). + }) + +DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCMethodDecl, { + if (D->getReturnTypeSourceInfo()) { + TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc())); + } + for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + if (D->isThisDeclarationADefinition()) { + TRY_TO(TraverseStmt(D->getBody())); + } + return true; +}) + +DEF_TRAVERSE_DECL(ObjCPropertyDecl, { + if (D->getTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + else + TRY_TO(TraverseType(D->getType())); + return true; +}) + +DEF_TRAVERSE_DECL(UsingDecl, { + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); +}) + +DEF_TRAVERSE_DECL(UsingDirectiveDecl, { + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); +}) + +DEF_TRAVERSE_DECL(UsingShadowDecl, {}) + +DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { + for (auto *I : D->varlists()) { + TRY_TO(TraverseStmt(I)); + } +}) + +// A helper method for TemplateDecl's children. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( + TemplateParameterList *TPL) { + if (TPL) { + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + } + return true; +} + +// A helper method for traversing the implicit instantiations of a +// class template. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations( + ClassTemplateDecl *D) { + for (auto *SD : D->specializations()) { + for (auto *RD : SD->redecls()) { + // We don't want to visit injected-class-names in this traversal. + if (cast<CXXRecordDecl>(RD)->isInjectedClassName()) + continue; + + switch ( + cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) { + // Visit the implicit instantiations with the requested pattern. + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + TRY_TO(TraverseDecl(RD)); + break; + + // We don't need to do anything on an explicit instantiation + // or explicit specialization because there will be an explicit + // node for it elsewhere. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + break; + } + } + } + + return true; +} + +DEF_TRAVERSE_DECL(ClassTemplateDecl, { + CXXRecordDecl *TempDecl = D->getTemplatedDecl(); + TRY_TO(TraverseDecl(TempDecl)); + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + + // 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. + // + // 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 + // it was instantiated, and thus should not be traversed. +}) + +// A helper method for traversing the implicit instantiations of a +// class template. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations( + VarTemplateDecl *D) { + for (auto *SD : D->specializations()) { + for (auto *RD : SD->redecls()) { + switch ( + cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) { + // Visit the implicit instantiations with the requested pattern. + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + TRY_TO(TraverseDecl(RD)); + break; + + // We don't need to do anything on an explicit instantiation + // or explicit specialization because there will be an explicit + // node for it elsewhere. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + break; + } + } + } + + return true; +} + +DEF_TRAVERSE_DECL(VarTemplateDecl, { + VarDecl *TempDecl = D->getTemplatedDecl(); + TRY_TO(TraverseDecl(TempDecl)); + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + + // By default, we do not traverse the instantiations of + // variable templates since they do not appear in the user code. The + // following code optionally traverses them. + // + // We only traverse the variable 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(TraverseVariableInstantiations(D)); + + // Note that getInstantiatedFromMemberTemplate() is just a link + // from a template instantiation back to the template from which + // it was instantiated, and thus should not be traversed. +}) + +// A helper method for traversing the instantiations of a +// function while skipping its specializations. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( + FunctionTemplateDecl *D) { + for (auto *FD : D->specializations()) { + for (auto *RD : FD->redecls()) { + switch (RD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + // We don't know what kind of FunctionDecl this is. + TRY_TO(TraverseDecl(RD)); + break; + + // No need to visit explicit instantiations, we'll find the node + // eventually. + // FIXME: This is incorrect; there is no other node for an explicit + // instantiation of a function template specialization. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + break; + + case TSK_ExplicitSpecialization: + break; + } + } + } + + return true; +} + +DEF_TRAVERSE_DECL(FunctionTemplateDecl, { + TRY_TO(TraverseDecl(D->getTemplatedDecl())); + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + + // By default, we do not traverse the instantiations of + // function templates since they do not appear in the user code. The + // following code optionally traverses them. + // + // 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()) { + TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); + } + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); +}) + +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()) + TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_DECL(TypedefDecl, { + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the typedef, not something that was written in the + // source. +}) + +DEF_TRAVERSE_DECL(TypeAliasDecl, { + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type alias, not something that was written in the + // source. +}) + +DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, { + TRY_TO(TraverseDecl(D->getTemplatedDecl())); + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); +}) + +DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { + // A dependent using declaration which was marked with 'typename'. + // template<class T> class A : public B<T> { using typename B<T>::foo; }; + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type, not something that was written in the + // source. +}) + +DEF_TRAVERSE_DECL(EnumDecl, { + if (D->getTypeForDecl()) + TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); + + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + // The enumerators are already traversed by + // decls_begin()/decls_end(). +}) + +// Helper methods for RecordDecl and its children. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) { + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type, not something that was written in the source. + + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) { + if (!TraverseRecordHelper(D)) + return false; + if (D->isCompleteDefinition()) { + for (const auto &I : D->bases()) { + TRY_TO(TraverseTypeLoc(I.getTypeSourceInfo()->getTypeLoc())); + } + // We don't traverse the friends or the conversions, as they are + // already in decls_begin()/decls_end(). + } + return true; +} + +DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) + +DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) + +DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, { + // For implicit instantiations ("set<int> x;"), we don't want to + // recurse at all, since the instatiated class isn't written in + // the source code anywhere. (Note the instatiated *type* -- + // set<int> -- is written, and will still get a callback of + // TemplateSpecializationType). For explicit instantiations + // ("template set<int>;"), we do need a callback, since this + // is the only callback that's made for this instantiation. + // We use getTypeAsWritten() to distinguish. + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); + + if (!getDerived().shouldVisitTemplateInstantiations() && + D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + // Returning from here skips traversing the + // declaration context of the ClassTemplateSpecializationDecl + // (embedded in the DEF_TRAVERSE_DECL() macro) + // which contains the instantiated members of the class. + return true; +}) + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( + const TemplateArgumentLoc *TAL, unsigned Count) { + for (unsigned I = 0; I < Count; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); + } + return true; +} + +DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, { + // The partial specialization. + if (TemplateParameterList *TPL = D->getTemplateParameters()) { + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + } + // The args that remains unspecialized. + TRY_TO(TraverseTemplateArgumentLocsHelper( + D->getTemplateArgsAsWritten()->getTemplateArgs(), + D->getTemplateArgsAsWritten()->NumTemplateArgs)); + + // Don't need the ClassTemplatePartialSpecializationHelper, even + // though that's our parent class -- we already visit all the + // template args here. + TRY_TO(TraverseCXXRecordHelper(D)); + + // Instantiations will have been visited with the primary template. +}) + +DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); }) + +DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { + // Like UnresolvedUsingTypenameDecl, but without the 'typename': + // template <class T> Class A : public Base<T> { using Base<T>::foo; }; + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); +}) + +DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + if (D->getTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + else + TRY_TO(TraverseType(D->getType())); + return true; +} + +DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) + +DEF_TRAVERSE_DECL(FieldDecl, { + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->isBitField()) + TRY_TO(TraverseStmt(D->getBitWidth())); + else if (D->hasInClassInitializer()) + TRY_TO(TraverseStmt(D->getInClassInitializer())); +}) + +DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, { + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->isBitField()) + TRY_TO(TraverseStmt(D->getBitWidth())); + // FIXME: implement the rest. +}) + +DEF_TRAVERSE_DECL(ObjCIvarDecl, { + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->isBitField()) + TRY_TO(TraverseStmt(D->getBitWidth())); + // FIXME: implement the rest. +}) + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); + + // If we're an explicit template specialization, iterate over the + // template args that were explicitly specified. If we were doing + // this in typing order, we'd do it between the return type and + // the function args, but both are handled by the FunctionTypeLoc + // above, so we have to choose one side. I've decided to do before. + if (const FunctionTemplateSpecializationInfo *FTSI = + D->getTemplateSpecializationInfo()) { + if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared && + FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { + // A specialization might not have explicit template arguments if it has + // a templated return type and concrete arguments. + if (const ASTTemplateArgumentListInfo *TALI = + FTSI->TemplateArgumentsAsWritten) { + TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), + TALI->NumTemplateArgs)); + } + } + } + + // Visit the function type itself, which can be either + // 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 (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { + // Constructor initializers. + for (auto *I : Ctor->inits()) { + TRY_TO(TraverseConstructorInitializer(I)); + } + } + + if (D->isThisDeclarationADefinition()) { + TRY_TO(TraverseStmt(D->getBody())); // Function body. + } + return true; +} + +DEF_TRAVERSE_DECL(FunctionDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) + +DEF_TRAVERSE_DECL(CXXMethodDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) + +DEF_TRAVERSE_DECL(CXXConstructorDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) + +// CXXConversionDecl is the declaration of a type conversion operator. +// It's not a cast expression. +DEF_TRAVERSE_DECL(CXXConversionDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) + +DEF_TRAVERSE_DECL(CXXDestructorDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) + +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)) + TRY_TO(TraverseStmt(D->getInit())); + return true; +} + +DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); }) + +DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, { + // For implicit instantiations, we don't want to + // recurse at all, since the instatiated class isn't written in + // the source code anywhere. + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); + + if (!getDerived().shouldVisitTemplateInstantiations() && + D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + // Returning from here skips traversing the + // declaration context of the VarTemplateSpecializationDecl + // (embedded in the DEF_TRAVERSE_DECL() macro). + return true; +}) + +DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl, { + // The partial specialization. + if (TemplateParameterList *TPL = D->getTemplateParameters()) { + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + } + // The args that remains unspecialized. + TRY_TO(TraverseTemplateArgumentLocsHelper( + D->getTemplateArgsAsWritten()->getTemplateArgs(), + D->getTemplateArgsAsWritten()->NumTemplateArgs)); + + // Don't need the VarTemplatePartialSpecializationHelper, even + // though that's our parent class -- we already visit all the + // template args here. + TRY_TO(TraverseVarHelper(D)); + + // Instantiations will have been visited with the primary + // template. +}) + +DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); }) + +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())); +}) + +DEF_TRAVERSE_DECL(ParmVarDecl, { + TRY_TO(TraverseVarHelper(D)); + + if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() && + !D->hasUnparsedDefaultArg()) + TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg())); + + if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() && + !D->hasUnparsedDefaultArg()) + TRY_TO(TraverseStmt(D->getDefaultArg())); +}) + +#undef DEF_TRAVERSE_DECL + +// ----------------- Stmt traversal ----------------- +// +// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating +// over the children defined in children() (every stmt defines these, +// though sometimes the range is empty). Each individual Traverse* +// method only needs to worry about children other than those. To see +// what children() does for a given class, see, e.g., +// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html + +// This macro makes available a variable S, the passed-in stmt. +#define DEF_TRAVERSE_STMT(STMT, CODE) \ + template <typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \ + TRY_TO(WalkUpFrom##STMT(S)); \ + StmtQueueAction StmtQueue(*this); \ + { CODE; } \ + for (Stmt::child_range range = S->children(); range; ++range) { \ + StmtQueue.queue(*range); \ + } \ + return true; \ + } + +DEF_TRAVERSE_STMT(GCCAsmStmt, { + StmtQueue.queue(S->getAsmString()); + for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { + StmtQueue.queue(S->getInputConstraintLiteral(I)); + } + for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { + StmtQueue.queue(S->getOutputConstraintLiteral(I)); + } + for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { + StmtQueue.queue(S->getClobberStringLiteral(I)); + } + // 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. +}) + +DEF_TRAVERSE_STMT(DeclStmt, { + for (auto *I : S->decls()) { + TRY_TO(TraverseDecl(I)); + } + // Suppress the default iteration over children() by + // returning. Here's why: A DeclStmt looks like 'type var [= + // initializer]'. The decls above already traverse over the + // initializers, so we don't have to do it again (which + // children() would do). + return true; +}) + +// These non-expr stmts (most of them), do not need any action except +// iterating over the children. +DEF_TRAVERSE_STMT(BreakStmt, {}) +DEF_TRAVERSE_STMT(CXXTryStmt, {}) +DEF_TRAVERSE_STMT(CaseStmt, {}) +DEF_TRAVERSE_STMT(CompoundStmt, {}) +DEF_TRAVERSE_STMT(ContinueStmt, {}) +DEF_TRAVERSE_STMT(DefaultStmt, {}) +DEF_TRAVERSE_STMT(DoStmt, {}) +DEF_TRAVERSE_STMT(ForStmt, {}) +DEF_TRAVERSE_STMT(GotoStmt, {}) +DEF_TRAVERSE_STMT(IfStmt, {}) +DEF_TRAVERSE_STMT(IndirectGotoStmt, {}) +DEF_TRAVERSE_STMT(LabelStmt, {}) +DEF_TRAVERSE_STMT(AttributedStmt, {}) +DEF_TRAVERSE_STMT(NullStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtCatchStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtThrowStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtTryStmt, {}) +DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {}) +DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {}) +DEF_TRAVERSE_STMT(CXXForRangeStmt, {}) +DEF_TRAVERSE_STMT(MSDependentExistsStmt, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); +}) +DEF_TRAVERSE_STMT(ReturnStmt, {}) +DEF_TRAVERSE_STMT(SwitchStmt, {}) +DEF_TRAVERSE_STMT(WhileStmt, {}) + +DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); + } +}) + +DEF_TRAVERSE_STMT(DeclRefExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); +}) + +DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper( + S->getExplicitTemplateArgs().getTemplateArgs(), + S->getNumTemplateArgs())); + } +}) + +DEF_TRAVERSE_STMT(MemberExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); +}) + +DEF_TRAVERSE_STMT( + ImplicitCastExpr, + {// We don't traverse the cast type, as it's not written in the + // source code. + }) + +DEF_TRAVERSE_STMT(CStyleCastExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(CXXConstCastExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(CXXDynamicCastExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(CXXStaticCastExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) + +// InitListExpr is a tricky one, because we want to do all our work on +// the syntactic form of the listexpr, but this method takes the +// semantic form by default. We can't use the macro helper because it +// calls WalkUp*() on the semantic form, before our code can convert +// to the syntactic form. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { + if (InitListExpr *Syn = S->getSyntacticForm()) + S = Syn; + TRY_TO(WalkUpFromInitListExpr(S)); + StmtQueueAction StmtQueue(*this); + // All we need are the default actions. FIXME: use a helper function. + for (Stmt::child_range range = S->children(); range; ++range) { + StmtQueue.queue(*range); + } + return true; +} + +// GenericSelectionExpr is a special case because the types and expressions +// are interleaved. We also need to watch out for null types (default +// generic associations). +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr( + GenericSelectionExpr *S) { + TRY_TO(WalkUpFromGenericSelectionExpr(S)); + StmtQueueAction StmtQueue(*this); + StmtQueue.queue(S->getControllingExpr()); + for (unsigned i = 0; i != S->getNumAssocs(); ++i) { + if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i)) + TRY_TO(TraverseTypeLoc(TS->getTypeLoc())); + StmtQueue.queue(S->getAssocExpr(i)); + } + return true; +} + +// PseudoObjectExpr is a special case because of the wierdness with +// syntactic expressions and opaque values. +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) { + TRY_TO(WalkUpFromPseudoObjectExpr(S)); + StmtQueueAction StmtQueue(*this); + StmtQueue.queue(S->getSyntacticForm()); + for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(), + e = S->semantics_end(); + i != e; ++i) { + Expr *sub = *i; + if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub)) + sub = OVE->getSourceExpr(); + StmtQueue.queue(sub); + } + return true; +} + +DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { + // This is called for code like 'return T()' where T is a built-in + // (i.e. non-class) type. + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(CXXNewExpr, { + // The child-iterator will pick up the other arguments. + TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(OffsetOfExpr, { + // The child-iterator will pick up the expression representing + // the field. + // FIMXE: for code like offsetof(Foo, a.b.c), should we get + // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c? + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, { + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isArgumentType()) + TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(CXXTypeidExpr, { + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isTypeOperand()) + TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(MSPropertyRefExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); +}) + +DEF_TRAVERSE_STMT(CXXUuidofExpr, { + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isTypeOperand()) + TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(TypeTraitExpr, { + for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) + TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { + TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(ExpressionTraitExpr, + { StmtQueue.queue(S->getQueriedExpression()); }) + +DEF_TRAVERSE_STMT(VAArgExpr, { + // The child-iterator will pick up the expression argument. + TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); +}) + +DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { + // This is called for code like 'return T()' where T is a class type. + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) + +// Walk only the visible parts of lambda expressions. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { + TRY_TO(WalkUpFromLambdaExpr(S)); + + for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), + CEnd = S->explicit_capture_end(); + C != CEnd; ++C) { + TRY_TO(TraverseLambdaCapture(S, C)); + } + + if (S->hasExplicitParameters() || S->hasExplicitResultType()) { + TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); + if (S->hasExplicitParameters() && S->hasExplicitResultType()) { + // Visit the whole type. + TRY_TO(TraverseTypeLoc(TL)); + } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) { + if (S->hasExplicitParameters()) { + // Visit parameters. + for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { + TRY_TO(TraverseDecl(Proto.getParam(I))); + } + } else { + TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + } + } + } + + TRY_TO(TraverseLambdaBody(S)); + return true; +} + +DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { + // This is called for code like 'T()', where T is a template argument. + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) + +// These expressions all might take explicit template arguments. +// We traverse those if so. FIXME: implement these. +DEF_TRAVERSE_STMT(CXXConstructExpr, {}) +DEF_TRAVERSE_STMT(CallExpr, {}) +DEF_TRAVERSE_STMT(CXXMemberCallExpr, {}) + +// These exprs (most of them), do not need any action except iterating +// over the children. +DEF_TRAVERSE_STMT(AddrLabelExpr, {}) +DEF_TRAVERSE_STMT(ArraySubscriptExpr, {}) +DEF_TRAVERSE_STMT(BlockExpr, { + TRY_TO(TraverseDecl(S->getBlockDecl())); + return true; // no child statements to loop through. +}) +DEF_TRAVERSE_STMT(ChooseExpr, {}) +DEF_TRAVERSE_STMT(CompoundLiteralExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) +DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {}) +DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {}) +DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {}) +DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {}) +DEF_TRAVERSE_STMT(CXXDeleteExpr, {}) +DEF_TRAVERSE_STMT(ExprWithCleanups, {}) +DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {}) +DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {}) +DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) + TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc())); + if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo()) + TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc())); +}) +DEF_TRAVERSE_STMT(CXXThisExpr, {}) +DEF_TRAVERSE_STMT(CXXThrowExpr, {}) +DEF_TRAVERSE_STMT(UserDefinedLiteral, {}) +DEF_TRAVERSE_STMT(DesignatedInitExpr, {}) +DEF_TRAVERSE_STMT(ExtVectorElementExpr, {}) +DEF_TRAVERSE_STMT(GNUNullExpr, {}) +DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {}) +DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {}) +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, { + if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); +}) +DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {}) +DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {}) +DEF_TRAVERSE_STMT(ObjCProtocolExpr, {}) +DEF_TRAVERSE_STMT(ObjCSelectorExpr, {}) +DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {}) +DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) +DEF_TRAVERSE_STMT(ParenExpr, {}) +DEF_TRAVERSE_STMT(ParenListExpr, {}) +DEF_TRAVERSE_STMT(PredefinedExpr, {}) +DEF_TRAVERSE_STMT(ShuffleVectorExpr, {}) +DEF_TRAVERSE_STMT(ConvertVectorExpr, {}) +DEF_TRAVERSE_STMT(StmtExpr, {}) +DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); + } +}) + +DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); + } +}) + +DEF_TRAVERSE_STMT(SEHTryStmt, {}) +DEF_TRAVERSE_STMT(SEHExceptStmt, {}) +DEF_TRAVERSE_STMT(SEHFinallyStmt, {}) +DEF_TRAVERSE_STMT(SEHLeaveStmt, {}) +DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) + +DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) +DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) +DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) + +// These operators (all of them) do not need any action except +// iterating over the children. +DEF_TRAVERSE_STMT(BinaryConditionalOperator, {}) +DEF_TRAVERSE_STMT(ConditionalOperator, {}) +DEF_TRAVERSE_STMT(UnaryOperator, {}) +DEF_TRAVERSE_STMT(BinaryOperator, {}) +DEF_TRAVERSE_STMT(CompoundAssignOperator, {}) +DEF_TRAVERSE_STMT(CXXNoexceptExpr, {}) +DEF_TRAVERSE_STMT(PackExpansionExpr, {}) +DEF_TRAVERSE_STMT(SizeOfPackExpr, {}) +DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {}) +DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) +DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) +DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) +DEF_TRAVERSE_STMT(AtomicExpr, {}) + +// These literals (all of them) do not need any action. +DEF_TRAVERSE_STMT(IntegerLiteral, {}) +DEF_TRAVERSE_STMT(CharacterLiteral, {}) +DEF_TRAVERSE_STMT(FloatingLiteral, {}) +DEF_TRAVERSE_STMT(ImaginaryLiteral, {}) +DEF_TRAVERSE_STMT(StringLiteral, {}) +DEF_TRAVERSE_STMT(ObjCStringLiteral, {}) +DEF_TRAVERSE_STMT(ObjCBoxedExpr, {}) +DEF_TRAVERSE_STMT(ObjCArrayLiteral, {}) +DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, {}) + +// Traverse OpenCL: AsType, Convert. +DEF_TRAVERSE_STMT(AsTypeExpr, {}) + +// OpenMP directives. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective( + OMPExecutableDirective *S) { + for (auto *C : S->clauses()) { + TRY_TO(TraverseOMPClause(C)); + } + return true; +} + +DEF_TRAVERSE_STMT(OMPParallelDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPForDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPSectionsDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPSectionDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPSingleDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPMasterDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPCriticalDirective, { + TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName())); + TRY_TO(TraverseOMPExecutableDirective(S)); +}) + +DEF_TRAVERSE_STMT(OMPParallelForDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskyieldDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPBarrierDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskwaitDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPFlushDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +// OpenMP clauses. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { + if (!C) + return true; + switch (C->getClauseKind()) { +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_##Name: \ + TRY_TO(Visit##Class(static_cast<Class *>(C))); \ + break; +#include "clang/Basic/OpenMPKinds.def" + case OMPC_threadprivate: + case OMPC_unknown: + break; + } + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) { + TRY_TO(TraverseStmt(C->getCondition())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { + TRY_TO(TraverseStmt(C->getCondition())); + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { + TRY_TO(TraverseStmt(C->getNumThreads())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) { + TRY_TO(TraverseStmt(C->getSafelen())); + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) { + TRY_TO(TraverseStmt(C->getNumForLoops())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) { + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) { + TRY_TO(TraverseStmt(C->getChunkSize())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) { + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { + return true; +} + +template <typename Derived> +template <typename T> +bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { + for (auto *E : Node->varlists()) { + TRY_TO(TraverseStmt(E)); + } + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( + OMPFirstprivateClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause( + OMPLastprivateClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) { + TRY_TO(TraverseStmt(C->getStep())); + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) { + TRY_TO(TraverseStmt(C->getAlignment())); + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause( + OMPCopyprivateClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) { + TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +// FIXME: look at the following tricky-seeming exprs to see if we +// need to recurse on anything. These are ones that have methods +// returning decls or qualtypes or nestednamespecifier -- though I'm +// not sure if they own them -- or just seemed very complicated, or +// had lots of sub-types to explore. +// +// VisitOverloadExpr and its children: recurse on template args? etc? + +// FIXME: go through all the stmts and exprs again, and see which of them +// create new types, and recurse on the types (TypeLocs?) of those. +// Candidates: +// +// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html +// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html +// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html +// Every class that has getQualifier. + +#undef DEF_TRAVERSE_STMT + +#undef TRY_TO + +#undef RecursiveASTVisitor + +} // end namespace clang + +#endif // LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h index 244a7b8..ce8b8b7 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Decl.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h @@ -21,6 +21,7 @@ #include "clang/AST/Redeclarable.h" #include "clang/AST/Type.h" #include "clang/Basic/Linkage.h" +#include "clang/Basic/OperatorKinds.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" @@ -51,8 +52,7 @@ class VarTemplateDecl; /// A client can read the relevant info using TypeLoc wrappers, e.g: /// @code /// TypeLoc TL = TypeSourceInfo->getTypeLoc(); -/// if (PointerLoc *PL = dyn_cast<PointerLoc>(&TL)) -/// PL->getStarLoc().print(OS, SrcMgr); +/// TL.getStartLoc().print(OS, SrcMgr); /// @endcode /// class TypeSourceInfo { @@ -79,9 +79,9 @@ class TranslationUnitDecl : public Decl, public DeclContext { NamespaceDecl *AnonymousNamespace; explicit TranslationUnitDecl(ASTContext &ctx) - : Decl(TranslationUnit, 0, SourceLocation()), + : Decl(TranslationUnit, nullptr, SourceLocation()), DeclContext(TranslationUnit), - Ctx(ctx), AnonymousNamespace(0) {} + Ctx(ctx), AnonymousNamespace(nullptr) {} public: ASTContext &getASTContext() const { return Ctx; } @@ -110,7 +110,7 @@ class NamedDecl : public Decl { DeclarationName Name; private: - NamedDecl *getUnderlyingDeclImpl(); + NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY; protected: NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) @@ -161,9 +161,8 @@ public: void printQualifiedName(raw_ostream &OS) const; void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const; - // FIXME: Remove string versions. + // FIXME: Remove string version. std::string getQualifiedNameAsString() const; - std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const; /// getNameForDiagnostic - Appends a human-readable name for this /// declaration into the given stream. @@ -204,9 +203,8 @@ public: // C++0x [class.mem]p1: // The enumerators of an unscoped enumeration defined in // the class are members of the class. - // FIXME: support C++0x scoped enumerations. if (isa<EnumDecl>(DC)) - DC = DC->getParent(); + DC = DC->getRedeclContext(); return DC->isRecord(); } @@ -259,6 +257,16 @@ public: /// checking. Should always return true. bool isLinkageValid() const; + /// \brief True if something has required us to compute the linkage + /// of this declaration. + /// + /// Language features which can retroactively change linkage (like a + /// typedef name for linkage purposes) may need to consider this, + /// but hopefully only in transitory ways during parsing. + bool hasLinkageBeenComputed() const { + return hasCachedLinkage(); + } + /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. NamedDecl *getUnderlyingDecl() { @@ -295,7 +303,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) { /// location of the statement. For GNU local labels (__label__), the decl /// location is where the __label__ is. class LabelDecl : public NamedDecl { - virtual void anchor(); + void anchor() override; LabelStmt *TheStmt; /// LocStart - For normal labels, this is the same as the main declaration /// label, i.e., the location of the identifier; for GNU local labels, @@ -320,7 +328,7 @@ public: bool isGnuLocal() const { return LocStart != getLocation(); } void setLocStart(SourceLocation L) { LocStart = L; } - SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(LocStart, getLocation()); } @@ -333,8 +341,6 @@ public: class NamespaceDecl : public NamedDecl, public DeclContext, public Redeclarable<NamespaceDecl> { - virtual void anchor(); - /// LocStart - The starting location of the source range, pointing /// to either the namespace or the inline keyword. SourceLocation LocStart; @@ -347,21 +353,15 @@ class NamespaceDecl : public NamedDecl, public DeclContext, /// boolean value indicating whether this is an inline namespace. llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline; - NamespaceDecl(DeclContext *DC, bool Inline, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - NamespaceDecl *PrevDecl); - + NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, NamespaceDecl *PrevDecl); + typedef Redeclarable<NamespaceDecl> redeclarable_base; - virtual NamespaceDecl *getNextRedeclaration() { - return RedeclLink.getNext(); - } - virtual NamespaceDecl *getPreviousDeclImpl() { - return getPreviousDecl(); - } - virtual NamespaceDecl *getMostRecentDeclImpl() { - return getMostRecentDecl(); - } - + NamespaceDecl *getNextRedeclarationImpl() override; + NamespaceDecl *getPreviousDeclImpl() override; + NamespaceDecl *getMostRecentDeclImpl() override; + public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, @@ -370,9 +370,11 @@ public: static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID); + typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; + using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; @@ -432,14 +434,14 @@ public: } /// Retrieves the canonical declaration of this namespace. - NamespaceDecl *getCanonicalDecl() { + NamespaceDecl *getCanonicalDecl() override { return getOriginalNamespace(); } const NamespaceDecl *getCanonicalDecl() const { return getOriginalNamespace(); } - - virtual SourceRange getSourceRange() const LLVM_READONLY { + + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(LocStart, RBraceLoc); } @@ -466,7 +468,7 @@ public: /// an lvalue) a function (in which case it is a function designator) or /// an enum constant. class ValueDecl : public NamedDecl { - virtual void anchor(); + void anchor() override; QualType DeclType; protected: @@ -505,7 +507,8 @@ struct QualifierInfo { TemplateParameterList** TemplParamLists; /// Default constructor. - QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {} + QualifierInfo() + : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(nullptr) {} /// setTemplateParameterListsInfo - Sets info about "outer" template /// parameter lists. @@ -567,7 +570,7 @@ public: /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; - virtual SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; SourceLocation getLocStart() const LLVM_READONLY { return getOuterLocStart(); } @@ -576,7 +579,7 @@ public: /// declaration, if it was present in the source. NestedNameSpecifier *getQualifier() const { return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() - : 0; + : nullptr; } /// \brief Retrieve the nested-name-specifier (with source-location @@ -764,23 +767,27 @@ protected: ParmVarDeclBitfields ParmVarDeclBits; }; - VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC); typedef Redeclarable<VarDecl> redeclarable_base; - virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); } - virtual VarDecl *getPreviousDeclImpl() { + VarDecl *getNextRedeclarationImpl() override { + return getNextRedeclaration(); + } + VarDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } - virtual VarDecl *getMostRecentDeclImpl() { + VarDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } public: + typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; + using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; @@ -791,8 +798,8 @@ public: StorageClass S); static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - virtual SourceRange getSourceRange() const LLVM_READONLY; + + SourceRange getSourceRange() const override LLVM_READONLY; /// \brief Returns the storage class as written in the source. For the /// computed linkage of symbol, see getLinkage. @@ -803,22 +810,12 @@ public: void setTSCSpec(ThreadStorageClassSpecifier TSC) { VarDeclBits.TSCSpec = TSC; + assert(VarDeclBits.TSCSpec == TSC && "truncation"); } ThreadStorageClassSpecifier getTSCSpec() const { return static_cast<ThreadStorageClassSpecifier>(VarDeclBits.TSCSpec); } - TLSKind getTLSKind() const { - switch (VarDeclBits.TSCSpec) { - case TSCS_unspecified: - return TLS_None; - case TSCS___thread: // Fall through. - case TSCS__Thread_local: - return TLS_Static; - case TSCS_thread_local: - return TLS_Dynamic; - } - llvm_unreachable("Unknown thread storage class specifier!"); - } + TLSKind getTLSKind() const; /// hasLocalStorage - Returns true if a variable with function scope /// is a non-static local variable. @@ -827,6 +824,10 @@ public: // Second check is for C++11 [dcl.stc]p4. return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified; + // Global Named Register (GNU extension) + if (getStorageClass() == SC_Register && !isLocalVarDecl()) + return false; + // Return true for: Auto, Register. // Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal. @@ -913,7 +914,7 @@ public: return getKind() != Decl::ParmVar && getDeclContext()->isRecord(); } - virtual VarDecl *getCanonicalDecl(); + VarDecl *getCanonicalDecl() override; const VarDecl *getCanonicalDecl() const { return const_cast<VarDecl*>(this)->getCanonicalDecl(); } @@ -960,7 +961,7 @@ public: /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a static data member. - virtual bool isOutOfLine() const; + bool isOutOfLine() const override; /// \brief If this is a static data member, find its out-of-line definition. VarDecl *getOutOfLineDefinition(); @@ -996,7 +997,7 @@ public: } const Expr *getInit() const { if (Init.isNull()) - return 0; + return nullptr; const Stmt *S = Init.dyn_cast<Stmt *>(); if (!S) { @@ -1007,7 +1008,7 @@ public: } Expr *getInit() { if (Init.isNull()) - return 0; + return nullptr; Stmt *S = Init.dyn_cast<Stmt *>(); if (!S) { @@ -1058,7 +1059,7 @@ public: if (Eval->WasEvaluated) return &Eval->Evaluated; - return 0; + return nullptr; } /// \brief Determines whether it is already known whether the @@ -1208,18 +1209,18 @@ public: }; class ImplicitParamDecl : public VarDecl { - virtual void anchor(); + void anchor() override; public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T); static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - ImplicitParamDecl(DeclContext *DC, SourceLocation IdLoc, + + ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType Type) - : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type, - /*tinfo*/ 0, SC_None) { + : VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type, + /*tinfo*/ nullptr, SC_None) { setImplicit(); } @@ -1235,11 +1236,10 @@ public: enum { MaxFunctionScopeIndex = 255 }; protected: - ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, - StorageClass S, Expr *DefArg) - : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S) { + ParmVarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) + : VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) { assert(ParmVarDeclBits.HasInheritedDefaultArg == false); assert(ParmVarDeclBits.IsKNRPromoted == false); assert(ParmVarDeclBits.IsObjCMethodParam == false); @@ -1254,8 +1254,8 @@ public: StorageClass S, Expr *DefArg); static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - virtual SourceRange getSourceRange() const LLVM_READONLY; + + SourceRange getSourceRange() const override LLVM_READONLY; void setObjCMethodScopeInfo(unsigned parameterIndex) { ParmVarDeclBits.IsObjCMethodParam = true; @@ -1362,9 +1362,7 @@ public: /// real default argument via setDefaultArg when the class /// definition enclosing the function declaration that owns this /// default argument is completed. - void setUnparsedDefaultArg() { - Init = (UnparsedDefaultArgument *)0; - } + void setUnparsedDefaultArg() { Init = (UnparsedDefaultArgument *)nullptr; } bool hasInheritedDefaultArg() const { return ParmVarDeclBits.HasInheritedDefaultArg; @@ -1538,7 +1536,7 @@ private: void setParams(ASTContext &C, ArrayRef<ParmVarDecl *> NewParamInfo); protected: - FunctionDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified, @@ -1546,7 +1544,8 @@ protected: : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, StartLoc), DeclContext(DK), - ParamInfo(0), Body(), + redeclarable_base(C), + ParamInfo(nullptr), Body(), SClass(S), IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), @@ -1559,18 +1558,22 @@ protected: DNLoc(NameInfo.getInfo()) {} typedef Redeclarable<FunctionDecl> redeclarable_base; - virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); } - virtual FunctionDecl *getPreviousDeclImpl() { + FunctionDecl *getNextRedeclarationImpl() override { + return getNextRedeclaration(); + } + FunctionDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } - virtual FunctionDecl *getMostRecentDeclImpl() { + FunctionDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } public: + typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; + using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; @@ -1605,13 +1608,12 @@ public: return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } - virtual void getNameForDiagnostic(raw_ostream &OS, - const PrintingPolicy &Policy, - bool Qualified) const; + void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, + bool Qualified) const override; void setRangeEnd(SourceLocation E) { EndRangeLoc = E; } - virtual SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; /// \brief Returns true if the function has a body (definition). The /// function body might be in any of the (re-)declarations of this @@ -1620,7 +1622,7 @@ public: /// containing the body (if there is one). bool hasBody(const FunctionDecl *&Definition) const; - virtual bool hasBody() const { + bool hasBody() const override { const FunctionDecl* Definition; return hasBody(Definition); } @@ -1648,7 +1650,7 @@ public: /// unnecessary AST de-serialization of the body. Stmt *getBody(const FunctionDecl *&Definition) const; - virtual Stmt *getBody() const { + Stmt *getBody() const override { const FunctionDecl* Definition; return getBody(Definition); } @@ -1828,7 +1830,7 @@ public: void setPreviousDeclaration(FunctionDecl * PrevDecl); virtual const FunctionDecl *getCanonicalDecl() const; - virtual FunctionDecl *getCanonicalDecl(); + FunctionDecl *getCanonicalDecl() override; unsigned getBuiltinID() const; @@ -1836,12 +1838,24 @@ public: unsigned param_size() const { return getNumParams(); } typedef ParmVarDecl **param_iterator; typedef ParmVarDecl * const *param_const_iterator; + typedef llvm::iterator_range<param_iterator> param_range; + typedef llvm::iterator_range<param_const_iterator> param_const_range; - param_iterator param_begin() { return ParamInfo; } - param_iterator param_end() { return ParamInfo+param_size(); } + param_iterator param_begin() { return param_iterator(ParamInfo); } + param_iterator param_end() { + return param_iterator(ParamInfo + param_size()); + } + param_range params() { return param_range(param_begin(), param_end()); } - param_const_iterator param_begin() const { return ParamInfo; } - param_const_iterator param_end() const { return ParamInfo+param_size(); } + param_const_iterator param_begin() const { + return param_const_iterator(ParamInfo); + } + param_const_iterator param_end() const { + return param_const_iterator(ParamInfo + param_size()); + } + param_const_range params() const { + return param_const_range(param_begin(), param_end()); + } /// getNumParams - Return the number of parameters this function must have /// based on its FunctionType. This is the length of the ParamInfo array @@ -1860,6 +1874,12 @@ public: setParams(getASTContext(), NewParamInfo); } + // ArrayRef iterface to parameters. + // FIXME: Should one day replace iterator interface. + ArrayRef<ParmVarDecl*> parameters() const { + return llvm::makeArrayRef(ParamInfo, getNumParams()); + } + const ArrayRef<NamedDecl *> &getDeclsInPrototypeScope() const { return DeclsInPrototypeScope; } @@ -1871,10 +1891,15 @@ public: /// arguments (in C++). unsigned getMinRequiredArguments() const; - QualType getResultType() const { - return getType()->getAs<FunctionType>()->getResultType(); + QualType getReturnType() const { + return getType()->getAs<FunctionType>()->getReturnType(); } + /// \brief Attempt to compute an informative source range covering the + /// function return type. This may omit qualifiers and other information with + /// limited representation in the AST. + SourceRange getReturnTypeSourceRange() const; + /// \brief Determine the type of an expression that calls this function. QualType getCallResultType() const { return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); @@ -1906,6 +1931,8 @@ public: bool isInlineDefinitionExternallyVisible() const; + bool isMSExternInline() const; + bool doesDeclarationForceExternallyVisibleDefinition() const; /// isOverloadedOperator - Whether this function declaration @@ -1981,7 +2008,7 @@ public: /// \brief Determine whether this function is a function template /// specialization. bool isFunctionTemplateSpecialization() const { - return getPrimaryTemplate() != 0; + return getPrimaryTemplate() != nullptr; } /// \brief Retrieve the class scope template pattern that this function @@ -2054,11 +2081,11 @@ public: /// \param PointOfInstantiation point at which the function template /// specialization was first instantiated. void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs, - void *InsertPos, - TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, - const TemplateArgumentListInfo *TemplateArgsAsWritten = 0, - SourceLocation PointOfInstantiation = SourceLocation()) { + const TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, + const TemplateArgumentListInfo *TemplateArgsAsWritten = nullptr, + SourceLocation PointOfInstantiation = SourceLocation()) { setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs, InsertPos, TSK, TemplateArgsAsWritten, PointOfInstantiation); @@ -2095,7 +2122,7 @@ public: /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a member function. - virtual bool isOutOfLine() const; + bool isOutOfLine() const override; /// \brief Identify a memory copying or setting function. /// If the given function is a memory copy or setting function, returns @@ -2181,7 +2208,7 @@ public: bool isAnonymousStructOrUnion() const; Expr *getBitWidth() const { - return isBitField() ? InitializerOrBitWidth.getPointer() : 0; + return isBitField() ? InitializerOrBitWidth.getPointer() : nullptr; } unsigned getBitWidthValue(const ASTContext &Ctx) const; @@ -2192,7 +2219,7 @@ public: // Note: used by some clients (i.e., do not remove it). void removeBitWidth() { assert(isBitField() && "no bitfield width to remove"); - InitializerOrBitWidth.setPointer(0); + InitializerOrBitWidth.setPointer(nullptr); } /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which @@ -2211,7 +2238,8 @@ public: /// in-class initializer, but this returns null, then we have not parsed and /// attached it yet. Expr *getInClassInitializer() const { - return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() : 0; + return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() + : nullptr; } /// setInClassInitializer - Set the C++11 in-class initializer for this /// member. @@ -2220,7 +2248,7 @@ public: /// member. void removeInClassInitializer() { assert(hasInClassInitializer() && "no initializer to remove"); - InitializerOrBitWidth.setPointer(0); + InitializerOrBitWidth.setPointer(nullptr); InitializerOrBitWidth.setInt(ICIS_NoInit); } @@ -2234,10 +2262,10 @@ public: return cast<RecordDecl>(getDeclContext()); } - SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; /// Retrieves the canonical declaration of this field. - FieldDecl *getCanonicalDecl() { return getFirstDecl(); } + FieldDecl *getCanonicalDecl() override { return getFirstDecl(); } const FieldDecl *getCanonicalDecl() const { return getFirstDecl(); } // Implement isa/cast/dyncast/etc. @@ -2276,10 +2304,10 @@ public: void setInitExpr(Expr *E) { Init = (Stmt*) E; } void setInitVal(const llvm::APSInt &V) { Val = V; } - SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; /// Retrieves the canonical declaration of this enumerator. - EnumConstantDecl *getCanonicalDecl() { return getFirstDecl(); } + EnumConstantDecl *getCanonicalDecl() override { return getFirstDecl(); } const EnumConstantDecl *getCanonicalDecl() const { return getFirstDecl(); } // Implement isa/cast/dyncast/etc. @@ -2293,7 +2321,7 @@ public: /// field injected from an anonymous union/struct into the parent scope. /// IndirectFieldDecl are always implicit. class IndirectFieldDecl : public ValueDecl { - virtual void anchor(); + void anchor() override; NamedDecl **Chaining; unsigned ChainingSize; @@ -2310,8 +2338,13 @@ public: static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); typedef NamedDecl * const *chain_iterator; - chain_iterator chain_begin() const { return Chaining; } - chain_iterator chain_end() const { return Chaining+ChainingSize; } + typedef llvm::iterator_range<chain_iterator> chain_range; + + chain_range chain() const { return chain_range(chain_begin(), chain_end()); } + chain_iterator chain_begin() const { return chain_iterator(Chaining); } + chain_iterator chain_end() const { + return chain_iterator(Chaining + ChainingSize); + } unsigned getChainingSize() const { return ChainingSize; } @@ -2334,7 +2367,7 @@ public: /// TypeDecl - Represents a declaration of a type. /// class TypeDecl : public NamedDecl { - virtual void anchor(); + void anchor() override; /// TypeForDecl - This indicates the Type object that represents /// this TypeDecl. It is a cache maintained by /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and @@ -2343,16 +2376,11 @@ class TypeDecl : public NamedDecl { /// LocStart - The start of the source range for this declaration. SourceLocation LocStart; friend class ASTContext; - friend class DeclContext; - friend class TagDecl; - friend class TemplateTypeParmDecl; - friend class TagType; - friend class ASTReader; protected: TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation StartL = SourceLocation()) - : NamedDecl(DK, DC, L, Id), TypeForDecl(0), LocStart(StartL) {} + : NamedDecl(DK, DC, L, Id), TypeForDecl(nullptr), LocStart(StartL) {} public: // Low-level accessor. If you just want the type defined by this node, @@ -2364,7 +2392,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return LocStart; } void setLocStart(SourceLocation L) { LocStart = L; } - virtual SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { if (LocStart.isValid()) return SourceRange(LocStart, getLocation()); else @@ -2379,31 +2407,34 @@ public: /// Base class for declarations which introduce a typedef-name. class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> { - virtual void anchor(); + void anchor() override; typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo; llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo; protected: - TypedefNameDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - TypeSourceInfo *TInfo) - : TypeDecl(DK, DC, IdLoc, Id, StartLoc), MaybeModedTInfo(TInfo) {} + TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C), + MaybeModedTInfo(TInfo) {} typedef Redeclarable<TypedefNameDecl> redeclarable_base; - virtual TypedefNameDecl *getNextRedeclaration() { - return RedeclLink.getNext(); + TypedefNameDecl *getNextRedeclarationImpl() override { + return getNextRedeclaration(); } - virtual TypedefNameDecl *getPreviousDeclImpl() { + TypedefNameDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } - virtual TypedefNameDecl *getMostRecentDeclImpl() { + TypedefNameDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } public: + typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; + using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; @@ -2428,7 +2459,7 @@ public: } /// Retrieves the canonical declaration of this typedef-name. - TypedefNameDecl *getCanonicalDecl() { return getFirstDecl(); } + TypedefNameDecl *getCanonicalDecl() override { return getFirstDecl(); } const TypedefNameDecl *getCanonicalDecl() const { return getFirstDecl(); } // Implement isa/cast/dyncast/etc. @@ -2441,17 +2472,17 @@ public: /// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' /// type specifier. class TypedefDecl : public TypedefNameDecl { - TypedefDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypedefNameDecl(Typedef, DC, StartLoc, IdLoc, Id, TInfo) {} + TypedefDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(Typedef, C, DC, StartLoc, IdLoc, Id, TInfo) {} public: static TypedefDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo); static TypedefDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const LLVM_READONLY; + + SourceRange getSourceRange() const override LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2461,9 +2492,9 @@ public: /// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x /// alias-declaration. class TypeAliasDecl : public TypedefNameDecl { - TypeAliasDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypedefNameDecl(TypeAlias, DC, StartLoc, IdLoc, Id, TInfo) {} + TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo) {} public: static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, @@ -2471,7 +2502,7 @@ public: IdentifierInfo *Id, TypeSourceInfo *TInfo); static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); - SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2559,24 +2590,27 @@ private: } protected: - TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, TagDecl *PrevDecl, SourceLocation StartL) - : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), TagDeclKind(TK), - IsCompleteDefinition(false), IsBeingDefined(false), + TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl, + SourceLocation StartL) + : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C), + TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false), IsEmbeddedInDeclarator(false), IsFreeStanding(false), IsCompleteDefinitionRequired(false), - NamedDeclOrQualifier((NamedDecl *)0) { + NamedDeclOrQualifier((NamedDecl *)nullptr) { assert((DK != Enum || TK == TTK_Enum) && "EnumDecl not matched with TTK_Enum"); setPreviousDecl(PrevDecl); } typedef Redeclarable<TagDecl> redeclarable_base; - virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } - virtual TagDecl *getPreviousDeclImpl() { + TagDecl *getNextRedeclarationImpl() override { + return getNextRedeclaration(); + } + TagDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } - virtual TagDecl *getMostRecentDeclImpl() { + TagDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } @@ -2586,9 +2620,11 @@ protected: void completeDefinition(); public: + typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; + using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; @@ -2603,10 +2639,10 @@ public: /// getOuterLocStart - Return SourceLocation representing start of source /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; - virtual SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; - virtual TagDecl* getCanonicalDecl(); - const TagDecl* getCanonicalDecl() const { + TagDecl *getCanonicalDecl() override; + const TagDecl *getCanonicalDecl() const { return const_cast<TagDecl*>(this)->getCanonicalDecl(); } @@ -2673,8 +2709,7 @@ public: IsCompleteDefinitionRequired = V; } - // FIXME: Return StringRef; - const char *getKindName() const { + StringRef getKindName() const { return TypeWithKeyword::getTagTypeKindName(getTagKind()); } @@ -2714,12 +2749,12 @@ public: NamedDeclOrQualifier.get<NamedDecl *>()); } DeclaratorDecl *getDeclaratorForAnonDecl() const { - return hasExtInfo() ? 0 : dyn_cast_or_null<DeclaratorDecl>( + return hasExtInfo() ? nullptr : dyn_cast_or_null<DeclaratorDecl>( NamedDeclOrQualifier.get<NamedDecl *>()); } TypedefNameDecl *getTypedefNameForAnonDecl() const { - return hasExtInfo() ? 0 : dyn_cast_or_null<TypedefNameDecl>( + return hasExtInfo() ? nullptr : dyn_cast_or_null<TypedefNameDecl>( NamedDeclOrQualifier.get<NamedDecl *>()); } @@ -2731,7 +2766,7 @@ public: /// declaration, if it was present in the source. NestedNameSpecifier *getQualifier() const { return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() - : 0; + : nullptr; } /// \brief Retrieve the nested-name-specifier (with source-location @@ -2773,7 +2808,7 @@ public: /// with a fixed underlying type, and in C we allow them to be forward-declared /// with no underlying type as an extension. class EnumDecl : public TagDecl { - virtual void anchor(); + void anchor() override; /// IntegerType - This represent the integer type that the enum corresponds /// to for code generation purposes. Note that the enumerator constants may /// have a different type than this does. @@ -2802,13 +2837,13 @@ class EnumDecl : public TagDecl { /// information. MemberSpecializationInfo *SpecializationInfo; - EnumDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, EnumDecl *PrevDecl, + EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) - : TagDecl(Enum, TTK_Enum, DC, IdLoc, Id, PrevDecl, StartLoc), - SpecializationInfo(0) { + : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc), + SpecializationInfo(nullptr) { assert(Scoped || !ScopedUsingClassTag); - IntegerType = (const Type*)0; + IntegerType = (const Type *)nullptr; NumNegativeBits = 0; NumPositiveBits = 0; IsScoped = Scoped; @@ -2819,7 +2854,7 @@ class EnumDecl : public TagDecl { void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, TemplateSpecializationKind TSK); public: - EnumDecl *getCanonicalDecl() { + EnumDecl *getCanonicalDecl() override { return cast<EnumDecl>(TagDecl::getCanonicalDecl()); } const EnumDecl *getCanonicalDecl() const { @@ -2865,6 +2900,12 @@ public: // enumerator_iterator - Iterates through the enumerators of this // enumeration. typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; + typedef llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>> + enumerator_range; + + enumerator_range enumerators() const { + return enumerator_range(enumerator_begin(), enumerator_end()); + } enumerator_iterator enumerator_begin() const { const EnumDecl *E = getDefinition(); @@ -2888,27 +2929,32 @@ public: void setPromotionType(QualType T) { PromotionType = T; } /// getIntegerType - Return the integer type this enum decl corresponds to. - /// This returns a null qualtype for an enum forward definition. + /// This returns a null QualType for an enum forward definition with no fixed + /// underlying type. QualType getIntegerType() const { if (!IntegerType) return QualType(); - if (const Type* T = IntegerType.dyn_cast<const Type*>()) + if (const Type *T = IntegerType.dyn_cast<const Type*>()) return QualType(T, 0); - return IntegerType.get<TypeSourceInfo*>()->getType(); + return IntegerType.get<TypeSourceInfo*>()->getType().getUnqualifiedType(); } /// \brief Set the underlying integer type. void setIntegerType(QualType T) { IntegerType = T.getTypePtrOrNull(); } /// \brief Set the underlying integer type source info. - void setIntegerTypeSourceInfo(TypeSourceInfo* TInfo) { IntegerType = TInfo; } + void setIntegerTypeSourceInfo(TypeSourceInfo *TInfo) { IntegerType = TInfo; } /// \brief Return the type source info for the underlying integer type, /// if no type source info exists, return 0. - TypeSourceInfo* getIntegerTypeSourceInfo() const { + TypeSourceInfo *getIntegerTypeSourceInfo() const { return IntegerType.dyn_cast<TypeSourceInfo*>(); } + /// \brief Retrieve the source range that covers the underlying type if + /// specified. + SourceRange getIntegerTypeRange() const LLVM_READONLY; + /// \brief Returns the width in bits required to store all the /// non-negative enumerators of this enum. unsigned getNumPositiveBits() const { @@ -3024,14 +3070,14 @@ class RecordDecl : public TagDecl { friend class DeclContext; protected: - RecordDecl(Kind DK, TagKind TK, DeclContext *DC, + RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl *PrevDecl); public: static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, RecordDecl* PrevDecl = 0); + IdentifierInfo *Id, RecordDecl* PrevDecl = nullptr); static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); RecordDecl *getPreviousDecl() { @@ -3106,7 +3152,9 @@ public: // the non-static data members of this class, ignoring any static // data members, functions, constructors, destructors, etc. typedef specific_decl_iterator<FieldDecl> field_iterator; + typedef llvm::iterator_range<specific_decl_iterator<FieldDecl>> field_range; + field_range fields() const { return field_range(field_begin(), field_end()); } field_iterator field_begin() const; field_iterator field_end() const { @@ -3155,7 +3203,7 @@ public: SourceLocation getAsmLoc() const { return getLocation(); } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(getAsmLoc(), getRParenLoc()); } @@ -3206,7 +3254,7 @@ public: /// is not from outside the immediately enclosing function/block. bool isNested() const { return VariableAndFlags.getInt() & flag_isNested; } - bool hasCopyExpr() const { return CopyExpr != 0; } + bool hasCopyExpr() const { return CopyExpr != nullptr; } Expr *getCopyExpr() const { return CopyExpr; } void setCopyExpr(Expr *e) { CopyExpr = e; } }; @@ -3237,9 +3285,9 @@ protected: : Decl(Block, DC, CaretLoc), DeclContext(Block), IsVariadic(false), CapturesCXXThis(false), BlockMissingReturnType(true), IsConversionFromLambda(false), - ParamInfo(0), NumParams(0), Body(0), - SignatureAsWritten(0), Captures(0), NumCaptures(0), - ManglingNumber(0), ManglingContextDecl(0) {} + ParamInfo(nullptr), NumParams(0), Body(nullptr), + SignatureAsWritten(nullptr), Captures(nullptr), NumCaptures(0), + ManglingNumber(0), ManglingContextDecl(nullptr) {} public: static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); @@ -3251,7 +3299,7 @@ public: void setIsVariadic(bool value) { IsVariadic = value; } CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; } - Stmt *getBody() const { return (Stmt*) Body; } + Stmt *getBody() const override { return (Stmt*) Body; } void setBody(CompoundStmt *B) { Body = (Stmt*) B; } void setSignatureAsWritten(TypeSourceInfo *Sig) { SignatureAsWritten = Sig; } @@ -3261,13 +3309,31 @@ public: unsigned param_size() const { return getNumParams(); } typedef ParmVarDecl **param_iterator; typedef ParmVarDecl * const *param_const_iterator; + typedef llvm::iterator_range<param_iterator> param_range; + typedef llvm::iterator_range<param_const_iterator> param_const_range; + + // ArrayRef access to formal parameters. + // FIXME: Should eventual replace iterator access. + ArrayRef<ParmVarDecl*> parameters() const { + return llvm::makeArrayRef(ParamInfo, param_size()); + } bool param_empty() const { return NumParams == 0; } - param_iterator param_begin() { return ParamInfo; } - param_iterator param_end() { return ParamInfo+param_size(); } + param_range params() { return param_range(param_begin(), param_end()); } + param_iterator param_begin() { return param_iterator(ParamInfo); } + param_iterator param_end() { + return param_iterator(ParamInfo + param_size()); + } - param_const_iterator param_begin() const { return ParamInfo; } - param_const_iterator param_end() const { return ParamInfo+param_size(); } + param_const_range params() const { + return param_const_range(param_begin(), param_end()); + } + param_const_iterator param_begin() const { + return param_const_iterator(ParamInfo); + } + param_const_iterator param_end() const { + return param_const_iterator(ParamInfo + param_size()); + } unsigned getNumParams() const { return NumParams; } const ParmVarDecl *getParamDecl(unsigned i) const { @@ -3290,6 +3356,16 @@ public: typedef const Capture *capture_iterator; typedef const Capture *capture_const_iterator; + typedef llvm::iterator_range<capture_iterator> capture_range; + typedef llvm::iterator_range<capture_const_iterator> capture_const_range; + + capture_range captures() { + return capture_range(capture_begin(), capture_end()); + } + capture_const_range captures() const { + return capture_const_range(capture_begin(), capture_end()); + } + capture_iterator capture_begin() { return Captures; } capture_iterator capture_end() { return Captures + NumCaptures; } capture_const_iterator capture_begin() const { return Captures; } @@ -3321,7 +3397,7 @@ public: ManglingContextDecl = Ctx; } - virtual SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -3340,12 +3416,14 @@ class CapturedDecl : public Decl, public DeclContext { private: /// \brief The number of parameters to the outlined function. unsigned NumParams; + /// \brief The position of context parameter in list of parameters. + unsigned ContextParam; /// \brief The body of the outlined function. - Stmt *Body; + llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow; explicit CapturedDecl(DeclContext *DC, unsigned NumParams) : Decl(Captured, DC, SourceLocation()), DeclContext(Captured), - NumParams(NumParams), Body(0) { } + NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) { } ImplicitParamDecl **getParams() const { return reinterpret_cast<ImplicitParamDecl **>( @@ -3353,12 +3431,16 @@ private: } public: - static CapturedDecl *Create(ASTContext &C, DeclContext *DC, unsigned NumParams); + static CapturedDecl *Create(ASTContext &C, DeclContext *DC, + unsigned NumParams); static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumParams); - Stmt *getBody() const { return Body; } - void setBody(Stmt *B) { Body = B; } + Stmt *getBody() const override { return BodyAndNothrow.getPointer(); } + void setBody(Stmt *B) { BodyAndNothrow.setPointer(B); } + + bool isNothrow() const { return BodyAndNothrow.getInt(); } + void setNothrow(bool Nothrow = true) { BodyAndNothrow.setInt(Nothrow); } unsigned getNumParams() const { return NumParams; } @@ -3372,15 +3454,28 @@ public: } /// \brief Retrieve the parameter containing captured variables. - ImplicitParamDecl *getContextParam() const { return getParam(0); } - void setContextParam(ImplicitParamDecl *P) { setParam(0, P); } + ImplicitParamDecl *getContextParam() const { + assert(ContextParam < NumParams); + return getParam(ContextParam); + } + void setContextParam(unsigned i, ImplicitParamDecl *P) { + assert(i < NumParams); + ContextParam = i; + setParam(i, P); + } + unsigned getContextParamPosition() const { return ContextParam; } typedef ImplicitParamDecl **param_iterator; + typedef llvm::iterator_range<param_iterator> param_range; + /// \brief Retrieve an iterator pointing to the first parameter decl. param_iterator param_begin() const { return getParams(); } /// \brief Retrieve an iterator one past the last parameter decl. param_iterator param_end() const { return getParams() + NumParams; } + /// \brief Retrieve an iterator range for the parameter declarations. + param_range params() const { return param_range(param_begin(), param_end()); } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Captured; } @@ -3455,9 +3550,9 @@ public: /// This will return an empty array if the locations of the individual /// identifiers aren't available. ArrayRef<SourceLocation> getIdentifierLocs() const; - - virtual SourceRange getSourceRange() const LLVM_READONLY; - + + SourceRange getSourceRange() const override LLVM_READONLY; + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Import; } }; @@ -3496,6 +3591,8 @@ template<typename decl_type> void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) { // Note: This routine is implemented here because we need both NamedDecl // and Redeclarable to be defined. + assert(RedeclLink.NextIsLatest() && + "setPreviousDecl on a decl already in a redeclaration chain"); decl_type *First; @@ -3505,7 +3602,7 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) { // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. First = PrevDecl->getFirstDecl(); assert(First->RedeclLink.NextIsLatest() && "Expected first"); - decl_type *MostRecent = First->RedeclLink.getNext(); + decl_type *MostRecent = First->getNextRedeclaration(); RedeclLink = PreviousDeclLink(cast<decl_type>(MostRecent)); // If the declaration was previously visible, a redeclaration of it remains @@ -3519,7 +3616,8 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) { } // First one will point to this one as latest. - First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); + First->RedeclLink.setLatest(static_cast<decl_type*>(this)); + assert(!isa<NamedDecl>(static_cast<decl_type*>(this)) || cast<NamedDecl>(static_cast<decl_type*>(this))->isLinkageValid()); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h index 26eea64..607ca4e 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h @@ -16,9 +16,9 @@ #include "clang/AST/AttrIterator.h" #include "clang/AST/DeclarationName.h" -#include "clang/Basic/Linkage.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PrettyStackTrace.h" @@ -32,6 +32,8 @@ class DeclarationName; class DependentDiagnostic; class EnumDecl; class FunctionDecl; +class FunctionType; +enum Linkage : unsigned char; class LinkageComputer; class LinkageSpecDecl; class Module; @@ -52,20 +54,6 @@ class TranslationUnitDecl; class UsingDirectiveDecl; } -namespace llvm { -// DeclContext* is only 4-byte aligned on 32-bit systems. -template<> - class PointerLikeTypeTraits<clang::DeclContext*> { - typedef clang::DeclContext* PT; -public: - static inline void *getAsVoidPointer(PT P) { return P; } - static inline PT getFromVoidPointer(void *P) { - return static_cast<PT>(P); - } - enum { NumLowBitsAvailable = 2 }; -}; -} - namespace clang { /// \brief Captures the result of checking the availability of a @@ -302,8 +290,24 @@ protected: template<typename decl_type> friend class Redeclarable; + /// \brief Allocate memory for a deserialized declaration. + /// + /// This routine must be used to allocate memory for any declaration that is + /// deserialized from a module file. + /// + /// \param Size The size of the allocated object. + /// \param Ctx The context in which we will allocate memory. + /// \param ID The global ID of the deserialized declaration. + /// \param Extra The amount of extra space to allocate after the object. + void *operator new(std::size_t Size, const ASTContext &Ctx, unsigned ID, + std::size_t Extra = 0); + + /// \brief Allocate memory for a non-deserialized declaration. + void *operator new(std::size_t Size, const ASTContext &Ctx, + DeclContext *Parent, std::size_t Extra = 0); + private: - void CheckAccessDeclContext() const; + bool AccessDeclContextSanity() const; protected: @@ -330,18 +334,6 @@ protected: virtual ~Decl(); - /// \brief Allocate memory for a deserialized declaration. - /// - /// This routine must be used to allocate memory for any declaration that is - /// deserialized from a module file. - /// - /// \param Context The context in which we will allocate memory. - /// \param ID The global ID of the deserialized declaration. - /// \param Size The size of the allocated object. - static void *AllocateDeserializedDecl(const ASTContext &Context, - unsigned ID, - unsigned Size); - /// \brief Update a potentially out-of-date declaration. void updateOutOfDate(IdentifierInfo &II) const; @@ -405,19 +397,17 @@ public: bool isInAnonymousNamespace() const; + bool isInStdNamespace() const; + ASTContext &getASTContext() const LLVM_READONLY; void setAccess(AccessSpecifier AS) { Access = AS; -#ifndef NDEBUG - CheckAccessDeclContext(); -#endif + assert(AccessDeclContextSanity()); } AccessSpecifier getAccess() const { -#ifndef NDEBUG - CheckAccessDeclContext(); -#endif + assert(AccessDeclContextSanity()); return AccessSpecifier(Access); } @@ -445,14 +435,17 @@ public: } typedef AttrVec::const_iterator attr_iterator; + typedef llvm::iterator_range<attr_iterator> attr_range; + + attr_range attrs() const { + return attr_range(attr_begin(), attr_end()); + } - // FIXME: Do not rely on iterators having comparable singular values. - // Note that this should error out if they do not. attr_iterator attr_begin() const { - return hasAttrs() ? getAttrs().begin() : 0; + return hasAttrs() ? getAttrs().begin() : nullptr; } attr_iterator attr_end() const { - return hasAttrs() ? getAttrs().end() : 0; + return hasAttrs() ? getAttrs().end() : nullptr; } template <typename T> @@ -467,6 +460,12 @@ public: } template <typename T> + llvm::iterator_range<specific_attr_iterator<T>> specific_attrs() const { + return llvm::iterator_range<specific_attr_iterator<T>>( + specific_attr_begin<T>(), specific_attr_end<T>()); + } + + template <typename T> specific_attr_iterator<T> specific_attr_begin() const { return specific_attr_iterator<T>(attr_begin()); } @@ -476,7 +475,7 @@ public: } template<typename T> T *getAttr() const { - return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0; + return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : nullptr; } template<typename T> bool hasAttr() const { return hasAttrs() && hasSpecificAttr<T>(getAttrs()); @@ -573,14 +572,14 @@ public: /// AR_Available, will be set to a (possibly empty) message /// describing why the declaration has not been introduced, is /// deprecated, or is unavailable. - AvailabilityResult getAvailability(std::string *Message = 0) const; + AvailabilityResult getAvailability(std::string *Message = nullptr) const; /// \brief Determine whether this declaration is marked 'deprecated'. /// /// \param Message If non-NULL and the declaration is deprecated, /// this will be set to the message describing why the declaration /// was deprecated (which may be empty). - bool isDeprecated(std::string *Message = 0) const { + bool isDeprecated(std::string *Message = nullptr) const { return getAvailability(Message) == AR_Deprecated; } @@ -589,7 +588,7 @@ public: /// \param Message If non-NULL and the declaration is unavailable, /// this will be set to the message describing why the declaration /// was made unavailable (which may be empty). - bool isUnavailable(std::string *Message = 0) const { + bool isUnavailable(std::string *Message = nullptr) const { return getAvailability(Message) == AR_Unavailable; } @@ -636,7 +635,7 @@ private: public: Module *getOwningModule() const { if (!isFromASTFile()) - return 0; + return nullptr; return getOwningModuleSlow(); } @@ -691,7 +690,7 @@ public: /// roughly global variables and functions, but also handles enums (which /// could be defined inside or outside a function etc). bool isDefinedOutsideFunctionOrMethod() const { - return getParentFunctionOrMethod() == 0; + return getParentFunctionOrMethod() == nullptr; } /// \brief If this decl is defined inside a function/method/block it returns @@ -716,16 +715,16 @@ protected: /// /// Decl subclasses that can be redeclared should override this method so that /// Decl::redecl_iterator can iterate over them. - virtual Decl *getNextRedeclaration() { return this; } + virtual Decl *getNextRedeclarationImpl() { return this; } /// \brief Implementation of getPreviousDecl(), to be overridden by any /// subclass that has a redeclaration chain. - virtual Decl *getPreviousDeclImpl() { return 0; } - + virtual Decl *getPreviousDeclImpl() { return nullptr; } + /// \brief Implementation of getMostRecentDecl(), to be overridden by any - /// subclass that has a redeclaration chain. + /// subclass that has a redeclaration chain. virtual Decl *getMostRecentDeclImpl() { return this; } - + public: /// \brief Iterates through all the redeclarations of the same decl. class redecl_iterator { @@ -740,7 +739,7 @@ public: typedef std::forward_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; - redecl_iterator() : Current(0) { } + redecl_iterator() : Current(nullptr) { } explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { } reference operator*() const { return Current; } @@ -749,9 +748,9 @@ public: redecl_iterator& operator++() { assert(Current && "Advancing while iterator has reached end"); // Get either previous decl or latest decl. - Decl *Next = Current->getNextRedeclaration(); + Decl *Next = Current->getNextRedeclarationImpl(); assert(Next && "Should return next redeclaration or itself, never null!"); - Current = (Next != Starter ? Next : 0); + Current = (Next != Starter) ? Next : nullptr; return *this; } @@ -769,10 +768,16 @@ public: } }; - /// \brief Returns iterator for all the redeclarations of the same decl. - /// It will iterate at least once (when this decl is the only one). + typedef llvm::iterator_range<redecl_iterator> redecl_range; + + /// \brief Returns an iterator range for all the redeclarations of the same + /// decl. It will iterate at least once (when this decl is the only one). + redecl_range redecls() const { + return redecl_range(redecls_begin(), redecls_end()); + } + redecl_iterator redecls_begin() const { - return redecl_iterator(const_cast<Decl*>(this)); + return redecl_iterator(const_cast<Decl *>(this)); } redecl_iterator redecls_end() const { return redecl_iterator(); } @@ -788,7 +793,7 @@ public: /// \brief True if this is the first declaration in its redeclaration chain. bool isFirstDecl() const { - return getPreviousDecl() == 0; + return getPreviousDecl() == nullptr; } /// \brief Retrieve the most recent declaration that declares the same entity @@ -804,13 +809,13 @@ public: /// getBody - If this Decl represents a declaration for a body of code, /// such as a function or method definition, this method returns the /// top-level Stmt* of that body. Otherwise this method returns null. - virtual Stmt* getBody() const { return 0; } + virtual Stmt* getBody() const { return nullptr; } /// \brief Returns true if this \c Decl represents a declaration for a body of /// code, such as a function or method definition. /// Note that \c hasBody can also return true if any redeclaration of this /// \c Decl represents a declaration for a body of code. - virtual bool hasBody() const { return getBody() != 0; } + virtual bool hasBody() const { return getBody() != nullptr; } /// getBodyRBrace - Gets the right brace of the body, if a body exists. /// This works whether the body is a CompoundStmt or a CXXTryStmt. @@ -836,7 +841,19 @@ public: bool isTemplateDecl() const; /// \brief Whether this declaration is a function or function template. - bool isFunctionOrFunctionTemplate() const; + bool isFunctionOrFunctionTemplate() const { + return (DeclKind >= Decl::firstFunction && + DeclKind <= Decl::lastFunction) || + DeclKind == FunctionTemplate; + } + + /// \brief Returns the function itself, or the templated function if this is a + /// function template. + FunctionDecl *getAsFunction() LLVM_READONLY; + + const FunctionDecl *getAsFunction() const { + return const_cast<Decl *>(this)->getAsFunction(); + } /// \brief Changes the namespace of this declaration to reflect that it's /// a function-local extern declaration. @@ -938,11 +955,16 @@ public: raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); // Debuggers don't usually respect default arguments. - LLVM_ATTRIBUTE_USED void dump() const; + void dump() const; // Same as dump(), but forces color printing. - LLVM_ATTRIBUTE_USED void dumpColor() const; + void dumpColor() const; void dump(raw_ostream &Out) const; + /// \brief Looks through the Decl's underlying type to extract a FunctionType + /// when possible. Will return null if the type underlying the Decl does not + /// have a FunctionType. + const FunctionType *getFunctionType(bool BlocksToo = true) const; + private: void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx); void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, @@ -975,10 +997,10 @@ public: SourceManager &sm, const char *Msg) : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {} - virtual void print(raw_ostream &OS) const; + void print(raw_ostream &OS) const override; }; -typedef llvm::MutableArrayRef<NamedDecl*> DeclContextLookupResult; +typedef MutableArrayRef<NamedDecl *> DeclContextLookupResult; typedef ArrayRef<NamedDecl *> DeclContextLookupConstResult; @@ -1048,8 +1070,8 @@ protected: DeclContext(Decl::Kind K) : DeclKind(K), ExternalLexicalStorage(false), ExternalVisibleStorage(false), - NeedToReconcileExternalVisibleStorage(false), LookupPtr(0, false), - FirstDecl(0), LastDecl(0) {} + NeedToReconcileExternalVisibleStorage(false), LookupPtr(nullptr, false), + FirstDecl(nullptr), LastDecl(nullptr) {} public: ~DeclContext(); @@ -1136,6 +1158,8 @@ public: return DeclKind == Decl::Namespace; } + bool isStdNamespace() const; + bool isInlineNamespace() const; /// \brief Determines whether this context is dependent on a @@ -1256,7 +1280,7 @@ public: typedef std::forward_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; - decl_iterator() : Current(0) { } + decl_iterator() : Current(nullptr) { } explicit decl_iterator(Decl *C) : Current(C) { } reference operator*() const { return Current; } @@ -1282,8 +1306,11 @@ public: } }; + typedef llvm::iterator_range<decl_iterator> decl_range; + /// decls_begin/decls_end - Iterate over the declarations stored in /// this context. + decl_range decls() const { return decl_range(decls_begin(), decls_end()); } decl_iterator decls_begin() const; decl_iterator decls_end() const { return decl_iterator(); } bool decls_empty() const; @@ -1291,7 +1318,10 @@ public: /// 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_range noload_decls() const { + return decl_range(noload_decls_begin(), noload_decls_end()); + } + decl_iterator noload_decls_begin() const { return decl_iterator(FirstDecl); } decl_iterator noload_decls_end() const { return decl_iterator(); } /// specific_decl_iterator - Iterates over a subrange of @@ -1537,6 +1567,11 @@ public: /// of looking up every possible name. class all_lookups_iterator; + typedef llvm::iterator_range<all_lookups_iterator> lookups_range; + + lookups_range lookups() const; + lookups_range noload_lookups() const; + /// \brief Iterators over all possible lookups within this context. all_lookups_iterator lookups_begin() const; all_lookups_iterator lookups_end() const; @@ -1547,26 +1582,15 @@ public: all_lookups_iterator noload_lookups_begin() const; all_lookups_iterator noload_lookups_end() const; - /// udir_iterator - Iterates through the using-directives stored - /// within this context. - typedef UsingDirectiveDecl * const * udir_iterator; - - typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range; + typedef llvm::iterator_range<UsingDirectiveDecl * const *> udir_range; - udir_iterator_range getUsingDirectives() const; - - udir_iterator using_directives_begin() const { - return getUsingDirectives().first; - } - - udir_iterator using_directives_end() const { - return getUsingDirectives().second; - } + udir_range using_directives() const; // These are all defined in DependentDiagnostic.h. class ddiag_iterator; - inline ddiag_iterator ddiag_begin() const; - inline ddiag_iterator ddiag_end() const; + typedef llvm::iterator_range<DeclContext::ddiag_iterator> ddiag_range; + + inline ddiag_range ddiags() const; // Low-level accessors @@ -1616,12 +1640,12 @@ public: static bool classof(const Decl *D); static bool classof(const DeclContext *D) { return true; } - LLVM_ATTRIBUTE_USED void dumpDeclContext() const; - LLVM_ATTRIBUTE_USED void dumpLookups() const; - LLVM_ATTRIBUTE_USED void dumpLookups(llvm::raw_ostream &OS) const; + void dumpDeclContext() const; + void dumpLookups() const; + void dumpLookups(llvm::raw_ostream &OS) const; private: - void reconcileExternalVisibleStorage(); + void reconcileExternalVisibleStorage() const; void LoadLexicalDeclsFromExternalStorage() const; /// @brief Makes a declaration visible within this context, but @@ -1650,7 +1674,7 @@ inline bool Decl::isTemplateParameter() const { // Specialization selected when ToTy is not a known subclass of DeclContext. template <class ToTy, - bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value> + bool IsKnownSubtype = ::std::is_base_of<DeclContext, ToTy>::value> struct cast_convert_decl_context { static const ToTy *doit(const DeclContext *Val) { return static_cast<const ToTy*>(Decl::castFromDeclContext(Val)); diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h index dbc4132..72fad7c 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h @@ -17,13 +17,12 @@ #define LLVM_CLANG_AST_DECLCXX_H #include "clang/AST/ASTUnresolvedSet.h" +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/TypeLoc.h" +#include "clang/AST/LambdaCapture.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -122,14 +121,14 @@ public: /// \brief Sets the location of the colon. void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; } - SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(getAccessSpecifierLoc(), getColonLoc()); } static AccessSpecDecl *Create(ASTContext &C, AccessSpecifier AS, DeclContext *DC, SourceLocation ASLoc, SourceLocation ColonLoc) { - return new (C) AccessSpecDecl(AS, DC, ASLoc, ColonLoc); + return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc); } static AccessSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -258,20 +257,31 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; -/// The inheritance model to use for member pointers of a given CXXRecordDecl. -enum MSInheritanceModel { - MSIM_Single, - MSIM_SinglePolymorphic, - MSIM_Multiple, - MSIM_MultiplePolymorphic, - MSIM_Virtual, - MSIM_Unspecified +/// \brief A lazy pointer to the definition data for a declaration. +/// FIXME: This is a little CXXRecordDecl-specific that the moment. +template<typename Decl, typename T> class LazyDefinitionDataPtr { + llvm::PointerUnion<T *, Decl *> DataOrCanonicalDecl; + + LazyDefinitionDataPtr update() { + if (Decl *Canon = DataOrCanonicalDecl.template dyn_cast<Decl*>()) { + if (Canon->isCanonicalDecl()) + Canon->getMostRecentDecl(); + else + // Declaration isn't canonical any more; + // update it and perform path compression. + *this = Canon->getPreviousDecl()->DefinitionData.update(); + } + return *this; + } + +public: + LazyDefinitionDataPtr(Decl *Canon) : DataOrCanonicalDecl(Canon) {} + LazyDefinitionDataPtr(T *Data) : DataOrCanonicalDecl(Data) {} + T *getNotUpdated() { return DataOrCanonicalDecl.template dyn_cast<T*>(); } + T *get() { return update().getNotUpdated(); } }; /// \brief Represents a C++ struct/union/class. -/// -/// FIXME: This class will disappear once we've properly taught RecordDecl -/// to deal with C++-specific things. class CXXRecordDecl : public RecordDecl { friend void TagDecl::startDefinition(); @@ -350,10 +360,15 @@ class CXXRecordDecl : public RecordDecl { /// \brief True if this class (or any subobject) has mutable fields. bool HasMutableFields : 1; + /// \brief True if this class (or any nested anonymous struct or union) + /// has variant members. + bool HasVariantMembers : 1; + /// \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. + /// \brief True if any field has an in-class initializer, including those + /// within anonymous unions or structs. bool HasInClassInitializer : 1; /// \brief True if any field is of reference type, and does not have an @@ -409,7 +424,7 @@ class CXXRecordDecl : public RecordDecl { /// \brief True if this class has a constexpr default constructor. /// /// This is true for either a user-declared constexpr default constructor - /// or an implicitly declared constexpr default constructor.. + /// or an implicitly declared constexpr default constructor. bool HasConstexprDefaultConstructor : 1; /// \brief True when this class contains at least one non-static data @@ -447,6 +462,9 @@ class CXXRecordDecl : public RecordDecl { /// \brief Whether this class describes a C++ lambda. bool IsLambda : 1; + /// \brief Whether we are currently parsing base specifiers. + bool IsParsingBaseSpecifiers : 1; + /// \brief The number of base class specifiers in Bases. unsigned NumBases; @@ -486,33 +504,39 @@ class CXXRecordDecl : public RecordDecl { /// \brief Retrieve the set of direct base classes. CXXBaseSpecifier *getBases() const { if (!Bases.isOffset()) - return Bases.get(0); + return Bases.get(nullptr); return getBasesSlowCase(); } /// \brief Retrieve the set of virtual base classes. CXXBaseSpecifier *getVBases() const { if (!VBases.isOffset()) - return VBases.get(0); + return VBases.get(nullptr); return getVBasesSlowCase(); } private: CXXBaseSpecifier *getBasesSlowCase() const; CXXBaseSpecifier *getVBasesSlowCase() const; - } *DefinitionData; + }; + + typedef LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData> + DefinitionDataPtr; + friend class LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData>; + + mutable DefinitionDataPtr DefinitionData; /// \brief Describes a C++ closure type (generated by a lambda expression). struct LambdaDefinitionData : public DefinitionData { - typedef LambdaExpr::Capture Capture; - - LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, + typedef LambdaCapture Capture; + + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent, bool IsGeneric, LambdaCaptureDefault CaptureDefault) : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), - ManglingNumber(0), ContextDecl(0), Captures(0), MethodTyInfo(Info) - { + ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr), + MethodTyInfo(Info) { IsLambda = true; } @@ -557,23 +581,20 @@ class CXXRecordDecl : public RecordDecl { }; - struct DefinitionData &data() { - assert(DefinitionData && "queried property of class with no definition"); - return *DefinitionData; - } - - const struct DefinitionData &data() const { - assert(DefinitionData && "queried property of class with no definition"); - return *DefinitionData; + struct DefinitionData &data() const { + auto *DD = DefinitionData.get(); + assert(DD && "queried property of class with no definition"); + return *DD; } struct LambdaDefinitionData &getLambdaData() const { - assert(DefinitionData && "queried property of lambda with no definition"); - assert(DefinitionData->IsLambda && - "queried lambda property of non-lambda class"); - return static_cast<LambdaDefinitionData &>(*DefinitionData); + // No update required: a merged definition cannot change any lambda + // properties. + auto *DD = DefinitionData.getNotUpdated(); + assert(DD && DD->IsLambda && "queried lambda property of non-lambda class"); + return static_cast<LambdaDefinitionData&>(*DD); } - + /// \brief The template or declaration that this declaration /// describes or was instantiated from, respectively. /// @@ -610,7 +631,7 @@ class CXXRecordDecl : public RecordDecl { FriendDecl *getFirstFriend() const; protected: - CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, + CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl); @@ -621,17 +642,7 @@ public: /// \brief Iterator that traverses the base classes of a class. typedef const CXXBaseSpecifier* base_class_const_iterator; - /// \brief Iterator that traverses the base classes of a class in reverse - /// order. - typedef std::reverse_iterator<base_class_iterator> - reverse_base_class_iterator; - - /// \brief Iterator that traverses the base classes of a class in reverse - /// order. - typedef std::reverse_iterator<base_class_const_iterator> - reverse_base_class_const_iterator; - - virtual CXXRecordDecl *getCanonicalDecl() { + CXXRecordDecl *getCanonicalDecl() override { return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); } virtual const CXXRecordDecl *getCanonicalDecl() const { @@ -656,19 +667,20 @@ public: } CXXRecordDecl *getDefinition() const { - if (!DefinitionData) return 0; - return data().Definition; + auto *DD = DefinitionData.get(); + return DD ? DD->Definition : nullptr; } - bool hasDefinition() const { return DefinitionData != 0; } + bool hasDefinition() const { return DefinitionData.get(); } static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, + IdentifierInfo *Id, + CXXRecordDecl *PrevDecl = nullptr, bool DelayTypeCreation = false); static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool DependentLambda, bool IsGeneric, + bool DependentLambda, bool IsGeneric, LambdaCaptureDefault CaptureDefault); static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); @@ -676,52 +688,52 @@ public: return data().Polymorphic || data().NumVBases != 0; } + void setIsParsingBaseSpecifiers() { data().IsParsingBaseSpecifiers = true; } + + bool isParsingBaseSpecifiers() const { + return data().IsParsingBaseSpecifiers; + } + /// \brief Sets the base classes of this struct or class. void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); /// \brief Retrieves the number of base classes of this class. unsigned getNumBases() const { return data().NumBases; } + typedef llvm::iterator_range<base_class_iterator> base_class_range; + typedef llvm::iterator_range<base_class_const_iterator> + base_class_const_range; + + base_class_range bases() { + return base_class_range(bases_begin(), bases_end()); + } + base_class_const_range bases() const { + return base_class_const_range(bases_begin(), bases_end()); + } + base_class_iterator bases_begin() { return data().getBases(); } base_class_const_iterator bases_begin() const { return data().getBases(); } base_class_iterator bases_end() { return bases_begin() + data().NumBases; } base_class_const_iterator bases_end() const { return bases_begin() + data().NumBases; } - reverse_base_class_iterator bases_rbegin() { - return reverse_base_class_iterator(bases_end()); - } - reverse_base_class_const_iterator bases_rbegin() const { - return reverse_base_class_const_iterator(bases_end()); - } - reverse_base_class_iterator bases_rend() { - return reverse_base_class_iterator(bases_begin()); - } - reverse_base_class_const_iterator bases_rend() const { - return reverse_base_class_const_iterator(bases_begin()); - } /// \brief Retrieves the number of virtual base classes of this class. unsigned getNumVBases() const { return data().NumVBases; } + base_class_range vbases() { + return base_class_range(vbases_begin(), vbases_end()); + } + base_class_const_range vbases() const { + return base_class_const_range(vbases_begin(), vbases_end()); + } + base_class_iterator vbases_begin() { return data().getVBases(); } base_class_const_iterator vbases_begin() const { return data().getVBases(); } base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; } base_class_const_iterator vbases_end() const { return vbases_begin() + data().NumVBases; } - reverse_base_class_iterator vbases_rbegin() { - return reverse_base_class_iterator(vbases_end()); - } - reverse_base_class_const_iterator vbases_rbegin() const { - return reverse_base_class_const_iterator(vbases_end()); - } - reverse_base_class_iterator vbases_rend() { - return reverse_base_class_iterator(vbases_begin()); - } - reverse_base_class_const_iterator vbases_rend() const { - return reverse_base_class_const_iterator(vbases_begin()); - } /// \brief Determine whether this class has any dependent base classes which /// are not the current instantiation. @@ -731,6 +743,12 @@ public: /// all method members of the class, including non-instance methods, /// special methods, etc. typedef specific_decl_iterator<CXXMethodDecl> method_iterator; + typedef llvm::iterator_range<specific_decl_iterator<CXXMethodDecl>> + method_range; + + method_range methods() const { + return method_range(method_begin(), method_end()); + } /// \brief Method begin iterator. Iterates in the order the methods /// were declared. @@ -744,6 +762,10 @@ public: /// Iterator access to constructor members. typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator; + typedef llvm::iterator_range<specific_decl_iterator<CXXConstructorDecl>> + ctor_range; + + ctor_range ctors() const { return ctor_range(ctor_begin(), ctor_end()); } ctor_iterator ctor_begin() const { return ctor_iterator(decls_begin()); @@ -755,6 +777,9 @@ public: /// An iterator over friend declarations. All of these are defined /// in DeclFriend.h. class friend_iterator; + typedef llvm::iterator_range<friend_iterator> friend_range; + + friend_range friends() const; friend_iterator friend_begin() const; friend_iterator friend_end() const; void pushFriendDecl(FriendDecl *FD); @@ -984,7 +1009,11 @@ public: } /// \brief Determine whether this class describes a lambda function object. - bool isLambda() const { return hasDefinition() && data().IsLambda; } + bool isLambda() const { + // An update record can't turn a non-lambda into a lambda. + auto *DD = DefinitionData.getNotUpdated(); + return DD && DD->IsLambda; + } /// \brief Determine whether this class describes a generic /// lambda function object (i.e. function call operator is @@ -1025,12 +1054,18 @@ public: void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, FieldDecl *&ThisCapture) const; - typedef const LambdaExpr::Capture* capture_const_iterator; + typedef const LambdaCapture *capture_const_iterator; + typedef llvm::iterator_range<capture_const_iterator> capture_const_range; + + capture_const_range captures() const { + return capture_const_range(captures_begin(), captures_end()); + } capture_const_iterator captures_begin() const { - return isLambda() ? getLambdaData().Captures : NULL; + return isLambda() ? getLambdaData().Captures : nullptr; } capture_const_iterator captures_end() const { - return isLambda() ? captures_begin() + getLambdaData().NumCaptures : NULL; + return isLambda() ? captures_begin() + getLambdaData().NumCaptures + : nullptr; } typedef UnresolvedSetIterator conversion_iterator; @@ -1058,7 +1093,8 @@ public: bool isAggregate() const { return data().Aggregate; } /// \brief Whether this class has any in-class initializers - /// for non-static data members. + /// for non-static data members (including those in anonymous unions or + /// structs). bool hasInClassInitializer() const { return data().HasInClassInitializer; } /// \brief Whether this class or any of its subobjects has any members of @@ -1117,6 +1153,9 @@ public: /// contains a mutable field. bool hasMutableFields() const { return data().HasMutableFields; } + /// \brief Determine whether this class has any variant members. + bool hasVariantMembers() const { return data().HasVariantMembers; } + /// \brief Determine whether this class has a trivial default constructor /// (C++11 [class.ctor]p5). bool hasTrivialDefaultConstructor() const { @@ -1144,7 +1183,7 @@ public: /// would be constexpr. bool defaultedDefaultConstructorIsConstexpr() const { return data().DefaultedDefaultConstructorIsConstexpr && - (!isUnion() || hasInClassInitializer()); + (!isUnion() || hasInClassInitializer() || !hasVariantMembers()); } /// \brief Determine whether this class has a constexpr default constructor. @@ -1546,7 +1585,7 @@ public: void finishedDefaultedOrDeletedMember(CXXMethodDecl *MD); /// \brief Indicates that the definition of this class is now complete. - virtual void completeDefinition(); + void completeDefinition() override; /// \brief Indicates that the definition of this class is now complete, /// and provides a final overrider map to help determine @@ -1599,7 +1638,25 @@ public: } /// \brief Returns the inheritance model used for this record. - MSInheritanceModel getMSInheritanceModel() const; + MSInheritanceAttr::Spelling getMSInheritanceModel() const; + /// \brief Calculate what the inheritance model would be for this class. + MSInheritanceAttr::Spelling calculateInheritanceModel() const; + + /// In the Microsoft C++ ABI, use zero for the field offset of a null data + /// member pointer if we can guarantee that zero is not a valid field offset, + /// or if the member pointer has multiple fields. Polymorphic classes have a + /// vfptr at offset zero, so we can use zero for null. If there are multiple + /// fields, we can use zero even if it is a valid field offset because + /// null-ness testing will check the other fields. + bool nullFieldOffsetIsZero() const { + return !MSInheritanceAttr::hasOnlyOneField(/*IsMemberFunction=*/false, + getMSInheritanceModel()) || + (hasDefinition() && isPolymorphic()); + } + + /// \brief Controls when vtordisps will be emitted if this record is used as a + /// virtual base. + MSVtorDispAttr::Mode getMSVtorDispMode() const; /// \brief Determine whether this lambda expression was known to be dependent /// at the time it was created, even if its context does not appear to be @@ -1636,14 +1693,14 @@ public: /// In the terminology of the C++ Standard, these are the (static and /// non-static) member functions, whether virtual or not. class CXXMethodDecl : public FunctionDecl { - virtual void anchor(); + void anchor() override; protected: - CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, + CXXMethodDecl(Kind DK, ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInline, bool isConstexpr, SourceLocation EndLocation) - : FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo, + : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, isInline, isConstexpr) { if (EndLocation.isValid()) setRangeEnd(EndLocation); @@ -1683,9 +1740,9 @@ public: CXXMethodDecl *CD = cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl()); - // Methods declared in interfaces are automatically (pure) virtual. - if (CD->isVirtualAsWritten() || - (CD->getParent()->isInterface() && CD->isUserProvided())) + // Member function is virtual if it is marked explicitly so, or if it is + // declared in __interface -- then it is automatically pure virtual. + if (CD->isVirtualAsWritten() || CD->isPure()) return true; return (CD->begin_overridden_methods() != CD->end_overridden_methods()); @@ -1703,10 +1760,10 @@ public: /// \brief Determine whether this is a move assignment operator. bool isMoveAssignmentOperator() const; - CXXMethodDecl *getCanonicalDecl() { + CXXMethodDecl *getCanonicalDecl() override { return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); } - const CXXMethodDecl *getCanonicalDecl() const { + const CXXMethodDecl *getCanonicalDecl() const override { return const_cast<CXXMethodDecl*>(this)->getCanonicalDecl(); } @@ -1921,7 +1978,7 @@ public: /// In-class member initializers (also known as "non-static data member /// initializations", NSDMIs) were introduced in C++11. bool isInClassMemberInitializer() const { - return isa<CXXDefaultInitExpr>(Init); + return Init->getStmtClass() == Stmt::CXXDefaultInitExprClass; } /// \brief Determine whether this initializer is creating a delegating @@ -1968,20 +2025,20 @@ public: FieldDecl *getMember() const { if (isMemberInitializer()) return Initializee.get<FieldDecl*>(); - return 0; + return nullptr; } FieldDecl *getAnyMember() const { if (isMemberInitializer()) return Initializee.get<FieldDecl*>(); if (isIndirectMemberInitializer()) return Initializee.get<IndirectFieldDecl*>()->getAnonField(); - return 0; + return nullptr; } IndirectFieldDecl *getIndirectMember() const { if (isIndirectMemberInitializer()) return Initializee.get<IndirectFieldDecl*>(); - return 0; + return nullptr; } SourceLocation getMemberLocation() const { @@ -2066,7 +2123,7 @@ public: /// }; /// \endcode class CXXConstructorDecl : public CXXMethodDecl { - virtual void anchor(); + void anchor() override; /// \brief Whether this constructor declaration has the \c explicit keyword /// specified. bool IsExplicitSpecified : 1; @@ -2078,14 +2135,14 @@ class CXXConstructorDecl : public CXXMethodDecl { unsigned NumCtorInitializers; /// \} - CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared, bool isConstexpr) - : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, + : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, SourceLocation()), - IsExplicitSpecified(isExplicitSpecified), CtorInitializers(0), + IsExplicitSpecified(isExplicitSpecified), CtorInitializers(nullptr), NumCtorInitializers(0) { setImplicit(isImplicitlyDeclared); } @@ -2115,6 +2172,14 @@ public: /// \brief Iterates through the member/base initializer list. typedef CXXCtorInitializer * const * init_const_iterator; + typedef llvm::iterator_range<init_iterator> init_range; + typedef llvm::iterator_range<init_const_iterator> init_const_range; + + init_range inits() { return init_range(init_begin(), init_end()); } + init_const_range inits() const { + return init_const_range(init_begin(), init_end()); + } + /// \brief Retrieve an iterator to the first initializer. init_iterator init_begin() { return CtorInitializers; } /// \brief Retrieve an iterator to the first initializer. @@ -2240,10 +2305,10 @@ public: /// \brief Set the constructor that this inheriting constructor is based on. void setInheritedConstructor(const CXXConstructorDecl *BaseCtor); - const CXXConstructorDecl *getCanonicalDecl() const { + const CXXConstructorDecl *getCanonicalDecl() const override { return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl()); } - CXXConstructorDecl *getCanonicalDecl() { + CXXConstructorDecl *getCanonicalDecl() override { return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl()); } @@ -2266,17 +2331,17 @@ public: /// }; /// \endcode class CXXDestructorDecl : public CXXMethodDecl { - virtual void anchor(); + void anchor() override; FunctionDecl *OperatorDelete; - CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, + : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, /*isConstexpr=*/false, SourceLocation()), - OperatorDelete(0) { + OperatorDelete(nullptr) { setImplicit(isImplicitlyDeclared); } @@ -2289,8 +2354,12 @@ public: bool isImplicitlyDeclared); static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); - void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; } - const FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + void setOperatorDelete(FunctionDecl *OD) { + cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete = OD; + } + const FunctionDecl *getOperatorDelete() const { + return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete; + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2311,18 +2380,18 @@ public: /// }; /// \endcode class CXXConversionDecl : public CXXMethodDecl { - virtual void anchor(); + void anchor() override; /// Whether this conversion function declaration is marked /// "explicit", meaning that it can only be applied when the user /// explicitly wrote a cast. This is a C++0x feature. bool IsExplicitSpecified : 1; - CXXConversionDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicitSpecified, bool isConstexpr, SourceLocation EndLocation) - : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, + : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, EndLocation), IsExplicitSpecified(isExplicitSpecified) { } @@ -2351,7 +2420,7 @@ public: /// \brief Returns the type that this conversion function is converting to. QualType getConversionType() const { - return getType()->getAs<FunctionType>()->getResultType(); + return getType()->getAs<FunctionType>()->getReturnType(); } /// \brief Determine whether this conversion function is a conversion from @@ -2440,7 +2509,7 @@ public: return decls_empty() ? getLocation() : decls_begin()->getLocEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(ExternLoc, getLocEnd()); } @@ -2465,7 +2534,7 @@ public: /// artificial names for all using-directives in order to store /// them in DeclContext effectively. class UsingDirectiveDecl : public NamedDecl { - virtual void anchor(); + void anchor() override; /// \brief The location of the \c using keyword. SourceLocation UsingLoc; @@ -2546,8 +2615,8 @@ public: NamedDecl *Nominated, DeclContext *CommonAncestor); static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const LLVM_READONLY { + + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(UsingLoc, getLocation()); } @@ -2568,7 +2637,7 @@ public: /// namespace Foo = Bar; /// \endcode class NamespaceAliasDecl : public NamedDecl { - virtual void anchor(); + void anchor() override; /// \brief The location of the \c namespace keyword. SourceLocation NamespaceLoc; @@ -2641,8 +2710,8 @@ public: NamedDecl *Namespace); static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - virtual SourceRange getSourceRange() const LLVM_READONLY { + + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(NamespaceLoc, IdentLoc); } @@ -2664,7 +2733,7 @@ public: /// } /// \endcode class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> { - virtual void anchor(); + void anchor() override; /// The referenced declaration. NamedDecl *Underlying; @@ -2674,10 +2743,10 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> { NamedDecl *UsingOrNextShadow; friend class UsingDecl; - UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using, - NamedDecl *Target) + UsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc, + UsingDecl *Using, NamedDecl *Target) : NamedDecl(UsingShadow, DC, Loc, DeclarationName()), - Underlying(Target), + redeclarable_base(C), Underlying(Target), UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) { if (Target) { setDeclName(Target->getDeclName()); @@ -2687,13 +2756,13 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> { } typedef Redeclarable<UsingShadowDecl> redeclarable_base; - virtual UsingShadowDecl *getNextRedeclaration() { - return RedeclLink.getNext(); + UsingShadowDecl *getNextRedeclarationImpl() override { + return getNextRedeclaration(); } - virtual UsingShadowDecl *getPreviousDeclImpl() { + UsingShadowDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } - virtual UsingShadowDecl *getMostRecentDeclImpl() { + UsingShadowDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } @@ -2701,21 +2770,23 @@ public: static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, UsingDecl *Using, NamedDecl *Target) { - return new (C) UsingShadowDecl(DC, Loc, Using, Target); + return new (C, DC) UsingShadowDecl(C, DC, Loc, Using, Target); } static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); + typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; + using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; - virtual UsingShadowDecl *getCanonicalDecl() { + UsingShadowDecl *getCanonicalDecl() override { return getFirstDecl(); } - virtual const UsingShadowDecl *getCanonicalDecl() const { + const UsingShadowDecl *getCanonicalDecl() const { return getFirstDecl(); } @@ -2754,7 +2825,7 @@ public: /// using someNameSpace::someIdentifier; /// \endcode class UsingDecl : public NamedDecl { - virtual void anchor(); + void anchor() override; /// \brief The source location of the 'using' keyword itself. SourceLocation UsingLocation; @@ -2778,7 +2849,7 @@ class UsingDecl : public NamedDecl { const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword) : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), UsingLocation(UL), QualifierLoc(QualifierLoc), - DNLoc(NameInfo.getInfo()), FirstUsingShadow(0, HasTypenameKeyword) { + DNLoc(NameInfo.getInfo()), FirstUsingShadow(nullptr, HasTypenameKeyword) { } public: @@ -2823,7 +2894,7 @@ public: typedef std::forward_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; - shadow_iterator() : Current(0) { } + shadow_iterator() : Current(nullptr) { } explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { } reference operator*() const { return Current; } @@ -2848,6 +2919,11 @@ public: } }; + typedef llvm::iterator_range<shadow_iterator> shadow_range; + + shadow_range shadows() const { + return shadow_range(shadow_begin(), shadow_end()); + } shadow_iterator shadow_begin() const { return shadow_iterator(FirstUsingShadow.getPointer()); } @@ -2870,7 +2946,7 @@ public: static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID); - SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Using; } @@ -2891,7 +2967,7 @@ public: /// }; /// \endcode class UnresolvedUsingValueDecl : public ValueDecl { - virtual void anchor(); + void anchor() override; /// \brief The source location of the 'using' keyword SourceLocation UsingLocation; @@ -2944,7 +3020,7 @@ public: static UnresolvedUsingValueDecl * CreateDeserialized(ASTContext &C, unsigned ID); - SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } @@ -2965,7 +3041,7 @@ public: /// The type associated with an unresolved using typename decl is /// currently always a typename type. class UnresolvedUsingTypenameDecl : public TypeDecl { - virtual void anchor(); + void anchor() override; /// \brief The source location of the 'typename' keyword SourceLocation TypenameLocation; @@ -3043,7 +3119,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } - SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(getLocation(), getRParenLoc()); } @@ -3083,21 +3159,24 @@ public: class MSPropertyDecl : public DeclaratorDecl { IdentifierInfo *GetterId, *SetterId; -public: - MSPropertyDecl(DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo, - SourceLocation StartL, IdentifierInfo *Getter, - IdentifierInfo *Setter): - DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL), GetterId(Getter), - SetterId(Setter) {} + MSPropertyDecl(DeclContext *DC, SourceLocation L, DeclarationName N, + QualType T, TypeSourceInfo *TInfo, SourceLocation StartL, + IdentifierInfo *Getter, IdentifierInfo *Setter) + : DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL), + GetterId(Getter), SetterId(Setter) {} +public: + static MSPropertyDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName N, QualType T, + TypeSourceInfo *TInfo, SourceLocation StartL, + IdentifierInfo *Getter, IdentifierInfo *Setter); static MSPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); static bool classof(const Decl *D) { return D->getKind() == MSProperty; } - bool hasGetter() const { return GetterId != NULL; } + bool hasGetter() const { return GetterId != nullptr; } IdentifierInfo* getGetterId() const { return GetterId; } - bool hasSetter() const { return SetterId != NULL; } + bool hasSetter() const { return SetterId != nullptr; } IdentifierInfo* getSetterId() const { return SetterId; } friend class ASTDeclReader; diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h index 9c626c8..9068c00 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h @@ -46,10 +46,8 @@ struct StoredDeclsList { public: StoredDeclsList() {} - StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { - if (DeclsTy *RHSVec = RHS.getAsVector()) - Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), - RHS.hasExternalDecls()); + StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) { + RHS.Data = (NamedDecl *)nullptr; } ~StoredDeclsList() { @@ -58,12 +56,11 @@ public: delete Vector; } - StoredDeclsList &operator=(const StoredDeclsList &RHS) { + StoredDeclsList &operator=(StoredDeclsList &&RHS) { if (DeclsTy *Vector = getAsVector()) delete Vector; Data = RHS.Data; - if (DeclsTy *RHSVec = RHS.getAsVector()) - Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), hasExternalDecls()); + RHS.Data = (NamedDecl *)nullptr; return *this; } @@ -110,7 +107,7 @@ public: if (NamedDecl *Singleton = getAsDecl()) { assert(Singleton == D && "list is different singleton"); (void)Singleton; - Data = (NamedDecl *)0; + Data = (NamedDecl *)nullptr; return; } @@ -145,8 +142,8 @@ public: /// represents. DeclContext::lookup_result getLookupResult() { if (isNull()) - return DeclContext::lookup_result(DeclContext::lookup_iterator(0), - DeclContext::lookup_iterator(0)); + return DeclContext::lookup_result(DeclContext::lookup_iterator(nullptr), + DeclContext::lookup_iterator(nullptr)); // If we have a single NamedDecl, return it. if (getAsDecl()) { @@ -255,7 +252,7 @@ private: class DependentStoredDeclsMap : public StoredDeclsMap { public: - DependentStoredDeclsMap() : FirstDiagnostic(0) {} + DependentStoredDeclsMap() : FirstDiagnostic(nullptr) {} private: friend class DependentDiagnostic; diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h index be6f2eb..12b93b4 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/TypeLoc.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -91,7 +92,7 @@ private: FriendDecl *getNextFriend() { if (!NextFriend.isOffset()) - return cast_or_null<FriendDecl>(NextFriend.get(0)); + return cast_or_null<FriendDecl>(NextFriend.get(nullptr)); return getNextFriendSlowCase(); } FriendDecl *getNextFriendSlowCase(); @@ -132,10 +133,14 @@ public: } /// Retrieves the source range for the friend declaration. - SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { if (NamedDecl *ND = getFriendDecl()) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) + return FD->getSourceRange(); if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) return FTD->getSourceRange(); + if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND)) + return CTD->getSourceRange(); if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) { if (DD->getOuterLocStart() != DD->getInnerLocStart()) return DD->getSourceRange(); @@ -224,7 +229,11 @@ inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const { } inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const { - return friend_iterator(0); + return friend_iterator(nullptr); +} + +inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const { + return friend_range(friend_begin(), friend_end()); } inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) { diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h index cda6ae5..bd3dbd8 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h @@ -63,7 +63,7 @@ class DeclGroupRef { } public: - DeclGroupRef() : D(0) {} + DeclGroupRef() : D(nullptr) {} explicit DeclGroupRef(Decl* d) : D(d) {} explicit DeclGroupRef(DeclGroup* dg) @@ -80,7 +80,7 @@ public: typedef Decl** iterator; typedef Decl* const * const_iterator; - bool isNull() const { return D == 0; } + bool isNull() const { return D == nullptr; } bool isSingleDecl() const { return getKind() == SingleDeclKind; } bool isDeclGroup() const { return getKind() == DeclGroupKind; } @@ -102,26 +102,26 @@ public: iterator begin() { if (isSingleDecl()) - return D ? &D : 0; + return D ? &D : nullptr; return &getDeclGroup()[0]; } iterator end() { if (isSingleDecl()) - return D ? &D+1 : 0; + return D ? &D+1 : nullptr; DeclGroup &G = getDeclGroup(); return &G[0] + G.size(); } const_iterator begin() const { if (isSingleDecl()) - return D ? &D : 0; + return D ? &D : nullptr; return &getDeclGroup()[0]; } const_iterator end() const { if (isSingleDecl()) - return D ? &D+1 : 0; + return D ? &D+1 : nullptr; const DeclGroup &G = getDeclGroup(); return &G[0] + G.size(); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h index c16975a..d2016af 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h @@ -68,38 +68,40 @@ public: } }; -inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { +inline DeclContext::lookups_range DeclContext::lookups() const { DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); if (Primary->hasExternalVisibleStorage()) getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary); if (StoredDeclsMap *Map = Primary->buildLookup()) - return all_lookups_iterator(Map->begin(), Map->end()); - return all_lookups_iterator(); + return lookups_range(all_lookups_iterator(Map->begin(), Map->end()), + all_lookups_iterator(Map->end(), Map->end())); + return lookups_range(); +} + +inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { + return lookups().begin(); } inline DeclContext::all_lookups_iterator DeclContext::lookups_end() const { + return lookups().end(); +} + +inline DeclContext::lookups_range DeclContext::noload_lookups() const { DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); - if (Primary->hasExternalVisibleStorage()) - getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary); - if (StoredDeclsMap *Map = Primary->buildLookup()) - return all_lookups_iterator(Map->end(), Map->end()); - return all_lookups_iterator(); + if (StoredDeclsMap *Map = Primary->getLookupPtr()) + return lookups_range(all_lookups_iterator(Map->begin(), Map->end()), + all_lookups_iterator(Map->end(), Map->end())); + return lookups_range(); } inline DeclContext::all_lookups_iterator DeclContext::noload_lookups_begin() const { - DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); - if (StoredDeclsMap *Map = Primary->getLookupPtr()) - return all_lookups_iterator(Map->begin(), Map->end()); - return all_lookups_iterator(); + return noload_lookups().begin(); } inline DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const { - DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); - if (StoredDeclsMap *Map = Primary->getLookupPtr()) - return all_lookups_iterator(Map->end(), Map->end()); - return all_lookups_iterator(); + return noload_lookups().end(); } } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h index 2e760d6..db3b084 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h @@ -41,7 +41,7 @@ protected: unsigned NumElts; public: - ObjCListBase() : List(0), NumElts(0) {} + ObjCListBase() : List(nullptr), NumElts(0) {} unsigned size() const { return NumElts; } bool empty() const { return NumElts == 0; } @@ -79,7 +79,7 @@ class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> { using ObjCList<ObjCProtocolDecl>::set; public: - ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(0) { } + ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(nullptr) { } typedef const SourceLocation *loc_iterator; loc_iterator loc_begin() const { return Locations; } @@ -162,11 +162,11 @@ private: /// \brief Indicates if the method was a definition but its body was skipped. unsigned HasSkippedBody : 1; - // Result type of this method. + // Return type of this method. QualType MethodDeclType; - // Type source information for the result type. - TypeSourceInfo *ResultTInfo; + // Type source information for the return type. + TypeSourceInfo *ReturnTInfo; /// \brief Array of ParmVarDecls for the formal parameters of this method /// and optionally followed by selector locations. @@ -224,54 +224,44 @@ private: ArrayRef<SourceLocation> SelLocs); ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, - Selector SelInfo, QualType T, - TypeSourceInfo *ResultTInfo, - DeclContext *contextDecl, - bool isInstance = true, - bool isVariadic = false, - bool isPropertyAccessor = false, - bool isImplicitlyDeclared = false, - bool isDefined = false, + Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, + DeclContext *contextDecl, bool isInstance = true, + bool isVariadic = false, bool isPropertyAccessor = false, + bool isImplicitlyDeclared = false, bool isDefined = false, ImplementationControl impControl = None, bool HasRelatedResultType = false) - : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), - DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), - IsInstance(isInstance), IsVariadic(isVariadic), - IsPropertyAccessor(isPropertyAccessor), - IsDefined(isDefined), IsRedeclaration(0), HasRedeclaration(0), - DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), - RelatedResultType(HasRelatedResultType), - SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0), - MethodDeclType(T), ResultTInfo(ResultTInfo), - ParamsAndSelLocs(0), NumParams(0), - DeclEndLoc(endLoc), Body(), SelfDecl(0), CmdDecl(0) { + : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), + DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), + IsInstance(isInstance), IsVariadic(isVariadic), + IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined), + IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl), + objcDeclQualifier(OBJC_TQ_None), + RelatedResultType(HasRelatedResultType), + SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0), + MethodDeclType(T), ReturnTInfo(ReturnTInfo), ParamsAndSelLocs(nullptr), + NumParams(0), DeclEndLoc(endLoc), Body(), SelfDecl(nullptr), + CmdDecl(nullptr) { setImplicit(isImplicitlyDeclared); } /// \brief A definition will return its interface declaration. /// An interface declaration will return its definition. /// Otherwise it will return itself. - virtual ObjCMethodDecl *getNextRedeclaration(); + ObjCMethodDecl *getNextRedeclarationImpl() override; public: - static ObjCMethodDecl *Create(ASTContext &C, - SourceLocation beginLoc, - SourceLocation endLoc, - Selector SelInfo, - QualType T, - TypeSourceInfo *ResultTInfo, - DeclContext *contextDecl, - bool isInstance = true, - bool isVariadic = false, - bool isPropertyAccessor = false, - bool isImplicitlyDeclared = false, - bool isDefined = false, - ImplementationControl impControl = None, - bool HasRelatedResultType = false); + static ObjCMethodDecl * + Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, + Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, + DeclContext *contextDecl, bool isInstance = true, + bool isVariadic = false, bool isPropertyAccessor = false, + bool isImplicitlyDeclared = false, bool isDefined = false, + ImplementationControl impControl = None, + bool HasRelatedResultType = false); static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - virtual ObjCMethodDecl *getCanonicalDecl(); + + ObjCMethodDecl *getCanonicalDecl() override; const ObjCMethodDecl *getCanonicalDecl() const { return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl(); } @@ -300,7 +290,7 @@ public: // Location information, modeled after the Stmt API. SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); } SourceLocation getLocEnd() const LLVM_READONLY; - virtual SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(getLocation(), getLocEnd()); } @@ -314,8 +304,7 @@ public: if (hasStandardSelLocs()) return getStandardSelectorLoc(Index, getSelector(), getSelLocsKind() == SelLoc_StandardWithSpace, - llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()), - NumParams), + parameters(), DeclEndLoc); return getStoredSelLocs()[Index]; } @@ -338,32 +327,52 @@ public: Selector getSelector() const { return getDeclName().getObjCSelector(); } - QualType getResultType() const { return MethodDeclType; } - void setResultType(QualType T) { MethodDeclType = T; } + QualType getReturnType() const { return MethodDeclType; } + void setReturnType(QualType T) { MethodDeclType = T; } /// \brief Determine the type of an expression that sends a message to this /// function. QualType getSendResultType() const { - return getResultType().getNonLValueExprType(getASTContext()); + return getReturnType().getNonLValueExprType(getASTContext()); } - TypeSourceInfo *getResultTypeSourceInfo() const { return ResultTInfo; } - void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; } + TypeSourceInfo *getReturnTypeSourceInfo() const { return ReturnTInfo; } + void setReturnTypeSourceInfo(TypeSourceInfo *TInfo) { ReturnTInfo = TInfo; } // Iterator access to formal parameters. unsigned param_size() const { return NumParams; } typedef const ParmVarDecl *const *param_const_iterator; typedef ParmVarDecl *const *param_iterator; - param_const_iterator param_begin() const { return getParams(); } - param_const_iterator param_end() const { return getParams() + NumParams; } - param_iterator param_begin() { return getParams(); } - param_iterator param_end() { return getParams() + NumParams; } + typedef llvm::iterator_range<param_iterator> param_range; + typedef llvm::iterator_range<param_const_iterator> param_const_range; + + param_range params() { return param_range(param_begin(), param_end()); } + param_const_range params() const { + return param_const_range(param_begin(), param_end()); + } + + param_const_iterator param_begin() const { + return param_const_iterator(getParams()); + } + param_const_iterator param_end() const { + return param_const_iterator(getParams() + NumParams); + } + param_iterator param_begin() { return param_iterator(getParams()); } + param_iterator param_end() { return param_iterator(getParams() + NumParams); } + // This method returns and of the parameters which are part of the selector // name mangling requirements. param_const_iterator sel_param_end() const { return param_begin() + getSelector().getNumArgs(); } + // ArrayRef access to formal parameters. This should eventually + // replace the iterator interface above. + ArrayRef<ParmVarDecl*> parameters() const { + return llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()), + NumParams); + } + /// \brief Sets the method's parameters and selector source locations. /// If the method is implicit (not coming from source) \p SelLocs is /// ignored. @@ -375,12 +384,12 @@ public: // Iterator access to parameter types. typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun; typedef llvm::mapped_iterator<param_const_iterator, deref_fun> - arg_type_iterator; + param_type_iterator; - arg_type_iterator arg_type_begin() const { + param_type_iterator param_type_begin() const { return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType)); } - arg_type_iterator arg_type_end() const { + param_type_iterator param_type_end() const { return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType)); } @@ -451,11 +460,24 @@ public: return ImplementationControl(DeclImplementation); } + /// Returns true if this specific method declaration is marked with the + /// designated initializer attribute. + bool isThisDeclarationADesignatedInitializer() const; + + /// Returns true if the method selector resolves to a designated initializer + /// in the class's interface. + /// + /// \param InitMethod if non-null and the function returns true, it receives + /// the method declaration that was marked with the designated initializer + /// attribute. + bool isDesignatedInitializerForTheInterface( + const ObjCMethodDecl **InitMethod = nullptr) const; + /// \brief Determine whether this method has a body. - virtual bool hasBody() const { return Body.isValid(); } + bool hasBody() const override { return Body.isValid(); } /// \brief Retrieve the body of this method, if it has one. - virtual Stmt *getBody() const; + Stmt *getBody() const override; void setLazyBody(uint64_t Offset) { Body = Offset; } @@ -484,7 +506,7 @@ public: /// ObjCProtocolDecl, and ObjCImplDecl. /// class ObjCContainerDecl : public NamedDecl, public DeclContext { - virtual void anchor(); + void anchor() override; SourceLocation AtStart; @@ -500,6 +522,10 @@ public: // Iterator access to properties. typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; + typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>> + prop_range; + + prop_range properties() const { return prop_range(prop_begin(), prop_end()); } prop_iterator prop_begin() const { return prop_iterator(decls_begin()); } @@ -509,6 +535,12 @@ public: // Iterator access to instance/class methods. typedef specific_decl_iterator<ObjCMethodDecl> method_iterator; + typedef llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>> + method_range; + + method_range methods() const { + return method_range(meth_begin(), meth_end()); + } method_iterator meth_begin() const { return method_iterator(decls_begin()); } @@ -519,6 +551,11 @@ public: typedef filtered_decl_iterator<ObjCMethodDecl, &ObjCMethodDecl::isInstanceMethod> instmeth_iterator; + typedef llvm::iterator_range<instmeth_iterator> instmeth_range; + + instmeth_range instance_methods() const { + return instmeth_range(instmeth_begin(), instmeth_end()); + } instmeth_iterator instmeth_begin() const { return instmeth_iterator(decls_begin()); } @@ -529,6 +566,11 @@ public: typedef filtered_decl_iterator<ObjCMethodDecl, &ObjCMethodDecl::isClassMethod> classmeth_iterator; + typedef llvm::iterator_range<classmeth_iterator> classmeth_range; + + classmeth_range class_methods() const { + return classmeth_range(classmeth_begin(), classmeth_end()); + } classmeth_iterator classmeth_begin() const { return classmeth_iterator(decls_begin()); } @@ -575,7 +617,7 @@ public: AtEnd = atEnd; } - virtual SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(AtStart, getAtEndRange().getEnd()); } @@ -621,7 +663,7 @@ public: /// class ObjCInterfaceDecl : public ObjCContainerDecl , public Redeclarable<ObjCInterfaceDecl> { - virtual void anchor(); + void anchor() override; /// TypeForDecl - This indicates the Type object that represents this /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType @@ -661,6 +703,22 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// declared in the implementation. mutable bool IvarListMissingImplementation : 1; + /// Indicates that this interface decl contains at least one initializer + /// marked with the 'objc_designated_initializer' attribute. + bool HasDesignatedInitializers : 1; + + enum InheritedDesignatedInitializersState { + /// We didn't calculate whether the designated initializers should be + /// inherited or not. + IDI_Unknown = 0, + /// Designated initializers are inherited for the super class. + IDI_Inherited = 1, + /// The class does not inherit designated initializers. + IDI_NotInherited = 2 + }; + /// One of the \c InheritedDesignatedInitializersState enumeratos. + mutable unsigned InheritedDesignatedInitializers : 2; + /// \brief The location of the superclass, if any. SourceLocation SuperClassLoc; @@ -671,12 +729,14 @@ class ObjCInterfaceDecl : public ObjCContainerDecl DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(), ExternallyCompleted(), - IvarListMissingImplementation(true) { } + IvarListMissingImplementation(true), + HasDesignatedInitializers(), + InheritedDesignatedInitializers(IDI_Unknown) { } }; - ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, - bool isInternal); + ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc, + IdentifierInfo *Id, SourceLocation CLoc, + ObjCInterfaceDecl *PrevDecl, bool IsInternal); void LoadExternalDefinition() const; @@ -696,13 +756,13 @@ class ObjCInterfaceDecl : public ObjCContainerDecl void allocateDefinitionData(); typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base; - virtual ObjCInterfaceDecl *getNextRedeclaration() { - return RedeclLink.getNext(); + ObjCInterfaceDecl *getNextRedeclarationImpl() override { + return getNextRedeclaration(); } - virtual ObjCInterfaceDecl *getPreviousDeclImpl() { + ObjCInterfaceDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } - virtual ObjCInterfaceDecl *getMostRecentDeclImpl() { + ObjCInterfaceDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } @@ -714,9 +774,9 @@ public: SourceLocation ClassLoc = SourceLocation(), bool isInternal = false); - static ObjCInterfaceDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID); - virtual SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { if (isThisDeclarationADefinition()) return ObjCContainerDecl::getSourceRange(); @@ -728,6 +788,20 @@ public: /// when a complete class is required. void setExternallyCompleted(); + /// Indicate that this interface decl contains at least one initializer + /// marked with the 'objc_designated_initializer' attribute. + void setHasDesignatedInitializers(); + + /// Returns true if this interface decl contains at least one initializer + /// marked with the 'objc_designated_initializer' attribute. + bool hasDesignatedInitializers() const; + + /// Returns true if this interface decl declares a designated initializer + /// or it inherites one from its super class. + bool declaresOrInheritsDesignatedInitializers() const { + return hasDesignatedInitializers() || inheritsDesignatedInitializers(); + } + const ObjCProtocolList &getReferencedProtocols() const { assert(hasDefinition() && "Caller did not check for forward reference!"); if (data().ExternallyCompleted) @@ -750,7 +824,11 @@ public: } typedef ObjCProtocolList::iterator protocol_iterator; + typedef llvm::iterator_range<protocol_iterator> protocol_range; + protocol_range protocols() const { + return protocol_range(protocol_begin(), protocol_end()); + } protocol_iterator protocol_begin() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) @@ -773,7 +851,11 @@ public: } typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; + typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range; + protocol_loc_range protocol_locs() const { + return protocol_loc_range(protocol_loc_begin(), protocol_loc_end()); + } protocol_loc_iterator protocol_loc_begin() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) @@ -797,7 +879,12 @@ public: } typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator; + typedef llvm::iterator_range<all_protocol_iterator> all_protocol_range; + all_protocol_range all_referenced_protocols() const { + return all_protocol_range(all_referenced_protocol_begin(), + all_referenced_protocol_end()); + } all_protocol_iterator all_referenced_protocol_begin() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) @@ -824,7 +911,9 @@ public: } typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range; + ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); } ivar_iterator ivar_begin() const { if (const ObjCInterfaceDecl *Def = getDefinition()) return ivar_iterator(Def->decls_begin()); @@ -867,6 +956,31 @@ public: unsigned Num, ASTContext &C); + /// Produce a name to be used for class's metadata. It comes either via + /// objc_runtime_name attribute or class name. + StringRef getObjCRuntimeNameAsString() const; + + /// Returns the designated initializers for the interface. + /// + /// If this declaration does not have methods marked as designated + /// initializers then the interface inherits the designated initializers of + /// its super class. + void getDesignatedInitializers( + llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const; + + /// Returns true if the given selector is a designated initializer for the + /// interface. + /// + /// If this declaration does not have methods marked as designated + /// initializers then the interface inherits the designated initializers of + /// its super class. + /// + /// \param InitMethod if non-null and the function returns true, it receives + /// the method that was marked as a designated initializer. + bool + isDesignatedInitializer(Selector Sel, + const ObjCMethodDecl **InitMethod = nullptr) const; + /// \brief Determine whether this particular declaration of this class is /// actually also a definition. bool isThisDeclarationADefinition() const { @@ -894,14 +1008,14 @@ public: /// has been forward-declared (with \@class) but not yet defined (with /// \@interface). ObjCInterfaceDecl *getDefinition() { - return hasDefinition()? Data.getPointer()->Definition : 0; + return hasDefinition()? Data.getPointer()->Definition : nullptr; } /// \brief Retrieve the definition of this class, or NULL if this class /// has been forward-declared (with \@class) but not yet defined (with /// \@interface). const ObjCInterfaceDecl *getDefinition() const { - return hasDefinition()? Data.getPointer()->Definition : 0; + return hasDefinition()? Data.getPointer()->Definition : nullptr; } /// \brief Starts the definition of this Objective-C class, taking it from @@ -911,7 +1025,7 @@ public: ObjCInterfaceDecl *getSuperClass() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) - return 0; + return nullptr; if (data().ExternallyCompleted) LoadExternalDefinition(); @@ -943,7 +1057,7 @@ public: typedef std::ptrdiff_t difference_type; typedef std::input_iterator_tag iterator_category; - filtered_category_iterator() : Current(0) { } + filtered_category_iterator() : Current(nullptr) { } explicit filtered_category_iterator(ObjCCategoryDecl *Current) : Current(Current) { @@ -984,6 +1098,14 @@ public: typedef filtered_category_iterator<isVisibleCategory> visible_categories_iterator; + typedef llvm::iterator_range<visible_categories_iterator> + visible_categories_range; + + visible_categories_range visible_categories() const { + return visible_categories_range(visible_categories_begin(), + visible_categories_end()); + } + /// \brief Retrieve an iterator to the beginning of the visible-categories /// list. visible_categories_iterator visible_categories_begin() const { @@ -1010,6 +1132,13 @@ public: /// \brief Iterator that walks over all of the known categories and /// extensions, including those that are hidden. typedef filtered_category_iterator<isKnownCategory> known_categories_iterator; + typedef llvm::iterator_range<known_categories_iterator> + known_categories_range; + + known_categories_range known_categories() const { + return known_categories_range(known_categories_begin(), + known_categories_end()); + } /// \brief Retrieve an iterator to the beginning of the known-categories /// list. @@ -1039,6 +1168,14 @@ public: typedef filtered_category_iterator<isVisibleExtension> visible_extensions_iterator; + typedef llvm::iterator_range<visible_extensions_iterator> + visible_extensions_range; + + visible_extensions_range visible_extensions() const { + return visible_extensions_range(visible_extensions_begin(), + visible_extensions_end()); + } + /// \brief Retrieve an iterator to the beginning of the visible-extensions /// list. visible_extensions_iterator visible_extensions_begin() const { @@ -1065,6 +1202,13 @@ public: /// \brief Iterator that walks over all of the known extensions. typedef filtered_category_iterator<isKnownExtension> known_extensions_iterator; + typedef llvm::iterator_range<known_extensions_iterator> + known_extensions_range; + + known_extensions_range known_extensions() const { + return known_extensions_range(known_extensions_begin(), + known_extensions_end()); + } /// \brief Retrieve an iterator to the beginning of the known-extensions /// list. @@ -1087,7 +1231,7 @@ public: ObjCCategoryDecl* getCategoryListRaw() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) - return 0; + return nullptr; if (data().ExternallyCompleted) LoadExternalDefinition(); @@ -1104,14 +1248,14 @@ public: ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const; - virtual void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const; + void collectPropertiesToImplement(PropertyMap &PM, + PropertyDeclOrder &PO) const override; /// isSuperClassOf - Return true if this class is the specified class or is a /// super class of the specified interface class. bool isSuperClassOf(const ObjCInterfaceDecl *I) const { // If RHS is derived from LHS it is OK; else it is not OK. - while (I != NULL) { + while (I != nullptr) { if (declaresSameEntity(this, I)) return true; @@ -1141,15 +1285,18 @@ public: // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, - bool shallowCategoryLookup= false, - const ObjCCategoryDecl *C= 0) const; - ObjCMethodDecl *lookupInstanceMethod(Selector Sel, - bool shallowCategoryLookup = false) const { - return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup); + bool shallowCategoryLookup = false, + bool followSuper = true, + const ObjCCategoryDecl *C = nullptr) const; + + /// Lookup an instance method for a given selector. + ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const { + return lookupMethod(Sel, true/*isInstance*/); } - ObjCMethodDecl *lookupClassMethod(Selector Sel, - bool shallowCategoryLookup = false) const { - return lookupMethod(Sel, false/*isInstance*/, shallowCategoryLookup); + + /// Lookup a class method for a given selector. + ObjCMethodDecl *lookupClassMethod(Selector Sel) const { + return lookupMethod(Sel, false/*isInstance*/); } ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); @@ -1167,7 +1314,9 @@ public: ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel, const ObjCCategoryDecl *Cat) const { return lookupMethod(Sel, true/*isInstance*/, - false/*shallowCategoryLookup*/, Cat); + false/*shallowCategoryLookup*/, + true /* followsSuper */, + Cat); } SourceLocation getEndOfDefinitionLoc() const { @@ -1196,15 +1345,17 @@ public: bool lookupCategory, bool RHSIsQualifiedID = false); + typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; + using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; /// Retrieves the canonical declaration of this Objective-C class. - ObjCInterfaceDecl *getCanonicalDecl() { return getFirstDecl(); } + ObjCInterfaceDecl *getCanonicalDecl() override { return getFirstDecl(); } const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); } // Low-level accessor @@ -1217,6 +1368,10 @@ public: friend class ASTReader; friend class ASTDeclReader; friend class ASTDeclWriter; + +private: + const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const; + bool inheritsDesignatedInitializers() const; }; /// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC @@ -1235,7 +1390,7 @@ public: /// } /// class ObjCIvarDecl : public FieldDecl { - virtual void anchor(); + void anchor() override; public: enum AccessControl { @@ -1246,21 +1401,18 @@ private: ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, - bool synthesized, - bool backingIvarReferencedInAccessor) + bool synthesized) : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit), - NextIvar(0), DeclAccess(ac), Synthesized(synthesized), - BackingIvarReferencedInAccessor(backingIvarReferencedInAccessor) {} + NextIvar(nullptr), DeclAccess(ac), Synthesized(synthesized) {} public: static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - AccessControl ac, Expr *BW = NULL, - bool synthesized=false, - bool backingIvarReferencedInAccessor=false); + AccessControl ac, Expr *BW = nullptr, + bool synthesized=false); static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1282,13 +1434,6 @@ public: return DeclAccess == None ? Protected : AccessControl(DeclAccess); } - void setBackingIvarReferencedInAccessor(bool val) { - BackingIvarReferencedInAccessor = val; - } - bool getBackingIvarReferencedInAccessor() const { - return BackingIvarReferencedInAccessor; - } - void setSynthesize(bool synth) { Synthesized = synth; } bool getSynthesize() const { return Synthesized; } @@ -1303,18 +1448,17 @@ private: // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum unsigned DeclAccess : 3; unsigned Synthesized : 1; - unsigned BackingIvarReferencedInAccessor : 1; }; /// \brief Represents a field declaration created by an \@defs(...). class ObjCAtDefsFieldDecl : public FieldDecl { - virtual void anchor(); + void anchor() override; ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW) : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T, - /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ? + /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ? BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {} public: @@ -1362,7 +1506,7 @@ public: /// class ObjCProtocolDecl : public ObjCContainerDecl, public Redeclarable<ObjCProtocolDecl> { - virtual void anchor(); + void anchor() override; struct DefinitionData { // \brief The declaration that defines this protocol. @@ -1384,20 +1528,20 @@ class ObjCProtocolDecl : public ObjCContainerDecl, return *Data.getPointer(); } - ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id, + ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, SourceLocation nameLoc, SourceLocation atStartLoc, ObjCProtocolDecl *PrevDecl); void allocateDefinitionData(); typedef Redeclarable<ObjCProtocolDecl> redeclarable_base; - virtual ObjCProtocolDecl *getNextRedeclaration() { - return RedeclLink.getNext(); + ObjCProtocolDecl *getNextRedeclarationImpl() override { + return getNextRedeclaration(); } - virtual ObjCProtocolDecl *getPreviousDeclImpl() { + ObjCProtocolDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } - virtual ObjCProtocolDecl *getMostRecentDeclImpl() { + ObjCProtocolDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } @@ -1409,12 +1553,17 @@ public: ObjCProtocolDecl *PrevDecl); static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID); - + const ObjCProtocolList &getReferencedProtocols() const { assert(hasDefinition() && "No definition available!"); return data().ReferencedProtocols; } typedef ObjCProtocolList::iterator protocol_iterator; + typedef llvm::iterator_range<protocol_iterator> protocol_range; + + protocol_range protocols() const { + return protocol_range(protocol_begin(), protocol_end()); + } protocol_iterator protocol_begin() const { if (!hasDefinition()) return protocol_iterator(); @@ -1428,6 +1577,11 @@ public: return data().ReferencedProtocols.end(); } typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; + typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range; + + protocol_loc_range protocol_locs() const { + return protocol_loc_range(protocol_loc_begin(), protocol_loc_end()); + } protocol_loc_iterator protocol_loc_begin() const { if (!hasDefinition()) return protocol_loc_iterator(); @@ -1486,12 +1640,12 @@ public: /// \brief Retrieve the definition of this protocol, if any. ObjCProtocolDecl *getDefinition() { - return hasDefinition()? Data.getPointer()->Definition : 0; + return hasDefinition()? Data.getPointer()->Definition : nullptr; } /// \brief Retrieve the definition of this protocol, if any. const ObjCProtocolDecl *getDefinition() const { - return hasDefinition()? Data.getPointer()->Definition : 0; + return hasDefinition()? Data.getPointer()->Definition : nullptr; } /// \brief Determine whether this particular declaration is also the @@ -1503,29 +1657,35 @@ public: /// \brief Starts the definition of this Objective-C protocol. void startDefinition(); - virtual SourceRange getSourceRange() const LLVM_READONLY { + /// Produce a name to be used for protocol's metadata. It comes either via + /// objc_runtime_name attribute or protocol name. + StringRef getObjCRuntimeNameAsString() const; + + SourceRange getSourceRange() const override LLVM_READONLY { if (isThisDeclarationADefinition()) return ObjCContainerDecl::getSourceRange(); return SourceRange(getAtStartLoc(), getLocation()); } + typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; + using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; /// Retrieves the canonical declaration of this Objective-C protocol. - ObjCProtocolDecl *getCanonicalDecl() { return getFirstDecl(); } + ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); } const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); } - virtual void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const; - -void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property, - ProtocolPropertyMap &PM) const; + void collectPropertiesToImplement(PropertyMap &PM, + PropertyDeclOrder &PO) const override; + + void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property, + ProtocolPropertyMap &PM) const; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCProtocol; } @@ -1553,7 +1713,7 @@ void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property, /// don't support this level of dynamism, which is both powerful and dangerous. /// class ObjCCategoryDecl : public ObjCContainerDecl { - virtual void anchor(); + void anchor() override; /// Interface belonging to this category ObjCInterfaceDecl *ClassInterface; @@ -1578,7 +1738,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl { SourceLocation IvarLBraceLoc=SourceLocation(), SourceLocation IvarRBraceLoc=SourceLocation()) : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), - ClassInterface(IDecl), NextClassCategory(0), + ClassInterface(IDecl), NextClassCategory(nullptr), CategoryNameLoc(CategoryNameLoc), IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { } @@ -1613,10 +1773,22 @@ public: } typedef ObjCProtocolList::iterator protocol_iterator; - protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} + typedef llvm::iterator_range<protocol_iterator> protocol_range; + + protocol_range protocols() const { + return protocol_range(protocol_begin(), protocol_end()); + } + protocol_iterator protocol_begin() const { + return ReferencedProtocols.begin(); + } protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } unsigned protocol_size() const { return ReferencedProtocols.size(); } typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; + typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range; + + protocol_loc_range protocol_locs() const { + return protocol_loc_range(protocol_loc_begin(), protocol_loc_end()); + } protocol_loc_iterator protocol_loc_begin() const { return ReferencedProtocols.loc_begin(); } @@ -1632,9 +1804,12 @@ public: return NextClassCategory; } - bool IsClassExtension() const { return getIdentifier() == 0; } + bool IsClassExtension() const { return getIdentifier() == nullptr; } typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range; + + ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); } ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } @@ -1664,7 +1839,7 @@ public: }; class ObjCImplDecl : public ObjCContainerDecl { - virtual void anchor(); + void anchor() override; /// Class interface for this class/category implementation ObjCInterfaceDecl *ClassInterface; @@ -1674,7 +1849,8 @@ protected: ObjCInterfaceDecl *classInterface, SourceLocation nameLoc, SourceLocation atStartLoc) : ObjCContainerDecl(DK, DC, - classInterface? classInterface->getIdentifier() : 0, + classInterface? classInterface->getIdentifier() + : nullptr, nameLoc, atStartLoc), ClassInterface(classInterface) {} @@ -1701,6 +1877,12 @@ public: // Iterator access to properties. typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator; + typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyImplDecl>> + propimpl_range; + + propimpl_range property_impls() const { + return propimpl_range(propimpl_begin(), propimpl_end()); + } propimpl_iterator propimpl_begin() const { return propimpl_iterator(decls_begin()); } @@ -1728,7 +1910,7 @@ public: /// /// ObjCCategoryImplDecl class ObjCCategoryImplDecl : public ObjCImplDecl { - virtual void anchor(); + void anchor() override; // Category name IdentifierInfo *Id; @@ -1753,8 +1935,8 @@ public: /// getIdentifier - Get the identifier that names the category /// interface associated with this implementation. - /// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier() - /// to mean something different. For example: + /// FIXME: This is a bad API, we are hiding NamedDecl::getIdentifier() + /// with a different meaning. For example: /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier() /// returns the class interface name, whereas /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier() @@ -1771,11 +1953,9 @@ public: /// getName - Get the name of identifier for the class interface associated /// with this implementation as a StringRef. // - // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean - // something different. - StringRef getName() const { - return Id ? Id->getNameStart() : ""; - } + // FIXME: This is a bad API, we are hiding NamedDecl::getName with a different + // meaning. + StringRef getName() const { return Id ? Id->getName() : StringRef(); } /// @brief Get the name of the class associated with this interface. // @@ -1802,13 +1982,16 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID); /// \@end /// @endcode /// -/// Typically, instance variables are specified in the class interface, -/// *not* in the implementation. Nevertheless (for legacy reasons), we -/// allow instance variables to be specified in the implementation. When -/// specified, they need to be *identical* to the interface. +/// In a non-fragile runtime, instance variables can appear in the class +/// interface, class extensions (nameless categories), and in the implementation +/// itself, as well as being synthesized as backing storage for properties. /// +/// In a fragile runtime, instance variables are specified in the class +/// interface, \em not in the implementation. Nevertheless (for legacy reasons), +/// we allow instance variables to be specified in the implementation. When +/// specified, they need to be \em identical to the interface. class ObjCImplementationDecl : public ObjCImplDecl { - virtual void anchor(); + void anchor() override; /// Implementation Class's super class. ObjCInterfaceDecl *SuperClass; SourceLocation SuperLoc; @@ -1839,7 +2022,7 @@ class ObjCImplementationDecl : public ObjCImplDecl { : ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc), SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc), - IvarInitializers(0), NumIvarInitializers(0), + IvarInitializers(nullptr), NumIvarInitializers(0), HasNonZeroConstructors(false), HasDestructors(false) {} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, @@ -1859,6 +2042,14 @@ public: /// init_const_iterator - Iterates through the ivar initializer list. typedef CXXCtorInitializer * const * init_const_iterator; + typedef llvm::iterator_range<init_iterator> init_range; + typedef llvm::iterator_range<init_const_iterator> init_const_range; + + init_range inits() { return init_range(init_begin(), init_end()); } + init_const_range inits() const { + return init_const_range(init_begin(), init_end()); + } + /// init_begin() - Retrieve an iterator to the first initializer. init_iterator init_begin() { return IvarInitializers; } /// begin() - Retrieve an iterator to the first initializer. @@ -1904,8 +2095,8 @@ public: /// getName - Get the name of identifier for the class interface associated /// with this implementation as a StringRef. // - // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean - // something different. + // FIXME: This is a bad API, we are hiding NamedDecl::getName with a different + // meaning. StringRef getName() const { assert(getIdentifier() && "Name is not a simple identifier"); return getIdentifier()->getName(); @@ -1917,6 +2108,10 @@ public: std::string getNameAsString() const { return getName(); } + + /// Produce a name to be used for class's metadata. It comes either via + /// class's objc_runtime_name attribute or class name. + StringRef getObjCRuntimeNameAsString() const; const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } ObjCInterfaceDecl *getSuperClass() { return SuperClass; } @@ -1930,6 +2125,9 @@ public: SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; } typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range; + + ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); } ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } @@ -1955,7 +2153,7 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID); /// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is /// declared as \@compatibility_alias alias class. class ObjCCompatibleAliasDecl : public NamedDecl { - virtual void anchor(); + void anchor() override; /// Class that this is an alias of. ObjCInterfaceDecl *AliasedClass; @@ -1986,7 +2184,7 @@ public: /// \@property (assign, readwrite) int MyProperty; /// \endcode class ObjCPropertyDecl : public NamedDecl { - virtual void anchor(); + void anchor() override; public: enum PropertyAttributeKind { OBJC_PR_noattr = 0x00, @@ -2038,7 +2236,9 @@ private: PropertyImplementation(None), GetterName(Selector()), SetterName(Selector()), - GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {} + GetterMethodDecl(nullptr), SetterMethodDecl(nullptr), + PropertyIvarDecl(nullptr) {} + public: static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -2145,7 +2345,7 @@ public: return PropertyIvarDecl; } - virtual SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(AtLoc, getLocation()); } @@ -2202,7 +2402,7 @@ private: SourceLocation ivarLoc) : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl), - GetterCXXConstructor(0), SetterCXXAssignment(0) { + GetterCXXConstructor(nullptr), SetterCXXAssignment(nullptr) { assert (PK == Dynamic || PropertyIvarDecl); } @@ -2215,8 +2415,8 @@ public: SourceLocation ivarLoc); static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - virtual SourceRange getSourceRange() const LLVM_READONLY; + + SourceRange getSourceRange() const override LLVM_READONLY; SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h index 42fe907..1b329dc 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h @@ -47,10 +47,10 @@ class OMPThreadPrivateDecl : public Decl { NumVars); } - llvm::MutableArrayRef<Expr *> getVars() { - return llvm::MutableArrayRef<Expr *>( - reinterpret_cast<Expr **>(this + 1), - NumVars); + MutableArrayRef<Expr *> getVars() { + return MutableArrayRef<Expr *>( + reinterpret_cast<Expr **>(this + 1), + NumVars); } void setVars(ArrayRef<Expr *> VL); @@ -62,11 +62,20 @@ public: static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, unsigned ID, unsigned N); - typedef llvm::MutableArrayRef<Expr *>::iterator varlist_iterator; + typedef MutableArrayRef<Expr *>::iterator varlist_iterator; typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; + typedef llvm::iterator_range<varlist_iterator> varlist_range; + typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; unsigned varlist_size() const { return NumVars; } bool varlist_empty() const { return NumVars == 0; } + + varlist_range varlists() { + return varlist_range(varlist_begin(), varlist_end()); + } + varlist_const_range varlists() const { + return varlist_const_range(varlist_begin(), varlist_end()); + } varlist_iterator varlist_begin() { return getVars().begin(); } varlist_iterator varlist_end() { return getVars().end(); } varlist_const_iterator varlist_begin() const { return getVars().begin(); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h index 24bd28a..980a06e 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h @@ -86,11 +86,11 @@ public: unsigned size() const { return NumParams; } - llvm::ArrayRef<NamedDecl*> asArray() { - return llvm::ArrayRef<NamedDecl*>(begin(), size()); + ArrayRef<NamedDecl*> asArray() { + return ArrayRef<NamedDecl*>(begin(), size()); } - llvm::ArrayRef<const NamedDecl*> asArray() const { - return llvm::ArrayRef<const NamedDecl*>(begin(), size()); + ArrayRef<const NamedDecl*> asArray() const { + return ArrayRef<const NamedDecl*>(begin(), size()); } NamedDecl* getParam(unsigned Idx) { @@ -203,8 +203,8 @@ public: const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); } /// \brief Produce this as an array ref. - llvm::ArrayRef<TemplateArgument> asArray() const { - return llvm::ArrayRef<TemplateArgument>(data(), size()); + ArrayRef<TemplateArgument> asArray() const { + return ArrayRef<TemplateArgument>(data(), size()); } /// \brief Retrieve the number of template arguments in this @@ -227,18 +227,20 @@ public: /// 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(); + void anchor() override; protected: // This is probably never used. TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0) { } + : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), + TemplateParams(nullptr) {} // Construct a template decl with the given name and parameters. // Used when there is not templated element (tt-params, alias?). TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params) { } + : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), + TemplateParams(Params) {} // Construct a template decl with name, parameters, and templated element. TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, @@ -261,7 +263,7 @@ public: return K >= firstTemplate && K <= lastTemplate; } - SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(TemplateParams->getTemplateLoc(), TemplatedDecl->getSourceRange().getEnd()); } @@ -274,8 +276,8 @@ public: /// \brief Initialize the underlying templated declaration and /// template parameters. void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { - assert(TemplatedDecl == 0 && "TemplatedDecl already set!"); - assert(TemplateParams == 0 && "TemplateParams already set!"); + assert(!TemplatedDecl && "TemplatedDecl already set!"); + assert(!TemplateParams && "TemplateParams already set!"); TemplatedDecl = templatedDecl; TemplateParams = templateParams; } @@ -378,16 +380,15 @@ public: } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, TemplateArguments->data(), - TemplateArguments->size(), + Profile(ID, TemplateArguments->asArray(), Function->getASTContext()); } static void - Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, ASTContext &Context) { - ID.AddInteger(NumTemplateArgs); - for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) + Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs, + ASTContext &Context) { + ID.AddInteger(TemplateArgs.size()); + for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg) TemplateArgs[Arg].Profile(ID, Context); } }; @@ -530,13 +531,13 @@ class RedeclarableTemplateDecl : public TemplateDecl, public Redeclarable<RedeclarableTemplateDecl> { typedef Redeclarable<RedeclarableTemplateDecl> redeclarable_base; - virtual RedeclarableTemplateDecl *getNextRedeclaration() { - return RedeclLink.getNext(); + RedeclarableTemplateDecl *getNextRedeclarationImpl() override { + return getNextRedeclaration(); } - virtual RedeclarableTemplateDecl *getPreviousDeclImpl() { + RedeclarableTemplateDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } - virtual RedeclarableTemplateDecl *getMostRecentDeclImpl() { + RedeclarableTemplateDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } @@ -595,11 +596,10 @@ protected: template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType* findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs, - const TemplateArgument *Args, unsigned NumArgs, - void *&InsertPos); + ArrayRef<TemplateArgument> Args, void *&InsertPos); struct CommonBase { - CommonBase() : InstantiatedFromMember(0, false) { } + CommonBase() : InstantiatedFromMember(nullptr, false) { } /// \brief The template from which this was most /// directly instantiated (or null). @@ -622,16 +622,19 @@ protected: virtual CommonBase *newCommon(ASTContext &C) const = 0; // Construct a template decl with name, parameters, and templated element. - RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) - : TemplateDecl(DK, DC, L, Name, Params, Decl), Common() { } + RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C), + Common() {} public: template <class decl_type> friend class RedeclarableTemplate; /// \brief Retrieves the canonical declaration of this template. - RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDecl(); } + RedeclarableTemplateDecl *getCanonicalDecl() override { + return getFirstDecl(); + } const RedeclarableTemplateDecl *getCanonicalDecl() const { return getFirstDecl(); } @@ -710,9 +713,11 @@ public: getCommonPtr()->InstantiatedFromMember.setPointer(TD); } + typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; + using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; @@ -769,11 +774,13 @@ protected: uint32_t *LazySpecializations; }; - FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } + FunctionTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : RedeclarableTemplateDecl(FunctionTemplate, C, DC, L, Name, Params, + Decl) {} - CommonBase *newCommon(ASTContext &C) const; + CommonBase *newCommon(ASTContext &C) const override; Common *getCommonPtr() const { return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); @@ -810,10 +817,10 @@ public: /// \brief Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. - FunctionDecl *findSpecialization(const TemplateArgument *Args, - unsigned NumArgs, void *&InsertPos); + FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args, + void *&InsertPos); - FunctionTemplateDecl *getCanonicalDecl() { + FunctionTemplateDecl *getCanonicalDecl() override { return cast<FunctionTemplateDecl>( RedeclarableTemplateDecl::getCanonicalDecl()); } @@ -842,7 +849,11 @@ public: } typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator; + typedef llvm::iterator_range<spec_iterator> spec_range; + spec_range specializations() const { + return spec_range(spec_begin(), spec_end()); + } spec_iterator spec_begin() const { return makeSpecIterator(getSpecializations(), false); } @@ -892,12 +903,9 @@ public: /// This class is inheritedly privately by different kinds of template /// parameters and is not part of the Decl hierarchy. Just a facility. class TemplateParmPosition { -protected: - // FIXME: This should probably never be called, but it's here as - TemplateParmPosition() - : Depth(0), Position(0) - { /* llvm_unreachable("Cannot create positionless template parameter"); */ } + TemplateParmPosition() LLVM_DELETED_FUNCTION; +protected: TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) { } @@ -967,7 +975,7 @@ public: /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { return DefaultArgument != 0; } + bool hasDefaultArgument() const { return DefaultArgument != nullptr; } /// \brief Retrieve the default argument, if any. QualType getDefaultArgument() const { return DefaultArgument->getType(); } @@ -992,7 +1000,7 @@ public: /// \brief Removes the default argument of this template parameter. void removeDefaultArgument() { - DefaultArgument = 0; + DefaultArgument = nullptr; InheritedDefault = false; } @@ -1009,7 +1017,7 @@ public: /// \brief Returns whether this is a parameter pack. bool isParameterPack() const; - SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1046,7 +1054,7 @@ class NonTypeTemplateParmDecl IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo) : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), - TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false), + TemplateParmPosition(D, P), DefaultArgumentAndInherited(nullptr, false), ParameterPack(ParameterPack), ExpandedParameterPack(false), NumExpandedTypes(0) { } @@ -1086,12 +1094,12 @@ public: using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; - SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; /// \brief Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { - return DefaultArgumentAndInherited.getPointer() != 0; + return DefaultArgumentAndInherited.getPointer() != nullptr; } /// \brief Retrieve the default argument, if any. @@ -1118,7 +1126,7 @@ public: /// \brief Removes the default argument of this template parameter. void removeDefaultArgument() { - DefaultArgumentAndInherited.setPointer(0); + DefaultArgumentAndInherited.setPointer(nullptr); DefaultArgumentAndInherited.setInt(false); } @@ -1206,7 +1214,7 @@ public: class TemplateTemplateParmDecl : public TemplateDecl, protected TemplateParmPosition { - virtual void anchor(); + void anchor() override; /// DefaultArgument - The default template argument, if any. TemplateArgumentLoc DefaultArgument; @@ -1347,7 +1355,7 @@ public: DefaultArgumentWasInherited = false; } - SourceRange getSourceRange() const LLVM_READONLY { + SourceRange getSourceRange() const override LLVM_READONLY { SourceLocation End = getLocation(); if (hasDefaultArgument() && !defaultArgumentWasInherited()) End = getDefaultArgument().getSourceRange().getEnd(); @@ -1405,7 +1413,7 @@ class ClassTemplateSpecializationDecl SourceLocation TemplateKeywordLoc; ExplicitSpecializationInfo() - : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {} + : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {} }; /// \brief Further info for explicit template specialization/instantiation. @@ -1431,7 +1439,7 @@ protected: unsigned NumArgs, ClassTemplateSpecializationDecl *PrevDecl); - explicit ClassTemplateSpecializationDecl(Kind DK); + explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK); public: static ClassTemplateSpecializationDecl * @@ -1444,10 +1452,14 @@ public: static ClassTemplateSpecializationDecl * CreateDeserialized(ASTContext &C, unsigned ID); - virtual void getNameForDiagnostic(raw_ostream &OS, - const PrintingPolicy &Policy, - bool Qualified) const; + void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, + bool Qualified) const override; + // FIXME: This is broken. CXXRecordDecl::getMostRecentDecl() returns a + // different "most recent" declaration from this function for the same + // declaration, because we don't override getMostRecentDeclImpl(). But + // it's not clear that we should override that, because the most recent + // declaration as a CXXRecordDecl sometimes is the injected-class-name. ClassTemplateSpecializationDecl *getMostRecentDecl() { CXXRecordDecl *Recent = static_cast<CXXRecordDecl *>( this)->getMostRecentDecl(); @@ -1516,17 +1528,11 @@ public: llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> getInstantiatedFrom() const { - if (getSpecializationKind() != TSK_ImplicitInstantiation && - getSpecializationKind() != TSK_ExplicitInstantiationDefinition && - getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) + if (!isTemplateInstantiation(getSpecializationKind())) return llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>(); - if (SpecializedPartialSpecialization *PartialSpec - = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) - return PartialSpec->PartialSpecialization; - - return SpecializedTemplate.get<ClassTemplateDecl*>(); + return getSpecializedTemplateOrPartial(); } /// \brief Retrieve the class template or class template partial @@ -1592,7 +1598,7 @@ public: /// \brief Gets the type of this specialization as it was written by /// the user, if it was so written. TypeSourceInfo *getTypeAsWritten() const { - return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0; + return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; } /// \brief Gets the location of the extern keyword, if present. @@ -1617,17 +1623,17 @@ public: return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } - SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const override LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext()); + Profile(ID, TemplateArgs->asArray(), getASTContext()); } static void - Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, ASTContext &Context) { - ID.AddInteger(NumTemplateArgs); - for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) + Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs, + ASTContext &Context) { + ID.AddInteger(TemplateArgs.size()); + for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg) TemplateArgs[Arg].Profile(ID, Context); } @@ -1643,7 +1649,7 @@ public: class ClassTemplatePartialSpecializationDecl : public ClassTemplateSpecializationDecl { - virtual void anchor(); + void anchor() override; /// \brief The list of template parameters TemplateParameterList* TemplateParams; @@ -1671,9 +1677,10 @@ class ClassTemplatePartialSpecializationDecl const ASTTemplateArgumentListInfo *ArgsAsWritten, ClassTemplatePartialSpecializationDecl *PrevDecl); - ClassTemplatePartialSpecializationDecl() - : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization), - TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) { } + ClassTemplatePartialSpecializationDecl(ASTContext &C) + : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization), + TemplateParams(nullptr), ArgsAsWritten(nullptr), + InstantiatedFromMember(nullptr, false) {} public: static ClassTemplatePartialSpecializationDecl * @@ -1832,15 +1839,12 @@ protected: llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> & getPartialSpecializations(); - ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } + ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {} - ClassTemplateDecl(EmptyShell Empty) - : RedeclarableTemplateDecl(ClassTemplate, 0, SourceLocation(), - DeclarationName(), 0, 0) { } - - CommonBase *newCommon(ASTContext &C) const; + CommonBase *newCommon(ASTContext &C) const override; Common *getCommonPtr() const { return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); @@ -1872,14 +1876,13 @@ public: /// \brief Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. ClassTemplateSpecializationDecl * - findSpecialization(const TemplateArgument *Args, unsigned NumArgs, - void *&InsertPos); + findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); /// \brief Insert the specified specialization knowing that it is not already /// in. InsertPos must be obtained from findSpecialization. void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos); - ClassTemplateDecl *getCanonicalDecl() { + ClassTemplateDecl *getCanonicalDecl() override { return cast<ClassTemplateDecl>( RedeclarableTemplateDecl::getCanonicalDecl()); } @@ -1919,8 +1922,7 @@ public: /// \brief Return the partial specialization with the provided arguments if it /// exists, otherwise return the insertion point. ClassTemplatePartialSpecializationDecl * - findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs, - void *&InsertPos); + findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); /// \brief Insert the specified partial specialization knowing that it is not /// already in. InsertPos must be obtained from findPartialSpecialization. @@ -1970,6 +1972,11 @@ public: QualType getInjectedClassNameSpecialization(); typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator; + typedef llvm::iterator_range<spec_iterator> spec_range; + + spec_range specializations() const { + return spec_range(spec_begin(), spec_end()); + } spec_iterator spec_begin() const { return makeSpecIterator(getSpecializations(), false); @@ -1979,17 +1986,6 @@ public: return makeSpecIterator(getSpecializations(), true); } - typedef SpecIterator<ClassTemplatePartialSpecializationDecl> - partial_spec_iterator; - - partial_spec_iterator partial_spec_begin() { - return makeSpecIterator(getPartialSpecializations(), false); - } - - partial_spec_iterator partial_spec_end() { - return makeSpecIterator(getPartialSpecializations(), true); - } - // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ClassTemplate; } @@ -2045,7 +2041,7 @@ private: FriendTemplateDecl(EmptyShell Empty) : Decl(Decl::FriendTemplate, Empty), NumParams(0), - Params(0) + Params(nullptr) {} public: @@ -2105,11 +2101,13 @@ class TypeAliasTemplateDecl : public RedeclarableTemplateDecl { protected: typedef CommonBase Common; - TypeAliasTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : RedeclarableTemplateDecl(TypeAliasTemplate, DC, L, Name, Params, Decl) { } + TypeAliasTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : RedeclarableTemplateDecl(TypeAliasTemplate, C, DC, L, Name, Params, + Decl) {} - CommonBase *newCommon(ASTContext &C) const; + CommonBase *newCommon(ASTContext &C) const override; Common *getCommonPtr() { return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); @@ -2122,7 +2120,7 @@ public: } - TypeAliasTemplateDecl *getCanonicalDecl() { + TypeAliasTemplateDecl *getCanonicalDecl() override { return cast<TypeAliasTemplateDecl>( RedeclarableTemplateDecl::getCanonicalDecl()); } @@ -2172,7 +2170,7 @@ public: /// \brief Declaration of a function specialization at template class scope. /// -/// This is a non standard extension needed to support MSVC. +/// This is a non-standard extension needed to support MSVC. /// /// For example: /// \code @@ -2214,9 +2212,8 @@ public: CXXMethodDecl *FD, bool HasExplicitTemplateArgs, TemplateArgumentListInfo TemplateArgs) { - return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD, - HasExplicitTemplateArgs, - TemplateArgs); + return new (C, DC) ClassScopeFunctionSpecializationDecl( + DC, Loc, FD, HasExplicitTemplateArgs, TemplateArgs); } static ClassScopeFunctionSpecializationDecl * @@ -2279,7 +2276,7 @@ class VarTemplateSpecializationDecl : public VarDecl, SourceLocation TemplateKeywordLoc; ExplicitSpecializationInfo() - : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {} + : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {} }; /// \brief Further info for explicit template specialization/instantiation. @@ -2298,14 +2295,14 @@ class VarTemplateSpecializationDecl : public VarDecl, unsigned SpecializationKind : 3; protected: - VarTemplateSpecializationDecl(ASTContext &Context, Kind DK, DeclContext *DC, + VarTemplateSpecializationDecl(Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, unsigned NumArgs); - explicit VarTemplateSpecializationDecl(Kind DK); + explicit VarTemplateSpecializationDecl(Kind DK, ASTContext &Context); public: static VarTemplateSpecializationDecl * @@ -2316,9 +2313,8 @@ public: static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C, unsigned ID); - virtual void getNameForDiagnostic(raw_ostream &OS, - const PrintingPolicy &Policy, - bool Qualified) const; + void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, + bool Qualified) const override; VarTemplateSpecializationDecl *getMostRecentDecl() { VarDecl *Recent = static_cast<VarDecl *>(this)->getMostRecentDecl(); @@ -2461,7 +2457,7 @@ public: /// \brief Gets the type of this specialization as it was written by /// the user, if it was so written. TypeSourceInfo *getTypeAsWritten() const { - return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0; + return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; } /// \brief Gets the location of the extern keyword, if present. @@ -2487,14 +2483,14 @@ public: } void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext()); + Profile(ID, TemplateArgs->asArray(), getASTContext()); } static void Profile(llvm::FoldingSetNodeID &ID, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, ASTContext &Context) { - ID.AddInteger(NumTemplateArgs); - for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) + ArrayRef<TemplateArgument> TemplateArgs, + ASTContext &Context) { + ID.AddInteger(TemplateArgs.size()); + for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg) TemplateArgs[Arg].Profile(ID, Context); } @@ -2510,7 +2506,7 @@ public: class VarTemplatePartialSpecializationDecl : public VarTemplateSpecializationDecl { - virtual void anchor(); + void anchor() override; /// \brief The list of template parameters TemplateParameterList *TemplateParams; @@ -2534,9 +2530,10 @@ class VarTemplatePartialSpecializationDecl StorageClass S, const TemplateArgument *Args, unsigned NumArgs, const ASTTemplateArgumentListInfo *ArgInfos); - VarTemplatePartialSpecializationDecl() - : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization), - TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) {} + VarTemplatePartialSpecializationDecl(ASTContext &Context) + : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context), + TemplateParams(nullptr), ArgsAsWritten(nullptr), + InstantiatedFromMember(nullptr, false) {} public: static VarTemplatePartialSpecializationDecl * @@ -2677,15 +2674,12 @@ protected: llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> & getPartialSpecializations(); - VarTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : RedeclarableTemplateDecl(VarTemplate, DC, L, Name, Params, Decl) {} + VarTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : RedeclarableTemplateDecl(VarTemplate, C, DC, L, Name, Params, Decl) {} - VarTemplateDecl(EmptyShell Empty) - : RedeclarableTemplateDecl(VarTemplate, 0, SourceLocation(), - DeclarationName(), 0, 0) {} - - CommonBase *newCommon(ASTContext &C) const; + CommonBase *newCommon(ASTContext &C) const override; Common *getCommonPtr() const { return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); @@ -2708,8 +2702,8 @@ public: /// \brief Create a variable template node. static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl, - VarTemplateDecl *PrevDecl); + TemplateParameterList *Params, + VarDecl *Decl); /// \brief Create an empty variable template node. static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2717,14 +2711,13 @@ public: /// \brief Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. VarTemplateSpecializationDecl * - findSpecialization(const TemplateArgument *Args, unsigned NumArgs, - void *&InsertPos); + findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); /// \brief Insert the specified specialization knowing that it is not already /// in. InsertPos must be obtained from findSpecialization. void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos); - VarTemplateDecl *getCanonicalDecl() { + VarTemplateDecl *getCanonicalDecl() override { return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl()); } const VarTemplateDecl *getCanonicalDecl() const { @@ -2754,8 +2747,7 @@ public: /// \brief Return the partial specialization with the provided arguments if it /// exists, otherwise return the insertion point. VarTemplatePartialSpecializationDecl * - findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs, - void *&InsertPos); + findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); /// \brief Insert the specified partial specialization knowing that it is not /// already in. InsertPos must be obtained from findPartialSpecialization. @@ -2780,6 +2772,11 @@ public: VarTemplatePartialSpecializationDecl *D); typedef SpecIterator<VarTemplateSpecializationDecl> spec_iterator; + typedef llvm::iterator_range<spec_iterator> spec_range; + + spec_range specializations() const { + return spec_range(spec_begin(), spec_end()); + } spec_iterator spec_begin() const { return makeSpecIterator(getSpecializations(), false); @@ -2789,17 +2786,6 @@ public: return makeSpecIterator(getSpecializations(), true); } - typedef SpecIterator<VarTemplatePartialSpecializationDecl> - partial_spec_iterator; - - partial_spec_iterator partial_spec_begin() { - return makeSpecIterator(getPartialSpecializations(), false); - } - - partial_spec_iterator partial_spec_end() { - return makeSpecIterator(getPartialSpecializations(), true); - } - // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == VarTemplate; } diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h index 00766c2..3076b30 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h @@ -29,6 +29,7 @@ namespace clang { class DeclarationNameExtra; class IdentifierInfo; class MultiKeywordSelector; + enum OverloadedOperatorKind : int; class QualType; class Type; class TypeSourceInfo; @@ -116,20 +117,20 @@ private: NameKind Kind = getNameKind(); if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName) return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask); - return 0; + return nullptr; } /// getAsCXXOperatorIdName CXXOperatorIdName *getAsCXXOperatorIdName() const { if (getNameKind() == CXXOperatorName) return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask); - return 0; + return nullptr; } CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const { if (getNameKind() == CXXLiteralOperatorName) return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask); - return 0; + return nullptr; } // Construct a declaration name from the name of a C++ constructor, @@ -221,7 +222,7 @@ public: IdentifierInfo *getAsIdentifierInfo() const { if (isIdentifier()) return reinterpret_cast<IdentifierInfo *>(Ptr); - return 0; + return nullptr; } /// getAsOpaqueInteger - Get the representation of this declaration diff --git a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h index 004b45d..63047ec 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h @@ -123,7 +123,7 @@ private: /// An iterator over the dependent diagnostics in a dependent context. class DeclContext::ddiag_iterator { public: - ddiag_iterator() : Ptr(0) {} + ddiag_iterator() : Ptr(nullptr) {} explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {} typedef DependentDiagnostic *value_type; @@ -171,18 +171,16 @@ private: DependentDiagnostic *Ptr; }; -inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const { +inline DeclContext::ddiag_range DeclContext::ddiags() const { assert(isDependentContext() && "cannot iterate dependent diagnostics of non-dependent context"); const DependentStoredDeclsMap *Map = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr()); - if (!Map) return ddiag_iterator(); - return ddiag_iterator(Map->FirstDiagnostic); -} + if (!Map) + return ddiag_range(); -inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const { - return ddiag_iterator(); + return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator()); } } diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h index f2648b9..b4bb0b6 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h @@ -293,8 +293,8 @@ public: /// \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. - isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, - SourceLocation *Loc = 0) const; + isModifiableLvalueResult + isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const; /// \brief The return type of classify(). Represents the C++11 expression /// taxonomy. @@ -372,7 +372,7 @@ public: /// lvalues and xvalues are collectively referred to as glvalues, while /// prvalues and xvalues together form rvalues. Classification Classify(ASTContext &Ctx) const { - return ClassifyImpl(Ctx, 0); + return ClassifyImpl(Ctx, nullptr); } /// \brief ClassifyModifiable - Classify this expression according to the @@ -483,10 +483,10 @@ public: /// Note: This does not perform the implicit conversions required by C++11 /// [expr.const]p5. bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx, - SourceLocation *Loc = 0, + SourceLocation *Loc = nullptr, bool isEvaluated = true) const; bool isIntegerConstantExpr(const ASTContext &Ctx, - SourceLocation *Loc = 0) const; + SourceLocation *Loc = nullptr) const; /// isCXX98IntegralConstantExpr - Return true if this expression is an /// integral constant expression in C++98. Can only be used in C++. @@ -497,8 +497,8 @@ public: /// /// Note: This does not perform the implicit conversions required by C++11 /// [expr.const]p5. - bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = 0, - SourceLocation *Loc = 0) const; + bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = nullptr, + SourceLocation *Loc = nullptr) const; /// isPotentialConstantExpr - Return true if this function's definition /// might be usable in a constant expression in C++11, if it were marked @@ -508,9 +508,22 @@ public: SmallVectorImpl< PartialDiagnosticAt> &Diags); + /// isPotentialConstantExprUnevaluted - Return true if this expression might + /// be usable in a constant expression in C++11 in an unevaluated context, if + /// it were in function FD marked constexpr. Return false if the function can + /// never produce a constant expression, along with diagnostics describing + /// why not. + static bool isPotentialConstantExprUnevaluated(Expr *E, + const FunctionDecl *FD, + SmallVectorImpl< + PartialDiagnosticAt> &Diags); + /// isConstantInitializer - Returns true if this expression can be emitted to /// IR as a constant, and thus can be used as a constant initializer in C. - bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const; + /// If this expression is not constant and Culprit is non-null, + /// it is used to store the address of first non constant expr. + bool isConstantInitializer(ASTContext &Ctx, bool ForRef, + const Expr **Culprit = nullptr) const; /// EvalStatus is a struct with detailed info about an evaluation in progress. struct EvalStatus { @@ -527,7 +540,7 @@ public: /// expression *is* a constant expression, no notes will be produced. SmallVectorImpl<PartialDiagnosticAt> *Diag; - EvalStatus() : HasSideEffects(false), Diag(0) {} + EvalStatus() : HasSideEffects(false), Diag(nullptr) {} // hasSideEffects - Return true if the evaluated expression has // side effects. @@ -584,7 +597,7 @@ public: /// integer. This must be called on an expression that constant folds to an /// integer. llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, - SmallVectorImpl<PartialDiagnosticAt> *Diag=0) const; + SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const; void EvaluateForOverflow(const ASTContext &Ctx) const; @@ -600,6 +613,14 @@ public: const VarDecl *VD, SmallVectorImpl<PartialDiagnosticAt> &Notes) const; + /// EvaluateWithSubstitution - Evaluate an expression as if from the context + /// of a call to the given function with the given arguments, inside an + /// unevaluated context. Returns true if the expression could be folded to a + /// constant. + bool EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, + const FunctionDecl *Callee, + ArrayRef<const Expr*> Args) const; + /// \brief Enumeration used to describe the kind of Null pointer constant /// returned from \c isNullPointerConstant(). enum NullPointerConstantKind { @@ -681,6 +702,9 @@ public: /// or CastExprs, returning their operand. Expr *IgnoreParenCasts() LLVM_READONLY; + /// Ignore casts. Strip off any CastExprs, returning their operand. + Expr *IgnoreCasts() LLVM_READONLY; + /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off /// any ParenExpr or ImplicitCastExprs, returning their operand. Expr *IgnoreParenImpCasts() LLVM_READONLY; @@ -742,6 +766,11 @@ public: const Expr *IgnoreParenCasts() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenCasts(); } + /// Strip off casts, but keep parentheses. + const Expr *IgnoreCasts() const LLVM_READONLY { + return const_cast<Expr*>(this)->IgnoreCasts(); + } + const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx); } @@ -764,11 +793,6 @@ public: SmallVectorImpl<const Expr *> &CommaLHS, SmallVectorImpl<SubobjectAdjustment> &Adjustments) const; - /// Skip irrelevant expressions to find what should be materialize for - /// binding with a reference. - const Expr * - findMaterializedTemporary(const MaterializeTemporaryExpr *&MTE) const; - static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && T->getStmtClass() <= lastExprConstant; @@ -793,7 +817,7 @@ class OpaqueValueExpr : public Expr { public: OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, ExprObjectKind OK = OK_Ordinary, - Expr *SourceExpr = 0) + Expr *SourceExpr = nullptr) : Expr(OpaqueValueExprClass, T, VK, OK, T->isDependentType(), T->isDependentType() || @@ -937,25 +961,19 @@ public: computeDependence(D->getASTContext()); } - static DeclRefExpr *Create(const ASTContext &Context, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - ValueDecl *D, - bool isEnclosingLocal, - SourceLocation NameLoc, - QualType T, ExprValueKind VK, - NamedDecl *FoundD = 0, - const TemplateArgumentListInfo *TemplateArgs = 0); - - static DeclRefExpr *Create(const ASTContext &Context, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - ValueDecl *D, - bool isEnclosingLocal, - const DeclarationNameInfo &NameInfo, - QualType T, ExprValueKind VK, - NamedDecl *FoundD = 0, - const TemplateArgumentListInfo *TemplateArgs = 0); + static DeclRefExpr * + Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal, + SourceLocation NameLoc, QualType T, ExprValueKind VK, + NamedDecl *FoundD = nullptr, + const TemplateArgumentListInfo *TemplateArgs = nullptr); + + static DeclRefExpr * + Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal, + const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, + NamedDecl *FoundD = nullptr, + const TemplateArgumentListInfo *TemplateArgs = nullptr); /// \brief Construct an empty declaration reference expression. static DeclRefExpr *CreateEmpty(const ASTContext &Context, @@ -985,7 +1003,7 @@ public: /// that precedes the name. Otherwise, returns NULL. NestedNameSpecifier *getQualifier() const { if (!hasQualifier()) - return 0; + return nullptr; return getInternalQualifierLoc().getNestedNameSpecifier(); } @@ -1021,7 +1039,7 @@ public: /// \brief Return the optional template keyword and arguments info. ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { if (!hasTemplateKWAndArgsInfo()) - return 0; + return nullptr; if (hasFoundDecl()) return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( @@ -1085,7 +1103,7 @@ public: /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return 0; + if (!hasExplicitTemplateArgs()) return nullptr; return &getExplicitTemplateArgs(); } @@ -1100,7 +1118,7 @@ public: /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { if (!hasExplicitTemplateArgs()) - return 0; + return nullptr; return getExplicitTemplateArgs().getTemplateArgs(); } @@ -1151,6 +1169,7 @@ public: Function, LFunction, // Same as Function, but as wide string. FuncDName, + FuncSig, PrettyFunction, /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. @@ -1862,7 +1881,7 @@ private: explicit OffsetOfExpr(unsigned numComps, unsigned numExprs) : Expr(OffsetOfExprClass, EmptyShell()), - TSInfo(0), NumComps(numComps), NumExprs(numExprs) {} + TSInfo(nullptr), NumComps(numComps), NumExprs(numExprs) {} public: @@ -2213,6 +2232,13 @@ public: typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; + typedef llvm::iterator_range<arg_iterator> arg_range; + typedef llvm::iterator_range<const_arg_iterator> arg_const_range; + + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } + arg_const_range arguments() const { + return arg_const_range(arg_begin(), arg_end()); + } arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); } arg_iterator arg_end() { @@ -2238,9 +2264,9 @@ public: /// this function call. unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } - /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If - /// not, return 0. - unsigned isBuiltinCall() const; + /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID + /// of the callee. If not, return 0. + unsigned getBuiltinCallee() const; /// \brief Returns \c true if this is a call to a builtin which does not /// evaluate side-effects within its arguments. @@ -2392,14 +2418,14 @@ public: /// \brief Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. - bool hasQualifier() const { return getQualifier() != 0; } + bool hasQualifier() const { return getQualifier() != nullptr; } /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. NestedNameSpecifier *getQualifier() const { if (!HasQualifierOrFoundDecl) - return 0; + return nullptr; return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier(); } @@ -2417,7 +2443,7 @@ public: /// \brief Return the optional template keyword and arguments info. ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { if (!HasTemplateKWAndArgsInfo) - return 0; + return nullptr; if (!HasQualifierOrFoundDecl) return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1); @@ -2485,7 +2511,7 @@ public: /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return 0; + if (!hasExplicitTemplateArgs()) return nullptr; return &getExplicitTemplateArgs(); } @@ -2493,7 +2519,7 @@ public: /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { if (!hasExplicitTemplateArgs()) - return 0; + return nullptr; return getExplicitTemplateArgs().getTemplateArgs(); } @@ -2633,7 +2659,7 @@ public: private: Stmt *Op; - void CheckCastConsistency() const; + bool CastConsistency() const; const CXXBaseSpecifier * const *path_buffer() const { return const_cast<CastExpr*>(this)->path_buffer(); @@ -2664,9 +2690,7 @@ protected: assert(kind != CK_Invalid && "creating cast with invalid cast kind"); CastExprBits.Kind = kind; setBasePathSize(BasePathSize); -#ifndef NDEBUG - CheckCastConsistency(); -#endif + assert(CastConsistency()); } /// \brief Construct an empty cast. @@ -3422,7 +3446,7 @@ public: /// \brief Build an empty vector-shuffle expression. explicit ShuffleVectorExpr(EmptyShell Empty) - : Expr(ShuffleVectorExprClass, Empty), SubExprs(0) { } + : Expr(ShuffleVectorExprClass, Empty), SubExprs(nullptr) { } SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } @@ -3774,6 +3798,14 @@ public: void setInit(unsigned Init, Expr *expr) { assert(Init < getNumInits() && "Initializer access out of range!"); InitExprs[Init] = expr; + + if (expr) { + ExprBits.TypeDependent |= expr->isTypeDependent(); + ExprBits.ValueDependent |= expr->isValueDependent(); + ExprBits.InstantiationDependent |= expr->isInstantiationDependent(); + ExprBits.ContainsUnexpandedParameterPack |= + expr->containsUnexpandedParameterPack(); + } } /// \brief Reserve space for some number of initializers. @@ -3824,8 +3856,8 @@ public: return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion(); } void setInitializedFieldInUnion(FieldDecl *FD) { - assert((FD == 0 - || getInitializedFieldInUnion() == 0 + assert((FD == nullptr + || getInitializedFieldInUnion() == nullptr || getInitializedFieldInUnion() == FD) && "Only one field of a union may be initialized at a time!"); ArrayFillerOrUnionFieldInit = FD; @@ -3848,10 +3880,10 @@ public: bool isSemanticForm() const { return AltForm.getInt(); } InitListExpr *getSemanticForm() const { - return isSemanticForm() ? 0 : AltForm.getPointer(); + return isSemanticForm() ? nullptr : AltForm.getPointer(); } InitListExpr *getSyntacticForm() const { - return isSemanticForm() ? AltForm.getPointer() : 0; + return isSemanticForm() ? AltForm.getPointer() : nullptr; } void setSyntacticForm(InitListExpr *Init) { @@ -3877,6 +3909,7 @@ public: // Iterators child_range children() { + // FIXME: This does not include the array filler expression. if (InitExprs.empty()) return child_range(); return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size()); } @@ -3953,7 +3986,7 @@ private: explicit DesignatedInitExpr(unsigned NumSubExprs) : Expr(DesignatedInitExprClass, EmptyShell()), - NumDesignators(0), NumSubExprs(NumSubExprs), Designators(0) { } + NumDesignators(0), NumSubExprs(NumSubExprs), Designators(nullptr) { } public: /// A field designator, e.g., ".x". @@ -4050,7 +4083,7 @@ public: FieldDecl *getField() const { assert(Kind == FieldDesignator && "Only valid on a field designator"); if (Field.NameOrField & 0x01) - return 0; + return nullptr; else return reinterpret_cast<FieldDecl *>(Field.NameOrField); } @@ -4134,6 +4167,17 @@ public: return Designators + NumDesignators; } + typedef llvm::iterator_range<designators_iterator> designators_range; + designators_range designators() { + return designators_range(designators_begin(), designators_end()); + } + + typedef llvm::iterator_range<const_designators_iterator> + designators_const_range; + designators_const_range designators() const { + return designators_const_range(designators_begin(), designators_end()); + } + typedef std::reverse_iterator<designators_iterator> reverse_designators_iterator; reverse_designators_iterator designators_rbegin() { @@ -4186,18 +4230,14 @@ public: /// and array-range designators. unsigned getNumSubExprs() const { return NumSubExprs; } - Expr *getSubExpr(unsigned Idx) { + Expr *getSubExpr(unsigned Idx) const { assert(Idx < NumSubExprs && "Subscript out of range"); - char* Ptr = static_cast<char*>(static_cast<void *>(this)); - Ptr += sizeof(DesignatedInitExpr); - return reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx]; + return cast<Expr>(reinterpret_cast<Stmt *const *>(this + 1)[Idx]); } void setSubExpr(unsigned Idx, Expr *E) { assert(Idx < NumSubExprs && "Subscript out of range"); - char* Ptr = static_cast<char*>(static_cast<void *>(this)); - Ptr += sizeof(DesignatedInitExpr); - reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx] = E; + reinterpret_cast<Stmt **>(this + 1)[Idx] = E; } /// \brief Replaces the designator at index @p Idx with the series @@ -4621,7 +4661,7 @@ class PseudoObjectExpr : public Expr { public: /// NoResult - A value for the result index indicating that there is /// no semantic result. - enum LLVM_ENUM_INT_TYPE(unsigned) { NoResult = ~0U }; + enum : unsigned { NoResult = ~0U }; static PseudoObjectExpr *Create(const ASTContext &Context, Expr *syntactic, ArrayRef<Expr*> semantic, @@ -4646,7 +4686,7 @@ public: /// Return the result-bearing expression, or null if there is none. Expr *getResultExpr() { if (PseudoObjectExprBits.ResultIndex == 0) - return 0; + return nullptr; return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex]; } const Expr *getResultExpr() const { @@ -4713,6 +4753,16 @@ public: BI_First = 0 }; + // The ABI values for various atomic memory orderings. + enum AtomicOrderingKind { + AO_ABI_memory_order_relaxed = 0, + AO_ABI_memory_order_consume = 1, + AO_ABI_memory_order_acquire = 2, + AO_ABI_memory_order_release = 3, + AO_ABI_memory_order_acq_rel = 4, + AO_ABI_memory_order_seq_cst = 5 + }; + private: enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR }; Stmt* SubExprs[END_EXPR]; diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h index 6356ee7..3a43d6d 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h @@ -20,7 +20,7 @@ #include "clang/AST/TemplateBase.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/ExpressionTraits.h" -#include "clang/Basic/Lambda.h" +#include "clang/AST/LambdaCapture.h" #include "clang/Basic/TypeTraits.h" #include "llvm/Support/Compiler.h" @@ -486,7 +486,7 @@ class CXXStdInitializerListExpr : public Expr { Stmt *SubExpr; CXXStdInitializerListExpr(EmptyShell Empty) - : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(0) {} + : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(nullptr) {} public: CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr) @@ -553,9 +553,9 @@ public: CXXTypeidExpr(EmptyShell Empty, bool isExpr) : Expr(CXXTypeidExprClass, Empty) { if (isExpr) - Operand = (Expr*)0; + Operand = (Expr*)nullptr; else - Operand = (TypeSourceInfo*)0; + Operand = (TypeSourceInfo*)nullptr; } /// Determine whether this typeid has a type operand which is potentially @@ -692,9 +692,9 @@ public: CXXUuidofExpr(EmptyShell Empty, bool isExpr) : Expr(CXXUuidofExprClass, Empty) { if (isExpr) - Operand = (Expr*)0; + Operand = (Expr*)nullptr; else - Operand = (TypeSourceInfo*)0; + Operand = (TypeSourceInfo*)nullptr; } bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } @@ -737,8 +737,8 @@ public: /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to /// a single GUID. - static UuidAttr *GetUuidAttrOfType(QualType QT, - bool *HasMultipleGUIDsPtr = 0); + static const UuidAttr *GetUuidAttrOfType(QualType QT, + bool *HasMultipleGUIDsPtr = nullptr); // Iterators child_range children() { @@ -832,7 +832,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; } SourceLocation getLocEnd() const LLVM_READONLY { - if (getSubExpr() == 0) + if (!getSubExpr()) return ThrowLoc; return getSubExpr()->getLocEnd(); } @@ -1031,7 +1031,7 @@ class CXXBindTemporaryExpr : public Expr { public: CXXBindTemporaryExpr(EmptyShell Empty) - : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {} + : Expr(CXXBindTemporaryExprClass, Empty), Temp(nullptr), SubExpr(nullptr) {} static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp, Expr* SubExpr); @@ -1077,6 +1077,7 @@ private: bool Elidable : 1; bool HadMultipleCandidates : 1; bool ListInitialization : 1; + bool StdInitListInitialization : 1; bool ZeroInitialization : 1; unsigned ConstructKind : 2; Stmt **Args; @@ -1088,24 +1089,25 @@ protected: ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Constructor(0), NumArgs(0), Elidable(false), + : Expr(SC, Empty), Constructor(nullptr), NumArgs(0), Elidable(false), HadMultipleCandidates(false), ListInitialization(false), - ZeroInitialization(false), ConstructKind(0), Args(0) + ZeroInitialization(false), ConstructKind(0), Args(nullptr) { } public: /// \brief Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) - : Expr(CXXConstructExprClass, Empty), Constructor(0), + : Expr(CXXConstructExprClass, Empty), Constructor(nullptr), NumArgs(0), Elidable(false), HadMultipleCandidates(false), ListInitialization(false), ZeroInitialization(false), - ConstructKind(0), Args(0) + ConstructKind(0), Args(nullptr) { } static CXXConstructExpr *Create(const ASTContext &C, QualType T, @@ -1114,6 +1116,7 @@ public: ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); @@ -1137,6 +1140,13 @@ public: bool isListInitialization() const { return ListInitialization; } void setListInitialization(bool V) { ListInitialization = V; } + /// \brief Whether this constructor call was written as list-initialization, + /// but was interpreted as forming a std::initializer_list<T> from the list + /// and passing that as a single constructor argument. + /// See C++11 [over.match.list]p1 bullet 1. + bool isStdInitListInitialization() const { return StdInitListInitialization; } + void setStdInitListInitialization(bool V) { StdInitListInitialization = V; } + /// \brief Whether this construction first requires /// zero-initialization before the initializer is called. bool requiresZeroInitialization() const { return ZeroInitialization; } @@ -1161,7 +1171,10 @@ public: const_arg_iterator arg_begin() const { return Args; } const_arg_iterator arg_end() const { return Args + NumArgs; } - Expr **getArgs() const { return reinterpret_cast<Expr **>(Args); } + Expr **getArgs() { return reinterpret_cast<Expr **>(Args); } + const Expr *const *getArgs() const { + return const_cast<CXXConstructExpr *>(this)->getArgs(); + } unsigned getNumArgs() const { return NumArgs; } /// \brief Return the specified argument. @@ -1269,6 +1282,7 @@ public: SourceRange ParenOrBraceRange, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization); explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } @@ -1307,18 +1321,6 @@ public: /// includes an initializing expression (rather than capturing a variable), /// and which can never occur implicitly. class LambdaExpr : public Expr { - enum { - /// \brief Flag used by the Capture class to indicate that the given - /// capture was implicit. - Capture_Implicit = 0x01, - - /// \brief Flag used by the Capture class to indicate that the - /// given capture was by-copy. - /// - /// This includes the case of a non-reference init-capture. - Capture_ByCopy = 0x02 - }; - /// \brief The source range that covers the lambda introducer ([...]). SourceRange IntroducerRange; @@ -1357,93 +1359,8 @@ class LambdaExpr : public Expr { // expression, along with the index variables used to initialize by-copy // array captures. -public: - /// \brief Describes the capture of a variable or of \c this, or of a - /// C++1y init-capture. - class Capture { - llvm::PointerIntPair<Decl *, 2> DeclAndBits; - SourceLocation Loc; - SourceLocation EllipsisLoc; - - friend class ASTStmtReader; - friend class ASTStmtWriter; - - public: - /// \brief Create a new capture of a variable or of \c this. - /// - /// \param Loc The source location associated with this capture. - /// - /// \param Kind The kind of capture (this, byref, bycopy), which must - /// not be init-capture. - /// - /// \param Implicit Whether the capture was implicit or explicit. - /// - /// \param Var The local variable being captured, or null if capturing - /// \c this. - /// - /// \param EllipsisLoc The location of the ellipsis (...) for a - /// capture that is a pack expansion, or an invalid source - /// location to indicate that this is not a pack expansion. - Capture(SourceLocation Loc, bool Implicit, - LambdaCaptureKind Kind, VarDecl *Var = 0, - SourceLocation EllipsisLoc = SourceLocation()); - - /// \brief Determine the kind of capture. - LambdaCaptureKind getCaptureKind() const; - - /// \brief Determine whether this capture handles the C++ \c this - /// pointer. - bool capturesThis() const { return DeclAndBits.getPointer() == 0; } - - /// \brief Determine whether this capture handles a variable. - bool capturesVariable() const { - return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer()); - } - - /// \brief Determine whether this is an init-capture. - bool isInitCapture() const { - return capturesVariable() && getCapturedVar()->isInitCapture(); - } - - /// \brief Retrieve the declaration of the local variable being - /// captured. - /// - /// This operation is only valid if this capture is a variable capture - /// (other than a capture of \c this). - VarDecl *getCapturedVar() const { - assert(capturesVariable() && "No variable available for 'this' capture"); - return cast<VarDecl>(DeclAndBits.getPointer()); - } - - /// \brief Determine whether this was an implicit capture (not - /// written between the square brackets introducing the lambda). - bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; } - - /// \brief Determine whether this was an explicit capture (written - /// between the square brackets introducing the lambda). - bool isExplicit() const { return !isImplicit(); } - - /// \brief Retrieve the source location of the capture. - /// - /// For an explicit capture, this returns the location of the - /// explicit capture in the source. For an implicit capture, this - /// returns the location at which the variable or \c this was first - /// used. - SourceLocation getLocation() const { return Loc; } - - /// \brief Determine whether this capture is a pack expansion, - /// which captures a function parameter pack. - bool isPackExpansion() const { return EllipsisLoc.isValid(); } - - /// \brief Retrieve the location of the ellipsis for a capture - /// that is a pack expansion. - SourceLocation getEllipsisLoc() const { - assert(isPackExpansion() && "No ellipsis location for a non-expansion"); - return EllipsisLoc; - } - }; + typedef LambdaCapture Capture; -private: /// \brief Construct a lambda expression. LambdaExpr(QualType T, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, @@ -1462,7 +1379,7 @@ private: : Expr(LambdaExprClass, Empty), NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false), ExplicitResultType(false), HasArrayIndexVars(true) { - getStoredStmts()[NumCaptures] = 0; + getStoredStmts()[NumCaptures] = nullptr; } Stmt **getStoredStmts() const { @@ -1520,6 +1437,12 @@ public: /// both implicit and explicit. typedef const Capture *capture_iterator; + /// \brief An iterator over a range of lambda captures. + typedef llvm::iterator_range<capture_iterator> capture_range; + + /// \brief Retrieve this lambda's captures. + capture_range captures() const; + /// \brief Retrieve an iterator pointing to the first lambda capture. capture_iterator capture_begin() const; @@ -1529,6 +1452,9 @@ public: /// \brief Determine the number of captures in this lambda. unsigned capture_size() const { return NumCaptures; } + + /// \brief Retrieve this lambda's explicit captures. + capture_range explicit_captures() const; /// \brief Retrieve an iterator pointing to the first explicit /// lambda capture. @@ -1538,6 +1464,9 @@ public: /// explicit lambda captures. capture_iterator explicit_capture_end() const; + /// \brief Retrieve this lambda's implicit captures. + capture_range implicit_captures() const; + /// \brief Retrieve an iterator pointing to the first implicit /// lambda capture. capture_iterator implicit_capture_begin() const; @@ -1550,6 +1479,12 @@ public: /// arguments. typedef Expr **capture_init_iterator; + /// \brief Retrieve the initialization expressions for this lambda's captures. + llvm::iterator_range<capture_init_iterator> capture_inits() const { + return llvm::iterator_range<capture_init_iterator>(capture_init_begin(), + capture_init_end()); + } + /// \brief Retrieve the first initialization argument for this /// lambda expression (which initializes the first capture field). capture_init_iterator capture_init_begin() const { @@ -1717,7 +1652,7 @@ public: QualType ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange directInitRange); explicit CXXNewExpr(EmptyShell Shell) - : Expr(CXXNewExprClass, Shell), SubExprs(0) { } + : Expr(CXXNewExprClass, Shell), SubExprs(nullptr) { } void AllocateArgsArray(const ASTContext &C, bool isArray, unsigned numPlaceArgs, bool hasInitializer); @@ -1751,10 +1686,10 @@ public: bool isArray() const { return Array; } Expr *getArraySize() { - return Array ? cast<Expr>(SubExprs[0]) : 0; + return Array ? cast<Expr>(SubExprs[0]) : nullptr; } const Expr *getArraySize() const { - return Array ? cast<Expr>(SubExprs[0]) : 0; + return Array ? cast<Expr>(SubExprs[0]) : nullptr; } unsigned getNumPlacementArgs() const { return NumPlacementArgs; } @@ -1788,10 +1723,10 @@ public: /// \brief The initializer of this new-expression. Expr *getInitializer() { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0; + return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; } const Expr *getInitializer() const { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0; + return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; } /// \brief Returns the CXXConstructExpr from this new-expression, or null. @@ -1885,7 +1820,8 @@ public: ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { } explicit CXXDeleteExpr(EmptyShell Shell) - : Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { } + : Expr(CXXDeleteExprClass, Shell), OperatorDelete(nullptr), + Argument(nullptr) {} bool isGlobalDelete() const { return GlobalDelete; } bool isArrayForm() const { return ArrayForm; } @@ -2017,7 +1953,7 @@ public: explicit CXXPseudoDestructorExpr(EmptyShell Shell) : Expr(CXXPseudoDestructorExprClass, Shell), - Base(0), IsArrow(false), QualifierLoc(), ScopeType(0) { } + Base(nullptr), IsArrow(false), QualifierLoc(), ScopeType(nullptr) { } Expr *getBase() const { return cast<Expr>(Base); } @@ -2110,138 +2046,12 @@ public: child_range children() { return child_range(&Base, &Base + 1); } }; -/// \brief Represents a GCC or MS unary type trait, as used in the -/// implementation of TR1/C++11 type trait templates. -/// -/// Example: -/// \code -/// __is_pod(int) == true -/// __is_enum(std::string) == false -/// \endcode -class UnaryTypeTraitExpr : public Expr { - /// \brief The trait. A UnaryTypeTrait enum in MSVC compatible unsigned. - unsigned UTT : 31; - /// The value of the type trait. Unspecified if dependent. - bool Value : 1; - - /// \brief The location of the type trait keyword. - SourceLocation Loc; - - /// \brief The location of the closing paren. - SourceLocation RParen; - - /// \brief The type being queried. - TypeSourceInfo *QueriedType; - -public: - UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, - TypeSourceInfo *queried, bool value, - SourceLocation rparen, QualType ty) - : Expr(UnaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, - false, queried->getType()->isDependentType(), - queried->getType()->isInstantiationDependentType(), - queried->getType()->containsUnexpandedParameterPack()), - UTT(utt), Value(value), Loc(loc), RParen(rparen), QueriedType(queried) { } - - explicit UnaryTypeTraitExpr(EmptyShell Empty) - : Expr(UnaryTypeTraitExprClass, Empty), UTT(0), Value(false), - QueriedType() { } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } - - UnaryTypeTrait getTrait() const { return static_cast<UnaryTypeTrait>(UTT); } - - QualType getQueriedType() const { return QueriedType->getType(); } - - TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } - - bool getValue() const { return Value; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnaryTypeTraitExprClass; - } - - // Iterators - child_range children() { return child_range(); } - - friend class ASTStmtReader; -}; - -/// \brief Represents a GCC or MS binary type trait, as used in the -/// implementation of TR1/C++11 type trait templates. -/// -/// Example: -/// \code -/// __is_base_of(Base, Derived) == true -/// \endcode -class BinaryTypeTraitExpr : public Expr { - /// \brief The trait. A BinaryTypeTrait enum in MSVC compatible unsigned. - unsigned BTT : 8; - - /// The value of the type trait. Unspecified if dependent. - bool Value : 1; - - /// \brief The location of the type trait keyword. - SourceLocation Loc; - - /// \brief The location of the closing paren. - SourceLocation RParen; - - /// \brief The lhs type being queried. - TypeSourceInfo *LhsType; - - /// \brief The rhs type being queried. - TypeSourceInfo *RhsType; - -public: - BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt, - TypeSourceInfo *lhsType, TypeSourceInfo *rhsType, - bool value, SourceLocation rparen, QualType ty) - : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false, - lhsType->getType()->isDependentType() || - rhsType->getType()->isDependentType(), - (lhsType->getType()->isInstantiationDependentType() || - rhsType->getType()->isInstantiationDependentType()), - (lhsType->getType()->containsUnexpandedParameterPack() || - rhsType->getType()->containsUnexpandedParameterPack())), - BTT(btt), Value(value), Loc(loc), RParen(rparen), - LhsType(lhsType), RhsType(rhsType) { } - - - explicit BinaryTypeTraitExpr(EmptyShell Empty) - : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false), - LhsType(), RhsType() { } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } - - BinaryTypeTrait getTrait() const { - return static_cast<BinaryTypeTrait>(BTT); - } - - QualType getLhsType() const { return LhsType->getType(); } - QualType getRhsType() const { return RhsType->getType(); } - - TypeSourceInfo *getLhsTypeSourceInfo() const { return LhsType; } - TypeSourceInfo *getRhsTypeSourceInfo() const { return RhsType; } - - bool getValue() const { assert(!isTypeDependent()); return Value; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == BinaryTypeTraitExprClass; - } - - // Iterators - child_range children() { return child_range(); } - - friend class ASTStmtReader; -}; - /// \brief A type trait used in the implementation of various C++11 and /// Library TR1 trait templates. /// /// \code +/// __is_pod(int) == true +/// __is_enum(std::string) == false /// __is_trivially_constructible(vector<int>, int*, int*) /// \endcode class TypeTraitExpr : public Expr { @@ -2334,7 +2144,7 @@ public: friend class ASTStmtWriter; }; - + /// \brief An Embarcadero array type trait, as used in the implementation of /// __array_rank and __array_extent. /// @@ -2504,7 +2314,7 @@ protected: bool KnownContainsUnexpandedParameterPack); OverloadExpr(StmtClass K, EmptyShell Empty) - : Expr(K, Empty), QualifierLoc(), Results(0), NumResults(0), + : Expr(K, Empty), QualifierLoc(), Results(nullptr), NumResults(0), HasTemplateKWAndArgsInfo(false) { } void initializeResults(const ASTContext &C, @@ -2554,6 +2364,9 @@ public: decls_iterator decls_end() const { return UnresolvedSetIterator(Results + NumResults); } + llvm::iterator_range<decls_iterator> decls() const { + return llvm::iterator_range<decls_iterator>(decls_begin(), decls_end()); + } /// \brief Gets the number of declarations in the unresolved set. unsigned getNumDecls() const { return NumResults; } @@ -2634,7 +2447,7 @@ public: /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return 0; + if (!hasExplicitTemplateArgs()) return nullptr; return &getExplicitTemplateArgs(); } @@ -2691,7 +2504,7 @@ class UnresolvedLookupExpr : public OverloadExpr { UnresolvedLookupExpr(EmptyShell Empty) : OverloadExpr(UnresolvedLookupExprClass, Empty), - RequiresADL(false), Overloaded(false), NamingClass(0) + RequiresADL(false), Overloaded(false), NamingClass(nullptr) {} friend class ASTStmtReader; @@ -2706,7 +2519,7 @@ public: UnresolvedSetIterator End) { return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, SourceLocation(), NameInfo, - ADL, Overloaded, 0, Begin, End); + ADL, Overloaded, nullptr, Begin, End); } static UnresolvedLookupExpr *Create(const ASTContext &C, @@ -2781,7 +2594,7 @@ class DependentScopeDeclRefExpr : public Expr { /// \brief Return the optional template keyword and arguments info. ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return 0; + if (!HasTemplateKWAndArgsInfo) return nullptr; return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); } /// \brief Return the optional template keyword and arguments info. @@ -2875,7 +2688,7 @@ public: /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return 0; + if (!hasExplicitTemplateArgs()) return nullptr; return &getExplicitTemplateArgs(); } @@ -3151,7 +2964,7 @@ class CXXDependentScopeMemberExpr : public Expr { /// \brief Return the optional template keyword and arguments info. ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return 0; + if (!HasTemplateKWAndArgsInfo) return nullptr; return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); } /// \brief Return the optional template keyword and arguments info. @@ -3296,7 +3109,7 @@ public: /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return 0; + if (!hasExplicitTemplateArgs()) return nullptr; return &getExplicitTemplateArgs(); } @@ -3398,7 +3211,7 @@ class UnresolvedMemberExpr : public OverloadExpr { UnresolvedMemberExpr(EmptyShell Empty) : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), - HasUnresolvedUsing(false), Base(0) { } + HasUnresolvedUsing(false), Base(nullptr) { } friend class ASTStmtReader; @@ -3612,7 +3425,7 @@ public: }; inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return 0; + if (!HasTemplateKWAndArgsInfo) return nullptr; if (isa<UnresolvedLookupExpr>(this)) return reinterpret_cast<ASTTemplateKWAndArgsInfo*> (cast<UnresolvedLookupExpr>(this) + 1); @@ -3904,39 +3717,51 @@ public: /// temporary. When either happens, the expression will also track the /// declaration which is responsible for the lifetime extension. class MaterializeTemporaryExpr : public Expr { -public: - /// \brief The temporary-generating expression whose value will be - /// materialized. - Stmt *Temporary; +private: + struct ExtraState { + /// \brief The temporary-generating expression whose value will be + /// materialized. + Stmt *Temporary; - /// \brief The declaration which lifetime-extended this reference, if any. - /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. - const ValueDecl *ExtendingDecl; + /// \brief The declaration which lifetime-extended this reference, if any. + /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. + const ValueDecl *ExtendingDecl; + + unsigned ManglingNumber; + }; + llvm::PointerUnion<Stmt *, ExtraState *> State; friend class ASTStmtReader; friend class ASTStmtWriter; + void initializeExtraState(const ValueDecl *ExtendedBy, + unsigned ManglingNumber); + public: MaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference, - const ValueDecl *ExtendedBy) + bool BoundToLvalueReference) : Expr(MaterializeTemporaryExprClass, T, BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, Temporary->isTypeDependent(), Temporary->isValueDependent(), Temporary->isInstantiationDependent(), Temporary->containsUnexpandedParameterPack()), - Temporary(Temporary), ExtendingDecl(ExtendedBy) { - } + State(Temporary) {} MaterializeTemporaryExpr(EmptyShell Empty) : Expr(MaterializeTemporaryExprClass, Empty) { } + Stmt *getTemporary() const { + return State.is<Stmt *>() ? State.get<Stmt *>() + : State.get<ExtraState *>()->Temporary; + } + /// \brief Retrieve the temporary-generating subexpression whose value will /// be materialized into a glvalue. - Expr *GetTemporaryExpr() const { return static_cast<Expr *>(Temporary); } + Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); } /// \brief Retrieve the storage duration for the materialized temporary. StorageDuration getStorageDuration() const { + const ValueDecl *ExtendingDecl = getExtendingDecl(); if (!ExtendingDecl) return SD_FullExpression; // FIXME: This is not necessarily correct for a temporary materialized @@ -3948,10 +3773,15 @@ public: /// \brief Get the declaration which triggered the lifetime-extension of this /// temporary, if any. - const ValueDecl *getExtendingDecl() const { return ExtendingDecl; } + const ValueDecl *getExtendingDecl() const { + return State.is<Stmt *>() ? nullptr + : State.get<ExtraState *>()->ExtendingDecl; + } + + void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber); - void setExtendingDecl(const ValueDecl *ExtendedBy) { - ExtendingDecl = ExtendedBy; + unsigned getManglingNumber() const { + return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber; } /// \brief Determine whether this materialized temporary is bound to an @@ -3961,10 +3791,10 @@ public: } SourceLocation getLocStart() const LLVM_READONLY { - return Temporary->getLocStart(); + return getTemporary()->getLocStart(); } SourceLocation getLocEnd() const LLVM_READONLY { - return Temporary->getLocEnd(); + return getTemporary()->getLocEnd(); } static bool classof(const Stmt *T) { @@ -3972,7 +3802,13 @@ public: } // Iterators - child_range children() { return child_range(&Temporary, &Temporary + 1); } + child_range children() { + if (State.is<Stmt *>()) + return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1); + + auto ES = State.get<ExtraState *>(); + return child_range(&ES->Temporary, &ES->Temporary + 1); + } }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h index aeb55da..817c0cc 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h @@ -215,7 +215,7 @@ struct ObjCDictionaryElement { } // end namespace clang namespace llvm { -template <> struct isPodLike<clang::ObjCDictionaryElement> : llvm::true_type {}; +template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {}; } namespace clang { @@ -277,14 +277,14 @@ class ObjCDictionaryLiteral : public Expr { ExpansionData *getExpansionData() { if (!HasPackExpansions) - return 0; + return nullptr; return reinterpret_cast<ExpansionData *>(getKeyValues() + NumElements); } const ExpansionData *getExpansionData() const { if (!HasPackExpansions) - return 0; + return nullptr; return reinterpret_cast<const ExpansionData *>(getKeyValues()+NumElements); } @@ -683,13 +683,13 @@ public: if (isExplicitProperty()) { const ObjCPropertyDecl *PDecl = getExplicitProperty(); if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl()) - ResultType = Getter->getResultType(); + ResultType = Getter->getReturnType(); else ResultType = PDecl->getType(); } else { const ObjCMethodDecl *Getter = getImplicitPropertyGetter(); if (Getter) - ResultType = Getter->getResultType(); // with reference! + ResultType = Getter->getReturnType(); // with reference! } return ResultType; } @@ -743,7 +743,7 @@ private: void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) { PropertyOrGetter.setPointer(D); PropertyOrGetter.setInt(false); - SetterAndMethodRefFlags.setPointer(0); + SetterAndMethodRefFlags.setPointer(nullptr); SetterAndMethodRefFlags.setInt(methRefFlags); } void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, @@ -1174,7 +1174,7 @@ public: if (getReceiverKind() == Instance) return static_cast<Expr *>(getReceiverPointer()); - return 0; + return nullptr; } const Expr *getInstanceReceiver() const { return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver(); @@ -1201,7 +1201,7 @@ public: TypeSourceInfo *getClassReceiverTypeInfo() const { if (getReceiverKind() == Class) return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer()); - return 0; + return nullptr; } void setClassReceiver(TypeSourceInfo *TSInfo) { @@ -1270,14 +1270,14 @@ public: if (HasMethod) return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod); - return 0; + return nullptr; } ObjCMethodDecl *getMethodDecl() { if (HasMethod) return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod); - return 0; + return nullptr; } void setMethodDecl(ObjCMethodDecl *MD) { diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h index b077426..1e8eff3 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h @@ -45,7 +45,7 @@ enum ExternalLoadResult { /// no additional processing is required. ELR_AlreadyLoaded }; - + /// \brief Abstract interface for external sources of AST nodes. /// /// External AST sources provide AST nodes constructed from some @@ -53,7 +53,11 @@ enum ExternalLoadResult { /// sources can resolve types and declarations from abstract IDs into /// actual type and declaration nodes, and read parts of declaration /// contexts. -class ExternalASTSource { +class ExternalASTSource : public RefCountedBase<ExternalASTSource> { + /// Generation number for this external AST source. Must be increased + /// whenever we might have added new redeclarations for existing decls. + uint32_t CurrentGeneration; + /// \brief Whether this AST source also provides information for /// semantic analysis. bool SemaSource; @@ -61,7 +65,7 @@ class ExternalASTSource { friend class ExternalSemaSource; public: - ExternalASTSource() : SemaSource(false) { } + ExternalASTSource() : CurrentGeneration(0), SemaSource(false) { } virtual ~ExternalASTSource(); @@ -79,6 +83,11 @@ public: } }; + /// \brief Get the current generation of this AST source. This number + /// is incremented each time the AST source lazily extends an existing + /// entity. + uint32_t getGeneration() const { return CurrentGeneration; } + /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. /// @@ -138,7 +147,7 @@ public: virtual void completeVisibleDeclsMap(const DeclContext *DC); /// \brief Retrieve the module that corresponds to the given module ID. - virtual Module *getModule(unsigned ID) { return 0; } + virtual Module *getModule(unsigned ID) { return nullptr; } /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. @@ -160,7 +169,7 @@ public: /// \return true if an error occurred ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, SmallVectorImpl<Decl*> &Result) { - return FindExternalLexicalDecls(DC, 0, Result); + return FindExternalLexicalDecls(DC, nullptr, Result); } template <typename DeclTy> @@ -171,43 +180,50 @@ public: /// \brief Get the decls that are contained in a file in the Offset/Length /// range. \p Length can be 0 to indicate a point at \p Offset instead of - /// a range. - virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, - SmallVectorImpl<Decl *> &Decls) {} + /// a range. + virtual void FindFileRegionDecls(FileID File, unsigned Offset, + unsigned Length, + SmallVectorImpl<Decl *> &Decls); + + /// \brief Gives the external AST source an opportunity to complete + /// the redeclaration chain for a declaration. Called each time we + /// need the most recent declaration of a declaration after the + /// generation count is incremented. + virtual void CompleteRedeclChain(const Decl *D); /// \brief Gives the external AST source an opportunity to complete /// an incomplete type. - virtual void CompleteType(TagDecl *Tag) {} + virtual void CompleteType(TagDecl *Tag); /// \brief Gives the external AST source an opportunity to complete an /// incomplete Objective-C class. /// /// This routine will only be invoked if the "externally completed" bit is - /// set on the ObjCInterfaceDecl via the function + /// set on the ObjCInterfaceDecl via the function /// \c ObjCInterfaceDecl::setExternallyCompleted(). - virtual void CompleteType(ObjCInterfaceDecl *Class) { } + virtual void CompleteType(ObjCInterfaceDecl *Class); /// \brief Loads comment ranges. - virtual void ReadComments() { } + 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. /// /// The default implementation of this method is a no-op. - virtual void StartedDeserializing() { } + virtual void StartedDeserializing(); /// \brief Notify ExternalASTSource that we finished the deserialization of /// a decl or type. Must be paired with StartedDeserializing. /// /// The default implementation of this method is a no-op. - virtual void FinishedDeserializing() { } + virtual void FinishedDeserializing(); /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. /// /// The default implementation of this method is a no-op. - virtual void StartTranslationUnit(ASTConsumer *Consumer) { } + virtual void StartTranslationUnit(ASTConsumer *Consumer); /// \brief Print any statistics that have been gathered regarding /// the external AST source. @@ -243,16 +259,12 @@ public: /// out according to the ABI. /// /// \returns true if the record layout was provided, false otherwise. - virtual bool - layoutRecordType(const RecordDecl *Record, - uint64_t &Size, uint64_t &Alignment, - llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, - llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, - llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets) - { - return false; - } - + virtual bool layoutRecordType( + const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets); + //===--------------------------------------------------------------------===// // Queries for performance analysis. //===--------------------------------------------------------------------===// @@ -284,6 +296,9 @@ protected: static DeclContextLookupResult SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name); + + /// \brief Increment the current generation. + uint32_t incrementGeneration(ASTContext &C); }; /// \brief A lazy pointer to an AST node (of base type T) that resides @@ -354,6 +369,100 @@ public: } }; +/// \brief A lazy value (of type T) that is within an AST node of type Owner, +/// where the value might change in later generations of the external AST +/// source. +template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)> +struct LazyGenerationalUpdatePtr { + /// A cache of the value of this pointer, in the most recent generation in + /// which we queried it. + struct LazyData { + LazyData(ExternalASTSource *Source, T Value) + : ExternalSource(Source), LastGeneration(0), LastValue(Value) {} + ExternalASTSource *ExternalSource; + uint32_t LastGeneration; + T LastValue; + }; + + // Our value is represented as simply T if there is no external AST source. + typedef llvm::PointerUnion<T, LazyData*> ValueType; + ValueType Value; + + LazyGenerationalUpdatePtr(ValueType V) : Value(V) {} + + // Defined in ASTContext.h + static ValueType makeValue(const ASTContext &Ctx, T Value); + +public: + explicit LazyGenerationalUpdatePtr(const ASTContext &Ctx, T Value = T()) + : Value(makeValue(Ctx, Value)) {} + + /// Create a pointer that is not potentially updated by later generations of + /// the external AST source. + enum NotUpdatedTag { NotUpdated }; + LazyGenerationalUpdatePtr(NotUpdatedTag, T Value = T()) + : Value(Value) {} + + /// Forcibly set this pointer (which must be lazy) as needing updates. + void markIncomplete() { + Value.template get<LazyData *>()->LastGeneration = 0; + } + + /// Set the value of this pointer, in the current generation. + void set(T NewValue) { + if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) { + LazyVal->LastValue = NewValue; + return; + } + Value = NewValue; + } + + /// Set the value of this pointer, for this and all future generations. + void setNotUpdated(T NewValue) { Value = NewValue; } + + /// Get the value of this pointer, updating its owner if necessary. + T get(Owner O) { + if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) { + if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) { + LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration(); + (LazyVal->ExternalSource->*Update)(O); + } + return LazyVal->LastValue; + } + return Value.template get<T>(); + } + + /// Get the most recently computed value of this pointer without updating it. + T getNotUpdated() const { + if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) + return LazyVal->LastValue; + return Value.template get<T>(); + } + + void *getOpaqueValue() { return Value.getOpaqueValue(); } + static LazyGenerationalUpdatePtr getFromOpaqueValue(void *Ptr) { + return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr)); + } +}; +} // end namespace clang + +/// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be +/// placed into a PointerUnion. +namespace llvm { +template<typename Owner, typename T, + void (clang::ExternalASTSource::*Update)(Owner)> +struct PointerLikeTypeTraits< + clang::LazyGenerationalUpdatePtr<Owner, T, Update>> { + typedef clang::LazyGenerationalUpdatePtr<Owner, T, Update> Ptr; + static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); } + static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); } + enum { + NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1 + }; +}; +} + +namespace clang { /// \brief Represents a lazily-loaded vector of data. /// /// The lazily-loaded vector of data contains data that is partially loaded @@ -519,7 +628,7 @@ public: if (From.Position < 0) { Loaded.erase(Loaded.end() + From.Position, Loaded.end()); - From = begin(0, true); + From = begin(nullptr, true); } Local.erase(Local.begin() + From.Position, Local.begin() + To.Position); diff --git a/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h b/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h new file mode 100644 index 0000000..8633c97 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h @@ -0,0 +1,123 @@ +//===--- LambdaCapture.h - Types for C++ Lambda Captures --------*- 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 the LambdaCapture class. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_LAMBDACAPTURE_H +#define LLVM_CLANG_AST_LAMBDACAPTURE_H + +#include "clang/AST/Decl.h" +#include "clang/Basic/Lambda.h" +#include "llvm/ADT/PointerIntPair.h" + +namespace clang { + +/// \brief Describes the capture of a variable or of \c this, or of a +/// C++1y init-capture. +class LambdaCapture { + enum { + /// \brief Flag used by the Capture class to indicate that the given + /// capture was implicit. + Capture_Implicit = 0x01, + + /// \brief Flag used by the Capture class to indicate that the + /// given capture was by-copy. + /// + /// This includes the case of a non-reference init-capture. + Capture_ByCopy = 0x02 + }; + + llvm::PointerIntPair<Decl *, 2> DeclAndBits; + SourceLocation Loc; + SourceLocation EllipsisLoc; + + friend class ASTStmtReader; + friend class ASTStmtWriter; + +public: + /// \brief Create a new capture of a variable or of \c this. + /// + /// \param Loc The source location associated with this capture. + /// + /// \param Kind The kind of capture (this, byref, bycopy), which must + /// not be init-capture. + /// + /// \param Implicit Whether the capture was implicit or explicit. + /// + /// \param Var The local variable being captured, or null if capturing + /// \c this. + /// + /// \param EllipsisLoc The location of the ellipsis (...) for a + /// capture that is a pack expansion, or an invalid source + /// location to indicate that this is not a pack expansion. + LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind, + VarDecl *Var = nullptr, + SourceLocation EllipsisLoc = SourceLocation()); + + /// \brief Determine the kind of capture. + LambdaCaptureKind getCaptureKind() const; + + /// \brief Determine whether this capture handles the C++ \c this + /// pointer. + bool capturesThis() const { return DeclAndBits.getPointer() == nullptr; } + + /// \brief Determine whether this capture handles a variable. + bool capturesVariable() const { + return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer()); + } + + /// \brief Determine whether this is an init-capture. + bool isInitCapture() const { + return capturesVariable() && getCapturedVar()->isInitCapture(); + } + + /// \brief Retrieve the declaration of the local variable being + /// captured. + /// + /// This operation is only valid if this capture is a variable capture + /// (other than a capture of \c this). + VarDecl *getCapturedVar() const { + assert(capturesVariable() && "No variable available for 'this' capture"); + return cast<VarDecl>(DeclAndBits.getPointer()); + } + + /// \brief Determine whether this was an implicit capture (not + /// written between the square brackets introducing the lambda). + bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; } + + /// \brief Determine whether this was an explicit capture (written + /// between the square brackets introducing the lambda). + bool isExplicit() const { return !isImplicit(); } + + /// \brief Retrieve the source location of the capture. + /// + /// For an explicit capture, this returns the location of the + /// explicit capture in the source. For an implicit capture, this + /// returns the location at which the variable or \c this was first + /// used. + SourceLocation getLocation() const { return Loc; } + + /// \brief Determine whether this capture is a pack expansion, + /// which captures a function parameter pack. + bool isPackExpansion() const { return EllipsisLoc.isValid(); } + + /// \brief Retrieve the location of the ellipsis for a capture + /// that is a pack expansion. + SourceLocation getEllipsisLoc() const { + assert(isPackExpansion() && "No ellipsis location for a non-expansion"); + return EllipsisLoc; + } +}; + +} // end namespace clang + +#endif // LLVM_CLANG_AST_LAMBDACAPTURE_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/Mangle.h b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h index c4d0d22..a8d1199 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Mangle.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h @@ -31,36 +31,10 @@ namespace clang { class FunctionDecl; class NamedDecl; class ObjCMethodDecl; - class VarDecl; + class StringLiteral; struct ThisAdjustment; struct ThunkInfo; - -/// MangleBuffer - a convenient class for storing a name which is -/// either the result of a mangling or is a constant string with -/// external memory ownership. -class MangleBuffer { -public: - void setString(StringRef Ref) { - String = Ref; - } - - SmallVectorImpl<char> &getBuffer() { - return Buffer; - } - - StringRef getString() const { - if (!String.empty()) return String; - return Buffer.str(); - } - - operator StringRef() const { - return getString(); - } - -private: - StringRef String; - SmallString<256> Buffer; -}; + class VarDecl; /// MangleContext - Context for tracking state which persists across multiple /// calls to the C++ name mangler. @@ -80,6 +54,7 @@ private: llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds; llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds; + llvm::DenseMap<const TagDecl*, uint64_t> AnonStructIds; public: ManglerKind getKind() const { return Kind; } @@ -104,12 +79,19 @@ public: Result = BlockIds.insert(std::make_pair(BD, BlockIds.size())); return Result.first->second; } - + + uint64_t getAnonymousStructId(const TagDecl *TD) { + std::pair<llvm::DenseMap<const TagDecl *, uint64_t>::iterator, bool> + Result = AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size())); + return Result.first->second; + } + /// @name Mangler Entry Points /// @{ bool shouldMangleDeclName(const NamedDecl *D); virtual bool shouldMangleCXXName(const NamedDecl *D) = 0; + virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0; // FIXME: consider replacing raw_ostream & with something like SmallString &. void mangleName(const NamedDecl *D, raw_ostream &); @@ -121,6 +103,7 @@ public: const ThisAdjustment &ThisAdjustment, raw_ostream &) = 0; virtual void mangleReferenceTemporary(const VarDecl *D, + unsigned ManglingNumber, raw_ostream &) = 0; virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0; virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0; @@ -128,6 +111,7 @@ public: raw_ostream &) = 0; virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, raw_ostream &) = 0; + virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0; void mangleGlobalBlock(const BlockDecl *BD, const NamedDecl *ID, @@ -200,9 +184,23 @@ public: raw_ostream &Out) = 0; virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, - uint64_t OffsetInVFTable, raw_ostream &) = 0; + virtual void mangleCXXRTTIBaseClassDescriptor( + const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset, + uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0; + + virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived, + raw_ostream &Out) = 0; + virtual void + mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived, + raw_ostream &Out) = 0; + + virtual void + mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived, + ArrayRef<const CXXRecordDecl *> BasePath, + raw_ostream &Out) = 0; + static bool classof(const MangleContext *C) { return C->getKind() == MK_Microsoft; } diff --git a/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h b/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h index 5a227f2..56c9952 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h +++ b/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h @@ -33,7 +33,6 @@ class VarDecl; class MangleNumberingContext : public RefCountedBase<MangleNumberingContext> { llvm::DenseMap<const Type *, unsigned> ManglingNumbers; - llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers; public: virtual ~MangleNumberingContext() {} @@ -46,13 +45,18 @@ public: /// context. unsigned getManglingNumber(const BlockDecl *BD); + /// Static locals are numbered by source order. + unsigned getStaticLocalNumber(const VarDecl *VD); + /// \brief Retrieve the mangling number of a static local variable within /// this context. - virtual unsigned getManglingNumber(const VarDecl *VD) = 0; + virtual unsigned getManglingNumber(const VarDecl *VD, + unsigned MSLocalManglingNumber) = 0; /// \brief Retrieve the mangling number of a static local variable within /// this context. - unsigned getManglingNumber(const TagDecl *TD); + virtual unsigned getManglingNumber(const TagDecl *TD, + unsigned MSLocalManglingNumber) = 0; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h index b332b15..fc719bd 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h +++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h @@ -88,7 +88,8 @@ public: private: /// \brief Builds the global specifier. - NestedNameSpecifier() : Prefix(0, StoredIdentifier), Specifier(0) { } + NestedNameSpecifier() + : Prefix(nullptr, StoredIdentifier), Specifier(nullptr) {} /// \brief Copy constructor used internally to clone nested name /// specifiers. @@ -160,7 +161,7 @@ public: if (Prefix.getInt() == StoredIdentifier) return (IdentifierInfo *)Specifier; - return 0; + return nullptr; } /// \brief Retrieve the namespace stored in this nested name @@ -177,7 +178,7 @@ public: Prefix.getInt() == StoredTypeSpecWithTemplate) return (const Type *)Specifier; - return 0; + return nullptr; } /// \brief Whether this nested name specifier refers to a dependent @@ -222,7 +223,7 @@ class NestedNameSpecifierLoc { public: /// \brief Construct an empty nested-name-specifier. - NestedNameSpecifierLoc() : Qualifier(0), Data(0) { } + NestedNameSpecifierLoc() : Qualifier(nullptr), Data(nullptr) { } /// \brief Construct a nested-name-specifier with source location information /// from @@ -344,7 +345,8 @@ class NestedNameSpecifierLocBuilder { public: NestedNameSpecifierLocBuilder() - : Representation(0), Buffer(0), BufferSize(0), BufferCapacity(0) { } + : Representation(nullptr), Buffer(nullptr), BufferSize(0), + BufferCapacity(0) {} NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); @@ -457,7 +459,7 @@ public: /// \brief Clear out this builder, and prepare it to build another /// nested-name-specifier with source-location information. void Clear() { - Representation = 0; + Representation = nullptr; BufferSize = 0; } diff --git a/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h new file mode 100644 index 0000000..3345959 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h @@ -0,0 +1,1455 @@ +//===- OpenMPClause.h - Classes for OpenMP clauses --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// \brief This file defines OpenMP AST classes for clauses. +/// There are clauses for executable directives, clauses for declarative +/// directives and clauses which can be used in both kinds of directives. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_OPENMPCLAUSE_H +#define LLVM_CLANG_AST_OPENMPCLAUSE_H + +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" +#include "clang/Basic/OpenMPKinds.h" +#include "clang/Basic/SourceLocation.h" + +namespace clang { + +//===----------------------------------------------------------------------===// +// AST classes for clauses. +//===----------------------------------------------------------------------===// + +/// \brief This is a basic class for representing single OpenMP clause. +/// +class OMPClause { + /// \brief Starting location of the clause (the clause keyword). + SourceLocation StartLoc; + /// \brief Ending location of the clause. + SourceLocation EndLoc; + /// \brief Kind of the clause. + OpenMPClauseKind Kind; + +protected: + OMPClause(OpenMPClauseKind K, SourceLocation StartLoc, SourceLocation EndLoc) + : StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {} + +public: + /// \brief Returns the starting location of the clause. + SourceLocation getLocStart() const { return StartLoc; } + /// \brief Returns the ending location of the clause. + SourceLocation getLocEnd() const { return EndLoc; } + + /// \brief Sets the starting location of the clause. + void setLocStart(SourceLocation Loc) { StartLoc = Loc; } + /// \brief Sets the ending location of the clause. + void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } + + /// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.). + OpenMPClauseKind getClauseKind() const { return Kind; } + + bool isImplicit() const { return StartLoc.isInvalid(); } + + StmtRange children(); + ConstStmtRange children() const { + return const_cast<OMPClause *>(this)->children(); + } + static bool classof(const OMPClause *T) { return true; } +}; + +/// \brief This represents clauses with the list of variables like 'private', +/// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the +/// '#pragma omp ...' directives. +template <class T> class OMPVarListClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Number of variables in the list. + unsigned NumVars; + +protected: + /// \brief Fetches list of variables associated with this clause. + MutableArrayRef<Expr *> getVarRefs() { + return MutableArrayRef<Expr *>( + reinterpret_cast<Expr **>( + reinterpret_cast<char *>(this) + + llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())), + NumVars); + } + + /// \brief Sets the list of variables for this clause. + void setVarRefs(ArrayRef<Expr *> VL) { + assert(VL.size() == NumVars && + "Number of variables is not the same as the preallocated buffer"); + std::copy( + VL.begin(), VL.end(), + reinterpret_cast<Expr **>( + reinterpret_cast<char *>(this) + + llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>()))); + } + + /// \brief Build a clause with \a N variables + /// + /// \param K Kind of the clause. + /// \param StartLoc Starting location of the clause (the clause keyword). + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPVarListClause(OpenMPClauseKind K, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) + : OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc), NumVars(N) {} + +public: + typedef MutableArrayRef<Expr *>::iterator varlist_iterator; + typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; + typedef llvm::iterator_range<varlist_iterator> varlist_range; + typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; + + unsigned varlist_size() const { return NumVars; } + bool varlist_empty() const { return NumVars == 0; } + + varlist_range varlists() { + return varlist_range(varlist_begin(), varlist_end()); + } + varlist_const_range varlists() const { + return varlist_const_range(varlist_begin(), varlist_end()); + } + + varlist_iterator varlist_begin() { return getVarRefs().begin(); } + varlist_iterator varlist_end() { return getVarRefs().end(); } + varlist_const_iterator varlist_begin() const { return getVarRefs().begin(); } + varlist_const_iterator varlist_end() const { return getVarRefs().end(); } + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Fetches list of all variables in the clause. + ArrayRef<const Expr *> getVarRefs() const { + return ArrayRef<const Expr *>( + reinterpret_cast<const Expr *const *>( + reinterpret_cast<const char *>(this) + + llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())), + NumVars); + } +}; + +/// \brief This represents 'if' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp parallel if(a > 5) +/// \endcode +/// In this example directive '#pragma omp parallel' has simple 'if' +/// clause with condition 'a > 5'. +/// +class OMPIfClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Condition of the 'if' clause. + Stmt *Condition; + + /// \brief Set condition. + /// + void setCondition(Expr *Cond) { Condition = Cond; } + +public: + /// \brief Build 'if' clause with condition \a Cond. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param Cond Condition of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPIfClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc), + Condition(Cond) {} + + /// \brief Build an empty clause. + /// + OMPIfClause() + : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), Condition(nullptr) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Returns condition. + Expr *getCondition() const { return cast_or_null<Expr>(Condition); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_if; + } + + StmtRange children() { return StmtRange(&Condition, &Condition + 1); } +}; + +/// \brief This represents 'final' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp task final(a > 5) +/// \endcode +/// In this example directive '#pragma omp task' has simple 'final' +/// clause with condition 'a > 5'. +/// +class OMPFinalClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Condition of the 'if' clause. + Stmt *Condition; + + /// \brief Set condition. + /// + void setCondition(Expr *Cond) { Condition = Cond; } + +public: + /// \brief Build 'final' clause with condition \a Cond. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param Cond Condition of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc), + Condition(Cond) {} + + /// \brief Build an empty clause. + /// + OMPFinalClause() + : OMPClause(OMPC_final, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), Condition(nullptr) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Returns condition. + Expr *getCondition() const { return cast_or_null<Expr>(Condition); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_final; + } + + StmtRange children() { return StmtRange(&Condition, &Condition + 1); } +}; + +/// \brief This represents 'num_threads' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp parallel num_threads(6) +/// \endcode +/// In this example directive '#pragma omp parallel' has simple 'num_threads' +/// clause with number of threads '6'. +/// +class OMPNumThreadsClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Condition of the 'num_threads' clause. + Stmt *NumThreads; + + /// \brief Set condition. + /// + void setNumThreads(Expr *NThreads) { NumThreads = NThreads; } + +public: + /// \brief Build 'num_threads' clause with condition \a NumThreads. + /// + /// \param NumThreads Number of threads for the construct. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// + OMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_num_threads, StartLoc, EndLoc), LParenLoc(LParenLoc), + NumThreads(NumThreads) {} + + /// \brief Build an empty clause. + /// + OMPNumThreadsClause() + : OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), NumThreads(nullptr) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Returns number of threads. + Expr *getNumThreads() const { return cast_or_null<Expr>(NumThreads); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_num_threads; + } + + StmtRange children() { return StmtRange(&NumThreads, &NumThreads + 1); } +}; + +/// \brief This represents 'safelen' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp simd safelen(4) +/// \endcode +/// In this example directive '#pragma omp simd' has clause 'safelen' +/// with single expression '4'. +/// If the safelen clause is used then no two iterations executed +/// concurrently with SIMD instructions can have a greater distance +/// in the logical iteration space than its value. The parameter of +/// the safelen clause must be a constant positive integer expression. +/// +class OMPSafelenClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Safe iteration space distance. + Stmt *Safelen; + + /// \brief Set safelen. + void setSafelen(Expr *Len) { Safelen = Len; } + +public: + /// \brief Build 'safelen' clause. + /// + /// \param Len Expression associated with this clause. + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc), + Safelen(Len) {} + + /// \brief Build an empty clause. + /// + explicit OMPSafelenClause() + : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), Safelen(nullptr) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Return safe iteration space distance. + Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_safelen; + } + + StmtRange children() { return StmtRange(&Safelen, &Safelen + 1); } +}; + +/// \brief This represents 'collapse' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp simd collapse(3) +/// \endcode +/// In this example directive '#pragma omp simd' has clause 'collapse' +/// with single expression '3'. +/// The parameter must be a constant positive integer expression, it specifies +/// the number of nested loops that should be collapsed into a single iteration +/// space. +/// +class OMPCollapseClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Number of for-loops. + Stmt *NumForLoops; + + /// \brief Set the number of associated for-loops. + void setNumForLoops(Expr *Num) { NumForLoops = Num; } + +public: + /// \brief Build 'collapse' clause. + /// + /// \param Num Expression associated with this clause. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// + OMPCollapseClause(Expr *Num, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_collapse, StartLoc, EndLoc), LParenLoc(LParenLoc), + NumForLoops(Num) {} + + /// \brief Build an empty clause. + /// + explicit OMPCollapseClause() + : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), NumForLoops(nullptr) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Return the number of associated for-loops. + Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_collapse; + } + + StmtRange children() { return StmtRange(&NumForLoops, &NumForLoops + 1); } +}; + +/// \brief This represents 'default' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp parallel default(shared) +/// \endcode +/// In this example directive '#pragma omp parallel' has simple 'default' +/// clause with kind 'shared'. +/// +class OMPDefaultClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief A kind of the 'default' clause. + OpenMPDefaultClauseKind Kind; + /// \brief Start location of the kind in source code. + SourceLocation KindKwLoc; + + /// \brief Set kind of the clauses. + /// + /// \param K Argument of clause. + /// + void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; } + + /// \brief Set argument location. + /// + /// \param KLoc Argument location. + /// + void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } + +public: + /// \brief Build 'default' clause with argument \a A ('none' or 'shared'). + /// + /// \param A Argument of the clause ('none' or 'shared'). + /// \param ALoc Starting location of the argument. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// + OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc), + Kind(A), KindKwLoc(ALoc) {} + + /// \brief Build an empty clause. + /// + OMPDefaultClause() + : OMPClause(OMPC_default, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown), + KindKwLoc(SourceLocation()) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Returns kind of the clause. + OpenMPDefaultClauseKind getDefaultKind() const { return Kind; } + + /// \brief Returns location of clause kind. + SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_default; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'proc_bind' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp parallel proc_bind(master) +/// \endcode +/// In this example directive '#pragma omp parallel' has simple 'proc_bind' +/// clause with kind 'master'. +/// +class OMPProcBindClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief A kind of the 'proc_bind' clause. + OpenMPProcBindClauseKind Kind; + /// \brief Start location of the kind in source code. + SourceLocation KindKwLoc; + + /// \brief Set kind of the clause. + /// + /// \param K Kind of clause. + /// + void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; } + + /// \brief Set clause kind location. + /// + /// \param KLoc Kind location. + /// + void setProcBindKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } + +public: + /// \brief Build 'proc_bind' clause with argument \a A ('master', 'close' or + /// 'spread'). + /// + /// \param A Argument of the clause ('master', 'close' or 'spread'). + /// \param ALoc Starting location of the argument. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// + OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc), + Kind(A), KindKwLoc(ALoc) {} + + /// \brief Build an empty clause. + /// + OMPProcBindClause() + : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), Kind(OMPC_PROC_BIND_unknown), + KindKwLoc(SourceLocation()) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Returns kind of the clause. + OpenMPProcBindClauseKind getProcBindKind() const { return Kind; } + + /// \brief Returns location of clause kind. + SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_proc_bind; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'schedule' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp for schedule(static, 3) +/// \endcode +/// In this example directive '#pragma omp for' has 'schedule' clause with +/// arguments 'static' and '3'. +/// +class OMPScheduleClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief A kind of the 'schedule' clause. + OpenMPScheduleClauseKind Kind; + /// \brief Start location of the schedule ind in source code. + SourceLocation KindLoc; + /// \brief Location of ',' (if any). + SourceLocation CommaLoc; + /// \brief Chunk size. + Stmt *ChunkSize; + + /// \brief Set schedule kind. + /// + /// \param K Schedule kind. + /// + void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; } + /// \brief Sets the location of '('. + /// + /// \param Loc Location of '('. + /// + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Set schedule kind start location. + /// + /// \param KLoc Schedule kind location. + /// + void setScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } + /// \brief Set location of ','. + /// + /// \param Loc Location of ','. + /// + void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; } + /// \brief Set chunk size. + /// + /// \param E Chunk size. + /// + void setChunkSize(Expr *E) { ChunkSize = E; } + +public: + /// \brief Build 'schedule' clause with schedule kind \a Kind and chunk size + /// expression \a ChunkSize. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param KLoc Starting location of the argument. + /// \param CommaLoc Location of ','. + /// \param EndLoc Ending location of the clause. + /// \param Kind Schedule kind. + /// \param ChunkSize Chunk size. + /// + OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation KLoc, SourceLocation CommaLoc, + SourceLocation EndLoc, OpenMPScheduleClauseKind Kind, + Expr *ChunkSize) + : OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc), + Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc), ChunkSize(ChunkSize) {} + + /// \brief Build an empty clause. + /// + explicit OMPScheduleClause() + : OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()), + Kind(OMPC_SCHEDULE_unknown), ChunkSize(nullptr) {} + + /// \brief Get kind of the clause. + /// + OpenMPScheduleClauseKind getScheduleKind() const { return Kind; } + /// \brief Get location of '('. + /// + SourceLocation getLParenLoc() { return LParenLoc; } + /// \brief Get kind location. + /// + SourceLocation getScheduleKindLoc() { return KindLoc; } + /// \brief Get location of ','. + /// + SourceLocation getCommaLoc() { return CommaLoc; } + /// \brief Get chunk size. + /// + Expr *getChunkSize() { return dyn_cast_or_null<Expr>(ChunkSize); } + /// \brief Get chunk size. + /// + Expr *getChunkSize() const { return dyn_cast_or_null<Expr>(ChunkSize); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_schedule; + } + + StmtRange children() { return StmtRange(&ChunkSize, &ChunkSize + 1); } +}; + +/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp for ordered +/// \endcode +/// In this example directive '#pragma omp for' has 'ordered' clause. +/// +class OMPOrderedClause : public OMPClause { +public: + /// \brief Build 'ordered' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_ordered, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPOrderedClause() + : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_ordered; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'nowait' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp for nowait +/// \endcode +/// In this example directive '#pragma omp for' has 'nowait' clause. +/// +class OMPNowaitClause : public OMPClause { +public: + /// \brief Build 'nowait' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_nowait, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPNowaitClause() + : OMPClause(OMPC_nowait, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_nowait; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'untied' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp task untied +/// \endcode +/// In this example directive '#pragma omp task' has 'untied' clause. +/// +class OMPUntiedClause : public OMPClause { +public: + /// \brief Build 'untied' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_untied, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPUntiedClause() + : OMPClause(OMPC_untied, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_untied; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'mergeable' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp task mergeable +/// \endcode +/// In this example directive '#pragma omp task' has 'mergeable' clause. +/// +class OMPMergeableClause : public OMPClause { +public: + /// \brief Build 'mergeable' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_mergeable, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPMergeableClause() + : OMPClause(OMPC_mergeable, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_mergeable; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents clause 'private' in the '#pragma omp ...' directives. +/// +/// \code +/// #pragma omp parallel private(a,b) +/// \endcode +/// In this example directive '#pragma omp parallel' has clause 'private' +/// with the variables 'a' and 'b'. +/// +class OMPPrivateClause : public OMPVarListClause<OMPPrivateClause> { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPPrivateClause>(OMPC_private, StartLoc, LParenLoc, + EndLoc, N) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPPrivateClause(unsigned N) + : OMPVarListClause<OMPPrivateClause>(OMPC_private, SourceLocation(), + SourceLocation(), SourceLocation(), + N) {} + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_private; + } +}; + +/// \brief This represents clause 'firstprivate' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp parallel firstprivate(a,b) +/// \endcode +/// In this example directive '#pragma omp parallel' has clause 'firstprivate' +/// with the variables 'a' and 'b'. +/// +class OMPFirstprivateClause : public OMPVarListClause<OMPFirstprivateClause> { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPFirstprivateClause>(OMPC_firstprivate, StartLoc, + LParenLoc, EndLoc, N) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPFirstprivateClause(unsigned N) + : OMPVarListClause<OMPFirstprivateClause>( + OMPC_firstprivate, SourceLocation(), SourceLocation(), + SourceLocation(), N) {} + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPFirstprivateClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_firstprivate; + } +}; + +/// \brief This represents clause 'lastprivate' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp simd lastprivate(a,b) +/// \endcode +/// In this example directive '#pragma omp simd' has clause 'lastprivate' +/// with the variables 'a' and 'b'. +/// +class OMPLastprivateClause : public OMPVarListClause<OMPLastprivateClause> { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPLastprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPLastprivateClause>(OMPC_lastprivate, StartLoc, + LParenLoc, EndLoc, N) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPLastprivateClause(unsigned N) + : OMPVarListClause<OMPLastprivateClause>( + OMPC_lastprivate, SourceLocation(), SourceLocation(), + SourceLocation(), N) {} + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPLastprivateClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPLastprivateClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_lastprivate; + } +}; + +/// \brief This represents clause 'shared' in the '#pragma omp ...' directives. +/// +/// \code +/// #pragma omp parallel shared(a,b) +/// \endcode +/// In this example directive '#pragma omp parallel' has clause 'shared' +/// with the variables 'a' and 'b'. +/// +class OMPSharedClause : public OMPVarListClause<OMPSharedClause> { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPSharedClause>(OMPC_shared, StartLoc, LParenLoc, + EndLoc, N) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPSharedClause(unsigned N) + : OMPVarListClause<OMPSharedClause>(OMPC_shared, SourceLocation(), + SourceLocation(), SourceLocation(), + N) {} + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPSharedClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_shared; + } +}; + +/// \brief This represents clause 'reduction' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp parallel reduction(+:a,b) +/// \endcode +/// In this example directive '#pragma omp parallel' has clause 'reduction' +/// with operator '+' and the variables 'a' and 'b'. +/// +class OMPReductionClause : public OMPVarListClause<OMPReductionClause> { + friend class OMPClauseReader; + /// \brief Location of ':'. + SourceLocation ColonLoc; + /// \brief Nested name specifier for C++. + NestedNameSpecifierLoc QualifierLoc; + /// \brief Name of custom operator. + DeclarationNameInfo NameInfo; + + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param ColonLoc Location of ':'. + /// \param N Number of the variables in the clause. + /// \param QualifierLoc The nested-name qualifier with location information + /// \param NameInfo The full name info for reduction identifier. + /// + OMPReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo) + : OMPVarListClause<OMPReductionClause>(OMPC_reduction, StartLoc, + LParenLoc, EndLoc, N), + ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPReductionClause(unsigned N) + : OMPVarListClause<OMPReductionClause>(OMPC_reduction, SourceLocation(), + SourceLocation(), SourceLocation(), + N), + ColonLoc(), QualifierLoc(), NameInfo() {} + + /// \brief Sets location of ':' symbol in clause. + void setColonLoc(SourceLocation CL) { ColonLoc = CL; } + /// \brief Sets the name info for specified reduction identifier. + void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; } + /// \brief Sets the nested name specifier. + void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; } + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ColonLoc Location of ':'. + /// \param EndLoc Ending location of the clause. + /// \param VL The variables in the clause. + /// \param QualifierLoc The nested-name qualifier with location information + /// \param NameInfo The full name info for reduction identifier. + /// + static OMPReductionClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo); + /// \brief Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPReductionClause *CreateEmpty(const ASTContext &C, unsigned N); + + /// \brief Gets location of ':' symbol in clause. + SourceLocation getColonLoc() const { return ColonLoc; } + /// \brief Gets the name info for specified reduction identifier. + const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + /// \brief Gets the nested name specifier. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_reduction; + } +}; + +/// \brief This represents clause 'linear' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp simd linear(a,b : 2) +/// \endcode +/// In this example directive '#pragma omp simd' has clause 'linear' +/// with variables 'a', 'b' and linear step '2'. +/// +class OMPLinearClause : public OMPVarListClause<OMPLinearClause> { + friend class OMPClauseReader; + /// \brief Location of ':'. + SourceLocation ColonLoc; + + /// \brief Sets the linear step for clause. + void setStep(Expr *Step) { *varlist_end() = Step; } + + /// \brief Build 'linear' clause with given number of variables \a NumVars. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ColonLoc Location of ':'. + /// \param EndLoc Ending location of the clause. + /// \param NumVars Number of variables. + /// + OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, + unsigned NumVars) + : OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc, + EndLoc, NumVars), + ColonLoc(ColonLoc) {} + + /// \brief Build an empty clause. + /// + /// \param NumVars Number of variables. + /// + explicit OMPLinearClause(unsigned NumVars) + : OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(), + SourceLocation(), SourceLocation(), + NumVars), + ColonLoc(SourceLocation()) {} + +public: + /// \brief Creates clause with a list of variables \a VL and a linear step + /// \a Step. + /// + /// \param C AST Context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ColonLoc Location of ':'. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// \param Step Linear step. + static OMPLinearClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, + ArrayRef<Expr *> VL, Expr *Step); + + /// \brief Creates an empty clause with the place for \a NumVars variables. + /// + /// \param C AST context. + /// \param NumVars Number of variables. + /// + static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars); + + /// \brief Sets the location of ':'. + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getColonLoc() const { return ColonLoc; } + + /// \brief Returns linear step. + Expr *getStep() { return *varlist_end(); } + /// \brief Returns linear step. + const Expr *getStep() const { return *varlist_end(); } + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end() + 1)); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_linear; + } +}; + +/// \brief This represents clause 'aligned' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp simd aligned(a,b : 8) +/// \endcode +/// In this example directive '#pragma omp simd' has clause 'aligned' +/// with variables 'a', 'b' and alignment '8'. +/// +class OMPAlignedClause : public OMPVarListClause<OMPAlignedClause> { + friend class OMPClauseReader; + /// \brief Location of ':'. + SourceLocation ColonLoc; + + /// \brief Sets the alignment for clause. + void setAlignment(Expr *A) { *varlist_end() = A; } + + /// \brief Build 'aligned' clause with given number of variables \a NumVars. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ColonLoc Location of ':'. + /// \param EndLoc Ending location of the clause. + /// \param NumVars Number of variables. + /// + OMPAlignedClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, + unsigned NumVars) + : OMPVarListClause<OMPAlignedClause>(OMPC_aligned, StartLoc, LParenLoc, + EndLoc, NumVars), + ColonLoc(ColonLoc) {} + + /// \brief Build an empty clause. + /// + /// \param NumVars Number of variables. + /// + explicit OMPAlignedClause(unsigned NumVars) + : OMPVarListClause<OMPAlignedClause>(OMPC_aligned, SourceLocation(), + SourceLocation(), SourceLocation(), + NumVars), + ColonLoc(SourceLocation()) {} + +public: + /// \brief Creates clause with a list of variables \a VL and alignment \a A. + /// + /// \param C AST Context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ColonLoc Location of ':'. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// \param A Alignment. + static OMPAlignedClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, + Expr *A); + + /// \brief Creates an empty clause with the place for \a NumVars variables. + /// + /// \param C AST context. + /// \param NumVars Number of variables. + /// + static OMPAlignedClause *CreateEmpty(const ASTContext &C, unsigned NumVars); + + /// \brief Sets the location of ':'. + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + /// \brief Returns the location of ':'. + SourceLocation getColonLoc() const { return ColonLoc; } + + /// \brief Returns alignment. + Expr *getAlignment() { return *varlist_end(); } + /// \brief Returns alignment. + const Expr *getAlignment() const { return *varlist_end(); } + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end() + 1)); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_aligned; + } +}; + +/// \brief This represents clause 'copyin' in the '#pragma omp ...' directives. +/// +/// \code +/// #pragma omp parallel copyin(a,b) +/// \endcode +/// In this example directive '#pragma omp parallel' has clause 'copyin' +/// with the variables 'a' and 'b'. +/// +class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPCopyinClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc, + EndLoc, N) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPCopyinClause(unsigned N) + : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, SourceLocation(), + SourceLocation(), SourceLocation(), + N) {} + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPCopyinClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPCopyinClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_copyin; + } +}; + +/// \brief This represents clause 'copyprivate' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp single copyprivate(a,b) +/// \endcode +/// In this example directive '#pragma omp single' has clause 'copyprivate' +/// with the variables 'a' and 'b'. +/// +class OMPCopyprivateClause : public OMPVarListClause<OMPCopyprivateClause> { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPCopyprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc, + LParenLoc, EndLoc, N) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPCopyprivateClause(unsigned N) + : OMPVarListClause<OMPCopyprivateClause>( + OMPC_copyprivate, SourceLocation(), SourceLocation(), + SourceLocation(), N) {} + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPCopyprivateClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_copyprivate; + } +}; + +/// \brief This represents pseudo clause 'flush' for the '#pragma omp flush' +/// directive. +/// +/// \code +/// #pragma omp flush(a,b) +/// \endcode +/// In this example directive '#pragma omp flush' has pseudo clause 'flush' +/// with the variables 'a' and 'b'. +/// +class OMPFlushClause : public OMPVarListClause<OMPFlushClause> { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPFlushClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPFlushClause>(OMPC_flush, StartLoc, LParenLoc, + EndLoc, N) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPFlushClause(unsigned N) + : OMPVarListClause<OMPFlushClause>(OMPC_flush, SourceLocation(), + SourceLocation(), SourceLocation(), + N) {} + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPFlushClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_flush; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h index 5e41d95..aba88d6 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h +++ b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h @@ -295,7 +295,10 @@ enum CastKind { CK_BuiltinFnToFnPtr, // Convert a zero value for OpenCL event_t initialization. - CK_ZeroToOCLEvent + CK_ZeroToOCLEvent, + + // Convert a pointer to a different address space. + CK_AddressSpaceConversion }; static const CastKind CK_Invalid = static_cast<CastKind>(-1); diff --git a/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h b/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h index bd2ebf5..eece851 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h @@ -53,7 +53,7 @@ public: } bool hasParent(Stmt* S) const { - return getParent(S) != 0; + return getParent(S) != nullptr; } bool isConsumedExpr(Expr *E) const; diff --git a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h index 7642699..349f4c4 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h +++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h @@ -41,7 +41,8 @@ struct PrintingPolicy { ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false), - MSWChar(LO.MicrosoftExt && !LO.WChar) { } + Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), + IncludeNewlines(true) { } /// \brief What language we're printing. LangOptions LangOpts; @@ -125,7 +126,7 @@ struct PrintingPolicy { /// \brief When printing an anonymous tag name, also print the location of /// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just - /// prints "<anonymous>" for the name. + /// prints "(anonymous)" for the name. bool AnonymousTagLocations : 1; /// \brief When true, suppress printing of the __strong lifetime qualifier in @@ -152,9 +153,16 @@ struct PrintingPolicy { /// unsigned PolishForDeclaration : 1; + /// \brief When true, print the half-precision floating-point type as 'half' + /// instead of '__fp16' + unsigned Half : 1; + /// \brief When true, print the built-in wchar_t type as __wchar_t. For use in /// Microsoft mode when wchar_t is not available. unsigned MSWChar : 1; + + /// \brief When true, include newlines after statements like "break", etc. + unsigned IncludeNewlines : 1; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h b/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h index a4fcc10..8ba85c4 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h +++ b/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h @@ -193,9 +193,7 @@ private: SourceManager &SourceMgr; std::vector<RawComment *> Comments; - void addCommentsToFront(const std::vector<RawComment *> &C) { - Comments.insert(Comments.begin(), C.begin(), C.end()); - } + void addDeserializedComments(ArrayRef<RawComment *> DeserializedComments); friend class ASTReader; }; diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h index 7268b3a..4befb45 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h +++ b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h @@ -66,6 +66,10 @@ private: // Alignment - Alignment of record in characters. CharUnits Alignment; + /// RequiredAlignment - The required alignment of the object. In the MS-ABI + /// the __declspec(align()) trumps #pramga pack and must always be obeyed. + CharUnits RequiredAlignment; + /// FieldOffsets - Array of field offsets in bits. uint64_t *FieldOffsets; @@ -78,9 +82,9 @@ private: /// the size of the object without virtual bases. CharUnits NonVirtualSize; - /// NonVirtualAlign - The non-virtual alignment (in chars) of an object, + /// NonVirtualAlignment - The non-virtual alignment (in chars) of an object, /// which is the alignment of the object without virtual bases. - CharUnits NonVirtualAlign; + CharUnits NonVirtualAlignment; /// SizeOfLargestEmptySubobject - The size of the largest empty subobject /// (either a base or a member). Will be zero if the class doesn't contain @@ -100,10 +104,15 @@ private: /// a primary base class. bool HasExtendableVFPtr : 1; - /// AlignAfterVBases - Force appropriate alignment after virtual bases are - /// laid out in MS-C++-ABI. - bool AlignAfterVBases : 1; - + /// HasZeroSizedSubObject - True if this class contains a zero sized member + /// or base or a base with a zero sized member or base. Only used for + /// MS-ABI. + bool HasZeroSizedSubObject : 1; + + /// \brief True if this class is zero sized or first base is zero sized or + /// has this property. Only used for MS-ABI. + bool LeadsWithZeroSizedBase : 1; + /// PrimaryBase - The primary base info for this record. llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; @@ -127,6 +136,7 @@ private: friend class ASTContext; ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, + CharUnits requiredAlignment, CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount); @@ -134,16 +144,18 @@ private: typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, + CharUnits requiredAlignment, bool hasOwnVFPtr, bool hasExtendableVFPtr, CharUnits vbptroffset, CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount, - CharUnits nonvirtualsize, CharUnits nonvirtualalign, + CharUnits nonvirtualsize, CharUnits nonvirtualalignment, CharUnits SizeOfLargestEmptySubobject, const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, const CXXRecordDecl *BaseSharingVBPtr, - bool ForceAlign, + bool HasZeroSizedSubObject, + bool LeadsWithZeroSizedBase, const BaseOffsetsMapTy& BaseOffsets, const VBaseOffsetsMapTy& VBaseOffsets); @@ -187,10 +199,10 @@ public: /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object, /// which is the alignment of the object without virtual bases. - CharUnits getNonVirtualAlign() const { + CharUnits getNonVirtualAlignment() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->NonVirtualAlign; + return CXXInfo->NonVirtualAlignment; } /// getPrimaryBase - Get the primary base for this record. @@ -267,9 +279,17 @@ public: return !CXXInfo->VBPtrOffset.isNegative(); } - bool getAlignAfterVBases() const { + CharUnits getRequiredAlignment() const { + return RequiredAlignment; + } + + bool hasZeroSizedSubObject() const { + return CXXInfo && CXXInfo->HasZeroSizedSubObject; + } + + bool leadsWithZeroSizedBase() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->AlignAfterVBases; + return CXXInfo->LeadsWithZeroSizedBase; } /// getVBPtrOffset - Get the offset for virtual base table pointer. diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h index d09550f..ff46ffb 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H #define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" @@ -37,34 +38,24 @@ // using them is responsible for defining macro OPERATOR(). // All unary operators. -#define UNARYOP_LIST() \ - OPERATOR(PostInc) OPERATOR(PostDec) \ - OPERATOR(PreInc) OPERATOR(PreDec) \ - OPERATOR(AddrOf) OPERATOR(Deref) \ - OPERATOR(Plus) OPERATOR(Minus) \ - OPERATOR(Not) OPERATOR(LNot) \ - OPERATOR(Real) OPERATOR(Imag) \ - OPERATOR(Extension) +#define UNARYOP_LIST() \ + OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \ + OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \ + OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \ + OPERATOR(Extension) // All binary operators (excluding compound assign operators). -#define BINOP_LIST() \ - OPERATOR(PtrMemD) OPERATOR(PtrMemI) \ - OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) \ - OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) \ - OPERATOR(Shr) \ - \ - OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) \ - OPERATOR(GE) OPERATOR(EQ) OPERATOR(NE) \ - OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \ - OPERATOR(LAnd) OPERATOR(LOr) \ - \ - OPERATOR(Assign) \ - OPERATOR(Comma) +#define BINOP_LIST() \ + OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \ + OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \ + OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \ + OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) OPERATOR(LAnd) \ + OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma) // All compound assign operators. -#define CAO_LIST() \ - OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \ - OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) +#define CAO_LIST() \ + OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \ + OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) namespace clang { @@ -72,8 +63,11 @@ namespace clang { // invokes CALL_EXPR, which must be a method call, on the derived // object (s.t. a user of RecursiveASTVisitor can override the method // in CALL_EXPR). -#define TRY_TO(CALL_EXPR) \ - do { if (!getDerived().CALL_EXPR) return false; } while (0) +#define TRY_TO(CALL_EXPR) \ + do { \ + if (!getDerived().CALL_EXPR) \ + return false; \ + } while (0) /// \brief A class that does preorder depth-first traversal on the /// entire Clang AST and visits each node. @@ -136,11 +130,10 @@ namespace clang { /// to return true, in which case all known implicit and explicit /// instantiations will be visited at the same time as the pattern /// from which they were produced. -template<typename Derived> -class RecursiveASTVisitor { +template <typename Derived> class RecursiveASTVisitor { public: /// \brief Return a reference to the derived class. - Derived &getDerived() { return *static_cast<Derived*>(this); } + Derived &getDerived() { return *static_cast<Derived *>(this); } /// \brief Return whether this visitor should recurse into /// template instantiations. @@ -182,6 +175,13 @@ public: /// otherwise (including when the argument is a Null type location). bool TraverseTypeLoc(TypeLoc TL); + /// \brief Recursively visit an attribute, by dispatching to + /// Traverse*Attr() based on the argument's dynamic type. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is a Null type location). + bool TraverseAttr(Attr *At); + /// \brief Recursively visit a declaration, by dispatching to /// Traverse*Decl() based on the argument's dynamic type. /// @@ -244,7 +244,7 @@ public: /// \brief Recursively visit a lambda capture. /// /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaExpr::Capture *C); + bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C); /// \brief Recursively visit the body of a lambda expression. /// @@ -254,107 +254,114 @@ public: /// \returns false if the visitation was terminated early, true otherwise. bool TraverseLambdaBody(LambdaExpr *LE); - // ---- Methods on Stmts ---- + // ---- Methods on Attrs ---- + + // \brief Visit an attribute. + bool VisitAttr(Attr *A) { return true; } - // Declare Traverse*() for all concrete Stmt classes. +// Declare Traverse* and empty Visit* for all Attr classes. +#define ATTR_VISITOR_DECLS_ONLY +#include "clang/AST/AttrVisitor.inc" +#undef ATTR_VISITOR_DECLS_ONLY + +// ---- Methods on Stmts ---- + +// Declare Traverse*() for all concrete Stmt classes. #define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - bool Traverse##CLASS(CLASS *S); +#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S); #include "clang/AST/StmtNodes.inc" // The above header #undefs ABSTRACT_STMT and STMT upon exit. // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } bool VisitStmt(Stmt *S) { return true; } -#define STMT(CLASS, PARENT) \ - bool WalkUpFrom##CLASS(CLASS *S) { \ - TRY_TO(WalkUpFrom##PARENT(S)); \ - TRY_TO(Visit##CLASS(S)); \ - return true; \ - } \ +#define STMT(CLASS, PARENT) \ + bool WalkUpFrom##CLASS(CLASS *S) { \ + TRY_TO(WalkUpFrom##PARENT(S)); \ + TRY_TO(Visit##CLASS(S)); \ + return true; \ + } \ bool Visit##CLASS(CLASS *S) { return true; } #include "clang/AST/StmtNodes.inc" - // Define Traverse*(), WalkUpFrom*(), and Visit*() for unary - // operator methods. Unary operators are not classes in themselves - // (they're all opcodes in UnaryOperator) but do have visitors. -#define OPERATOR(NAME) \ - bool TraverseUnary##NAME(UnaryOperator *S) { \ - TRY_TO(WalkUpFromUnary##NAME(S)); \ - TRY_TO(TraverseStmt(S->getSubExpr())); \ - return true; \ - } \ - bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ - TRY_TO(WalkUpFromUnaryOperator(S)); \ - TRY_TO(VisitUnary##NAME(S)); \ - return true; \ - } \ +// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary +// operator methods. Unary operators are not classes in themselves +// (they're all opcodes in UnaryOperator) but do have visitors. +#define OPERATOR(NAME) \ + bool TraverseUnary##NAME(UnaryOperator *S) { \ + TRY_TO(WalkUpFromUnary##NAME(S)); \ + TRY_TO(TraverseStmt(S->getSubExpr())); \ + return true; \ + } \ + bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ + TRY_TO(WalkUpFromUnaryOperator(S)); \ + TRY_TO(VisitUnary##NAME(S)); \ + return true; \ + } \ bool VisitUnary##NAME(UnaryOperator *S) { return true; } UNARYOP_LIST() #undef OPERATOR - // Define Traverse*(), WalkUpFrom*(), and Visit*() for binary - // operator methods. Binary operators are not classes in themselves - // (they're all opcodes in BinaryOperator) but do have visitors. -#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ - bool TraverseBin##NAME(BINOP_TYPE *S) { \ - TRY_TO(WalkUpFromBin##NAME(S)); \ - TRY_TO(TraverseStmt(S->getLHS())); \ - TRY_TO(TraverseStmt(S->getRHS())); \ - return true; \ - } \ - bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ - TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \ - TRY_TO(VisitBin##NAME(S)); \ - return true; \ - } \ +// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary +// operator methods. Binary operators are not classes in themselves +// (they're all opcodes in BinaryOperator) but do have visitors. +#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ + bool TraverseBin##NAME(BINOP_TYPE *S) { \ + TRY_TO(WalkUpFromBin##NAME(S)); \ + TRY_TO(TraverseStmt(S->getLHS())); \ + TRY_TO(TraverseStmt(S->getRHS())); \ + return true; \ + } \ + bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ + TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \ + TRY_TO(VisitBin##NAME(S)); \ + return true; \ + } \ bool VisitBin##NAME(BINOP_TYPE *S) { return true; } #define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator) BINOP_LIST() #undef OPERATOR - // Define Traverse*(), WalkUpFrom*(), and Visit*() for compound - // assignment methods. Compound assignment operators are not - // classes in themselves (they're all opcodes in - // CompoundAssignOperator) but do have visitors. -#define OPERATOR(NAME) \ +// Define Traverse*(), WalkUpFrom*(), and Visit*() for compound +// assignment methods. Compound assignment operators are not +// classes in themselves (they're all opcodes in +// CompoundAssignOperator) but do have visitors. +#define OPERATOR(NAME) \ GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator) CAO_LIST() #undef OPERATOR #undef GENERAL_BINOP_FALLBACK - // ---- Methods on Types ---- - // FIXME: revamp to take TypeLoc's rather than Types. +// ---- Methods on Types ---- +// FIXME: revamp to take TypeLoc's rather than Types. - // Declare Traverse*() for all concrete Type classes. +// Declare Traverse*() for all concrete Type classes. #define ABSTRACT_TYPE(CLASS, BASE) -#define TYPE(CLASS, BASE) \ - bool Traverse##CLASS##Type(CLASS##Type *T); +#define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T); #include "clang/AST/TypeNodes.def" // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. // Define WalkUpFrom*() and empty Visit*() for all Type classes. bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); } bool VisitType(Type *T) { return true; } -#define TYPE(CLASS, BASE) \ - bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ - TRY_TO(WalkUpFrom##BASE(T)); \ - TRY_TO(Visit##CLASS##Type(T)); \ - return true; \ - } \ +#define TYPE(CLASS, BASE) \ + bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ + TRY_TO(WalkUpFrom##BASE(T)); \ + TRY_TO(Visit##CLASS##Type(T)); \ + return true; \ + } \ bool Visit##CLASS##Type(CLASS##Type *T) { return true; } #include "clang/AST/TypeNodes.def" - // ---- Methods on TypeLocs ---- - // FIXME: this currently just calls the matching Type methods +// ---- Methods on TypeLocs ---- +// FIXME: this currently just calls the matching Type methods - // Declare Traverse*() for all concrete TypeLoc classes. +// Declare Traverse*() for all concrete TypeLoc classes. #define ABSTRACT_TYPELOC(CLASS, BASE) -#define TYPELOC(CLASS, BASE) \ - bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); +#define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); #include "clang/AST/TypeLocNodes.def" // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit. @@ -373,34 +380,33 @@ public: } bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; } - // Note that BASE includes trailing 'Type' which CLASS doesn't. -#define TYPE(CLASS, BASE) \ - bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ - TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ - TRY_TO(Visit##CLASS##TypeLoc(TL)); \ - return true; \ - } \ +// Note that BASE includes trailing 'Type' which CLASS doesn't. +#define TYPE(CLASS, BASE) \ + bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ + TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ + TRY_TO(Visit##CLASS##TypeLoc(TL)); \ + return true; \ + } \ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } #include "clang/AST/TypeNodes.def" - // ---- Methods on Decls ---- +// ---- Methods on Decls ---- - // Declare Traverse*() for all concrete Decl classes. +// Declare Traverse*() for all concrete Decl classes. #define ABSTRACT_DECL(DECL) -#define DECL(CLASS, BASE) \ - bool Traverse##CLASS##Decl(CLASS##Decl *D); +#define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D); #include "clang/AST/DeclNodes.inc" // The above header #undefs ABSTRACT_DECL and DECL upon exit. // Define WalkUpFrom*() and empty Visit*() for all Decl classes. bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } bool VisitDecl(Decl *D) { return true; } -#define DECL(CLASS, BASE) \ - bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ - TRY_TO(WalkUpFrom##BASE(D)); \ - TRY_TO(Visit##CLASS##Decl(D)); \ - return true; \ - } \ +#define DECL(CLASS, BASE) \ + bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ + TRY_TO(WalkUpFrom##BASE(D)); \ + TRY_TO(Visit##CLASS##Decl(D)); \ + return true; \ + } \ bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } #include "clang/AST/DeclNodes.inc" @@ -422,13 +428,12 @@ private: bool TraverseDeclContextHelper(DeclContext *DC); bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); + bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); bool TraverseOMPClause(OMPClause *C); -#define OPENMP_CLAUSE(Name, Class) \ - bool Visit##Class(Class *C); +#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C); #include "clang/Basic/OpenMPKinds.def" /// \brief Process clauses with list of variables. - template <typename T> - void VisitOMPClauseList(T *Node); + template <typename T> bool VisitOMPClauseList(T *Node); struct EnqueueJob { Stmt *S; @@ -440,7 +445,7 @@ private: bool dataTraverseNode(Stmt *S, bool &EnqueueChildren); }; -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) { SmallVector<EnqueueJob, 16> Queue; @@ -457,7 +462,8 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) { if (getDerived().shouldUseDataRecursionFor(CurrS)) { if (job.StmtIt == Stmt::child_iterator()) { bool EnqueueChildren = true; - if (!dataTraverseNode(CurrS, EnqueueChildren)) return false; + if (!dataTraverseNode(CurrS, EnqueueChildren)) + return false; if (!EnqueueChildren) { Queue.pop_back(); continue; @@ -481,53 +487,57 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) { return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, bool &EnqueueChildren) { - // 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) \ - { \ - bool (Derived::*DerivedFn)(CLASS*) = &Derived::Traverse##NAME; \ - bool (Derived::*BaseFn)(CLASS*) = &RecursiveASTVisitor::Traverse##NAME; \ - if (DerivedFn == BaseFn) \ - return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR)); \ - } \ - EnqueueChildren = false; \ - return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR)); +// 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) \ + { \ + bool (Derived::*DerivedFn)(CLASS *) = &Derived::Traverse##NAME; \ + bool (Derived::*BaseFn)(CLASS *) = &RecursiveASTVisitor::Traverse##NAME; \ + if (DerivedFn == BaseFn) \ + 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()) { -#define OPERATOR(NAME) \ - case BO_##NAME: DISPATCH_WALK(Bin##NAME, BinaryOperator, S); +#define OPERATOR(NAME) \ + case BO_##NAME: \ + DISPATCH_WALK(Bin##NAME, BinaryOperator, S); - BINOP_LIST() + BINOP_LIST() #undef OPERATOR -#define OPERATOR(NAME) \ - case BO_##NAME##Assign: \ +#define OPERATOR(NAME) \ + case BO_##NAME##Assign: \ DISPATCH_WALK(Bin##NAME##Assign, CompoundAssignOperator, S); - CAO_LIST() + CAO_LIST() #undef OPERATOR } } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { switch (UnOp->getOpcode()) { -#define OPERATOR(NAME) \ - case UO_##NAME: DISPATCH_WALK(Unary##NAME, UnaryOperator, S); +#define OPERATOR(NAME) \ + case UO_##NAME: \ + DISPATCH_WALK(Unary##NAME, UnaryOperator, S); - UNARYOP_LIST() + UNARYOP_LIST() #undef OPERATOR } } // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. switch (S->getStmtClass()) { - case Stmt::NoStmtClass: break; + case Stmt::NoStmtClass: + break; #define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - case Stmt::CLASS##Class: DISPATCH_WALK(CLASS, CLASS, S); +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS##Class: \ + DISPATCH_WALK(CLASS, CLASS, S); #include "clang/AST/StmtNodes.inc" } @@ -536,14 +546,16 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, return true; } -#define DISPATCH(NAME, CLASS, VAR) \ - return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR)) +#define DISPATCH(NAME, CLASS, VAR) \ + return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)) -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { if (!S) return true; +#define DISPATCH_STMT(NAME, CLASS, VAR) DISPATCH(NAME, CLASS, VAR) + if (getDerived().shouldUseDataRecursionFor(S)) return dataTraverse(S); @@ -552,27 +564,29 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { // below. if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { -#define OPERATOR(NAME) \ - case BO_##NAME: DISPATCH(Bin##NAME, BinaryOperator, S); +#define OPERATOR(NAME) \ + case BO_##NAME: \ + DISPATCH_STMT(Bin##NAME, BinaryOperator, S); - BINOP_LIST() + BINOP_LIST() #undef OPERATOR #undef BINOP_LIST -#define OPERATOR(NAME) \ - case BO_##NAME##Assign: \ - DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S); +#define OPERATOR(NAME) \ + case BO_##NAME##Assign: \ + DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); - CAO_LIST() + CAO_LIST() #undef OPERATOR #undef CAO_LIST } } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { switch (UnOp->getOpcode()) { -#define OPERATOR(NAME) \ - case UO_##NAME: DISPATCH(Unary##NAME, UnaryOperator, S); +#define OPERATOR(NAME) \ + case UO_##NAME: \ + DISPATCH_STMT(Unary##NAME, UnaryOperator, S); - UNARYOP_LIST() + UNARYOP_LIST() #undef OPERATOR #undef UNARYOP_LIST } @@ -580,41 +594,45 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. switch (S->getStmtClass()) { - case Stmt::NoStmtClass: break; + case Stmt::NoStmtClass: + break; #define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - case Stmt::CLASS##Class: DISPATCH(CLASS, CLASS, S); +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS##Class: \ + DISPATCH_STMT(CLASS, CLASS, S); #include "clang/AST/StmtNodes.inc" } return true; } -template<typename Derived> +#undef DISPATCH_STMT + +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { if (T.isNull()) return true; switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, BASE) -#define TYPE(CLASS, BASE) \ - case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, \ - const_cast<Type*>(T.getTypePtr())); +#define TYPE(CLASS, BASE) \ + case Type::CLASS: \ + DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr())); #include "clang/AST/TypeNodes.def" } return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { if (TL.isNull()) return true; switch (TL.getTypeLocClass()) { #define ABSTRACT_TYPELOC(CLASS, BASE) -#define TYPELOC(CLASS, BASE) \ - case TypeLoc::CLASS: \ +#define TYPELOC(CLASS, BASE) \ + case TypeLoc::CLASS: \ return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>()); #include "clang/AST/TypeLocNodes.def" } @@ -622,8 +640,12 @@ bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { return true; } +// Define the Traverse*Attr(Attr* A) methods +#define VISITORCLASS RecursiveASTVisitor +#include "clang/AST/AttrVisitor.inc" +#undef VISITORCLASS -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { if (!D) return true; @@ -635,19 +657,27 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { switch (D->getKind()) { #define ABSTRACT_DECL(DECL) -#define DECL(CLASS, BASE) \ - case Decl::CLASS: DISPATCH(CLASS##Decl, CLASS##Decl, D); +#define DECL(CLASS, BASE) \ + case Decl::CLASS: \ + if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \ + return false; \ + break; #include "clang/AST/DeclNodes.inc" - } + } + // Visit any attributes attached to this declaration. + for (auto *I : D->attrs()) { + if (!getDerived().TraverseAttr(I)) + return false; + } return true; } #undef DISPATCH -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( - NestedNameSpecifier *NNS) { + NestedNameSpecifier *NNS) { if (!NNS) return true; @@ -669,14 +699,14 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( - NestedNameSpecifierLoc NNS) { + NestedNameSpecifierLoc NNS) { if (!NNS) return true; - if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) - TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); + if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) + TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); switch (NNS.getNestedNameSpecifier()->getKind()) { case NestedNameSpecifier::Identifier: @@ -694,9 +724,9 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( - DeclarationNameInfo NameInfo) { + DeclarationNameInfo NameInfo) { switch (NameInfo.getName().getNameKind()) { case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: @@ -719,7 +749,7 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); @@ -729,9 +759,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( - const TemplateArgument &Arg) { + const TemplateArgument &Arg) { switch (Arg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Declaration: @@ -745,7 +775,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: return getDerived().TraverseTemplateName( - Arg.getAsTemplateOrTemplatePattern()); + Arg.getAsTemplateOrTemplatePattern()); case TemplateArgument::Expression: return getDerived().TraverseStmt(Arg.getAsExpr()); @@ -760,9 +790,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( // FIXME: no template name location? // FIXME: no source locations for a template argument pack? -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( - const TemplateArgumentLoc &ArgLoc) { + const TemplateArgumentLoc &ArgLoc) { const TemplateArgument &Arg = ArgLoc.getArgument(); switch (Arg.getKind()) { @@ -784,9 +814,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( case TemplateArgument::TemplateExpansion: if (ArgLoc.getTemplateQualifierLoc()) TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( - ArgLoc.getTemplateQualifierLoc())); + ArgLoc.getTemplateQualifierLoc())); return getDerived().TraverseTemplateName( - Arg.getAsTemplateOrTemplatePattern()); + Arg.getAsTemplateOrTemplatePattern()); case TemplateArgument::Expression: return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); @@ -799,10 +829,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( - const TemplateArgument *Args, - unsigned NumArgs) { + const TemplateArgument *Args, unsigned NumArgs) { for (unsigned I = 0; I != NumArgs; ++I) { TRY_TO(TraverseTemplateArgument(Args[I])); } @@ -810,9 +839,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( - CXXCtorInitializer *Init) { + CXXCtorInitializer *Init) { if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); @@ -821,197 +850,164 @@ bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( return true; } -template<typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseLambdaCapture( - LambdaExpr *LE, const LambdaExpr::Capture *C) { +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE, + const LambdaCapture *C) { if (C->isInitCapture()) TRY_TO(TraverseDecl(C->getCapturedVar())); return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) { TRY_TO(TraverseStmt(LE->getBody())); return true; } - // ----------------- Type traversal ----------------- // This macro makes available a variable T, the passed-in type. -#define DEF_TRAVERSE_TYPE(TYPE, CODE) \ - template<typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##TYPE (TYPE *T) { \ - TRY_TO(WalkUpFrom##TYPE (T)); \ - { CODE; } \ - return true; \ +#define DEF_TRAVERSE_TYPE(TYPE, CODE) \ + template <typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \ + TRY_TO(WalkUpFrom##TYPE(T)); \ + { CODE; } \ + return true; \ } -DEF_TRAVERSE_TYPE(BuiltinType, { }) +DEF_TRAVERSE_TYPE(BuiltinType, {}) -DEF_TRAVERSE_TYPE(ComplexType, { - TRY_TO(TraverseType(T->getElementType())); - }) +DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); }) -DEF_TRAVERSE_TYPE(PointerType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) +DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) -DEF_TRAVERSE_TYPE(BlockPointerType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) +DEF_TRAVERSE_TYPE(BlockPointerType, + { TRY_TO(TraverseType(T->getPointeeType())); }) -DEF_TRAVERSE_TYPE(LValueReferenceType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) +DEF_TRAVERSE_TYPE(LValueReferenceType, + { TRY_TO(TraverseType(T->getPointeeType())); }) -DEF_TRAVERSE_TYPE(RValueReferenceType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) +DEF_TRAVERSE_TYPE(RValueReferenceType, + { TRY_TO(TraverseType(T->getPointeeType())); }) DEF_TRAVERSE_TYPE(MemberPointerType, { - TRY_TO(TraverseType(QualType(T->getClass(), 0))); - TRY_TO(TraverseType(T->getPointeeType())); - }) + TRY_TO(TraverseType(QualType(T->getClass(), 0))); + TRY_TO(TraverseType(T->getPointeeType())); +}) -DEF_TRAVERSE_TYPE(DecayedType, { - TRY_TO(TraverseType(T->getOriginalType())); - }) +DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); }) -DEF_TRAVERSE_TYPE(ConstantArrayType, { - TRY_TO(TraverseType(T->getElementType())); - }) +DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); }) -DEF_TRAVERSE_TYPE(IncompleteArrayType, { - TRY_TO(TraverseType(T->getElementType())); - }) +DEF_TRAVERSE_TYPE(ConstantArrayType, + { TRY_TO(TraverseType(T->getElementType())); }) + +DEF_TRAVERSE_TYPE(IncompleteArrayType, + { TRY_TO(TraverseType(T->getElementType())); }) DEF_TRAVERSE_TYPE(VariableArrayType, { - TRY_TO(TraverseType(T->getElementType())); - TRY_TO(TraverseStmt(T->getSizeExpr())); - }) + TRY_TO(TraverseType(T->getElementType())); + TRY_TO(TraverseStmt(T->getSizeExpr())); +}) DEF_TRAVERSE_TYPE(DependentSizedArrayType, { - TRY_TO(TraverseType(T->getElementType())); - if (T->getSizeExpr()) - TRY_TO(TraverseStmt(T->getSizeExpr())); - }) + TRY_TO(TraverseType(T->getElementType())); + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); +}) DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { - if (T->getSizeExpr()) - TRY_TO(TraverseStmt(T->getSizeExpr())); - TRY_TO(TraverseType(T->getElementType())); - }) + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); + TRY_TO(TraverseType(T->getElementType())); +}) -DEF_TRAVERSE_TYPE(VectorType, { - TRY_TO(TraverseType(T->getElementType())); - }) +DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); }) -DEF_TRAVERSE_TYPE(ExtVectorType, { - TRY_TO(TraverseType(T->getElementType())); - }) +DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); }) -DEF_TRAVERSE_TYPE(FunctionNoProtoType, { - TRY_TO(TraverseType(T->getResultType())); - }) +DEF_TRAVERSE_TYPE(FunctionNoProtoType, + { TRY_TO(TraverseType(T->getReturnType())); }) DEF_TRAVERSE_TYPE(FunctionProtoType, { - TRY_TO(TraverseType(T->getResultType())); + TRY_TO(TraverseType(T->getReturnType())); - for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), - AEnd = T->arg_type_end(); - A != AEnd; ++A) { - TRY_TO(TraverseType(*A)); - } + for (const auto &A : T->param_types()) { + TRY_TO(TraverseType(A)); + } - for (FunctionProtoType::exception_iterator E = T->exception_begin(), - EEnd = T->exception_end(); - E != EEnd; ++E) { - TRY_TO(TraverseType(*E)); - } - }) + for (const auto &E : T->exceptions()) { + TRY_TO(TraverseType(E)); + } +}) -DEF_TRAVERSE_TYPE(UnresolvedUsingType, { }) -DEF_TRAVERSE_TYPE(TypedefType, { }) +DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) +DEF_TRAVERSE_TYPE(TypedefType, {}) -DEF_TRAVERSE_TYPE(TypeOfExprType, { - TRY_TO(TraverseStmt(T->getUnderlyingExpr())); - }) +DEF_TRAVERSE_TYPE(TypeOfExprType, + { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) -DEF_TRAVERSE_TYPE(TypeOfType, { - TRY_TO(TraverseType(T->getUnderlyingType())); - }) +DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); }) -DEF_TRAVERSE_TYPE(DecltypeType, { - TRY_TO(TraverseStmt(T->getUnderlyingExpr())); - }) +DEF_TRAVERSE_TYPE(DecltypeType, + { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) DEF_TRAVERSE_TYPE(UnaryTransformType, { - TRY_TO(TraverseType(T->getBaseType())); - TRY_TO(TraverseType(T->getUnderlyingType())); - }) + TRY_TO(TraverseType(T->getBaseType())); + TRY_TO(TraverseType(T->getUnderlyingType())); +}) -DEF_TRAVERSE_TYPE(AutoType, { - TRY_TO(TraverseType(T->getDeducedType())); - }) +DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); }) -DEF_TRAVERSE_TYPE(RecordType, { }) -DEF_TRAVERSE_TYPE(EnumType, { }) -DEF_TRAVERSE_TYPE(TemplateTypeParmType, { }) -DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { }) -DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { }) +DEF_TRAVERSE_TYPE(RecordType, {}) +DEF_TRAVERSE_TYPE(EnumType, {}) +DEF_TRAVERSE_TYPE(TemplateTypeParmType, {}) +DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {}) +DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {}) DEF_TRAVERSE_TYPE(TemplateSpecializationType, { - TRY_TO(TraverseTemplateName(T->getTemplateName())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); - }) + TRY_TO(TraverseTemplateName(T->getTemplateName())); + TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); +}) -DEF_TRAVERSE_TYPE(InjectedClassNameType, { }) +DEF_TRAVERSE_TYPE(InjectedClassNameType, {}) -DEF_TRAVERSE_TYPE(AttributedType, { - TRY_TO(TraverseType(T->getModifiedType())); - }) +DEF_TRAVERSE_TYPE(AttributedType, + { TRY_TO(TraverseType(T->getModifiedType())); }) -DEF_TRAVERSE_TYPE(ParenType, { - TRY_TO(TraverseType(T->getInnerType())); - }) +DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); }) DEF_TRAVERSE_TYPE(ElaboratedType, { - if (T->getQualifier()) { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - } - TRY_TO(TraverseType(T->getNamedType())); - }) - -DEF_TRAVERSE_TYPE(DependentNameType, { + if (T->getQualifier()) { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - }) + } + TRY_TO(TraverseType(T->getNamedType())); +}) + +DEF_TRAVERSE_TYPE(DependentNameType, + { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); }) DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); - }) + TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); + TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); +}) -DEF_TRAVERSE_TYPE(PackExpansionType, { - TRY_TO(TraverseType(T->getPattern())); - }) +DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) -DEF_TRAVERSE_TYPE(ObjCInterfaceType, { }) +DEF_TRAVERSE_TYPE(ObjCInterfaceType, {}) DEF_TRAVERSE_TYPE(ObjCObjectType, { - // We have to watch out here because an ObjCInterfaceType's base - // type is itself. - if (T->getBaseType().getTypePtr() != T) - TRY_TO(TraverseType(T->getBaseType())); - }) + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (T->getBaseType().getTypePtr() != T) + TRY_TO(TraverseType(T->getBaseType())); +}) -DEF_TRAVERSE_TYPE(ObjCObjectPointerType, { - TRY_TO(TraverseType(T->getPointeeType())); - }) +DEF_TRAVERSE_TYPE(ObjCObjectPointerType, + { TRY_TO(TraverseType(T->getPointeeType())); }) -DEF_TRAVERSE_TYPE(AtomicType, { - TRY_TO(TraverseType(T->getValueType())); - }) +DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) #undef DEF_TRAVERSE_TYPE @@ -1022,19 +1018,19 @@ DEF_TRAVERSE_TYPE(AtomicType, { // in addition to WalkUpFrom* for the TypeLoc itself, such that existing // clients that override the WalkUpFrom*Type() and/or Visit*Type() methods // continue to work. -#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ - template<typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ - if (getDerived().shouldWalkTypesOfTypeLocs()) \ - TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE*>(TL.getTypePtr()))); \ - TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ - { CODE; } \ - return true; \ - } - -template<typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc( - QualifiedTypeLoc TL) { +#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ + template <typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ + if (getDerived().shouldWalkTypesOfTypeLocs()) \ + TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ + TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ + { CODE; } \ + return true; \ + } + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { // Move this over to the 'main' typeloc tree. Note that this is a // move -- we pretend that we were really looking at the unqualified // typeloc all along -- rather than a recursion, so we don't follow @@ -1053,42 +1049,40 @@ bool RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc( return TraverseTypeLoc(TL.getUnqualifiedLoc()); } -DEF_TRAVERSE_TYPELOC(BuiltinType, { }) +DEF_TRAVERSE_TYPELOC(BuiltinType, {}) // FIXME: ComplexTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(ComplexType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); - }) + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) -DEF_TRAVERSE_TYPELOC(PointerType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) +DEF_TRAVERSE_TYPELOC(PointerType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) -DEF_TRAVERSE_TYPELOC(BlockPointerType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) +DEF_TRAVERSE_TYPELOC(BlockPointerType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) -DEF_TRAVERSE_TYPELOC(LValueReferenceType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) +DEF_TRAVERSE_TYPELOC(LValueReferenceType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) -DEF_TRAVERSE_TYPELOC(RValueReferenceType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) +DEF_TRAVERSE_TYPELOC(RValueReferenceType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) // FIXME: location of base class? // We traverse this in the type case as well, but how is it not reached through // the pointee type? DEF_TRAVERSE_TYPELOC(MemberPointerType, { - TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) + TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); + TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); +}) -DEF_TRAVERSE_TYPELOC(DecayedType, { - TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); - }) +DEF_TRAVERSE_TYPELOC(AdjustedType, + { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) + +DEF_TRAVERSE_TYPELOC(DecayedType, + { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { // This isn't available for ArrayType, but is for the ArrayTypeLoc. TRY_TO(TraverseStmt(TL.getSizeExpr())); @@ -1096,158 +1090,147 @@ bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { } DEF_TRAVERSE_TYPELOC(ConstantArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); - }) + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); +}) DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); - }) + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); +}) DEF_TRAVERSE_TYPELOC(VariableArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); - }) + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); +}) DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); - }) + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); +}) // FIXME: order? why not size expr first? // FIXME: base VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { - if (TL.getTypePtr()->getSizeExpr()) - TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); - }) + if (TL.getTypePtr()->getSizeExpr()) + TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) // FIXME: VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(VectorType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); - }) + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) // FIXME: size and attributes // FIXME: base VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(ExtVectorType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); - }) + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) -DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, { - TRY_TO(TraverseTypeLoc(TL.getResultLoc())); - }) +DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, + { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); }) // FIXME: location of exception specifications (attributes?) DEF_TRAVERSE_TYPELOC(FunctionProtoType, { - TRY_TO(TraverseTypeLoc(TL.getResultLoc())); + TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); - const FunctionProtoType *T = TL.getTypePtr(); + const FunctionProtoType *T = TL.getTypePtr(); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - if (TL.getArg(I)) { - TRY_TO(TraverseDecl(TL.getArg(I))); - } else if (I < T->getNumArgs()) { - TRY_TO(TraverseType(T->getArgType(I))); - } + for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) { + if (TL.getParam(I)) { + TRY_TO(TraverseDecl(TL.getParam(I))); + } else if (I < T->getNumParams()) { + TRY_TO(TraverseType(T->getParamType(I))); } + } - for (FunctionProtoType::exception_iterator E = T->exception_begin(), - EEnd = T->exception_end(); - E != EEnd; ++E) { - TRY_TO(TraverseType(*E)); - } - }) + for (const auto &E : T->exceptions()) { + TRY_TO(TraverseType(E)); + } +}) -DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, { }) -DEF_TRAVERSE_TYPELOC(TypedefType, { }) +DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) +DEF_TRAVERSE_TYPELOC(TypedefType, {}) -DEF_TRAVERSE_TYPELOC(TypeOfExprType, { - TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); - }) +DEF_TRAVERSE_TYPELOC(TypeOfExprType, + { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) DEF_TRAVERSE_TYPELOC(TypeOfType, { - TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); - }) + TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); +}) // FIXME: location of underlying expr DEF_TRAVERSE_TYPELOC(DecltypeType, { - TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); - }) + TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); +}) DEF_TRAVERSE_TYPELOC(UnaryTransformType, { - TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); - }) + TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); +}) DEF_TRAVERSE_TYPELOC(AutoType, { - TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); - }) + TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); +}) -DEF_TRAVERSE_TYPELOC(RecordType, { }) -DEF_TRAVERSE_TYPELOC(EnumType, { }) -DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { }) -DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { }) -DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { }) +DEF_TRAVERSE_TYPELOC(RecordType, {}) +DEF_TRAVERSE_TYPELOC(EnumType, {}) +DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {}) +DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {}) +DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {}) // FIXME: use the loc for the template name? DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { - TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); - } - }) + TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); + } +}) -DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { }) +DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {}) -DEF_TRAVERSE_TYPELOC(ParenType, { - TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); - }) +DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) -DEF_TRAVERSE_TYPELOC(AttributedType, { - TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); - }) +DEF_TRAVERSE_TYPELOC(AttributedType, + { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) DEF_TRAVERSE_TYPELOC(ElaboratedType, { - if (TL.getQualifierLoc()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - } - TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); - }) + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); + } + TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); +}) DEF_TRAVERSE_TYPELOC(DependentNameType, { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - }) + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); +}) DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { - if (TL.getQualifierLoc()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - } + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); + } - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); - } - }) + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); + } +}) -DEF_TRAVERSE_TYPELOC(PackExpansionType, { - TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); - }) +DEF_TRAVERSE_TYPELOC(PackExpansionType, + { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) -DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, { }) +DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) DEF_TRAVERSE_TYPELOC(ObjCObjectType, { - // We have to watch out here because an ObjCInterfaceType's base - // type is itself. - if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) - TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); - }) + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) + TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); +}) -DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, { - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); - }) +DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, + { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) -DEF_TRAVERSE_TYPELOC(AtomicType, { - TRY_TO(TraverseTypeLoc(TL.getValueLoc())); - }) +DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) #undef DEF_TRAVERSE_TYPELOC @@ -1258,195 +1241,191 @@ DEF_TRAVERSE_TYPELOC(AtomicType, { // Therefore each Traverse* only needs to worry about children other // than those. -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { if (!DC) return true; - for (DeclContext::decl_iterator Child = DC->decls_begin(), - ChildEnd = DC->decls_end(); - Child != ChildEnd; ++Child) { + for (auto *Child : DC->decls()) { // BlockDecls and CapturedDecls are traversed through BlockExprs and // CapturedStmts respectively. - if (!isa<BlockDecl>(*Child) && !isa<CapturedDecl>(*Child)) - TRY_TO(TraverseDecl(*Child)); + if (!isa<BlockDecl>(Child) && !isa<CapturedDecl>(Child)) + TRY_TO(TraverseDecl(Child)); } return true; } // This macro makes available a variable D, the passed-in decl. -#define DEF_TRAVERSE_DECL(DECL, CODE) \ -template<typename Derived> \ -bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \ - TRY_TO(WalkUpFrom##DECL (D)); \ - { CODE; } \ - TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ - return true; \ -} +#define DEF_TRAVERSE_DECL(DECL, CODE) \ + template <typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \ + TRY_TO(WalkUpFrom##DECL(D)); \ + { CODE; } \ + TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ + return true; \ + } -DEF_TRAVERSE_DECL(AccessSpecDecl, { }) +DEF_TRAVERSE_DECL(AccessSpecDecl, {}) DEF_TRAVERSE_DECL(BlockDecl, { - 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) - // is skipped - don't remove it. - return true; - }) + if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); + TRY_TO(TraverseStmt(D->getBody())); + for (const auto &I : D->captures()) { + if (I.hasCopyExpr()) { + TRY_TO(TraverseStmt(I.getCopyExpr())); + } + } + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; +}) DEF_TRAVERSE_DECL(CapturedDecl, { - TRY_TO(TraverseStmt(D->getBody())); - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; - }) + TRY_TO(TraverseStmt(D->getBody())); + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; +}) -DEF_TRAVERSE_DECL(EmptyDecl, { }) +DEF_TRAVERSE_DECL(EmptyDecl, {}) -DEF_TRAVERSE_DECL(FileScopeAsmDecl, { - TRY_TO(TraverseStmt(D->getAsmString())); - }) +DEF_TRAVERSE_DECL(FileScopeAsmDecl, + { TRY_TO(TraverseStmt(D->getAsmString())); }) -DEF_TRAVERSE_DECL(ImportDecl, { }) +DEF_TRAVERSE_DECL(ImportDecl, {}) DEF_TRAVERSE_DECL(FriendDecl, { - // Friend is either decl or a type. - if (D->getFriendType()) - TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); - else - TRY_TO(TraverseDecl(D->getFriendDecl())); - }) + // Friend is either decl or a type. + if (D->getFriendType()) + TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); + else + TRY_TO(TraverseDecl(D->getFriendDecl())); +}) DEF_TRAVERSE_DECL(FriendTemplateDecl, { - if (D->getFriendType()) - TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); - else - TRY_TO(TraverseDecl(D->getFriendDecl())); - for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { - TemplateParameterList *TPL = D->getTemplateParameterList(I); - for (TemplateParameterList::iterator ITPL = TPL->begin(), - ETPL = TPL->end(); - ITPL != ETPL; ++ITPL) { - TRY_TO(TraverseDecl(*ITPL)); - } + if (D->getFriendType()) + TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); + else + TRY_TO(TraverseDecl(D->getFriendDecl())); + for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { + TemplateParameterList *TPL = D->getTemplateParameterList(I); + for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = TPL->end(); + ITPL != ETPL; ++ITPL) { + TRY_TO(TraverseDecl(*ITPL)); } - }) + } +}) 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())); - } - }) + if (D->hasExplicitTemplateArgs()) { + const TemplateArgumentListInfo &args = D->templateArgs(); + TRY_TO(TraverseTemplateArgumentLocsHelper(args.getArgumentArray(), + args.size())); + } +}) -DEF_TRAVERSE_DECL(LinkageSpecDecl, { }) +DEF_TRAVERSE_DECL(LinkageSpecDecl, {}) -DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, { - // FIXME: implement this - }) +DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this + }) DEF_TRAVERSE_DECL(StaticAssertDecl, { - TRY_TO(TraverseStmt(D->getAssertExpr())); - TRY_TO(TraverseStmt(D->getMessage())); - }) + TRY_TO(TraverseStmt(D->getAssertExpr())); + TRY_TO(TraverseStmt(D->getMessage())); +}) -DEF_TRAVERSE_DECL(TranslationUnitDecl, { - // Code in an unnamed namespace shows up automatically in - // decls_begin()/decls_end(). Thus we don't need to recurse on - // D->getAnonymousNamespace(). - }) +DEF_TRAVERSE_DECL( + TranslationUnitDecl, + {// Code in an unnamed namespace shows up automatically in + // decls_begin()/decls_end(). Thus we don't need to recurse on + // D->getAnonymousNamespace(). + }) DEF_TRAVERSE_DECL(NamespaceAliasDecl, { - // We shouldn't traverse an aliased namespace, since it will be - // defined (and, therefore, traversed) somewhere else. - // - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; - }) - -DEF_TRAVERSE_DECL(LabelDecl, { - // There is no code in a LabelDecl. + // We shouldn't traverse an aliased namespace, since it will be + // defined (and, therefore, traversed) somewhere else. + // + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; }) +DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl. + }) -DEF_TRAVERSE_DECL(NamespaceDecl, { - // Code in an unnamed namespace shows up automatically in - // decls_begin()/decls_end(). Thus we don't need to recurse on - // D->getAnonymousNamespace(). - }) +DEF_TRAVERSE_DECL( + NamespaceDecl, + {// Code in an unnamed namespace shows up automatically in + // decls_begin()/decls_end(). Thus we don't need to recurse on + // D->getAnonymousNamespace(). + }) -DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, { - // FIXME: implement - }) +DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement + }) -DEF_TRAVERSE_DECL(ObjCCategoryDecl, { - // FIXME: implement - }) +DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement + }) -DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, { - // FIXME: implement - }) +DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement + }) -DEF_TRAVERSE_DECL(ObjCImplementationDecl, { - // FIXME: implement - }) +DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement + }) -DEF_TRAVERSE_DECL(ObjCInterfaceDecl, { - // FIXME: implement - }) +DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement + }) -DEF_TRAVERSE_DECL(ObjCProtocolDecl, { - // FIXME: implement - }) +DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement + }) DEF_TRAVERSE_DECL(ObjCMethodDecl, { - if (D->getResultTypeSourceInfo()) { - TRY_TO(TraverseTypeLoc(D->getResultTypeSourceInfo()->getTypeLoc())); - } - for (ObjCMethodDecl::param_iterator - I = D->param_begin(), E = D->param_end(); I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - if (D->isThisDeclarationADefinition()) { - TRY_TO(TraverseStmt(D->getBody())); - } - return true; - }) + if (D->getReturnTypeSourceInfo()) { + TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc())); + } + for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + if (D->isThisDeclarationADefinition()) { + TRY_TO(TraverseStmt(D->getBody())); + } + return true; +}) DEF_TRAVERSE_DECL(ObjCPropertyDecl, { - // FIXME: implement - }) + if (D->getTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + else + TRY_TO(TraverseType(D->getType())); + return true; +}) DEF_TRAVERSE_DECL(UsingDecl, { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); - }) + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); +}) DEF_TRAVERSE_DECL(UsingDirectiveDecl, { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - }) + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); +}) -DEF_TRAVERSE_DECL(UsingShadowDecl, { }) +DEF_TRAVERSE_DECL(UsingShadowDecl, {}) DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { - for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), - E = D->varlist_end(); - I != E; ++I) { - TRY_TO(TraverseStmt(*I)); - } - }) + for (auto *I : D->varlists()) { + TRY_TO(TraverseStmt(I)); + } +}) // A helper method for TemplateDecl's children. -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( TemplateParameterList *TPL) { if (TPL) { @@ -1458,65 +1437,84 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( return true; } -#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ -/* A helper method for traversing the implicit instantiations of a - class or variable template. */ \ -template<typename Derived> \ -bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( \ - TMPLDECLKIND##TemplateDecl *D) { \ - TMPLDECLKIND##TemplateDecl::spec_iterator end = D->spec_end(); \ - for (TMPLDECLKIND##TemplateDecl::spec_iterator it = D->spec_begin(); \ - it != end; ++it) { \ - TMPLDECLKIND##TemplateSpecializationDecl* SD = *it; \ - \ - switch (SD->getSpecializationKind()) { \ - /* Visit the implicit instantiations with the requested pattern. */ \ - 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 - node for it elsewhere. */ \ - case TSK_ExplicitInstantiationDeclaration: \ - case TSK_ExplicitInstantiationDefinition: \ - case TSK_ExplicitSpecialization: \ - break; \ - } \ - } \ - \ - return true; \ +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( + ClassTemplateDecl *D) { + for (auto *SD : D->specializations()) { + for (auto *RD : SD->redecls()) { + // We don't want to visit injected-class-names in this traversal. + if (cast<CXXRecordDecl>(RD)->isInjectedClassName()) + continue; + + switch ( + cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) { + // Visit the implicit instantiations with the requested pattern. + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + TRY_TO(TraverseDecl(RD)); + break; + + // We don't need to do anything on an explicit instantiation + // or explicit specialization because there will be an explicit + // node for it elsewhere. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + break; + } + } + } + + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( + VarTemplateDecl *D) { + for (auto *SD : D->specializations()) { + for (auto *RD : SD->redecls()) { + switch ( + cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + TRY_TO(TraverseDecl(RD)); + break; + + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + break; + } + } + } + + return true; } - -DEF_TRAVERSE_TMPL_INST(Class) -DEF_TRAVERSE_TMPL_INST(Var) // A helper method for traversing the instantiations of a // function while skipping its specializations. -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( 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; - - // 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_ExplicitSpecialization: - break; + for (auto *FD : D->specializations()) { + for (auto *RD : FD->redecls()) { + switch (RD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + // We don't know what kind of FunctionDecl this is. + TRY_TO(TraverseDecl(RD)); + break; + + // 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(RD)); + break; + + case TSK_ExplicitSpecialization: + break; + } } } @@ -1525,24 +1523,24 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( // This macro unifies the traversal of class, variable and function // template declarations. -#define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ -DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ - TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ - \ - /* 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. - - 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(TraverseTemplateInstantiations(D)); \ - \ - /* Note that getInstantiatedFromMemberTemplate() is just a link - from a template instantiation back to the template from which - it was instantiated, and thus should not be traversed. */ \ +#define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ + DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ + TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ + \ + /* 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. \ + \ + 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(TraverseTemplateInstantiations(D)); \ + \ + /* Note that getInstantiatedFromMemberTemplate() is just a link \ + from a template instantiation back to the template from which \ + it was instantiated, and thus should not be traversed. */ \ }) DEF_TRAVERSE_TMPL_DECL(Class) @@ -1550,65 +1548,63 @@ DEF_TRAVERSE_TMPL_DECL(Var) DEF_TRAVERSE_TMPL_DECL(Function) 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() && !D->defaultArgumentWasInherited()) { - TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); - } - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - }) + // D is the "T" in something like + // template <template <typename> class T> class container { }; + TRY_TO(TraverseDecl(D->getTemplatedDecl())); + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { + TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); + } + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); +}) 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() && !D->defaultArgumentWasInherited()) - TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); - }) + // 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() && !D->defaultArgumentWasInherited()) + TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); +}) DEF_TRAVERSE_DECL(TypedefDecl, { - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the typedef, not something that was written in the - // source. - }) + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the typedef, not something that was written in the + // source. +}) DEF_TRAVERSE_DECL(TypeAliasDecl, { - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the type alias, not something that was written in the - // source. - }) + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type alias, not something that was written in the + // source. +}) DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, { - TRY_TO(TraverseDecl(D->getTemplatedDecl())); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - }) + TRY_TO(TraverseDecl(D->getTemplatedDecl())); + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); +}) DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { - // A dependent using declaration which was marked with 'typename'. - // template<class T> class A : public B<T> { using typename B<T>::foo; }; - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the type, not something that was written in the - // source. - }) + // A dependent using declaration which was marked with 'typename'. + // template<class T> class A : public B<T> { using typename B<T>::foo; }; + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type, not something that was written in the + // source. +}) DEF_TRAVERSE_DECL(EnumDecl, { - if (D->getTypeForDecl()) - TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - // The enumerators are already traversed by - // decls_begin()/decls_end(). - }) + if (D->getTypeForDecl()) + TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + // The enumerators are already traversed by + // decls_begin()/decls_end(). +}) // Helper methods for RecordDecl and its children. -template<typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseRecordHelper( - RecordDecl *D) { +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) { // We shouldn't traverse D->getTypeForDecl(); it's a result of // declaring the type, not something that was written in the source. @@ -1616,16 +1612,13 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper( return true; } -template<typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper( - CXXRecordDecl *D) { +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) { if (!TraverseRecordHelper(D)) return false; if (D->isCompleteDefinition()) { - for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), - E = D->bases_end(); - I != E; ++I) { - TRY_TO(TraverseTypeLoc(I->getTypeSourceInfo()->getTypeLoc())); + for (const auto &I : D->bases()) { + TRY_TO(TraverseTypeLoc(I.getTypeSourceInfo()->getTypeLoc())); } // We don't traverse the friends or the conversions, as they are // already in decls_begin()/decls_end(). @@ -1633,34 +1626,30 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper( return true; } -DEF_TRAVERSE_DECL(RecordDecl, { - TRY_TO(TraverseRecordHelper(D)); - }) - -DEF_TRAVERSE_DECL(CXXRecordDecl, { - TRY_TO(TraverseCXXRecordHelper(D)); - }) - -#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \ -DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ - /* For implicit instantiations ("set<int> x;"), we don't want to - recurse at all, since the instatiated template isn't written in - the source code anywhere. (Note the instatiated *type* -- - set<int> -- is written, and will still get a callback of - TemplateSpecializationType). For explicit instantiations - ("template set<int>;"), we do need a callback, since this - is the only callback that's made for this instantiation. - We use getTypeAsWritten() to distinguish. */ \ - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ - TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ - \ - if (!getDerived().shouldVisitTemplateInstantiations() && \ - D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ - /* Returning from here skips traversing the - declaration context of the *TemplateSpecializationDecl - (embedded in the DEF_TRAVERSE_DECL() macro) - which contains the instantiated members of the template. */ \ - return true; \ +DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) + +DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) + +#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \ + DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ + /* For implicit instantiations ("set<int> x;"), we don't want to \ + recurse at all, since the instatiated template isn't written in \ + the source code anywhere. (Note the instatiated *type* -- \ + set<int> -- is written, and will still get a callback of \ + TemplateSpecializationType). For explicit instantiations \ + ("template set<int>;"), we do need a callback, since this \ + is the only callback that's made for this instantiation. \ + We use getTypeAsWritten() to distinguish. */ \ + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ + \ + if (!getDerived().shouldVisitTemplateInstantiations() && \ + D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ + /* Returning from here skips traversing the \ + declaration context of the *TemplateSpecializationDecl \ + (embedded in the DEF_TRAVERSE_DECL() macro) \ + which contains the instantiated members of the template. */ \ + return true; \ }) DEF_TRAVERSE_TMPL_SPEC_DECL(Class) @@ -1675,45 +1664,43 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( return true; } -#define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ -DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ - /* The partial specialization. */ \ - if (TemplateParameterList *TPL = D->getTemplateParameters()) { \ - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \ - I != E; ++I) { \ - TRY_TO(TraverseDecl(*I)); \ - } \ - } \ - /* The args that remains unspecialized. */ \ - TRY_TO(TraverseTemplateArgumentLocsHelper( \ - D->getTemplateArgsAsWritten()->getTemplateArgs(), \ - D->getTemplateArgsAsWritten()->NumTemplateArgs)); \ - \ - /* Don't need the *TemplatePartialSpecializationHelper, even - though that's our parent class -- we already visit all the - template args here. */ \ - TRY_TO(Traverse##DECLKIND##Helper(D)); \ - \ - /* Instantiations will have been visited with the primary template. */ \ +#define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ + DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ + /* The partial specialization. */ \ + if (TemplateParameterList *TPL = D->getTemplateParameters()) { \ + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \ + I != E; ++I) { \ + TRY_TO(TraverseDecl(*I)); \ + } \ + } \ + /* The args that remains unspecialized. */ \ + TRY_TO(TraverseTemplateArgumentLocsHelper( \ + D->getTemplateArgsAsWritten()->getTemplateArgs(), \ + D->getTemplateArgsAsWritten()->NumTemplateArgs)); \ + \ + /* Don't need the *TemplatePartialSpecializationHelper, even \ + though that's our parent class -- we already visit all the \ + template args here. */ \ + TRY_TO(Traverse##DECLKIND##Helper(D)); \ + \ + /* Instantiations will have been visited with the primary template. */ \ }) DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord) DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var) -DEF_TRAVERSE_DECL(EnumConstantDecl, { - TRY_TO(TraverseStmt(D->getInitExpr())); - }) +DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); }) DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { - // Like UnresolvedUsingTypenameDecl, but without the 'typename': - // template <class T> Class A : public Base<T> { using Base<T>::foo; }; - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); - }) + // Like UnresolvedUsingTypenameDecl, but without the 'typename': + // template <class T> Class A : public Base<T> { using Base<T>::foo; }; + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); +}) DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); if (D->getTypeSourceInfo()) @@ -1723,33 +1710,31 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { return true; } -DEF_TRAVERSE_DECL(MSPropertyDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - }) +DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) DEF_TRAVERSE_DECL(FieldDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->isBitField()) - TRY_TO(TraverseStmt(D->getBitWidth())); - else if (D->hasInClassInitializer()) - TRY_TO(TraverseStmt(D->getInClassInitializer())); - }) + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->isBitField()) + TRY_TO(TraverseStmt(D->getBitWidth())); + else if (D->hasInClassInitializer()) + TRY_TO(TraverseStmt(D->getInClassInitializer())); +}) DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->isBitField()) - TRY_TO(TraverseStmt(D->getBitWidth())); - // FIXME: implement the rest. - }) + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->isBitField()) + TRY_TO(TraverseStmt(D->getBitWidth())); + // FIXME: implement the rest. +}) DEF_TRAVERSE_DECL(ObjCIvarDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->isBitField()) - TRY_TO(TraverseStmt(D->getBitWidth())); - // FIXME: implement the rest. - }) + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->isBitField()) + TRY_TO(TraverseStmt(D->getBitWidth())); + // FIXME: implement the rest. +}) -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); @@ -1760,13 +1745,13 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { // the function args, but both are handled by the FunctionTypeLoc // above, so we have to choose one side. I've decided to do before. if (const FunctionTemplateSpecializationInfo *FTSI = - D->getTemplateSpecializationInfo()) { + D->getTemplateSpecializationInfo()) { if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared && FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { // A specialization might not have explicit template arguments if it has // a templated return type and concrete arguments. if (const ASTTemplateArgumentListInfo *TALI = - FTSI->TemplateArgumentsAsWritten) { + FTSI->TemplateArgumentsAsWritten) { TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), TALI->NumTemplateArgs)); } @@ -1785,58 +1770,57 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { // declarations do not have valid TypeSourceInfo, so to visit them // we need to traverse the declarations explicitly. for (FunctionDecl::param_const_iterator I = D->param_begin(), - E = D->param_end(); I != E; ++I) + E = D->param_end(); + I != E; ++I) TRY_TO(TraverseDecl(*I)); } if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { // Constructor initializers. - for (CXXConstructorDecl::init_iterator I = Ctor->init_begin(), - E = Ctor->init_end(); - I != E; ++I) { - TRY_TO(TraverseConstructorInitializer(*I)); + for (auto *I : Ctor->inits()) { + TRY_TO(TraverseConstructorInitializer(I)); } } if (D->isThisDeclarationADefinition()) { - TRY_TO(TraverseStmt(D->getBody())); // Function body. + TRY_TO(TraverseStmt(D->getBody())); // Function body. } return true; } DEF_TRAVERSE_DECL(FunctionDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); - }) + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) DEF_TRAVERSE_DECL(CXXMethodDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); - }) + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) DEF_TRAVERSE_DECL(CXXConstructorDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); - }) + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) // CXXConversionDecl is the declaration of a type conversion operator. // It's not a cast expression. DEF_TRAVERSE_DECL(CXXConversionDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); - }) + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) DEF_TRAVERSE_DECL(CXXDestructorDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); - }) + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); +}) -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { TRY_TO(TraverseDeclaratorHelper(D)); // Default params are taken care of when we traverse the ParmVarDecl. @@ -1846,34 +1830,28 @@ bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { return true; } -DEF_TRAVERSE_DECL(VarDecl, { - TRY_TO(TraverseVarHelper(D)); - }) +DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); }) -DEF_TRAVERSE_DECL(ImplicitParamDecl, { - TRY_TO(TraverseVarHelper(D)); - }) +DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); }) DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { - // A non-type template parameter, e.g. "S" in template<int S> class Foo ... - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - TRY_TO(TraverseStmt(D->getDefaultArgument())); - }) + // A non-type template parameter, e.g. "S" in template<int S> class Foo ... + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) + TRY_TO(TraverseStmt(D->getDefaultArgument())); +}) DEF_TRAVERSE_DECL(ParmVarDecl, { - TRY_TO(TraverseVarHelper(D)); + TRY_TO(TraverseVarHelper(D)); - if (D->hasDefaultArg() && - D->hasUninstantiatedDefaultArg() && - !D->hasUnparsedDefaultArg()) - TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg())); + if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() && + !D->hasUnparsedDefaultArg()) + TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg())); - if (D->hasDefaultArg() && - !D->hasUninstantiatedDefaultArg() && - !D->hasUnparsedDefaultArg()) - TRY_TO(TraverseStmt(D->getDefaultArg())); - }) + if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() && + !D->hasUnparsedDefaultArg()) + TRY_TO(TraverseStmt(D->getDefaultArg())); +}) #undef DEF_TRAVERSE_DECL @@ -1887,78 +1865,77 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { // http://clang.llvm.org/doxygen/Stmt_8cpp_source.html // This macro makes available a variable S, the passed-in stmt. -#define DEF_TRAVERSE_STMT(STMT, CODE) \ -template<typename Derived> \ -bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \ - TRY_TO(WalkUpFrom##STMT(S)); \ - { CODE; } \ - for (Stmt::child_range range = S->children(); range; ++range) { \ - TRY_TO(TraverseStmt(*range)); \ - } \ - return true; \ -} +#define DEF_TRAVERSE_STMT(STMT, CODE) \ + template <typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \ + TRY_TO(WalkUpFrom##STMT(S)); \ + { CODE; } \ + for (Stmt::child_range range = S->children(); range; ++range) { \ + TRY_TO(TraverseStmt(*range)); \ + } \ + return true; \ + } DEF_TRAVERSE_STMT(GCCAsmStmt, { - TRY_TO(TraverseStmt(S->getAsmString())); - for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { - TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I))); - } - for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { - TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I))); - } - for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { - TRY_TO(TraverseStmt(S->getClobberStringLiteral(I))); - } - // children() iterates over inputExpr and outputExpr. - }) + TRY_TO(TraverseStmt(S->getAsmString())); + for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { + TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I))); + } + for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { + TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I))); + } + for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { + TRY_TO(TraverseStmt(S->getClobberStringLiteral(I))); + } + // 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( + 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. - }) + TRY_TO(TraverseDecl(S->getExceptionDecl())); + // children() iterates over the handler block. +}) DEF_TRAVERSE_STMT(DeclStmt, { - for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - // Suppress the default iteration over children() by - // returning. Here's why: A DeclStmt looks like 'type var [= - // initializer]'. The decls above already traverse over the - // initializers, so we don't have to do it again (which - // children() would do). - return true; - }) - + for (auto *I : S->decls()) { + TRY_TO(TraverseDecl(I)); + } + // Suppress the default iteration over children() by + // returning. Here's why: A DeclStmt looks like 'type var [= + // initializer]'. The decls above already traverse over the + // initializers, so we don't have to do it again (which + // children() would do). + return true; +}) // These non-expr stmts (most of them), do not need any action except // iterating over the children. -DEF_TRAVERSE_STMT(BreakStmt, { }) -DEF_TRAVERSE_STMT(CXXTryStmt, { }) -DEF_TRAVERSE_STMT(CaseStmt, { }) -DEF_TRAVERSE_STMT(CompoundStmt, { }) -DEF_TRAVERSE_STMT(ContinueStmt, { }) -DEF_TRAVERSE_STMT(DefaultStmt, { }) -DEF_TRAVERSE_STMT(DoStmt, { }) -DEF_TRAVERSE_STMT(ForStmt, { }) -DEF_TRAVERSE_STMT(GotoStmt, { }) -DEF_TRAVERSE_STMT(IfStmt, { }) -DEF_TRAVERSE_STMT(IndirectGotoStmt, { }) -DEF_TRAVERSE_STMT(LabelStmt, { }) -DEF_TRAVERSE_STMT(AttributedStmt, { }) -DEF_TRAVERSE_STMT(NullStmt, { }) -DEF_TRAVERSE_STMT(ObjCAtCatchStmt, { }) -DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, { }) -DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, { }) -DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) -DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) -DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) -DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, { }) +DEF_TRAVERSE_STMT(BreakStmt, {}) +DEF_TRAVERSE_STMT(CXXTryStmt, {}) +DEF_TRAVERSE_STMT(CaseStmt, {}) +DEF_TRAVERSE_STMT(CompoundStmt, {}) +DEF_TRAVERSE_STMT(ContinueStmt, {}) +DEF_TRAVERSE_STMT(DefaultStmt, {}) +DEF_TRAVERSE_STMT(DoStmt, {}) +DEF_TRAVERSE_STMT(ForStmt, {}) +DEF_TRAVERSE_STMT(GotoStmt, {}) +DEF_TRAVERSE_STMT(IfStmt, {}) +DEF_TRAVERSE_STMT(IndirectGotoStmt, {}) +DEF_TRAVERSE_STMT(LabelStmt, {}) +DEF_TRAVERSE_STMT(AttributedStmt, {}) +DEF_TRAVERSE_STMT(NullStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtCatchStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtThrowStmt, {}) +DEF_TRAVERSE_STMT(ObjCAtTryStmt, {}) +DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {}) +DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {}) DEF_TRAVERSE_STMT(CXXForRangeStmt, { if (!getDerived().shouldVisitImplicitCode()) { TRY_TO(TraverseStmt(S->getLoopVarStmt())); @@ -1969,82 +1946,82 @@ DEF_TRAVERSE_STMT(CXXForRangeStmt, { } }) DEF_TRAVERSE_STMT(MSDependentExistsStmt, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); }) -DEF_TRAVERSE_STMT(ReturnStmt, { }) -DEF_TRAVERSE_STMT(SwitchStmt, { }) -DEF_TRAVERSE_STMT(WhileStmt, { }) - +DEF_TRAVERSE_STMT(ReturnStmt, {}) +DEF_TRAVERSE_STMT(SwitchStmt, {}) +DEF_TRAVERSE_STMT(WhileStmt, {}) DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper( - S->getTemplateArgs(), S->getNumTemplateArgs())); - } - }) + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); + } +}) DEF_TRAVERSE_STMT(DeclRefExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); - TRY_TO(TraverseTemplateArgumentLocsHelper( - S->getTemplateArgs(), S->getNumTemplateArgs())); - }) + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); +}) DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper( - S->getExplicitTemplateArgs().getTemplateArgs(), - S->getNumTemplateArgs())); - } - }) + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper( + S->getExplicitTemplateArgs().getTemplateArgs(), + S->getNumTemplateArgs())); + } +}) DEF_TRAVERSE_STMT(MemberExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); - TRY_TO(TraverseTemplateArgumentLocsHelper( - S->getTemplateArgs(), S->getNumTemplateArgs())); - }) + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); +}) -DEF_TRAVERSE_STMT(ImplicitCastExpr, { - // We don't traverse the cast type, as it's not written in the - // source code. - }) +DEF_TRAVERSE_STMT( + ImplicitCastExpr, + {// We don't traverse the cast type, as it's not written in the + // source code. + }) DEF_TRAVERSE_STMT(CStyleCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); - }) + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); - }) + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXConstCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); - }) + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXDynamicCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); - }) + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); - }) + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXStaticCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); - }) + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) // InitListExpr is a tricky one, because we want to do all our work on // the syntactic form of the listexpr, but this method takes the // semantic form by default. We can't use the macro helper because it // calls WalkUp*() on the semantic form, before our code can convert // to the syntactic form. -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { if (InitListExpr *Syn = S->getSyntacticForm()) S = Syn; @@ -2059,9 +2036,9 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { // GenericSelectionExpr is a special case because the types and expressions // are interleaved. We also need to watch out for null types (default // generic associations). -template<typename Derived> -bool RecursiveASTVisitor<Derived>:: -TraverseGenericSelectionExpr(GenericSelectionExpr *S) { +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr( + GenericSelectionExpr *S) { TRY_TO(WalkUpFromGenericSelectionExpr(S)); TRY_TO(TraverseStmt(S->getControllingExpr())); for (unsigned i = 0; i != S->getNumAssocs(); ++i) { @@ -2074,13 +2051,14 @@ TraverseGenericSelectionExpr(GenericSelectionExpr *S) { // PseudoObjectExpr is a special case because of the wierdness with // syntactic expressions and opaque values. -template<typename Derived> -bool RecursiveASTVisitor<Derived>:: -TraversePseudoObjectExpr(PseudoObjectExpr *S) { +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) { TRY_TO(WalkUpFromPseudoObjectExpr(S)); TRY_TO(TraverseStmt(S->getSyntacticForm())); - for (PseudoObjectExpr::semantics_iterator - i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) { + for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(), + e = S->semantics_end(); + i != e; ++i) { Expr *sub = *i; if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub)) sub = OVE->getSourceExpr(); @@ -2090,57 +2068,48 @@ TraversePseudoObjectExpr(PseudoObjectExpr *S) { } DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { - // This is called for code like 'return T()' where T is a built-in - // (i.e. non-class) type. - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); - }) + // This is called for code like 'return T()' where T is a built-in + // (i.e. non-class) type. + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXNewExpr, { // The child-iterator will pick up the other arguments. TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc())); - }) +}) DEF_TRAVERSE_STMT(OffsetOfExpr, { - // The child-iterator will pick up the expression representing - // the field. - // FIMXE: for code like offsetof(Foo, a.b.c), should we get - // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c? - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); - }) + // The child-iterator will pick up the expression representing + // the field. + // FIMXE: for code like offsetof(Foo, a.b.c), should we get + // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c? + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, { - // The child-iterator will pick up the arg if it's an expression, - // but not if it's a type. - if (S->isArgumentType()) - TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc())); - }) + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isArgumentType()) + TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXTypeidExpr, { - // The child-iterator will pick up the arg if it's an expression, - // but not if it's a type. - if (S->isTypeOperand()) - TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); - }) + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isTypeOperand()) + TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(MSPropertyRefExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); }) DEF_TRAVERSE_STMT(CXXUuidofExpr, { - // The child-iterator will pick up the arg if it's an expression, - // but not if it's a type. - if (S->isTypeOperand()) - TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); - }) - -DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { - TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); - }) - -DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, { - TRY_TO(TraverseTypeLoc(S->getLhsTypeSourceInfo()->getTypeLoc())); - TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc())); - }) + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isTypeOperand()) + TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(TypeTraitExpr, { for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) @@ -2148,30 +2117,29 @@ DEF_TRAVERSE_STMT(TypeTraitExpr, { }) DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { - TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); - }) + TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); +}) -DEF_TRAVERSE_STMT(ExpressionTraitExpr, { - TRY_TO(TraverseStmt(S->getQueriedExpression())); - }) +DEF_TRAVERSE_STMT(ExpressionTraitExpr, + { TRY_TO(TraverseStmt(S->getQueriedExpression())); }) DEF_TRAVERSE_STMT(VAArgExpr, { - // The child-iterator will pick up the expression argument. - TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); - }) + // The child-iterator will pick up the expression argument. + TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { - // This is called for code like 'return T()' where T is a class type. - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); - }) + // This is called for code like 'return T()' where T is a class type. + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) -// Walk only the visible parts of lambda expressions. -template<typename Derived> +// Walk only the visible parts of lambda expressions. +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { TRY_TO(WalkUpFromLambdaExpr(S)); for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), - CEnd = S->explicit_capture_end(); + CEnd = S->explicit_capture_end(); C != CEnd; ++C) { TRY_TO(TraverseLambdaCapture(S, C)); } @@ -2184,12 +2152,12 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) { if (S->hasExplicitParameters()) { // Visit parameters. - for (unsigned I = 0, N = Proto.getNumArgs(); I != N; ++I) { - TRY_TO(TraverseDecl(Proto.getArg(I))); + for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { + TRY_TO(TraverseDecl(Proto.getParam(I))); } } else { - TRY_TO(TraverseTypeLoc(Proto.getResultLoc())); - } + TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + } } } @@ -2198,36 +2166,36 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { } DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { - // This is called for code like 'T()', where T is a template argument. - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); - }) + // This is called for code like 'T()', where T is a template argument. + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) // These expressions all might take explicit template arguments. // We traverse those if so. FIXME: implement these. -DEF_TRAVERSE_STMT(CXXConstructExpr, { }) -DEF_TRAVERSE_STMT(CallExpr, { }) -DEF_TRAVERSE_STMT(CXXMemberCallExpr, { }) +DEF_TRAVERSE_STMT(CXXConstructExpr, {}) +DEF_TRAVERSE_STMT(CallExpr, {}) +DEF_TRAVERSE_STMT(CXXMemberCallExpr, {}) // These exprs (most of them), do not need any action except iterating // over the children. -DEF_TRAVERSE_STMT(AddrLabelExpr, { }) -DEF_TRAVERSE_STMT(ArraySubscriptExpr, { }) +DEF_TRAVERSE_STMT(AddrLabelExpr, {}) +DEF_TRAVERSE_STMT(ArraySubscriptExpr, {}) DEF_TRAVERSE_STMT(BlockExpr, { TRY_TO(TraverseDecl(S->getBlockDecl())); return true; // no child statements to loop through. }) -DEF_TRAVERSE_STMT(ChooseExpr, { }) +DEF_TRAVERSE_STMT(ChooseExpr, {}) DEF_TRAVERSE_STMT(CompoundLiteralExpr, { TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); }) -DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) -DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { }) -DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { }) -DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { }) -DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) -DEF_TRAVERSE_STMT(ExprWithCleanups, { }) -DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) -DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, { }) +DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {}) +DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {}) +DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {}) +DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {}) +DEF_TRAVERSE_STMT(CXXDeleteExpr, {}) +DEF_TRAVERSE_STMT(ExprWithCleanups, {}) +DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {}) +DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {}) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) @@ -2235,38 +2203,38 @@ DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo()) TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc())); }) -DEF_TRAVERSE_STMT(CXXThisExpr, { }) -DEF_TRAVERSE_STMT(CXXThrowExpr, { }) -DEF_TRAVERSE_STMT(UserDefinedLiteral, { }) -DEF_TRAVERSE_STMT(DesignatedInitExpr, { }) -DEF_TRAVERSE_STMT(ExtVectorElementExpr, { }) -DEF_TRAVERSE_STMT(GNUNullExpr, { }) -DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { }) -DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, { }) +DEF_TRAVERSE_STMT(CXXThisExpr, {}) +DEF_TRAVERSE_STMT(CXXThrowExpr, {}) +DEF_TRAVERSE_STMT(UserDefinedLiteral, {}) +DEF_TRAVERSE_STMT(DesignatedInitExpr, {}) +DEF_TRAVERSE_STMT(ExtVectorElementExpr, {}) +DEF_TRAVERSE_STMT(GNUNullExpr, {}) +DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {}) +DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {}) 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(ObjCIsaExpr, {}) +DEF_TRAVERSE_STMT(ObjCIvarRefExpr, {}) DEF_TRAVERSE_STMT(ObjCMessageExpr, { if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo()) TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); }) -DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { }) -DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, { }) -DEF_TRAVERSE_STMT(ObjCProtocolExpr, { }) -DEF_TRAVERSE_STMT(ObjCSelectorExpr, { }) -DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, { }) +DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {}) +DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {}) +DEF_TRAVERSE_STMT(ObjCProtocolExpr, {}) +DEF_TRAVERSE_STMT(ObjCSelectorExpr, {}) +DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {}) DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, { TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) -DEF_TRAVERSE_STMT(ParenExpr, { }) -DEF_TRAVERSE_STMT(ParenListExpr, { }) -DEF_TRAVERSE_STMT(PredefinedExpr, { }) -DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) -DEF_TRAVERSE_STMT(ConvertVectorExpr, { }) -DEF_TRAVERSE_STMT(StmtExpr, { }) +DEF_TRAVERSE_STMT(ParenExpr, {}) +DEF_TRAVERSE_STMT(ParenListExpr, {}) +DEF_TRAVERSE_STMT(PredefinedExpr, {}) +DEF_TRAVERSE_STMT(ShuffleVectorExpr, {}) +DEF_TRAVERSE_STMT(ConvertVectorExpr, {}) +DEF_TRAVERSE_STMT(StmtExpr, {}) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { @@ -2285,97 +2253,263 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { DEF_TRAVERSE_STMT(SEHTryStmt, {}) DEF_TRAVERSE_STMT(SEHExceptStmt, {}) -DEF_TRAVERSE_STMT(SEHFinallyStmt,{}) -DEF_TRAVERSE_STMT(CapturedStmt, { - TRY_TO(TraverseDecl(S->getCapturedDecl())); -}) +DEF_TRAVERSE_STMT(SEHFinallyStmt, {}) +DEF_TRAVERSE_STMT(SEHLeaveStmt, {}) +DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) -DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { }) -DEF_TRAVERSE_STMT(OpaqueValueExpr, { }) -DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { }) +DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) +DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) +DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) // These operators (all of them) do not need any action except // iterating over the children. -DEF_TRAVERSE_STMT(BinaryConditionalOperator, { }) -DEF_TRAVERSE_STMT(ConditionalOperator, { }) -DEF_TRAVERSE_STMT(UnaryOperator, { }) -DEF_TRAVERSE_STMT(BinaryOperator, { }) -DEF_TRAVERSE_STMT(CompoundAssignOperator, { }) -DEF_TRAVERSE_STMT(CXXNoexceptExpr, { }) -DEF_TRAVERSE_STMT(PackExpansionExpr, { }) -DEF_TRAVERSE_STMT(SizeOfPackExpr, { }) -DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { }) -DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { }) -DEF_TRAVERSE_STMT(FunctionParmPackExpr, { }) -DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { }) -DEF_TRAVERSE_STMT(AtomicExpr, { }) +DEF_TRAVERSE_STMT(BinaryConditionalOperator, {}) +DEF_TRAVERSE_STMT(ConditionalOperator, {}) +DEF_TRAVERSE_STMT(UnaryOperator, {}) +DEF_TRAVERSE_STMT(BinaryOperator, {}) +DEF_TRAVERSE_STMT(CompoundAssignOperator, {}) +DEF_TRAVERSE_STMT(CXXNoexceptExpr, {}) +DEF_TRAVERSE_STMT(PackExpansionExpr, {}) +DEF_TRAVERSE_STMT(SizeOfPackExpr, {}) +DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {}) +DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) +DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) +DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) +DEF_TRAVERSE_STMT(AtomicExpr, {}) // These literals (all of them) do not need any action. -DEF_TRAVERSE_STMT(IntegerLiteral, { }) -DEF_TRAVERSE_STMT(CharacterLiteral, { }) -DEF_TRAVERSE_STMT(FloatingLiteral, { }) -DEF_TRAVERSE_STMT(ImaginaryLiteral, { }) -DEF_TRAVERSE_STMT(StringLiteral, { }) -DEF_TRAVERSE_STMT(ObjCStringLiteral, { }) -DEF_TRAVERSE_STMT(ObjCBoxedExpr, { }) -DEF_TRAVERSE_STMT(ObjCArrayLiteral, { }) -DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { }) - +DEF_TRAVERSE_STMT(IntegerLiteral, {}) +DEF_TRAVERSE_STMT(CharacterLiteral, {}) +DEF_TRAVERSE_STMT(FloatingLiteral, {}) +DEF_TRAVERSE_STMT(ImaginaryLiteral, {}) +DEF_TRAVERSE_STMT(StringLiteral, {}) +DEF_TRAVERSE_STMT(ObjCStringLiteral, {}) +DEF_TRAVERSE_STMT(ObjCBoxedExpr, {}) +DEF_TRAVERSE_STMT(ObjCArrayLiteral, {}) +DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, {}) + // Traverse OpenCL: AsType, Convert. -DEF_TRAVERSE_STMT(AsTypeExpr, { }) +DEF_TRAVERSE_STMT(AsTypeExpr, {}) // OpenMP directives. -DEF_TRAVERSE_STMT(OMPParallelDirective, { - ArrayRef<OMPClause *> Clauses = S->clauses(); - for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end(); - I != E; ++I) - if (!TraverseOMPClause(*I)) return false; +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective( + OMPExecutableDirective *S) { + for (auto *C : S->clauses()) { + TRY_TO(TraverseOMPClause(C)); + } + return true; +} + +DEF_TRAVERSE_STMT(OMPParallelDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPForDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPSectionsDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPSectionDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPSingleDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPMasterDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPCriticalDirective, { + TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName())); + TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPParallelForDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskyieldDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPBarrierDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskwaitDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPFlushDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { - if (!C) return true; + if (!C) + return true; switch (C->getClauseKind()) { -#define OPENMP_CLAUSE(Name, Class) \ - case OMPC_##Name: \ - return getDerived().Visit##Class(static_cast<Class*>(C)); +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_##Name: \ + TRY_TO(Visit##Class(static_cast<Class *>(C))); \ + break; #include "clang/Basic/OpenMPKinds.def" - default: break; + case OMPC_threadprivate: + case OMPC_unknown: + break; } return true; } -template<typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) { +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) { + TRY_TO(TraverseStmt(C->getCondition())); return true; } -template<typename Derived> -template<typename T> -void RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { - for (typename T::varlist_iterator I = Node->varlist_begin(), - E = Node->varlist_end(); - I != E; ++I) - TraverseStmt(*I); +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { + TRY_TO(TraverseStmt(C->getCondition())); + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { + TRY_TO(TraverseStmt(C->getNumThreads())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) { + TRY_TO(TraverseStmt(C->getSafelen())); + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) { + TRY_TO(TraverseStmt(C->getNumForLoops())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) { + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) { + TRY_TO(TraverseStmt(C->getChunkSize())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) { + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { + return true; +} + +template <typename Derived> +template <typename T> +bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { + for (auto *E : Node->varlists()) { + TRY_TO(TraverseStmt(E)); + } + return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { - VisitOMPClauseList(C); + TRY_TO(VisitOMPClauseList(C)); return true; } -template<typename Derived> +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( - OMPFirstprivateClause *C) { - VisitOMPClauseList(C); + OMPFirstprivateClause *C) { + TRY_TO(VisitOMPClauseList(C)); return true; } -template<typename Derived> +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause( + OMPLastprivateClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) { - VisitOMPClauseList(C); + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) { + TRY_TO(TraverseStmt(C->getStep())); + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) { + TRY_TO(TraverseStmt(C->getAlignment())); + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause( + OMPCopyprivateClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) { + TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) { + TRY_TO(VisitOMPClauseList(C)); return true; } diff --git a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h index cfe5a90..7aa11d4 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_REDECLARABLE_H #define LLVM_CLANG_AST_REDECLARABLE_H +#include "clang/AST/ExternalASTSource.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Casting.h" #include <iterator> @@ -23,26 +24,82 @@ namespace clang { /// \brief Provides common interface for the Decls that can be redeclared. template<typename decl_type> class Redeclarable { - protected: class DeclLink { - llvm::PointerIntPair<decl_type *, 1, bool> NextAndIsPrevious; + /// A pointer to a known latest declaration, either statically known or + /// generationally updated as decls are added by an external source. + typedef LazyGenerationalUpdatePtr<const Decl*, Decl*, + &ExternalASTSource::CompleteRedeclChain> + KnownLatest; + + typedef const ASTContext *UninitializedLatest; + typedef Decl *Previous; + + /// A pointer to either an uninitialized latest declaration (where either + /// we've not yet set the previous decl or there isn't one), or to a known + /// previous declaration. + typedef llvm::PointerUnion<Previous, UninitializedLatest> NotKnownLatest; + + mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Next; + public: - DeclLink(decl_type *D, bool isLatest) - : NextAndIsPrevious(D, isLatest) { } + enum PreviousTag { PreviousLink }; + enum LatestTag { LatestLink }; + + DeclLink(LatestTag, const ASTContext &Ctx) + : Next(NotKnownLatest(&Ctx)) {} + DeclLink(PreviousTag, decl_type *D) + : Next(NotKnownLatest(Previous(D))) {} + + bool NextIsPrevious() const { + return Next.is<NotKnownLatest>() && + // FIXME: 'template' is required on the next line due to an + // apparent clang bug. + Next.get<NotKnownLatest>().template is<Previous>(); + } + + bool NextIsLatest() const { return !NextIsPrevious(); } + + decl_type *getNext(const decl_type *D) const { + if (Next.is<NotKnownLatest>()) { + NotKnownLatest NKL = Next.get<NotKnownLatest>(); + if (NKL.is<Previous>()) + return static_cast<decl_type*>(NKL.get<Previous>()); + + // Allocate the generational 'most recent' cache now, if needed. + Next = KnownLatest(*NKL.get<UninitializedLatest>(), + const_cast<decl_type *>(D)); + } + + return static_cast<decl_type*>(Next.get<KnownLatest>().get(D)); + } + + void setPrevious(decl_type *D) { + assert(NextIsPrevious() && "decl became non-canonical unexpectedly"); + Next = Previous(D); + } + + void setLatest(decl_type *D) { + assert(NextIsLatest() && "decl became canonical unexpectedly"); + if (Next.is<NotKnownLatest>()) { + NotKnownLatest NKL = Next.get<NotKnownLatest>(); + Next = KnownLatest(*NKL.get<UninitializedLatest>(), D); + } else { + auto Latest = Next.get<KnownLatest>(); + Latest.set(D); + Next = Latest; + } + } - 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); } + void markIncomplete() { Next.get<KnownLatest>().markIncomplete(); } }; static DeclLink PreviousDeclLink(decl_type *D) { - return DeclLink(D, false); + return DeclLink(DeclLink::PreviousLink, D); } - static DeclLink LatestDeclLink(decl_type *D) { - return DeclLink(D, true); + static DeclLink LatestDeclLink(const ASTContext &Ctx) { + return DeclLink(DeclLink::LatestLink, Ctx); } /// \brief Points to the next redeclaration in the chain. @@ -58,15 +115,20 @@ protected: /// If there is only one declaration, it is <pointer to self, true> DeclLink RedeclLink; + decl_type *getNextRedeclaration() const { + return RedeclLink.getNext(static_cast<const decl_type *>(this)); + } + public: - Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { } + Redeclarable(const ASTContext &Ctx) + : RedeclLink(LatestDeclLink(Ctx)) {} /// \brief Return the previous declaration of this declaration or NULL if this /// is the first declaration. decl_type *getPreviousDecl() { if (RedeclLink.NextIsPrevious()) - return RedeclLink.getNext(); - return 0; + return getNextRedeclaration(); + return nullptr; } const decl_type *getPreviousDecl() const { return const_cast<decl_type *>( @@ -96,14 +158,14 @@ public: /// \brief Returns the most recent (re)declaration of this declaration. decl_type *getMostRecentDecl() { - return getFirstDecl()->RedeclLink.getNext(); + return getFirstDecl()->getNextRedeclaration(); } /// \brief Returns the most recent (re)declaration of this declaration. const decl_type *getMostRecentDecl() const { - return getFirstDecl()->RedeclLink.getNext(); + return getFirstDecl()->getNextRedeclaration(); } - + /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the /// first and only declaration. void setPreviousDecl(decl_type *PrevDecl); @@ -122,7 +184,7 @@ public: typedef std::forward_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; - redecl_iterator() : Current(0) { } + redecl_iterator() : Current(nullptr) { } explicit redecl_iterator(decl_type *C) : Current(C), Starter(C), PassedFirst(false) { } @@ -135,15 +197,15 @@ public: if (Current->isFirstDecl()) { if (PassedFirst) { assert(0 && "Passed first decl twice, invalid redecl chain!"); - Current = 0; + Current = nullptr; return *this; } PassedFirst = true; } // Get either previous decl or latest decl. - decl_type *Next = Current->RedeclLink.getNext(); - Current = (Next != Starter ? Next : 0); + decl_type *Next = Current->getNextRedeclaration(); + Current = (Next != Starter) ? Next : nullptr; return *this; } @@ -161,13 +223,18 @@ public: } }; - /// \brief Returns iterator for all the redeclarations of the same decl. - /// It will iterate at least once (when this decl is the only one). - redecl_iterator redecls_begin() const { - return redecl_iterator(const_cast<decl_type*>( - static_cast<const decl_type*>(this))); + typedef llvm::iterator_range<redecl_iterator> redecl_range; + + /// \brief Returns an iterator range for all the redeclarations of the same + /// decl. It will iterate at least once (when this decl is the only one). + redecl_range redecls() const { + return redecl_range(redecl_iterator(const_cast<decl_type *>( + static_cast<const decl_type *>(this))), + redecl_iterator()); } - redecl_iterator redecls_end() const { return redecl_iterator(); } + + redecl_iterator redecls_begin() const { return redecls().begin(); } + redecl_iterator redecls_end() const { return redecls().end(); } friend class ASTDeclReader; friend class ASTDeclWriter; diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h index ace53d8..fb94097 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h @@ -62,7 +62,7 @@ namespace clang { Stmt** I; public: ExprIterator(Stmt** i) : I(i) {} - ExprIterator() : I(0) {} + ExprIterator() : I(nullptr) {} ExprIterator& operator++() { ++I; return *this; } ExprIterator operator-(size_t i) { return I-i; } ExprIterator operator+(size_t i) { return I+i; } @@ -81,7 +81,7 @@ namespace clang { const Stmt * const *I; public: ConstExprIterator(const Stmt * const *i) : I(i) {} - ConstExprIterator() : I(0) {} + ConstExprIterator() : I(nullptr) {} ConstExprIterator& operator++() { ++I; return *this; } ConstExprIterator operator+(size_t i) const { return I+i; } ConstExprIterator operator-(size_t i) const { return I-i; } @@ -371,12 +371,12 @@ public: /// \brief Dumps the specified AST fragment and all subtrees to /// \c llvm::errs(). - LLVM_ATTRIBUTE_USED void dump() const; - LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const; + void dump() const; + void dump(SourceManager &SM) const; void dump(raw_ostream &OS, SourceManager &SM) const; /// dumpColor - same as dump(), but forces color highlighting. - LLVM_ATTRIBUTE_USED void dumpColor() const; + void dumpColor() const; /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST /// back to its original source language syntax. @@ -485,7 +485,13 @@ public: typedef DeclGroupRef::iterator decl_iterator; typedef DeclGroupRef::const_iterator const_decl_iterator; + typedef llvm::iterator_range<decl_iterator> decl_range; + typedef llvm::iterator_range<const_decl_iterator> decl_const_range; + decl_range decls() { return decl_range(decl_begin(), decl_end()); } + decl_const_range decls() const { + return decl_const_range(decl_begin(), decl_end()); + } decl_iterator decl_begin() { return DG.begin(); } decl_iterator decl_end() { return DG.end(); } const_decl_iterator decl_begin() const { return DG.begin(); } @@ -549,13 +555,13 @@ public: // \brief Build an empty compound statement with a location. explicit CompoundStmt(SourceLocation Loc) - : Stmt(CompoundStmtClass), Body(0), LBracLoc(Loc), RBracLoc(Loc) { + : Stmt(CompoundStmtClass), Body(nullptr), LBracLoc(Loc), RBracLoc(Loc) { CompoundStmtBits.NumStmts = 0; } // \brief Build an empty compound statement. explicit CompoundStmt(EmptyShell Empty) - : Stmt(CompoundStmtClass, Empty), Body(0) { + : Stmt(CompoundStmtClass, Empty), Body(nullptr) { CompoundStmtBits.NumStmts = 0; } @@ -565,9 +571,12 @@ public: unsigned size() const { return CompoundStmtBits.NumStmts; } typedef Stmt** body_iterator; + typedef llvm::iterator_range<body_iterator> body_range; + + body_range body() { return body_range(body_begin(), body_end()); } body_iterator body_begin() { return Body; } body_iterator body_end() { return Body + size(); } - Stmt *body_back() { return !body_empty() ? Body[size()-1] : 0; } + Stmt *body_back() { return !body_empty() ? Body[size()-1] : nullptr; } void setLastStmt(Stmt *S) { assert(!body_empty() && "setLastStmt"); @@ -575,9 +584,16 @@ public: } typedef Stmt* const * const_body_iterator; + typedef llvm::iterator_range<const_body_iterator> body_const_range; + + body_const_range body() const { + return body_const_range(body_begin(), body_end()); + } const_body_iterator body_begin() const { return Body; } const_body_iterator body_end() const { return Body + size(); } - const Stmt *body_back() const { return !body_empty() ? Body[size()-1] : 0; } + const Stmt *body_back() const { + return !body_empty() ? Body[size() - 1] : nullptr; + } typedef std::reverse_iterator<body_iterator> reverse_body_iterator; reverse_body_iterator body_rbegin() { @@ -612,11 +628,11 @@ public: // Iterators child_range children() { - return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts); + return child_range(Body, Body + CompoundStmtBits.NumStmts); } const_child_range children() const { - return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts); + return child_range(Body, Body + CompoundStmtBits.NumStmts); } }; @@ -630,10 +646,11 @@ protected: SourceLocation ColonLoc; SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc) - : Stmt(SC), NextSwitchCase(0), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {} + : Stmt(SC), NextSwitchCase(nullptr), KeywordLoc(KWLoc), ColonLoc(ColonLoc) { + } SwitchCase(StmtClass SC, EmptyShell) - : Stmt(SC), NextSwitchCase(0) {} + : Stmt(SC), NextSwitchCase(nullptr) {} public: const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } @@ -670,7 +687,7 @@ public: CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, SourceLocation ellipsisLoc, SourceLocation colonLoc) : SwitchCase(CaseStmtClass, caseLoc, colonLoc) { - SubExprs[SUBSTMT] = 0; + SubExprs[SUBSTMT] = nullptr; SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs); SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs); EllipsisLoc = ellipsisLoc; @@ -802,20 +819,24 @@ class AttributedStmt : public Stmt { Stmt *SubStmt; SourceLocation AttrLoc; unsigned NumAttrs; - const Attr *Attrs[1]; friend class ASTStmtReader; 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*)); + memcpy(getAttrArrayPtr(), Attrs.data(), Attrs.size() * sizeof(Attr *)); } explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs) : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) { - memset(Attrs, 0, NumAttrs * sizeof(Attr*)); + memset(getAttrArrayPtr(), 0, NumAttrs * sizeof(Attr *)); + } + + Attr *const *getAttrArrayPtr() const { + return reinterpret_cast<Attr *const *>(this + 1); } + Attr **getAttrArrayPtr() { return reinterpret_cast<Attr **>(this + 1); } public: static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc, @@ -825,7 +846,7 @@ public: SourceLocation getAttrLoc() const { return AttrLoc; } ArrayRef<const Attr*> getAttrs() const { - return ArrayRef<const Attr*>(Attrs, NumAttrs); + return ArrayRef<const Attr*>(getAttrArrayPtr(), NumAttrs); } Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } @@ -852,7 +873,8 @@ class IfStmt : public Stmt { public: IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, - Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0); + Stmt *then, SourceLocation EL = SourceLocation(), + Stmt *elsev = nullptr); /// \brief Build an empty if/then/else statement explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } @@ -1320,7 +1342,8 @@ class ReturnStmt : public Stmt { public: ReturnStmt(SourceLocation RL) - : Stmt(ReturnStmtClass), RetExpr(0), RetLoc(RL), NRVOCandidate(0) { } + : Stmt(ReturnStmtClass), RetExpr(nullptr), RetLoc(RL), + NRVOCandidate(nullptr) {} ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) : Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL), @@ -1389,7 +1412,7 @@ protected: public: /// \brief Build an empty inline-assembly statement. explicit AsmStmt(StmtClass SC, EmptyShell Empty) : - Stmt(SC, Empty), Exprs(0) { } + Stmt(SC, Empty), Exprs(nullptr) { } SourceLocation getAsmLoc() const { return AsmLoc; } void setAsmLoc(SourceLocation L) { AsmLoc = L; } @@ -1454,6 +1477,8 @@ public: typedef ExprIterator inputs_iterator; typedef ConstExprIterator const_inputs_iterator; + typedef llvm::iterator_range<inputs_iterator> inputs_range; + typedef llvm::iterator_range<const_inputs_iterator> inputs_const_range; inputs_iterator begin_inputs() { return &Exprs[0] + NumOutputs; @@ -1463,6 +1488,8 @@ public: return &Exprs[0] + NumOutputs + NumInputs; } + inputs_range inputs() { return inputs_range(begin_inputs(), end_inputs()); } + const_inputs_iterator begin_inputs() const { return &Exprs[0] + NumOutputs; } @@ -1471,10 +1498,16 @@ public: return &Exprs[0] + NumOutputs + NumInputs; } + inputs_const_range inputs() const { + return inputs_const_range(begin_inputs(), end_inputs()); + } + // Output expr iterators. typedef ExprIterator outputs_iterator; typedef ConstExprIterator const_outputs_iterator; + typedef llvm::iterator_range<outputs_iterator> outputs_range; + typedef llvm::iterator_range<const_outputs_iterator> outputs_const_range; outputs_iterator begin_outputs() { return &Exprs[0]; @@ -1482,6 +1515,9 @@ public: outputs_iterator end_outputs() { return &Exprs[0] + NumOutputs; } + outputs_range outputs() { + return outputs_range(begin_outputs(), end_outputs()); + } const_outputs_iterator begin_outputs() const { return &Exprs[0]; @@ -1489,6 +1525,9 @@ public: const_outputs_iterator end_outputs() const { return &Exprs[0] + NumOutputs; } + outputs_const_range outputs() const { + return outputs_const_range(begin_outputs(), end_outputs()); + } child_range children() { return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs); @@ -1517,7 +1556,7 @@ public: /// \brief Build an empty inline-assembly statement. explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty), - Constraints(0), Clobbers(0), Names(0) { } + Constraints(nullptr), Clobbers(nullptr), Names(nullptr) { } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } @@ -1693,7 +1732,7 @@ public: /// \brief Build an empty MS-style inline-assembly statement. explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty), - NumAsmToks(0), AsmToks(0), Constraints(0), Clobbers(0) { } + NumAsmToks(0), AsmToks(nullptr), Constraints(nullptr), Clobbers(nullptr) { } SourceLocation getLBraceLoc() const { return LBraceLoc; } void setLBraceLoc(SourceLocation L) { LBraceLoc = L; } @@ -1767,7 +1806,7 @@ public: } child_range children() { - return child_range(&Exprs[0], &Exprs[0]); + return child_range(&Exprs[0], &Exprs[NumInputs + NumOutputs]); } }; @@ -1853,22 +1892,24 @@ class SEHTryStmt : public Stmt { bool IsCXXTry; SourceLocation TryLoc; Stmt *Children[2]; + int HandlerIndex; + int HandlerParentIndex; enum { TRY = 0, HANDLER = 1 }; SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try' - SourceLocation TryLoc, - Stmt *TryBlock, - Stmt *Handler); + SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler, + int HandlerIndex, int HandlerParentIndex); friend class ASTReader; friend class ASTStmtReader; explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { } public: - static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry, + static SEHTryStmt *Create(const ASTContext &C, bool isCXXTry, SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler); + Stmt *Handler, int HandlerIndex, + int HandlerParentIndex); SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } @@ -1895,6 +1936,34 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SEHTryStmtClass; } + + int getHandlerIndex() const { return HandlerIndex; } + int getHandlerParentIndex() const { return HandlerParentIndex; } +}; + +/// Represents a __leave statement. +/// +class SEHLeaveStmt : public Stmt { + SourceLocation LeaveLoc; +public: + explicit SEHLeaveStmt(SourceLocation LL) + : Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {} + + /// \brief Build an empty __leave statement. + explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) { } + + SourceLocation getLeaveLoc() const { return LeaveLoc; } + void setLeaveLoc(SourceLocation L) { LeaveLoc = L; } + + SourceLocation getLocStart() const LLVM_READONLY { return LeaveLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return LeaveLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHLeaveStmtClass; + } + + // Iterators + child_range children() { return child_range(); } }; /// \brief This captures a statement into a function. For example, the following @@ -1928,11 +1997,12 @@ public: /// /// \param Var The variable being captured, or null if capturing this. /// - Capture(SourceLocation Loc, VariableCaptureKind Kind, VarDecl *Var = 0) + Capture(SourceLocation Loc, VariableCaptureKind Kind, + VarDecl *Var = nullptr) : VarAndKind(Var, Kind), Loc(Loc) { switch (Kind) { case VCK_This: - assert(Var == 0 && "'this' capture cannot have a variable!"); + assert(!Var && "'this' capture cannot have a variable!"); break; case VCK_ByRef: assert(Var && "capturing by reference must have a variable!"); @@ -2042,6 +2112,15 @@ public: /// \brief An iterator that walks over the captures. typedef Capture *capture_iterator; typedef const Capture *const_capture_iterator; + typedef llvm::iterator_range<capture_iterator> capture_range; + typedef llvm::iterator_range<const_capture_iterator> capture_const_range; + + capture_range captures() { + return capture_range(capture_begin(), capture_end()); + } + capture_const_range captures() const { + return capture_const_range(capture_begin(), capture_end()); + } /// \brief Retrieve an iterator pointing to the first capture. capture_iterator capture_begin() { return getStoredCaptures(); } @@ -2058,6 +2137,11 @@ public: /// \brief Iterator that walks over the capture initialization arguments. typedef Expr **capture_init_iterator; + typedef llvm::iterator_range<capture_init_iterator> capture_init_range; + + capture_init_range capture_inits() const { + return capture_init_range(capture_init_begin(), capture_init_end()); + } /// \brief Retrieve the first initialization argument. capture_init_iterator capture_init_begin() const { diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h index df98d41..837dc45 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h @@ -39,7 +39,7 @@ public: HandlerBlock(handlerBlock) {} CXXCatchStmt(EmptyShell Empty) - : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {} + : Stmt(CXXCatchStmtClass), ExceptionDecl(nullptr), HandlerBlock(nullptr) {} SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; } SourceLocation getLocEnd() const LLVM_READONLY { diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h index fbc8e5d..18c5516 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h @@ -14,8 +14,8 @@ #ifndef LLVM_CLANG_AST_STMT_ITR_H #define LLVM_CLANG_AST_STMT_ITR_H -#include "llvm/Support/DataTypes.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <cstddef> #include <iterator> @@ -64,10 +64,10 @@ protected: Stmt*& GetDeclExpr() const; - StmtIteratorBase(Stmt **s) : stmt(s), DGI(0), RawVAPtr(0) {} + StmtIteratorBase(Stmt **s) : stmt(s), DGI(nullptr), RawVAPtr(0) {} StmtIteratorBase(const VariableArrayType *t); StmtIteratorBase(Decl **dgi, Decl **dge); - StmtIteratorBase() : stmt(0), DGI(0), RawVAPtr(0) {} + StmtIteratorBase() : stmt(nullptr), DGI(nullptr), RawVAPtr(0) {} }; diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h index bfb4a9b..d0527e2 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h @@ -107,7 +107,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return AtCatchLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return Body->getLocEnd(); } - bool hasEllipsis() const { return getCatchParamDecl() == 0; } + bool hasEllipsis() const { return getCatchParamDecl() == nullptr; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtCatchStmtClass; @@ -222,13 +222,13 @@ public: /// \brief Retrieve the \@finally statement, if any. const ObjCAtFinallyStmt *getFinallyStmt() const { if (!HasFinally) - return 0; + return nullptr; return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); } ObjCAtFinallyStmt *getFinallyStmt() { if (!HasFinally) - return 0; + return nullptr; return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h index 8570d88..db02afe0 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h @@ -1,4 +1,4 @@ -//===- StmtOpenMP.h - Classes for OpenMP directives and clauses --*- C++ -*-===// +//===- StmtOpenMP.h - Classes for OpenMP directives ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,514 +15,1019 @@ #ifndef LLVM_CLANG_AST_STMTOPENMP_H #define LLVM_CLANG_AST_STMTOPENMP_H -#include "clang/Basic/OpenMPKinds.h" -#include "clang/Basic/SourceLocation.h" #include "clang/AST/Expr.h" +#include "clang/AST/OpenMPClause.h" #include "clang/AST/Stmt.h" +#include "clang/Basic/OpenMPKinds.h" +#include "clang/Basic/SourceLocation.h" namespace clang { //===----------------------------------------------------------------------===// -// AST classes for clauses. +// AST classes for directives. //===----------------------------------------------------------------------===// -/// \brief This is a basic class for representing single OpenMP clause. +/// \brief This is a basic class for representing single OpenMP executable +/// directive. /// -class OMPClause { - /// \brief Starting location of the clause (the clause keyword). +class OMPExecutableDirective : public Stmt { + friend class ASTStmtReader; + /// \brief Kind of the directive. + OpenMPDirectiveKind Kind; + /// \brief Starting location of the directive (directive keyword). SourceLocation StartLoc; - /// \brief Ending location of the clause. + /// \brief Ending location of the directive. SourceLocation EndLoc; - /// \brief Kind of the clause. - OpenMPClauseKind Kind; + /// \brief Numbers of clauses. + const unsigned NumClauses; + /// \brief Number of child expressions/stmts. + const unsigned NumChildren; + /// \brief Offset from this to the start of clauses. + /// There are NumClauses pointers to clauses, they are followed by + /// NumChildren pointers to child stmts/exprs (if the directive type + /// requires an associated stmt, then it has to be the first of them). + const unsigned ClausesOffset; + + /// \brief Get the clauses storage. + MutableArrayRef<OMPClause *> getClauses() { + OMPClause **ClauseStorage = reinterpret_cast<OMPClause **>( + reinterpret_cast<char *>(this) + ClausesOffset); + return MutableArrayRef<OMPClause *>(ClauseStorage, NumClauses); + } + protected: - OMPClause(OpenMPClauseKind K, SourceLocation StartLoc, SourceLocation EndLoc) - : StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {} + /// \brief Build instance of directive of class \a K. + /// + /// \param SC Statement class. + /// \param K Kind of OpenMP directive. + /// \param StartLoc Starting location of the directive (directive keyword). + /// \param EndLoc Ending location of the directive. + /// + template <typename T> + OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K, + SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses, unsigned NumChildren) + : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)), + EndLoc(std::move(EndLoc)), NumClauses(NumClauses), + NumChildren(NumChildren), + ClausesOffset(llvm::RoundUpToAlignment(sizeof(T), + llvm::alignOf<OMPClause *>())) {} + + /// \brief Sets the list of variables for this clause. + /// + /// \param Clauses The list of clauses for the directive. + /// + void setClauses(ArrayRef<OMPClause *> Clauses); + + /// \brief Set the associated statement for the directive. + /// + /// /param S Associated statement. + /// + void setAssociatedStmt(Stmt *S) { + assert(hasAssociatedStmt() && "no associated statement."); + *child_begin() = S; + } public: + /// \brief Iterates over a filtered subrange of clauses applied to a + /// directive. + /// + /// This iterator visits only those declarations that meet some run-time + /// criteria. + template <class FilterPredicate> class filtered_clause_iterator { + ArrayRef<OMPClause *>::const_iterator Current; + ArrayRef<OMPClause *>::const_iterator End; + FilterPredicate Pred; + void SkipToNextClause() { + while (Current != End && !Pred(*Current)) + ++Current; + } + + public: + typedef const OMPClause *value_type; + filtered_clause_iterator() : Current(), End() {} + filtered_clause_iterator(ArrayRef<OMPClause *> Arr, FilterPredicate Pred) + : Current(Arr.begin()), End(Arr.end()), Pred(Pred) { + SkipToNextClause(); + } + value_type operator*() const { return *Current; } + value_type operator->() const { return *Current; } + filtered_clause_iterator &operator++() { + ++Current; + SkipToNextClause(); + return *this; + } + + filtered_clause_iterator operator++(int) { + filtered_clause_iterator tmp(*this); + ++(*this); + return tmp; + } - /// \brief Returns the starting location of the clause. + bool operator!() { return Current == End; } + operator bool() { return Current != End; } + }; + + /// \brief Returns starting location of directive kind. SourceLocation getLocStart() const { return StartLoc; } - /// \brief Returns the ending location of the clause. + /// \brief Returns ending location of directive. SourceLocation getLocEnd() const { return EndLoc; } - /// \brief Sets the starting location of the clause. + /// \brief Set starting location of directive kind. + /// + /// \param Loc New starting location of directive. + /// void setLocStart(SourceLocation Loc) { StartLoc = Loc; } - /// \brief Sets the ending location of the clause. + /// \brief Set ending location of directive. + /// + /// \param Loc New ending location of directive. + /// void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } - /// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.). - OpenMPClauseKind getClauseKind() const { return Kind; } + /// \brief Get number of clauses. + unsigned getNumClauses() const { return NumClauses; } + + /// \brief Returns specified clause. + /// + /// \param i Number of clause. + /// + OMPClause *getClause(unsigned i) const { return clauses()[i]; } - bool isImplicit() const { return StartLoc.isInvalid();} + /// \brief Returns true if directive has associated statement. + bool hasAssociatedStmt() const { return NumChildren > 0; } - StmtRange children(); - ConstStmtRange children() const { - return const_cast<OMPClause *>(this)->children(); + /// \brief Returns statement associated with the directive. + Stmt *getAssociatedStmt() const { + assert(hasAssociatedStmt() && "no associated statement."); + return const_cast<Stmt *>(*child_begin()); } - static bool classof(const OMPClause *T) { - return true; + + OpenMPDirectiveKind getDirectiveKind() const { return Kind; } + + static bool classof(const Stmt *S) { + return S->getStmtClass() >= firstOMPExecutableDirectiveConstant && + S->getStmtClass() <= lastOMPExecutableDirectiveConstant; } -}; -/// \brief This represents clauses with the list of variables like 'private', -/// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the -/// '#pragma omp ...' directives. -template <class T> -class OMPVarList { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief Number of variables in the list. - unsigned NumVars; -protected: - /// \brief Fetches list of variables associated with this clause. - llvm::MutableArrayRef<Expr *> getVarRefs() { - return llvm::MutableArrayRef<Expr *>( - reinterpret_cast<Expr **>(static_cast<T *>(this) + 1), - NumVars); + child_range children() { + if (!hasAssociatedStmt()) + return child_range(); + Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end()); + return child_range(ChildStorage, ChildStorage + NumChildren); } - /// \brief Sets the list of variables for this clause. - void setVarRefs(ArrayRef<Expr *> VL) { - assert(VL.size() == NumVars && - "Number of variables is not the same as the preallocated buffer"); - std::copy(VL.begin(), VL.end(), - reinterpret_cast<Expr **>(static_cast<T *>(this) + 1)); + ArrayRef<OMPClause *> clauses() { return getClauses(); } + + ArrayRef<OMPClause *> clauses() const { + return const_cast<OMPExecutableDirective *>(this)->getClauses(); } +}; + +/// \brief This represents '#pragma omp parallel' directive. +/// +/// \code +/// #pragma omp parallel private(a,b) reduction(+: c,d) +/// \endcode +/// In this example directive '#pragma omp parallel' has clauses 'private' +/// with the variables 'a' and 'b' and 'reduction' with operator '+' and +/// variables 'c' and 'd'. +/// +class OMPParallelDirective : public OMPExecutableDirective { + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive (directive keyword). + /// \param EndLoc Ending Location of the directive. + /// + OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, + StartLoc, EndLoc, NumClauses, 1) {} - /// \brief Build clause with number of variables \a N. + /// \brief Build an empty directive. /// - /// \param N Number of the variables in the clause. + /// \param NumClauses Number of clauses. /// - OMPVarList(SourceLocation LParenLoc, unsigned N) - : LParenLoc(LParenLoc), NumVars(N) { } + explicit OMPParallelDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, + SourceLocation(), SourceLocation(), NumClauses, + 1) {} + public: - typedef llvm::MutableArrayRef<Expr *>::iterator varlist_iterator; - typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; - - unsigned varlist_size() const { return NumVars; } - bool varlist_empty() const { return NumVars == 0; } - varlist_iterator varlist_begin() { return getVarRefs().begin(); } - varlist_iterator varlist_end() { return getVarRefs().end(); } - varlist_const_iterator varlist_begin() const { return getVarRefs().begin(); } - varlist_const_iterator varlist_end() const { return getVarRefs().end(); } - - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } - - /// \brief Fetches list of all variables in the clause. - ArrayRef<const Expr *> getVarRefs() const { - return ArrayRef<const Expr *>( - reinterpret_cast<const Expr *const *>(static_cast<const T *>(this) + 1), - NumVars); + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement associated with the directive. + /// + static OMPParallelDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a N clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPParallelDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelDirectiveClass; } }; -/// \brief This represents 'default' clause in the '#pragma omp ...' directive. +/// \brief This represents '#pragma omp simd' directive. /// /// \code -/// #pragma omp parallel default(shared) +/// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d) /// \endcode -/// In this example directive '#pragma omp parallel' has simple 'default' -/// clause with kind 'shared'. +/// In this example directive '#pragma omp simd' has clauses 'private' +/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and +/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'. /// -class OMPDefaultClause : public OMPClause { - friend class OMPClauseReader; - /// \brief Location of '('. - SourceLocation LParenLoc; - /// \brief A kind of the 'default' clause. - OpenMPDefaultClauseKind Kind; - /// \brief Start location of the kind in source code. - SourceLocation KindKwLoc; - - /// \brief Set kind of the clauses. +class OMPSimdDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Number of collapsed loops as specified by 'collapse' clause. + unsigned CollapsedNum; + /// \brief Build directive with the given start and end location. /// - /// \param K Argument of clause. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. /// - void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; } + OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc, + EndLoc, NumClauses, 1), + CollapsedNum(CollapsedNum) {} - /// \brief Set argument location. + /// \brief Build an empty directive. /// - /// \param KLoc Argument location. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. /// - void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } + explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses) + : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, + SourceLocation(), SourceLocation(), NumClauses, + 1), + CollapsedNum(CollapsedNum) {} + public: - /// \brief Build 'default' clause with argument \a A ('none' or 'shared'). + /// \brief Creates directive with a list of \a Clauses. /// - /// \param A Argument of the clause ('none' or 'shared'). - /// \param ALoc Starting location of the argument. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. /// - OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc), - Kind(A), KindKwLoc(ALoc) { } + static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt); - /// \brief Build an empty clause. + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. /// - OMPDefaultClause() - : OMPClause(OMPC_default, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown), - KindKwLoc(SourceLocation()) { } + static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, + unsigned CollapsedNum, EmptyShell); - /// \brief Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + unsigned getCollapsedNumber() const { return CollapsedNum; } - /// \brief Returns kind of the clause. - OpenMPDefaultClauseKind getDefaultKind() const { return Kind; } + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPSimdDirectiveClass; + } +}; - /// \brief Returns location of clause kind. - SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; } +/// \brief This represents '#pragma omp for' directive. +/// +/// \code +/// #pragma omp for private(a,b) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp for' has clauses 'private' with the +/// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c' +/// and 'd'. +/// +class OMPForDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Number of collapsed loops as specified by 'collapse' clause. + unsigned CollapsedNum; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, + EndLoc, NumClauses, 1), + CollapsedNum(CollapsedNum) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_default; - } + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses) + : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, + SourceLocation(), SourceLocation(), NumClauses, + 1), + CollapsedNum(CollapsedNum) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, + unsigned CollapsedNum, EmptyShell); - StmtRange children() { - return StmtRange(); + unsigned getCollapsedNumber() const { return CollapsedNum; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPForDirectiveClass; } }; -/// \brief This represents clause 'private' in the '#pragma omp ...' directives. +/// \brief This represents '#pragma omp sections' directive. /// /// \code -/// #pragma omp parallel private(a,b) +/// #pragma omp sections private(a,b) reduction(+:c,d) /// \endcode -/// In this example directive '#pragma omp parallel' has clause 'private' -/// with the variables 'a' and 'b'. +/// In this example directive '#pragma omp sections' has clauses 'private' with +/// the variables 'a' and 'b' and 'reduction' with operator '+' and variables +/// 'c' and 'd'. /// -class OMPPrivateClause : public OMPClause, public OMPVarList<OMPPrivateClause> { - /// \brief Build clause with number of variables \a N. +class OMPSectionsDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. /// - OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPClause(OMPC_private, StartLoc, EndLoc), - OMPVarList<OMPPrivateClause>(LParenLoc, N) { } + OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections, + StartLoc, EndLoc, NumClauses, 1) {} - /// \brief Build an empty clause. + /// \brief Build an empty directive. /// - /// \param N Number of variables. + /// \param NumClauses Number of clauses. /// - explicit OMPPrivateClause(unsigned N) - : OMPClause(OMPC_private, SourceLocation(), SourceLocation()), - OMPVarList<OMPPrivateClause>(SourceLocation(), N) { } + explicit OMPSectionsDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections, + SourceLocation(), SourceLocation(), NumClauses, + 1) {} + public: - /// \brief Creates clause with a list of variables \a VL. + /// \brief Creates directive with a list of \a Clauses. /// /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. /// - static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL); - /// \brief Creates an empty clause with the place for \a N variables. + static OMPSectionsDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. /// /// \param C AST context. - /// \param N The number of variables. + /// \param NumClauses Number of clauses. /// - static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N); + static OMPSectionsDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPSectionsDirectiveClass; } +}; + +/// \brief This represents '#pragma omp section' directive. +/// +/// \code +/// #pragma omp section +/// \endcode +/// +class OMPSectionDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section, + StartLoc, EndLoc, 0, 1) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_private; + /// \brief Build an empty directive. + /// + explicit OMPSectionDirective() + : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section, + SourceLocation(), SourceLocation(), 0, 1) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPSectionDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPSectionDirectiveClass; } }; -/// \brief This represents clause 'firstprivate' in the '#pragma omp ...' -/// directives. +/// \brief This represents '#pragma omp single' directive. /// /// \code -/// #pragma omp parallel firstprivate(a,b) +/// #pragma omp single private(a,b) copyprivate(c,d) /// \endcode -/// In this example directive '#pragma omp parallel' has clause 'firstprivate' -/// with the variables 'a' and 'b'. +/// In this example directive '#pragma omp single' has clauses 'private' with +/// the variables 'a' and 'b' and 'copyprivate' with variables 'c' and 'd'. /// -class OMPFirstprivateClause : public OMPClause, - public OMPVarList<OMPFirstprivateClause> { - /// \brief Build clause with number of variables \a N. +class OMPSingleDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. /// - OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPClause(OMPC_firstprivate, StartLoc, EndLoc), - OMPVarList<OMPFirstprivateClause>(LParenLoc, N) { } + OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single, + StartLoc, EndLoc, NumClauses, 1) {} - /// \brief Build an empty clause. + /// \brief Build an empty directive. /// - /// \param N Number of variables. + /// \param NumClauses Number of clauses. /// - explicit OMPFirstprivateClause(unsigned N) - : OMPClause(OMPC_firstprivate, SourceLocation(), SourceLocation()), - OMPVarList<OMPFirstprivateClause>(SourceLocation(), N) { } + explicit OMPSingleDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single, + SourceLocation(), SourceLocation(), NumClauses, + 1) {} + public: - /// \brief Creates clause with a list of variables \a VL. + /// \brief Creates directive with a list of \a Clauses. /// /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. - /// - static OMPFirstprivateClause *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL); - /// \brief Creates an empty clause with the place for \a N variables. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPSingleDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. /// /// \param C AST context. - /// \param N The number of variables. + /// \param NumClauses Number of clauses. /// - static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N); + static OMPSingleDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPSingleDirectiveClass; } +}; + +/// \brief This represents '#pragma omp master' directive. +/// +/// \code +/// #pragma omp master +/// \endcode +/// +class OMPMasterDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, + StartLoc, EndLoc, 0, 1) {} + + /// \brief Build an empty directive. + /// + explicit OMPMasterDirective() + : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, + SourceLocation(), SourceLocation(), 0, 1) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPMasterDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPMasterDirective *CreateEmpty(const ASTContext &C, EmptyShell); - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_firstprivate; + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPMasterDirectiveClass; } }; -/// \brief This represents clause 'shared' in the '#pragma omp ...' directives. +/// \brief This represents '#pragma omp critical' directive. /// /// \code -/// #pragma omp parallel shared(a,b) +/// #pragma omp critical /// \endcode -/// In this example directive '#pragma omp parallel' has clause 'shared' -/// with the variables 'a' and 'b'. /// -class OMPSharedClause : public OMPClause, public OMPVarList<OMPSharedClause> { - /// \brief Build clause with number of variables \a N. +class OMPCriticalDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Name of the directive. + DeclarationNameInfo DirName; + /// \brief Build directive with the given start and end location. + /// + /// \param Name Name of the directive. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. /// - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. + OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc, + SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, + StartLoc, EndLoc, 0, 1), + DirName(Name) {} + + /// \brief Build an empty directive. /// - OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPClause(OMPC_shared, StartLoc, EndLoc), - OMPVarList<OMPSharedClause>(LParenLoc, N) { } + explicit OMPCriticalDirective() + : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, + SourceLocation(), SourceLocation(), 0, 1), + DirName() {} - /// \brief Build an empty clause. + /// \brief Set name of the directive. /// - /// \param N Number of variables. + /// \param Name Name of the directive. /// - explicit OMPSharedClause(unsigned N) - : OMPClause(OMPC_shared, SourceLocation(), SourceLocation()), - OMPVarList<OMPSharedClause>(SourceLocation(), N) { } + void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; } + public: - /// \brief Creates clause with a list of variables \a VL. + /// \brief Creates directive. /// /// \param C AST context. - /// \param StartLoc Starting location of the clause. - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. + /// \param Name Name of the directive. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. /// - static OMPSharedClause *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL); - /// \brief Creates an empty clause with \a N variables. + static OMPCriticalDirective * + Create(const ASTContext &C, const DeclarationNameInfo &Name, + SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. /// /// \param C AST context. - /// \param N The number of variables. /// - static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N); + static OMPCriticalDirective *CreateEmpty(const ASTContext &C, EmptyShell); - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); - } + /// \brief Return name of the directive. + /// + DeclarationNameInfo getDirectiveName() const { return DirName; } - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_shared; + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPCriticalDirectiveClass; } }; -//===----------------------------------------------------------------------===// -// AST classes for directives. -//===----------------------------------------------------------------------===// - -/// \brief This is a basic class for representing single OpenMP executable -/// directive. +/// \brief This represents '#pragma omp parallel for' directive. /// -class OMPExecutableDirective : public Stmt { +/// \code +/// #pragma omp parallel for private(a,b) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp parallel for' has clauses 'private' +/// with the variables 'a' and 'b' and 'reduction' with operator '+' and +/// variables 'c' and 'd'. +/// +class OMPParallelForDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Kind of the directive. - OpenMPDirectiveKind Kind; - /// \brief Starting location of the directive (directive keyword). - SourceLocation StartLoc; - /// \brief Ending location of the directive. - SourceLocation EndLoc; - /// \brief Pointer to the list of clauses. - llvm::MutableArrayRef<OMPClause *> Clauses; - /// \brief Associated statement (if any) and expressions. - llvm::MutableArrayRef<Stmt *> StmtAndExpressions; -protected: - /// \brief Build instance of directive of class \a K. + /// \brief Number of collapsed loops as specified by 'collapse' clause. + unsigned CollapsedNum; + /// \brief Build directive with the given start and end location. /// - /// \param SC Statement class. - /// \param K Kind of OpenMP directive. - /// \param StartLoc Starting location of the directive (directive keyword). + /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. /// - template <typename T> - OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K, - SourceLocation StartLoc, SourceLocation EndLoc, - unsigned NumClauses, unsigned NumberOfExpressions) - : Stmt(SC), Kind(K), StartLoc(StartLoc), EndLoc(EndLoc), - Clauses(reinterpret_cast<OMPClause **>(static_cast<T *>(this) + 1), - NumClauses), - StmtAndExpressions(reinterpret_cast<Stmt **>(Clauses.end()), - NumberOfExpressions) { } + OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPExecutableDirective(this, OMPParallelForDirectiveClass, + OMPD_parallel_for, StartLoc, EndLoc, NumClauses, + 1), + CollapsedNum(CollapsedNum) {} - /// \brief Sets the list of variables for this clause. + /// \brief Build an empty directive. /// - /// \param Clauses The list of clauses for the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. /// - void setClauses(ArrayRef<OMPClause *> Clauses); + explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses) + : OMPExecutableDirective(this, OMPParallelForDirectiveClass, + OMPD_parallel_for, SourceLocation(), + SourceLocation(), NumClauses, 1), + CollapsedNum(CollapsedNum) {} - /// \brief Set the associated statement for the directive. +public: + /// \brief Creates directive with a list of \a Clauses. /// - /// /param S Associated statement. + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. /// - void setAssociatedStmt(Stmt *S) { - StmtAndExpressions[0] = S; + static OMPParallelForDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPParallelForDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + unsigned getCollapsedNumber() const { return CollapsedNum; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelForDirectiveClass; } +}; + +/// \brief This represents '#pragma omp parallel sections' directive. +/// +/// \code +/// #pragma omp parallel sections private(a,b) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp parallel sections' has clauses +/// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+' +/// and variables 'c' and 'd'. +/// +class OMPParallelSectionsDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPParallelSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass, + OMPD_parallel_sections, StartLoc, EndLoc, + NumClauses, 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPParallelSectionsDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass, + OMPD_parallel_sections, SourceLocation(), + SourceLocation(), NumClauses, 1) {} public: - /// \brief Returns starting location of directive kind. - SourceLocation getLocStart() const { return StartLoc; } - /// \brief Returns ending location of directive. - SourceLocation getLocEnd() const { return EndLoc; } + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPParallelSectionsDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Set starting location of directive kind. + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. /// - /// \param Loc New starting location of directive. + /// \param C AST context. + /// \param NumClauses Number of clauses. /// - void setLocStart(SourceLocation Loc) { StartLoc = Loc; } - /// \brief Set ending location of directive. + static OMPParallelSectionsDirective * + CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelSectionsDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp task' directive. +/// +/// \code +/// #pragma omp task private(a,b) final(d) +/// \endcode +/// In this example directive '#pragma omp task' has clauses 'private' with the +/// variables 'a' and 'b' and 'final' with condition 'd'. +/// +class OMPTaskDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. /// - /// \param Loc New ending location of directive. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. /// - void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } + OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc, + EndLoc, NumClauses, 1) {} - /// \brief Get number of clauses. - unsigned getNumClauses() const { return Clauses.size(); } + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTaskDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, + SourceLocation(), SourceLocation(), NumClauses, + 1) {} - /// \brief Returns specified clause. +public: + /// \brief Creates directive with a list of \a Clauses. /// - /// \param i Number of clause. + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. /// - OMPClause *getClause(unsigned i) const { - assert(i < Clauses.size() && "index out of bound!"); - return Clauses[i]; - } + static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt); - /// \brief Returns statement associated with the directive. - Stmt *getAssociatedStmt() const { - return StmtAndExpressions[0]; + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskDirectiveClass; } +}; - OpenMPDirectiveKind getDirectiveKind() const { return Kind; } +/// \brief This represents '#pragma omp taskyield' directive. +/// +/// \code +/// #pragma omp taskyield +/// \endcode +/// +class OMPTaskyieldDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, + StartLoc, EndLoc, 0, 0) {} - static bool classof(const Stmt *S) { - return S->getStmtClass() >= firstOMPExecutableDirectiveConstant && - S->getStmtClass() <= lastOMPExecutableDirectiveConstant; - } + /// \brief Build an empty directive. + /// + explicit OMPTaskyieldDirective() + : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, + SourceLocation(), SourceLocation(), 0, 0) {} - child_range children() { - return child_range(StmtAndExpressions.begin(), StmtAndExpressions.end()); +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// + static OMPTaskyieldDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskyieldDirectiveClass; } +}; + +/// \brief This represents '#pragma omp barrier' directive. +/// +/// \code +/// #pragma omp barrier +/// \endcode +/// +class OMPBarrierDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, + StartLoc, EndLoc, 0, 0) {} - ArrayRef<OMPClause *> clauses() { return Clauses; } + /// \brief Build an empty directive. + /// + explicit OMPBarrierDirective() + : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, + SourceLocation(), SourceLocation(), 0, 0) {} - ArrayRef<OMPClause *> clauses() const { return Clauses; } +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// + static OMPBarrierDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPBarrierDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPBarrierDirectiveClass; + } }; -/// \brief This represents '#pragma omp parallel' directive. +/// \brief This represents '#pragma omp taskwait' directive. /// /// \code -/// #pragma omp parallel private(a,b) reduction(+: c,d) +/// #pragma omp taskwait /// \endcode -/// In this example directive '#pragma omp parallel' has clauses 'private' -/// with the variables 'a' and 'b' and 'reduction' with operator '+' and -/// variables 'c' and 'd'. /// -class OMPParallelDirective : public OMPExecutableDirective { +class OMPTaskwaitDirective : public OMPExecutableDirective { + friend class ASTStmtReader; /// \brief Build directive with the given start and end location. /// - /// \param StartLoc Starting location of the directive (directive keyword). + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait, + StartLoc, EndLoc, 0, 0) {} + + /// \brief Build an empty directive. + /// + explicit OMPTaskwaitDirective() + : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait, + SourceLocation(), SourceLocation(), 0, 0) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. /// - OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc, - unsigned N) - : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, - StartLoc, EndLoc, N, 1) { } + static OMPTaskwaitDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskwaitDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp flush' directive. +/// +/// \code +/// #pragma omp flush(a,b) +/// \endcode +/// In this example directive '#pragma omp flush' has 2 arguments- variables 'a' +/// and 'b'. +/// 'omp flush' directive does not have clauses but have an optional list of +/// variables to flush. This list of variables is stored within some fake clause +/// FlushClause. +class OMPFlushDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush, + StartLoc, EndLoc, NumClauses, 0) {} /// \brief Build an empty directive. /// - /// \param N Number of clauses. + /// \param NumClauses Number of clauses. /// - explicit OMPParallelDirective(unsigned N) - : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, - SourceLocation(), SourceLocation(), N, 1) { } + explicit OMPFlushDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush, + SourceLocation(), SourceLocation(), NumClauses, + 0) {} + public: /// \brief Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. - /// \param Clauses List of clauses. - /// \param AssociatedStmt Statement associated with the directive. + /// \param Clauses List of clauses (only single OMPFlushClause clause is + /// allowed). /// - static OMPParallelDirective *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses); - /// \brief Creates an empty directive with the place for \a N clauses. + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. /// /// \param C AST context. - /// \param N The number of clauses. + /// \param NumClauses Number of clauses. /// - static OMPParallelDirective *CreateEmpty(const ASTContext &C, unsigned N, - EmptyShell); + static OMPFlushDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); static bool classof(const Stmt *T) { - return T->getStmtClass() == OMPParallelDirectiveClass; + return T->getStmtClass() == OMPFlushDirectiveClass; } }; -} // end namespace clang +} // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h index 6c40eb1..1026a78 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h +++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h @@ -18,6 +18,7 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -34,8 +35,7 @@ struct PrintingPolicy; class TypeSourceInfo; class ValueDecl; -/// \brief Represents a template argument within a class template -/// specialization. +/// \brief Represents a template argument. class TemplateArgument { public: /// \brief The kind of template argument we're storing. @@ -52,16 +52,19 @@ public: /// was provided for a non-type template parameter. NullPtr, /// The template argument is an integral value stored in an llvm::APSInt - /// that was provided for an integral non-type template parameter. + /// that was provided for an integral non-type template parameter. Integral, - /// The template argument is a template name that was provided for a + /// The template argument is a template name that was provided for a /// template template parameter. Template, - /// The template argument is a pack expansion of a template name that was + /// The template argument is a pack expansion of a template name that was /// provided for a template template parameter. TemplateExpansion, - /// The template argument is a value- or type-dependent expression or a - /// non-dependent __uuidof expression stored in an Expr*. + /// The template argument is an expression, and we've not resolved it to one + /// of the other forms yet, either because it's dependent or because we're + /// representing a non-canonical template argument (for instance, in a + /// TemplateSpecializationType). Also used to represent a non-dependent + /// __uuidof expression (a Microsoft extension). Expression, /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. @@ -202,7 +205,7 @@ public: } static TemplateArgument getEmptyPack() { - return TemplateArgument((TemplateArgument*)0, 0); + return TemplateArgument((TemplateArgument*)nullptr, 0); } /// \brief Create a new template argument pack by copying the given set of @@ -325,6 +328,12 @@ public: return Args.Args + Args.NumArgs; } + /// \brief Iterator range referencing all of the elements of a template + /// argument pack. + llvm::iterator_range<pack_iterator> pack_elements() const { + return llvm::make_range(pack_begin(), pack_end()); + } + /// \brief The number of template arguments in the given template argument /// pack. unsigned pack_size() const { @@ -333,9 +342,9 @@ public: } /// \brief Return the array of arguments in this template argument pack. - llvm::ArrayRef<TemplateArgument> getPackAsArray() const { + ArrayRef<TemplateArgument> getPackAsArray() const { assert(getKind() == Pack); - return llvm::ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs); + return ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs); } /// \brief Determines whether two template arguments are superficially the @@ -541,6 +550,10 @@ public: return Arguments[I]; } + TemplateArgumentLoc &operator[](unsigned I) { + return Arguments[I]; + } + void addArgument(const TemplateArgumentLoc &Loc) { Arguments.push_back(Loc); } @@ -565,7 +578,8 @@ struct ASTTemplateArgumentListInfo { /// Force ASTTemplateArgumentListInfo to the right alignment /// for the following array of TemplateArgumentLocs. - void *Aligner; + llvm::AlignedCharArray< + llvm::AlignOf<TemplateArgumentLoc>::Alignment, 1> Aligner; }; /// \brief Retrieve the template arguments diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h index 0b9d4c8..f3d23b9 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h +++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h @@ -15,7 +15,6 @@ #define LLVM_CLANG_AST_TEMPLATENAME_H #include "clang/Basic/LLVM.h" -#include "clang/Basic/OperatorKinds.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" @@ -25,13 +24,14 @@ class ASTContext; class DependentTemplateName; class DiagnosticBuilder; class IdentifierInfo; +class NamedDecl; class NestedNameSpecifier; +enum OverloadedOperatorKind : int; class OverloadedTemplateStorage; struct PrintingPolicy; class QualifiedTemplateName; -class NamedDecl; -class SubstTemplateTemplateParmStorage; class SubstTemplateTemplateParmPackStorage; +class SubstTemplateTemplateParmStorage; class TemplateArgument; class TemplateDecl; class TemplateTemplateParmDecl; @@ -71,19 +71,19 @@ public: OverloadedTemplateStorage *getAsOverloadedStorage() { return Bits.Kind == Overloaded ? reinterpret_cast<OverloadedTemplateStorage *>(this) - : 0; + : nullptr; } SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() { return Bits.Kind == SubstTemplateTemplateParm ? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this) - : 0; + : nullptr; } SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() { return Bits.Kind == SubstTemplateTemplateParmPack ? reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) - : 0; + : nullptr; } }; @@ -243,7 +243,7 @@ public: Storage.dyn_cast<UncommonTemplateNameStorage *>()) return Uncommon->getAsOverloadedStorage(); - return 0; + return nullptr; } /// \brief Retrieve the substituted template template parameter, if @@ -256,7 +256,7 @@ public: Storage.dyn_cast<UncommonTemplateNameStorage *>()) return uncommon->getAsSubstTemplateTemplateParm(); - return 0; + return nullptr; } /// \brief Retrieve the substituted template template parameter pack, if @@ -270,7 +270,7 @@ public: Storage.dyn_cast<UncommonTemplateNameStorage *>()) return Uncommon->getAsSubstTemplateTemplateParmPack(); - return 0; + return nullptr; } /// \brief Retrieve the underlying qualified template name diff --git a/contrib/llvm/tools/clang/include/clang/AST/Type.h b/contrib/llvm/tools/clang/include/clang/AST/Type.h index fb829e4..09862e4 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Type.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Type.h @@ -18,20 +18,19 @@ #include "clang/AST/TemplateName.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/ExceptionSpecificationType.h" -#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" -#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/type_traits.h" namespace clang { enum { @@ -500,14 +499,14 @@ struct SplitQualType { /// The local qualifiers. Qualifiers Quals; - SplitQualType() : Ty(0), Quals() {} + SplitQualType() : Ty(nullptr), Quals() {} SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {} SplitQualType getSingleStepDesugaredType() const; // end of this file - // Make llvm::tie work. - operator std::pair<const Type *,Qualifiers>() const { - return std::pair<const Type *,Qualifiers>(Ty, Quals); + // Make std::tie work. + std::pair<const Type *,Qualifiers> asPair() const { + return std::pair<const Type *, Qualifiers>(Ty, Quals); } friend bool operator==(SplitQualType a, SplitQualType b) { @@ -1438,7 +1437,7 @@ public: /// \brief Def If non-NULL, and the type refers to some kind of declaration /// that can be completed (such as a C struct, C++ class, or Objective-C /// class), will be set to the declaration. - bool isIncompleteType(NamedDecl **Def = 0) const; + bool isIncompleteType(NamedDecl **Def = nullptr) const; /// isIncompleteOrObjectType - Return true if this is an incomplete or object /// type, in other words, not a function type. @@ -1797,7 +1796,7 @@ public: return CanonicalType; } CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h - LLVM_ATTRIBUTE_USED void dump() const; + void dump() const; friend class ASTReader; friend class ASTWriter; @@ -1996,39 +1995,59 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } }; -/// \brief Represents a pointer type decayed from an array or function type. -class DecayedType : public Type, public llvm::FoldingSetNode { - QualType OriginalType; - QualType DecayedPointer; +/// \brief Represents a type which was implicitly adjusted by the semantic +/// engine for arbitrary reasons. For example, array and function types can +/// decay, and function types can have their calling conventions adjusted. +class AdjustedType : public Type, public llvm::FoldingSetNode { + QualType OriginalTy; + QualType AdjustedTy; - DecayedType(QualType OriginalType, QualType DecayedPointer, - QualType CanonicalPtr) - : Type(Decayed, CanonicalPtr, OriginalType->isDependentType(), - OriginalType->isInstantiationDependentType(), - OriginalType->isVariablyModifiedType(), - OriginalType->containsUnexpandedParameterPack()), - OriginalType(OriginalType), DecayedPointer(DecayedPointer) { - assert(isa<PointerType>(DecayedPointer)); - } +protected: + AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy, + QualType CanonicalPtr) + : Type(TC, CanonicalPtr, OriginalTy->isDependentType(), + OriginalTy->isInstantiationDependentType(), + OriginalTy->isVariablyModifiedType(), + OriginalTy->containsUnexpandedParameterPack()), + OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {} friend class ASTContext; // ASTContext creates these. public: - QualType getDecayedType() const { return DecayedPointer; } - QualType getOriginalType() const { return OriginalType; } - - QualType getPointeeType() const { - return cast<PointerType>(DecayedPointer)->getPointeeType(); - } + QualType getOriginalType() const { return OriginalTy; } + QualType getAdjustedType() const { return AdjustedTy; } bool isSugared() const { return true; } - QualType desugar() const { return DecayedPointer; } + QualType desugar() const { return AdjustedTy; } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, OriginalType); + Profile(ID, OriginalTy, AdjustedTy); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Orig, QualType New) { + ID.AddPointer(Orig.getAsOpaquePtr()); + ID.AddPointer(New.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == Adjusted || T->getTypeClass() == Decayed; } - static void Profile(llvm::FoldingSetNodeID &ID, QualType OriginalType) { - ID.AddPointer(OriginalType.getAsOpaquePtr()); +}; + +/// \brief Represents a pointer type decayed from an array or function type. +class DecayedType : public AdjustedType { + + DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr) + : AdjustedType(Decayed, OriginalType, DecayedPtr, CanonicalPtr) { + assert(isa<PointerType>(getAdjustedType())); + } + + friend class ASTContext; // ASTContext creates these. + +public: + QualType getDecayedType() const { return getAdjustedType(); } + + QualType getPointeeType() const { + return cast<PointerType>(getDecayedType())->getPointeeType(); } static bool classof(const Type *T) { return T->getTypeClass() == Decayed; } @@ -2185,6 +2204,7 @@ public: } const Type *getClass() const { return Class; } + CXXRecordDecl *getMostRecentCXXRecordDecl() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2758,8 +2778,7 @@ protected: unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } public: - - QualType getResultType() const { return ResultType; } + QualType getReturnType() const { return ResultType; } bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } unsigned getRegParmType() const { return getExtInfo().getRegParm(); } @@ -2776,7 +2795,7 @@ public: /// \brief Determine the type of an expression that calls a function of /// this type. QualType getCallResultType(ASTContext &Context) const { - return getResultType().getNonLValueExprType(Context); + return getReturnType().getNonLValueExprType(Context); } static StringRef getNameForCallConv(CallingConv CC); @@ -2805,7 +2824,7 @@ public: QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getResultType(), getExtInfo()); + Profile(ID, getReturnType(), getExtInfo()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, ExtInfo Info) { @@ -2818,27 +2837,28 @@ public: } }; -/// FunctionProtoType - Represents a prototype with argument type info, e.g. +/// FunctionProtoType - Represents a prototype with parameter type info, e.g. /// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no -/// arguments, not as having a single void argument. Such a type can have an +/// parameters, not as having a single void parameter. Such a type can have an /// exception specification, but this specification is not part of the canonical /// type. class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { public: /// ExtProtoInfo - Extra information about a function prototype. struct ExtProtoInfo { - ExtProtoInfo() : - Variadic(false), HasTrailingReturn(false), TypeQuals(0), - ExceptionSpecType(EST_None), RefQualifier(RQ_None), - NumExceptions(0), Exceptions(0), NoexceptExpr(0), - ExceptionSpecDecl(0), ExceptionSpecTemplate(0), - ConsumedArguments(0) {} + ExtProtoInfo() + : Variadic(false), HasTrailingReturn(false), TypeQuals(0), + ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), + Exceptions(nullptr), NoexceptExpr(nullptr), + ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), + ConsumedParameters(nullptr) {} ExtProtoInfo(CallingConv CC) : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), - Exceptions(0), NoexceptExpr(0), ExceptionSpecDecl(0), - ExceptionSpecTemplate(0), ConsumedArguments(0) {} + Exceptions(nullptr), NoexceptExpr(nullptr), + ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), + ConsumedParameters(nullptr) {} FunctionType::ExtInfo ExtInfo; bool Variadic : 1; @@ -2851,7 +2871,7 @@ public: Expr *NoexceptExpr; FunctionDecl *ExceptionSpecDecl; FunctionDecl *ExceptionSpecTemplate; - const bool *ConsumedArguments; + const bool *ConsumedParameters; }; private: @@ -2866,11 +2886,11 @@ private: return false; } - FunctionProtoType(QualType result, ArrayRef<QualType> args, + FunctionProtoType(QualType result, ArrayRef<QualType> params, QualType canonical, const ExtProtoInfo &epi); - /// NumArgs - The number of arguments this function has, not counting '...'. - unsigned NumArgs : 15; + /// The number of parameters this function has, not counting '...'. + unsigned NumParams : 15; /// NumExceptions - The number of types in the exception spec, if any. unsigned NumExceptions : 9; @@ -2878,8 +2898,8 @@ private: /// ExceptionSpecType - The type of exception specification this function has. unsigned ExceptionSpecType : 3; - /// HasAnyConsumedArgs - Whether this function has any consumed arguments. - unsigned HasAnyConsumedArgs : 1; + /// HasAnyConsumedParams - Whether this function has any consumed parameters. + unsigned HasAnyConsumedParams : 1; /// Variadic - Whether the function is variadic. unsigned Variadic : 1; @@ -2892,8 +2912,8 @@ private: /// This is a value of type \c RefQualifierKind. unsigned RefQualifier : 2; - // ArgInfo - There is an variable size array after the class in memory that - // holds the argument types. + // ParamInfo - There is an variable size array after the class in memory that + // holds the parameter types. // Exceptions - There is another variable size array after ArgInfo that // holds the exception types. @@ -2906,17 +2926,17 @@ private: // instantiate this function type's exception specification, and the function // from which it should be instantiated. - // ConsumedArgs - A variable size array, following Exceptions - // and of length NumArgs, holding flags indicating which arguments - // are consumed. This only appears if HasAnyConsumedArgs is true. + // ConsumedParameters - A variable size array, following Exceptions + // and of length NumParams, holding flags indicating which parameters + // are consumed. This only appears if HasAnyConsumedParams is true. friend class ASTContext; // ASTContext creates these. - const bool *getConsumedArgsBuffer() const { - assert(hasAnyConsumedArgs()); + const bool *getConsumedParamsBuffer() const { + assert(hasAnyConsumedParams()); // Find the end of the exceptions. - Expr * const *eh_end = reinterpret_cast<Expr * const *>(arg_type_end()); + Expr *const *eh_end = reinterpret_cast<Expr *const *>(param_type_end()); if (getExceptionSpecType() != EST_ComputedNoexcept) eh_end += NumExceptions; else @@ -2926,13 +2946,13 @@ private: } public: - unsigned getNumArgs() const { return NumArgs; } - QualType getArgType(unsigned i) const { - assert(i < NumArgs && "Invalid argument number!"); - return arg_type_begin()[i]; + unsigned getNumParams() const { return NumParams; } + QualType getParamType(unsigned i) const { + assert(i < NumParams && "invalid parameter index"); + return param_type_begin()[i]; } - ArrayRef<QualType> getArgTypes() const { - return ArrayRef<QualType>(arg_type_begin(), arg_type_end()); + ArrayRef<QualType> getParamTypes() const { + return ArrayRef<QualType>(param_type_begin(), param_type_end()); } ExtProtoInfo getExtProtoInfo() const { @@ -2954,8 +2974,8 @@ public: } else if (EPI.ExceptionSpecType == EST_Unevaluated) { EPI.ExceptionSpecDecl = getExceptionSpecDecl(); } - if (hasAnyConsumedArgs()) - EPI.ConsumedArguments = getConsumedArgsBuffer(); + if (hasAnyConsumedParams()) + EPI.ConsumedParameters = getConsumedParamsBuffer(); return EPI; } @@ -2992,9 +3012,9 @@ public: } Expr *getNoexceptExpr() const { if (getExceptionSpecType() != EST_ComputedNoexcept) - return 0; + return nullptr; // NoexceptExpr sits where the arguments end. - return *reinterpret_cast<Expr *const *>(arg_type_end()); + return *reinterpret_cast<Expr *const *>(param_type_end()); } /// \brief If this function type has an exception specification which hasn't /// been determined yet (either because it has not been evaluated or because @@ -3003,8 +3023,8 @@ public: FunctionDecl *getExceptionSpecDecl() const { if (getExceptionSpecType() != EST_Uninstantiated && getExceptionSpecType() != EST_Unevaluated) - return 0; - return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[0]; + return nullptr; + return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0]; } /// \brief If this function type has an uninstantiated exception /// specification, this is the function whose exception specification @@ -3012,18 +3032,13 @@ public: /// this type. FunctionDecl *getExceptionSpecTemplate() const { if (getExceptionSpecType() != EST_Uninstantiated) - return 0; - return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[1]; - } - bool isNothrow(const ASTContext &Ctx) const { - ExceptionSpecificationType EST = getExceptionSpecType(); - assert(EST != EST_Unevaluated && EST != EST_Uninstantiated); - if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) - return true; - if (EST != EST_ComputedNoexcept) - return false; - return getNoexceptSpec(Ctx) == NR_Nothrow; + return nullptr; + return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1]; } + /// \brief Determine whether this function type has a non-throwing exception + /// specification. If this depends on template arguments, returns + /// \c ResultIfDependent. + bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const; bool isVariadic() const { return Variadic; } @@ -3045,16 +3060,28 @@ public: return static_cast<RefQualifierKind>(RefQualifier); } - typedef const QualType *arg_type_iterator; - arg_type_iterator arg_type_begin() const { + typedef const QualType *param_type_iterator; + typedef llvm::iterator_range<param_type_iterator> param_type_range; + + param_type_range param_types() const { + return param_type_range(param_type_begin(), param_type_end()); + } + param_type_iterator param_type_begin() const { return reinterpret_cast<const QualType *>(this+1); } - arg_type_iterator arg_type_end() const { return arg_type_begin()+NumArgs; } + param_type_iterator param_type_end() const { + return param_type_begin() + NumParams; + } typedef const QualType *exception_iterator; + typedef llvm::iterator_range<exception_iterator> exception_range; + + exception_range exceptions() const { + return exception_range(exception_begin(), exception_end()); + } exception_iterator exception_begin() const { // exceptions begin where arguments end - return arg_type_end(); + return param_type_end(); } exception_iterator exception_end() const { if (getExceptionSpecType() != EST_Dynamic) @@ -3062,13 +3089,11 @@ public: return exception_begin() + NumExceptions; } - bool hasAnyConsumedArgs() const { - return HasAnyConsumedArgs; - } - bool isArgConsumed(unsigned I) const { - assert(I < getNumArgs() && "argument index out of range!"); - if (hasAnyConsumedArgs()) - return getConsumedArgsBuffer()[I]; + bool hasAnyConsumedParams() const { return HasAnyConsumedParams; } + bool isParamConsumed(unsigned I) const { + assert(I < getNumParams() && "parameter index out of range"); + if (hasAnyConsumedParams()) + return getConsumedParamsBuffer()[I]; return false; } @@ -3084,7 +3109,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx); static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, - arg_type_iterator ArgTys, unsigned NumArgs, + param_type_iterator ArgTys, unsigned NumArgs, const ExtProtoInfo &EPI, const ASTContext &Context); }; @@ -3495,7 +3520,7 @@ public: bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; } TemplateTypeParmDecl *getDecl() const { - return isCanonicalUnqualified() ? 0 : TTPDecl; + return isCanonicalUnqualified() ? nullptr : TTPDecl; } IdentifierInfo *getIdentifier() const; @@ -3956,9 +3981,9 @@ public: static bool KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword); - static const char *getKeywordName(ElaboratedTypeKeyword Keyword); + static StringRef getKeywordName(ElaboratedTypeKeyword Keyword); - static const char *getTagTypeKindName(TagTypeKind Kind) { + static StringRef getTagTypeKindName(TagTypeKind Kind) { return getKeywordName(getKeywordForTagTypeKind(Kind)); } @@ -3990,7 +4015,7 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { NamedType->isVariablyModifiedType(), NamedType->containsUnexpandedParameterPack()), NNS(NNS), NamedType(NamedType) { - assert(!(Keyword == ETK_None && NNS == 0) && + assert(!(Keyword == ETK_None && NNS == nullptr) && "ElaboratedType cannot have elaborated type keyword " "and name qualifier both null."); } @@ -4032,11 +4057,14 @@ public: /// dependent. /// /// DependentNameType represents a class of dependent types that involve a -/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent) +/// possibly dependent nested-name-specifier (e.g., "T::") followed by a /// name of a type. The DependentNameType may start with a "typename" (for a /// typename-specifier), "class", "struct", "union", or "enum" (for a /// dependent elaborated-type-specifier), or nothing (in contexts where we /// know that we must be referring to a type, e.g., in a base class specifier). +/// Typically the nested-name-specifier is dependent, but in MSVC compatibility +/// mode, this type is used with non-dependent names to delay name lookup until +/// instantiation. class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { /// \brief The nested name specifier containing the qualifier. @@ -4051,10 +4079,7 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { /*InstantiationDependent=*/true, /*VariablyModified=*/false, NNS->containsUnexpandedParameterPack()), - NNS(NNS), Name(Name) { - assert(NNS->isDependent() && - "DependentNameType requires a dependent nested-name-specifier"); - } + NNS(NNS), Name(Name) {} friend class ASTContext; // ASTContext creates these @@ -4199,7 +4224,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { Optional<unsigned> NumExpansions) : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), /*InstantiationDependent=*/true, - /*VariableModified=*/Pattern->isVariablyModifiedType(), + /*VariablyModified=*/Pattern->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), Pattern(Pattern), NumExpansions(NumExpansions? *NumExpansions + 1: 0) { } @@ -4326,7 +4351,9 @@ public: ObjCInterfaceDecl *getInterface() const; typedef ObjCProtocolDecl * const *qual_iterator; + typedef llvm::iterator_range<qual_iterator> qual_range; + qual_range quals() const { return qual_range(qual_begin(), qual_end()); } qual_iterator qual_begin() const { return getProtocolStorage(); } qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); } @@ -4430,7 +4457,7 @@ inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { if (const ObjCInterfaceType *T = getBaseType()->getAs<ObjCInterfaceType>()) return T->getDecl(); - return 0; + return nullptr; } /// ObjCObjectPointerType - Used to represent a pointer to an @@ -4528,7 +4555,9 @@ public: /// for convenience. This will always iterate over the full set of /// protocols on a type, not just those provided directly. typedef ObjCObjectType::qual_iterator qual_iterator; + typedef llvm::iterator_range<qual_iterator> qual_range; + qual_range quals() const { return qual_range(qual_begin(), qual_end()); } qual_iterator qual_begin() const { return getObjectType()->qual_begin(); } @@ -4633,7 +4662,7 @@ inline const Type *QualType::getTypePtr() const { } inline const Type *QualType::getTypePtrOrNull() const { - return (isNull() ? 0 : getCommonPtr()->BaseType); + return (isNull() ? nullptr : getCommonPtr()->BaseType); } inline SplitQualType QualType::split() const { @@ -5022,7 +5051,7 @@ inline const BuiltinType *Type::getAsPlaceholderType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) if (BT->isPlaceholderType()) return BT; - return 0; + return nullptr; } inline bool Type::isSpecificPlaceholderType(unsigned K) const { @@ -5159,10 +5188,9 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, // Helper class template that is used by Type::getAs to ensure that one does // not try to look through a qualified type to get to an array type. -template<typename T, - bool isArrayType = (llvm::is_same<T, ArrayType>::value || - llvm::is_base_of<ArrayType, T>::value)> -struct ArrayType_cannot_be_used_with_getAs { }; +template <typename T, bool isArrayType = (std::is_same<T, ArrayType>::value || + std::is_base_of<ArrayType, T>::value)> +struct ArrayType_cannot_be_used_with_getAs {}; template<typename T> struct ArrayType_cannot_be_used_with_getAs<T, true>; @@ -5178,7 +5206,7 @@ template <typename T> const T *Type::getAs() const { // If the canonical form of this type isn't the right kind, reject it. if (!isa<T>(CanonicalType)) - return 0; + return nullptr; // If this is a typedef for the type, strip the typedef off without // losing all typedef information. @@ -5192,7 +5220,7 @@ inline const ArrayType *Type::getAsArrayTypeUnsafe() const { // If the canonical form of this type isn't the right kind, reject it. if (!isa<ArrayType>(CanonicalType)) - return 0; + return nullptr; // If this is a typedef for the type, strip the typedef off without // losing all typedef information. diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h index 8ddfac7..3648d2a 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h @@ -81,7 +81,7 @@ public: Qualified }; - TypeLoc() : Ty(0), Data(0) { } + TypeLoc() : Ty(nullptr), Data(nullptr) { } TypeLoc(QualType ty, void *opaqueData) : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { } TypeLoc(const Type *ty, void *opaqueData) @@ -631,7 +631,7 @@ public: bool isDefinition() const { TagDecl *D = getDecl(); return D->isCompleteDefinition() && - (D->getIdentifier() == 0 || D->getLocation() == getNameLoc()); + (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc()); } }; @@ -786,7 +786,7 @@ public: setAttrNameLoc(loc); if (hasAttrExprOperand()) { setAttrOperandParensRange(SourceRange(loc)); - setAttrExprOperand(0); + setAttrExprOperand(nullptr); } else if (hasAttrEnumOperand()) { setAttrOperandParensRange(SourceRange(loc)); setAttrEnumOperandLoc(loc); @@ -978,12 +978,10 @@ inline TypeLoc TypeLoc::IgnoreParens() const { } -struct DecayedLocInfo { }; // Nothing. +struct AdjustedLocInfo { }; // Nothing. -/// \brief Wrapper for source info for pointers decayed from arrays and -/// functions. -class DecayedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, DecayedTypeLoc, - DecayedType, DecayedLocInfo> { +class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc, + AdjustedType, AdjustedLocInfo> { public: TypeLoc getOriginalLoc() const { return getInnerTypeLoc(); @@ -1004,12 +1002,17 @@ public: } unsigned getLocalDataSize() const { - // sizeof(DecayedLocInfo) is 1, but we don't need its address to be unique + // sizeof(AdjustedLocInfo) is 1, but we don't need its address to be unique // anyway. TypeLocBuilder can't handle data sizes of 1. return 0; // No data. } }; +/// \brief Wrapper for source info for pointers decayed from arrays and +/// functions. +class DecayedTypeLoc : public InheritingConcreteTypeLoc< + AdjustedTypeLoc, DecayedTypeLoc, DecayedType> { +}; struct PointerLikeLocInfo { SourceLocation StarLoc; @@ -1098,7 +1101,7 @@ public: void initializeLocal(ASTContext &Context, SourceLocation Loc) { setSigilLoc(Loc); - setClassTInfo(0); + setClassTInfo(nullptr); } SourceRange getLocalSourceRange() const { @@ -1205,23 +1208,23 @@ public: } ArrayRef<ParmVarDecl *> getParams() const { - return ArrayRef<ParmVarDecl *>(getParmArray(), getNumArgs()); + return ArrayRef<ParmVarDecl *>(getParmArray(), getNumParams()); } - // ParmVarDecls* are stored after Info, one for each argument. + // ParmVarDecls* are stored after Info, one for each parameter. ParmVarDecl **getParmArray() const { return (ParmVarDecl**) getExtraLocalData(); } - unsigned getNumArgs() const { + unsigned getNumParams() const { if (isa<FunctionNoProtoType>(getTypePtr())) return 0; - return cast<FunctionProtoType>(getTypePtr())->getNumArgs(); + return cast<FunctionProtoType>(getTypePtr())->getNumParams(); } - ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; } - void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } + ParmVarDecl *getParam(unsigned i) const { return getParmArray()[i]; } + void setParam(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } - TypeLoc getResultLoc() const { + TypeLoc getReturnLoc() const { return getInnerTypeLoc(); } @@ -1234,21 +1237,21 @@ public: setLParenLoc(Loc); setRParenLoc(Loc); setLocalRangeEnd(Loc); - for (unsigned i = 0, e = getNumArgs(); i != e; ++i) - setArg(i, NULL); + for (unsigned i = 0, e = getNumParams(); i != e; ++i) + setParam(i, nullptr); } /// \brief Returns the size of the type source info data block that is /// specific to this type. unsigned getExtraLocalDataSize() const { - return getNumArgs() * sizeof(ParmVarDecl*); + return getNumParams() * sizeof(ParmVarDecl *); } unsigned getExtraLocalDataAlignment() const { return llvm::alignOf<ParmVarDecl*>(); } - QualType getInnerType() const { return getTypePtr()->getResultType(); } + QualType getInnerType() const { return getTypePtr()->getReturnType(); } }; class FunctionProtoTypeLoc : @@ -1311,7 +1314,7 @@ public: void initializeLocal(ASTContext &Context, SourceLocation Loc) { setLBracketLoc(Loc); setRBracketLoc(Loc); - setSizeExpr(NULL); + setSizeExpr(nullptr); } QualType getInnerType() const { return getTypePtr()->getElementType(); } @@ -1771,7 +1774,7 @@ public: // template specialization type, we won't record the nested-name-specifier // location information when this type-source location information is // part of a nested-name-specifier. - getLocalData()->QualifierData = 0; + getLocalData()->QualifierData = nullptr; return; } diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def index 3126f48..3b2665b 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def @@ -81,7 +81,8 @@ TYPE(FunctionNoProto, FunctionType) DEPENDENT_TYPE(UnresolvedUsing, Type) NON_CANONICAL_TYPE(Paren, Type) NON_CANONICAL_TYPE(Typedef, Type) -NON_CANONICAL_TYPE(Decayed, Type) +NON_CANONICAL_TYPE(Adjusted, Type) +NON_CANONICAL_TYPE(Decayed, AdjustedType) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type) diff --git a/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h index 759af25..2ef5800 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h +++ b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h @@ -27,7 +27,7 @@ namespace clang { /// non-const iterator. class UnresolvedSetIterator { private: - typedef llvm::MutableArrayRef<DeclAccessPair> DeclsTy; + typedef MutableArrayRef<DeclAccessPair> DeclsTy; typedef DeclsTy::iterator IteratorTy; IteratorTy ir; diff --git a/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h index 4e45132..4e24bdd 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h +++ b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h @@ -19,8 +19,9 @@ #include "clang/AST/GlobalDecl.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/ABI.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" -#include "llvm/ADT/DenseSet.h" +#include <memory> #include <utility> namespace clang { @@ -208,11 +209,11 @@ public: typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; private: uint64_t NumVTableComponents; - llvm::OwningArrayPtr<VTableComponent> VTableComponents; + std::unique_ptr<VTableComponent[]> VTableComponents; /// \brief Contains thunks needed by vtables, sorted by indices. uint64_t NumVTableThunks; - llvm::OwningArrayPtr<VTableThunkTy> VTableThunks; + std::unique_ptr<VTableThunkTy[]> VTableThunks; /// \brief Address points for all vtables. AddressPointsMapTy AddressPoints; @@ -270,6 +271,10 @@ class VTableContextBase { public: typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; + bool isMicrosoft() const { return IsMicrosoftABI; } + + virtual ~VTableContextBase() {} + protected: typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy; @@ -280,7 +285,7 @@ protected: /// offset offsets, thunks etc) for the given record decl. virtual void computeVTableRelatedInformation(const CXXRecordDecl *RD) = 0; - virtual ~VTableContextBase() {} + VTableContextBase(bool MS) : IsMicrosoftABI(MS) {} public: virtual const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) { @@ -292,16 +297,17 @@ public: ThunksMapTy::const_iterator I = Thunks.find(MD); if (I == Thunks.end()) { // We did not find a thunk for this method. - return 0; + return nullptr; } return &I->second; } + + bool IsMicrosoftABI; }; class ItaniumVTableContext : public VTableContextBase { private: - bool IsMicrosoftABI; /// \brief Contains the index (relative to the vtable address point) /// where the function pointer for a virtual function is stored. @@ -323,7 +329,7 @@ private: VirtualBaseClassOffsetOffsetsMapTy; VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; - void computeVTableRelatedInformation(const CXXRecordDecl *RD); + void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; public: ItaniumVTableContext(ASTContext &Context); @@ -355,49 +361,83 @@ public: /// Base must be a virtual base class or an unambiguous base. CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase); + + static bool classof(const VTableContextBase *VT) { + return !VT->isMicrosoft(); + } }; -struct VFPtrInfo { +/// Holds information about the inheritance path to a virtual base or function +/// table pointer. A record may contain as many vfptrs or vbptrs as there are +/// base subobjects. +struct VPtrInfo { typedef SmallVector<const CXXRecordDecl *, 1> BasePath; - // Don't pass the PathToMangle as it should be calculated later. - VFPtrInfo(CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr) - : VBTableIndex(0), LastVBase(0), VFPtrOffset(VFPtrOffset), - PathToBaseWithVFPtr(PathToBaseWithVFPtr), VFPtrFullOffset(VFPtrOffset) { - } + VPtrInfo(const CXXRecordDecl *RD) + : ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {} - // Don't pass the PathToMangle as it should be calculated later. - VFPtrInfo(uint64_t VBTableIndex, const CXXRecordDecl *LastVBase, - CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr, - CharUnits VFPtrFullOffset) - : VBTableIndex(VBTableIndex), LastVBase(LastVBase), - VFPtrOffset(VFPtrOffset), PathToBaseWithVFPtr(PathToBaseWithVFPtr), - VFPtrFullOffset(VFPtrFullOffset) { - assert(VBTableIndex && "The full constructor should only be used " - "for vfptrs in virtual bases"); - assert(LastVBase); - } + // Copy constructor. + // FIXME: Uncomment when we've moved to C++11. + // VPtrInfo(const VPtrInfo &) = default; + + /// The vtable will hold all of the virtual bases or virtual methods of + /// ReusingBase. This may or may not be the same class as VPtrSubobject.Base. + /// A derived class will reuse the vptr of the first non-virtual base + /// subobject that has one. + const CXXRecordDecl *ReusingBase; + + /// BaseWithVPtr is at this offset from its containing complete object or + /// virtual base. + CharUnits NonVirtualOffset; - /// If nonzero, holds the vbtable index of the virtual base with the vfptr. - uint64_t VBTableIndex; + /// The vptr is stored inside this subobject. + const CXXRecordDecl *BaseWithVPtr; - /// Stores the last vbase on the path from the complete type to the vfptr. - const CXXRecordDecl *LastVBase; + /// The bases from the inheritance path that got used to mangle the vbtable + /// name. This is not really a full path like a CXXBasePath. It holds the + /// subset of records that need to be mangled into the vbtable symbol name in + /// order to get a unique name. + BasePath MangledPath; - /// This is the offset of the vfptr from the start of the last vbase, - /// or the complete type if there are no virtual bases. - CharUnits VFPtrOffset; + /// The next base to push onto the mangled path if this path is ambiguous in a + /// derived class. If it's null, then it's already been pushed onto the path. + const CXXRecordDecl *NextBaseToMangle; + + /// The set of possibly indirect vbases that contain this vbtable. When a + /// derived class indirectly inherits from the same vbase twice, we only keep + /// vtables and their paths from the first instance. + BasePath ContainingVBases; /// This holds the base classes path from the complete type to the first base - /// with the given vfptr offset, in the base-to-derived order. - BasePath PathToBaseWithVFPtr; + /// with the given vfptr offset, in the base-to-derived order. Only used for + /// vftables. + BasePath PathToBaseWithVPtr; + + /// Static offset from the top of the most derived class to this vfptr, + /// including any virtual base offset. Only used for vftables. + CharUnits FullOffsetInMDC; + + /// The vptr is stored inside the non-virtual component of this virtual base. + const CXXRecordDecl *getVBaseWithVPtr() const { + return ContainingVBases.empty() ? nullptr : ContainingVBases.front(); + } +}; + +typedef SmallVector<VPtrInfo *, 2> VPtrInfoVector; - /// This holds the subset of records that need to be mangled into the vftable - /// symbol name in order to get a unique name, in the derived-to-base order. - BasePath PathToMangle; +/// All virtual base related information about a given record decl. Includes +/// information on all virtual base tables and the path components that are used +/// to mangle them. +struct VirtualBaseInfo { + ~VirtualBaseInfo() { llvm::DeleteContainerPointers(VBPtrPaths); } - /// This is the full offset of the vfptr from the start of the complete type. - CharUnits VFPtrFullOffset; + /// A map from virtual base to vbtable index for doing a conversion from the + /// the derived class to the a base. + llvm::DenseMap<const CXXRecordDecl *, unsigned> VBTableIndices; + + /// Information on all virtual base tables used when this record is the most + /// derived class. + VPtrInfoVector VBPtrPaths; }; class MicrosoftVTableContext : public VTableContextBase { @@ -418,7 +458,7 @@ public: uint64_t Index; MethodVFTableLocation() - : VBTableIndex(0), VBase(0), VFPtrOffset(CharUnits::Zero()), + : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()), Index(0) {} MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase, @@ -431,16 +471,11 @@ public: assert(VBase != other.VBase); return VBTableIndex < other.VBTableIndex; } - if (VFPtrOffset != other.VFPtrOffset) - return VFPtrOffset < other.VFPtrOffset; - if (Index != other.Index) - return Index < other.Index; - return false; + return std::tie(VFPtrOffset, Index) < + std::tie(other.VFPtrOffset, other.Index); } }; - typedef SmallVector<VFPtrInfo, 1> VFPtrListTy; - private: ASTContext &Context; @@ -448,7 +483,7 @@ private: MethodVFTableLocationsTy; MethodVFTableLocationsTy MethodVFTableLocations; - typedef llvm::DenseMap<const CXXRecordDecl *, VFPtrListTy> + typedef llvm::DenseMap<const CXXRecordDecl *, VPtrInfoVector *> VFPtrLocationsMapTy; VFPtrLocationsMapTy VFPtrLocations; @@ -456,47 +491,40 @@ private: typedef llvm::DenseMap<VFTableIdTy, const VTableLayout *> VFTableLayoutMapTy; VFTableLayoutMapTy VFTableLayouts; - typedef llvm::SmallSetVector<const CXXRecordDecl *, 8> BasesSetVectorTy; - void enumerateVFPtrs(const CXXRecordDecl *MostDerivedClass, - const ASTRecordLayout &MostDerivedClassLayout, - BaseSubobject Base, const CXXRecordDecl *LastVBase, - const VFPtrInfo::BasePath &PathFromCompleteClass, - BasesSetVectorTy &VisitedVBases, - MicrosoftVTableContext::VFPtrListTy &Result); + llvm::DenseMap<const CXXRecordDecl *, VirtualBaseInfo *> VBaseInfo; - void enumerateVFPtrs(const CXXRecordDecl *ForClass, - MicrosoftVTableContext::VFPtrListTy &Result); + void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result); - void computeVTableRelatedInformation(const CXXRecordDecl *RD); + void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; void dumpMethodLocations(const CXXRecordDecl *RD, const MethodVFTableLocationsTy &NewMethods, raw_ostream &); - typedef std::pair<const CXXRecordDecl *, const CXXRecordDecl *> ClassPairTy; - typedef llvm::DenseMap<ClassPairTy, unsigned> VBTableIndicesTy; - VBTableIndicesTy VBTableIndices; - llvm::DenseSet<const CXXRecordDecl *> ComputedVBTableIndices; + const VirtualBaseInfo * + computeVBTableRelatedInformation(const CXXRecordDecl *RD); - void computeVBTableRelatedInformation(const CXXRecordDecl *RD); + void computeVTablePaths(bool ForVBTables, const CXXRecordDecl *RD, + VPtrInfoVector &Paths); public: - MicrosoftVTableContext(ASTContext &Context) : Context(Context) {} + MicrosoftVTableContext(ASTContext &Context) + : VTableContextBase(/*MS=*/true), Context(Context) {} - ~MicrosoftVTableContext() { llvm::DeleteContainerSeconds(VFTableLayouts); } + ~MicrosoftVTableContext(); - const VFPtrListTy &getVFPtrOffsets(const CXXRecordDecl *RD); + const VPtrInfoVector &getVFPtrOffsets(const CXXRecordDecl *RD); const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset); const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD); - const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) { + const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) override { // Complete destructors don't have a slot in a vftable, so no thunks needed. if (isa<CXXDestructorDecl>(GD.getDecl()) && GD.getDtorType() == Dtor_Complete) - return 0; + return nullptr; return VTableContextBase::getThunkInfo(GD); } @@ -505,14 +533,13 @@ public: /// The vbtable is an array of i32 offsets. The first entry is a self entry, /// and the rest are offsets from the vbptr to virtual bases. unsigned getVBTableIndex(const CXXRecordDecl *Derived, - const CXXRecordDecl *VBase) { - computeVBTableRelatedInformation(Derived); - ClassPairTy Pair(Derived, VBase); - assert(VBTableIndices.count(Pair) == 1 && - "VBase must be a vbase of Derived"); - return VBTableIndices[Pair]; - } + const CXXRecordDecl *VBase); + + const VPtrInfoVector &enumerateVBTables(const CXXRecordDecl *RD); + + static bool classof(const VTableContextBase *VT) { return VT->isMicrosoft(); } }; -} + +} // namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h index db0a83d..8af0546 100644 --- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h @@ -222,13 +222,13 @@ selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) { if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo)) return Node; } - return NULL; + return nullptr; } namespace internal { class CollectMatchesCallback : public MatchFinder::MatchCallback { public: - virtual void run(const MatchFinder::MatchResult &Result) { + void run(const MatchFinder::MatchResult &Result) override { Nodes.push_back(Result.Nodes); } SmallVector<BoundNodes, 1> Nodes; diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h index 0a3157d..1ff4ab3 100644 --- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -311,6 +311,12 @@ AST_MATCHER(Decl, isPrivate) { return Node.getAccess() == AS_private; } +/// \brief Matches a declaration that has been implicitly added +/// by the compiler (eg. implicit default/copy constructors). +AST_MATCHER(Decl, isImplicit) { + return Node.isImplicit(); +} + /// \brief Matches classTemplateSpecializations that have at least one /// TemplateArgument matching the given InnerMatcher. /// @@ -323,9 +329,13 @@ AST_MATCHER(Decl, isPrivate) { /// classTemplateSpecializationDecl(hasAnyTemplateArgument( /// refersToType(asString("int")))) /// matches the specialization \c A<int> -AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, - internal::Matcher<TemplateArgument>, InnerMatcher) { - llvm::ArrayRef<TemplateArgument> List = Node.getTemplateArgs().asArray(); +AST_POLYMORPHIC_MATCHER_P( + hasAnyTemplateArgument, + AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl, + TemplateSpecializationType), + internal::Matcher<TemplateArgument>, InnerMatcher) { + ArrayRef<TemplateArgument> List = + internal::getTemplateSpecializationArgs(Node); return matchesFirstInRange(InnerMatcher, List.begin(), List.end(), Finder, Builder); } @@ -419,12 +429,16 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts, /// classTemplateSpecializationDecl(hasTemplateArgument( /// 1, refersToType(asString("int")))) /// matches the specialization \c A<bool, int> -AST_MATCHER_P2(ClassTemplateSpecializationDecl, hasTemplateArgument, - unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) { - const TemplateArgumentList &List = Node.getTemplateArgs(); +AST_POLYMORPHIC_MATCHER_P2( + hasTemplateArgument, + AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl, + TemplateSpecializationType), + unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) { + ArrayRef<TemplateArgument> List = + internal::getTemplateSpecializationArgs(Node); if (List.size() <= N) return false; - return InnerMatcher.matches(List.get(N), Finder, Builder); + return InnerMatcher.matches(List[N], Finder, Builder); } /// \brief Matches a TemplateArgument that refers to a certain type. @@ -445,7 +459,8 @@ AST_MATCHER_P(TemplateArgument, refersToType, return InnerMatcher.matches(Node.getAsType(), Finder, Builder); } -/// \brief Matches a TemplateArgument that refers to a certain declaration. +/// \brief Matches a canonical TemplateArgument that refers to a certain +/// declaration. /// /// Given /// \code @@ -464,6 +479,24 @@ AST_MATCHER_P(TemplateArgument, refersToDeclaration, return false; } +/// \brief Matches a sugar TemplateArgument that refers to a certain expression. +/// +/// Given +/// \code +/// template<typename T> struct A {}; +/// struct B { B* next; }; +/// A<&B::next> a; +/// \endcode +/// templateSpecializationType(hasAnyTemplateArgument( +/// isExpr(hasDescendant(declRefExpr(to(fieldDecl(hasName("next")))))))) +/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching +/// \c B::next +AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) { + if (Node.getKind() == TemplateArgument::Expression) + return InnerMatcher.matches(*Node.getAsExpr(), Finder, Builder); + return false; +} + /// \brief Matches C++ constructor declarations. /// /// Example matches Foo::Foo() and Foo::Foo(int) @@ -518,7 +551,7 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example matches y /// \code -/// class X { void y() }; +/// class X { void y(); }; /// \endcode const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> methodDecl; @@ -635,6 +668,16 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, CXXMemberCallExpr> memberCallExpr; +/// \brief Matches expressions that introduce cleanups to be run at the end +/// of the sub-expression's evaluation. +/// +/// Example matches std::string() +/// \code +/// const std::string str = std::string(); +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups> +exprWithCleanups; + /// \brief Matches init list expressions. /// /// Given @@ -643,10 +686,23 @@ const internal::VariadicDynCastAllOfMatcher< /// struct B { int x, y; }; /// B b = { 5, 6 }; /// \endcode -/// initList() +/// initListExpr() /// matches "{ 1, 2 }" and "{ 5, 6 }" const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; +/// \brief Matches substitutions of non-type template parameters. +/// +/// Given +/// \code +/// template <int N> +/// struct A { static const int n = N; }; +/// struct B : public A<42> {}; +/// \endcode +/// substNonTypeTemplateParmExpr() +/// matches "N" in the right-hand side of "static const int n = N;" +const internal::VariadicDynCastAllOfMatcher<Stmt, SubstNonTypeTemplateParmExpr> +substNonTypeTemplateParmExpr; + /// \brief Matches using declarations. /// /// Given @@ -658,6 +714,18 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; /// matches \code using X::x \endcode const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; +/// \brief Matches using namespace declarations. +/// +/// Given +/// \code +/// namespace X { int x; } +/// using namespace X; +/// \endcode +/// usingDirectiveDecl() +/// matches \code using namespace X \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl> + usingDirectiveDecl; + /// \brief Matches unresolved using value declarations. /// /// Given @@ -842,15 +910,6 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; /// \endcode const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt; -/// \brief Matches range-based for statements. -/// -/// forRangeStmt() matches 'for (auto a : i)' -/// \code -/// int i[] = {1, 2, 3}; for (auto a : i); -/// for(int j = 0; j < 5; ++j); -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> forRangeStmt; - /// \brief Matches the increment statement of a for loop. /// /// Example: @@ -862,7 +921,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> forRangeStmt; AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>, InnerMatcher) { const Stmt *const Increment = Node.getInc(); - return (Increment != NULL && + return (Increment != nullptr && InnerMatcher.matches(*Increment, Finder, Builder)); } @@ -877,7 +936,44 @@ AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>, AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>, InnerMatcher) { const Stmt *const Init = Node.getInit(); - return (Init != NULL && InnerMatcher.matches(*Init, Finder, Builder)); + return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder)); +} + +/// \brief Matches range-based for statements. +/// +/// forRangeStmt() matches 'for (auto a : i)' +/// \code +/// int i[] = {1, 2, 3}; for (auto a : i); +/// for(int j = 0; j < 5; ++j); +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> forRangeStmt; + +/// \brief Matches the initialization statement of a for loop. +/// +/// Example: +/// forStmt(hasLoopVariable(anything())) +/// matches 'int x' in +/// \code +/// for (int x : a) { } +/// \endcode +AST_MATCHER_P(CXXForRangeStmt, hasLoopVariable, internal::Matcher<VarDecl>, + InnerMatcher) { + const VarDecl *const Var = Node.getLoopVariable(); + return (Var != nullptr && InnerMatcher.matches(*Var, Finder, Builder)); +} + +/// \brief Matches the range initialization statement of a for loop. +/// +/// Example: +/// forStmt(hasRangeInit(anything())) +/// matches 'a' in +/// \code +/// for (int x : a) { } +/// \endcode +AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>, + InnerMatcher) { + const Expr *const Init = Node.getRangeInit(); + return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder)); } /// \brief Matches while statements. @@ -1317,21 +1413,21 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; /// \c b. /// /// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc eachOf = { +const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = { internal::EachOfVariadicOperator }; /// \brief Matches if any of the given matchers matches. /// /// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc anyOf = { +const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = { internal::AnyOfVariadicOperator }; /// \brief Matches if all given matchers match. /// /// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc allOf = { +const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = { internal::AllOfVariadicOperator }; @@ -1458,14 +1554,14 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { /// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches /// the declaration of \c A. /// -/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl> +/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl> inline internal::PolymorphicMatcherWithParam1< internal::HasOverloadedOperatorNameMatcher, StringRef, - AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)> + AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)> hasOverloadedOperatorName(const StringRef Name) { return internal::PolymorphicMatcherWithParam1< internal::HasOverloadedOperatorNameMatcher, StringRef, - AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>( + AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>( Name); } @@ -1671,12 +1767,9 @@ const internal::ArgumentAdaptingMatcherFunc< /// \endcode /// /// Usable as: Any Matcher -template <typename M> -internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M> -unless(const M &InnerMatcher) { - return internal::PolymorphicMatcherWithParam1< - internal::NotMatcher, M>(InnerMatcher); -} +const internal::VariadicOperatorMatcherFunc<1, 1> unless = { + internal::NotUnaryOperator +}; /// \brief Matches a node if the declaration associated with that node /// matches the given matcher. @@ -1718,7 +1811,7 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, InnerMatcher) { const Expr *ExprNode = Node.getImplicitObjectArgument() ->IgnoreParenImpCasts(); - return (ExprNode != NULL && + return (ExprNode != nullptr && InnerMatcher.matches(*ExprNode, Finder, Builder)); } @@ -1741,7 +1834,7 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, InnerMatcher) { const Expr *ExprNode = Node.getCallee(); - return (ExprNode != NULL && + return (ExprNode != nullptr && InnerMatcher.matches(*ExprNode, Finder, Builder)); } @@ -1896,7 +1989,7 @@ AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>, AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, internal::Matcher<Expr>, InnerMatcher) { const Expr *ExprNode = Node.getImplicitObjectArgument(); - return (ExprNode != NULL && + return (ExprNode != nullptr && InnerMatcher.matches(*ExprNode, Finder, Builder)); } @@ -1929,7 +2022,7 @@ AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, InnerMatcher) { const Decl *DeclNode = Node.getDecl(); - return (DeclNode != NULL && + return (DeclNode != nullptr && InnerMatcher.matches(*DeclNode, Finder, Builder)); } @@ -1986,10 +2079,39 @@ AST_MATCHER_P( VarDecl, hasInitializer, internal::Matcher<Expr>, InnerMatcher) { const Expr *Initializer = Node.getAnyInitializer(); - return (Initializer != NULL && + return (Initializer != nullptr && InnerMatcher.matches(*Initializer, Finder, Builder)); } +/// \brief Matches a variable declaration that has function scope and is a +/// non-static local variable. +/// +/// Example matches x (matcher = varDecl(hasLocalStorage()) +/// \code +/// void f() { +/// int x; +/// static int y; +/// } +/// int z; +/// \endcode +AST_MATCHER(VarDecl, hasLocalStorage) { + return Node.hasLocalStorage(); +} + +/// \brief Matches a variable declaration that does not have local storage. +/// +/// Example matches y and z (matcher = varDecl(hasGlobalStorage()) +/// \code +/// void f() { +/// int x; +/// static int y; +/// } +/// int z; +/// \endcode +AST_MATCHER(VarDecl, hasGlobalStorage) { + return Node.hasGlobalStorage(); +} + /// \brief Checks that a call expression or a constructor call expression has /// a specific number of arguments (including absent default arguments). /// @@ -2098,7 +2220,7 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, AST_MATCHER_P(CXXCtorInitializer, forField, internal::Matcher<FieldDecl>, InnerMatcher) { const FieldDecl *NodeAsDecl = Node.getMember(); - return (NodeAsDecl != NULL && + return (NodeAsDecl != nullptr && InnerMatcher.matches(*NodeAsDecl, Finder, Builder)); } @@ -2118,7 +2240,7 @@ AST_MATCHER_P(CXXCtorInitializer, forField, AST_MATCHER_P(CXXCtorInitializer, withInitializer, internal::Matcher<Expr>, InnerMatcher) { const Expr* NodeAsExpr = Node.getInit(); - return (NodeAsExpr != NULL && + return (NodeAsExpr != nullptr && InnerMatcher.matches(*NodeAsExpr, Finder, Builder)); } @@ -2139,12 +2261,6 @@ 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. /// @@ -2175,6 +2291,11 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2( return false; } +/// \brief Matches a constructor call expression which uses list initialization. +AST_MATCHER(CXXConstructExpr, isListInitialization) { + return Node.isListInitialization(); +} + /// \brief Matches the n'th parameter of a function declaration. /// /// Given @@ -2234,7 +2355,7 @@ AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) { /// matches int f() { return 1; } AST_MATCHER_P(FunctionDecl, returns, internal::Matcher<QualType>, InnerMatcher) { - return InnerMatcher.matches(Node.getResultType(), Finder, Builder); + return InnerMatcher.matches(Node.getReturnType(), Finder, Builder); } /// \brief Matches extern "C" function declarations. @@ -2263,19 +2384,33 @@ AST_POLYMORPHIC_MATCHER_P( IfStmt, ForStmt, WhileStmt, DoStmt, ConditionalOperator), internal::Matcher<Expr>, InnerMatcher) { const Expr *const Condition = Node.getCond(); - return (Condition != NULL && + return (Condition != nullptr && InnerMatcher.matches(*Condition, Finder, Builder)); } -namespace internal { -struct NotEqualsBoundNodePredicate { - bool operator()(const internal::BoundNodesMap &Nodes) const { - return Nodes.getNode(ID) != Node; - } - std::string ID; - ast_type_traits::DynTypedNode Node; -}; -} // namespace internal +/// \brief Matches the then-statement of an if statement. +/// +/// Examples matches the if statement +/// (matcher = ifStmt(hasThen(boolLiteral(equals(true))))) +/// \code +/// if (false) true; else false; +/// \endcode +AST_MATCHER_P(IfStmt, hasThen, internal::Matcher<Stmt>, InnerMatcher) { + const Stmt *const Then = Node.getThen(); + return (Then != nullptr && InnerMatcher.matches(*Then, Finder, Builder)); +} + +/// \brief Matches the else-statement of an if statement. +/// +/// Examples matches the if statement +/// (matcher = ifStmt(hasElse(boolLiteral(equals(true))))) +/// \code +/// if (false) false; else true; +/// \endcode +AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) { + const Stmt *const Else = Node.getElse(); + return (Else != nullptr && InnerMatcher.matches(*Else, Finder, Builder)); +} /// \brief Matches if a node equals a previously bound node. /// @@ -2325,7 +2460,7 @@ AST_MATCHER_P(IfStmt, hasConditionVariableStatement, internal::Matcher<DeclStmt>, InnerMatcher) { const DeclStmt* const DeclarationStatement = Node.getConditionVariableDeclStmt(); - return DeclarationStatement != NULL && + return DeclarationStatement != nullptr && InnerMatcher.matches(*DeclarationStatement, Finder, Builder); } @@ -2373,11 +2508,13 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, /// matches 'for (;;) {}' /// with compoundStmt() /// matching '{}' -AST_POLYMORPHIC_MATCHER_P( - hasBody, AST_POLYMORPHIC_SUPPORTED_TYPES_3(DoStmt, ForStmt, WhileStmt), - internal::Matcher<Stmt>, InnerMatcher) { +AST_POLYMORPHIC_MATCHER_P(hasBody, + AST_POLYMORPHIC_SUPPORTED_TYPES_4(DoStmt, ForStmt, + WhileStmt, + CXXForRangeStmt), + internal::Matcher<Stmt>, InnerMatcher) { const Stmt *const Statement = Node.getBody(); - return (Statement != NULL && + return (Statement != nullptr && InnerMatcher.matches(*Statement, Finder, Builder)); } @@ -2451,7 +2588,7 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName, AST_POLYMORPHIC_SUPPORTED_TYPES_2( AST_MATCHER_P(BinaryOperator, hasLHS, internal::Matcher<Expr>, InnerMatcher) { Expr *LeftHandSide = Node.getLHS(); - return (LeftHandSide != NULL && + return (LeftHandSide != nullptr && InnerMatcher.matches(*LeftHandSide, Finder, Builder)); } @@ -2464,7 +2601,7 @@ AST_MATCHER_P(BinaryOperator, hasLHS, AST_MATCHER_P(BinaryOperator, hasRHS, internal::Matcher<Expr>, InnerMatcher) { Expr *RightHandSide = Node.getRHS(); - return (RightHandSide != NULL && + return (RightHandSide != nullptr && InnerMatcher.matches(*RightHandSide, Finder, Builder)); } @@ -2484,7 +2621,7 @@ inline internal::Matcher<BinaryOperator> hasEitherOperand( AST_MATCHER_P(UnaryOperator, hasUnaryOperand, internal::Matcher<Expr>, InnerMatcher) { const Expr * const Operand = Node.getSubExpr(); - return (Operand != NULL && + return (Operand != nullptr && InnerMatcher.matches(*Operand, Finder, Builder)); } @@ -2498,7 +2635,7 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand, AST_MATCHER_P(CastExpr, hasSourceExpression, internal::Matcher<Expr>, InnerMatcher) { const Expr* const SubExpression = Node.getSubExpr(); - return (SubExpression != NULL && + return (SubExpression != nullptr && InnerMatcher.matches(*SubExpression, Finder, Builder)); } @@ -2530,7 +2667,7 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType, AST_MATCHER_P(ConditionalOperator, hasTrueExpression, internal::Matcher<Expr>, InnerMatcher) { Expr *Expression = Node.getTrueExpr(); - return (Expression != NULL && + return (Expression != nullptr && InnerMatcher.matches(*Expression, Finder, Builder)); } @@ -2543,7 +2680,7 @@ AST_MATCHER_P(ConditionalOperator, hasTrueExpression, AST_MATCHER_P(ConditionalOperator, hasFalseExpression, internal::Matcher<Expr>, InnerMatcher) { Expr *Expression = Node.getFalseExpr(); - return (Expression != NULL && + return (Expression != nullptr && InnerMatcher.matches(*Expression, Finder, Builder)); } @@ -2585,7 +2722,7 @@ AST_POLYMORPHIC_MATCHER(isDefinition, AST_POLYMORPHIC_SUPPORTED_TYPES_3( AST_MATCHER_P(CXXMethodDecl, ofClass, internal::Matcher<CXXRecordDecl>, InnerMatcher) { const CXXRecordDecl *Parent = Node.getParent(); - return (Parent != NULL && + return (Parent != nullptr && InnerMatcher.matches(*Parent, Finder, Builder)); } @@ -2603,6 +2740,20 @@ AST_MATCHER(CXXMethodDecl, isVirtual) { return Node.isVirtual(); } +/// \brief Matches if the given method declaration is pure. +/// +/// Given +/// \code +/// class A { +/// public: +/// virtual void x() = 0; +/// }; +/// \endcode +/// matches A::x +AST_MATCHER(CXXMethodDecl, isPure) { + return Node.isPure(); +} + /// \brief Matches if the given method declaration is const. /// /// Given @@ -2822,8 +2973,8 @@ AST_POLYMORPHIC_MATCHER( /// \brief Matches \c TypeLocs for which the given inner /// QualType-matcher matches. -inline internal::BindableMatcher<TypeLoc> loc( - const internal::Matcher<QualType> &InnerMatcher) { +AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc, + internal::Matcher<QualType>, InnerMatcher, 0) { return internal::BindableMatcher<TypeLoc>( new internal::TypeLocTypeMatcher(InnerMatcher)); } @@ -3306,8 +3457,9 @@ const internal::VariadicAllOfMatcher< /// \brief Matches \c NestedNameSpecifierLocs for which the given inner /// NestedNameSpecifier-matcher matches. -inline internal::BindableMatcher<NestedNameSpecifierLoc> loc( - const internal::Matcher<NestedNameSpecifier> &InnerMatcher) { +AST_MATCHER_FUNCTION_P_OVERLOAD( + internal::BindableMatcher<NestedNameSpecifierLoc>, loc, + internal::Matcher<NestedNameSpecifier>, InnerMatcher, 1) { return internal::BindableMatcher<NestedNameSpecifierLoc>( new internal::LocMatcher<NestedNameSpecifierLoc, NestedNameSpecifier>( InnerMatcher)); @@ -3325,7 +3477,7 @@ inline internal::BindableMatcher<NestedNameSpecifierLoc> loc( /// matches "A::" AST_MATCHER_P(NestedNameSpecifier, specifiesType, internal::Matcher<QualType>, InnerMatcher) { - if (Node.getAsType() == NULL) + if (!Node.getAsType()) return false; return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder); } @@ -3343,7 +3495,7 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType, /// matches "A::" AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, internal::Matcher<TypeLoc>, InnerMatcher) { - return InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); + return Node && InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); } /// \brief Matches on the prefix of a \c NestedNameSpecifier. @@ -3359,7 +3511,7 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix, internal::Matcher<NestedNameSpecifier>, InnerMatcher, 0) { NestedNameSpecifier *NextNode = Node.getPrefix(); - if (NextNode == NULL) + if (!NextNode) return false; return InnerMatcher.matches(*NextNode, Finder, Builder); } @@ -3394,7 +3546,7 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix, /// matches "ns::" AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, internal::Matcher<NamespaceDecl>, InnerMatcher) { - if (Node.getAsNamespace() == NULL) + if (!Node.getAsNamespace()) return false; return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); } @@ -3406,14 +3558,14 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, /// \brief Matches if a node equals another node. /// /// \c Decl has pointer identity in the AST. -AST_MATCHER_P_OVERLOAD(Decl, equalsNode, Decl*, Other, 0) { +AST_MATCHER_P_OVERLOAD(Decl, equalsNode, const Decl*, Other, 0) { return &Node == Other; } /// \brief Matches if a node equals another node. /// /// \c Stmt has pointer identity in the AST. /// -AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, Stmt*, Other, 1) { +AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, const Stmt*, Other, 1) { return &Node == Other; } @@ -3463,11 +3615,9 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer, internal::Matcher<CXXCtorInitializer>, InnerMatcher) { BoundNodesTreeBuilder Result; bool Matched = false; - for (CXXConstructorDecl::init_const_iterator I = Node.init_begin(), - E = Node.init_end(); - I != E; ++I) { + for (const auto *I : Node.inits()) { BoundNodesTreeBuilder InitBuilder(*Builder); - if (InnerMatcher.matches(**I, Finder, &InitBuilder)) { + if (InnerMatcher.matches(*I, Finder, &InitBuilder)) { Matched = true; Result.addMatch(InitBuilder); } diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 69cee2e..94435fd 100644 --- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -44,7 +44,6 @@ #include "clang/AST/Type.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/VariadicFunction.h" -#include "llvm/Support/type_traits.h" #include <map> #include <string> #include <vector> @@ -52,11 +51,6 @@ 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 { @@ -80,7 +74,7 @@ public: const T *getNodeAs(StringRef ID) const { IDToNodeMap::const_iterator It = NodeMap.find(ID); if (It == NodeMap.end()) { - return NULL; + return nullptr; } return It->second.get<T>(); } @@ -198,9 +192,9 @@ public: private: /// Implements MatcherInterface::Matches. - virtual bool matches(const T &Node, - ASTMatchFinder * /* Finder */, - BoundNodesTreeBuilder * /* Builder */) const { + bool matches(const T &Node, + ASTMatchFinder * /* Finder */, + BoundNodesTreeBuilder * /* Builder */) const override { return matchesNode(Node); } }; @@ -225,9 +219,8 @@ public: /// Requires \c T to be derived from \c From. template <typename From> Matcher(const Matcher<From> &Other, - typename llvm::enable_if_c< - llvm::is_base_of<From, T>::value && - !llvm::is_same<From, T>::value >::type* = 0) + typename std::enable_if<std::is_base_of<From, T>::value && + !std::is_same<From, T>::value>::type * = 0) : Implementation(new ImplicitCastMatcher<From>(Other)) {} /// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>. @@ -235,9 +228,9 @@ public: /// The resulting matcher is not strict, i.e. ignores qualifiers. template <typename TypeT> Matcher(const Matcher<TypeT> &Other, - typename llvm::enable_if_c< - llvm::is_same<T, QualType>::value && - llvm::is_same<TypeT, Type>::value >::type* = 0) + typename std::enable_if< + std::is_same<T, QualType>::value && + std::is_same<TypeT, Type>::value>::type* = 0) : Implementation(new TypeToQualType<TypeT>(Other)) {} /// \brief Forwards the call to the underlying MatcherInterface<T> pointer. @@ -257,7 +250,7 @@ public: 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()); + return reinterpret_cast<uint64_t>(Implementation.get()); } /// \brief Allows the conversion of a \c Matcher<Type> to a \c @@ -272,9 +265,8 @@ public: TypeToQualType(const Matcher<TypeT> &InnerMatcher) : InnerMatcher(InnerMatcher) {} - virtual bool matches(const QualType &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const QualType &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { if (Node.isNull()) return false; return InnerMatcher.matches(*Node, Finder, Builder); @@ -292,9 +284,8 @@ private: explicit ImplicitCastMatcher(const Matcher<Base> &From) : From(From) {} - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { return From.matches(Node, Finder, Builder); } @@ -379,9 +370,7 @@ public: /// matcher can handle a value of T. /// /// If it is not compatible, then this matcher will never match anything. - template <typename T> Matcher<T> unconditionalConvertTo() const { - return Matcher<T>(new WrappedMatcher<T>(*this)); - } + template <typename T> Matcher<T> unconditionalConvertTo() const; private: class MatcherStorage : public RefCountedBaseVPTR { @@ -410,9 +399,6 @@ private: /// \brief Typed implementation of \c MatcherStorage. template <typename T> class TypedMatcherStorage; - /// \brief Simple MatcherInterface<T> wrapper around a DynTypedMatcher. - template <typename T> class WrappedMatcher; - IntrusiveRefCntPtr<const MatcherStorage> Storage; }; @@ -425,15 +411,15 @@ public: InnerMatcher(Other), AllowBind(AllowBind) {} bool matches(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const - LLVM_OVERRIDE { + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { if (const T *Node = DynNode.get<T>()) { return InnerMatcher.matches(*Node, Finder, Builder); } return false; } - llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const LLVM_OVERRIDE { + llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const override { if (!AllowBind) return llvm::Optional<DynTypedMatcher>(); return DynTypedMatcher(BindableMatcher<T>(InnerMatcher).bind(ID)); @@ -452,22 +438,6 @@ template <typename T> inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher<T> &M) : Storage(new TypedMatcherStorage<T>(M, true)) {} -template <typename T> -class DynTypedMatcher::WrappedMatcher : public MatcherInterface<T> { -public: - explicit WrappedMatcher(const DynTypedMatcher &Matcher) : Inner(Matcher) {} - virtual ~WrappedMatcher() {} - - bool matches(const T &Node, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return Inner.matches(ast_type_traits::DynTypedNode::create(Node), Finder, - Builder); - } - -private: - const DynTypedMatcher Inner; -}; - /// \brief Specialization of the conversion functions for QualType. /// /// These specializations provide the Matcher<Type>->Matcher<QualType> @@ -537,7 +507,7 @@ template <typename T> struct has_getDecl { static char (&f(CheckT<int Default::*, &C::getDecl>*))[1]; template<typename C> static char (&f(...))[2]; - static bool const value = sizeof(f<Derived>(0)) == 2; + static bool const value = sizeof(f<Derived>(nullptr)) == 2; }; /// \brief Matches overloaded operators with a specific name. @@ -546,16 +516,17 @@ template <typename T> struct has_getDecl { /// PolymorphicMatcherWithParam1 and should be StringRef. template <typename T, typename ArgT> class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> { - TOOLING_COMPILE_ASSERT((llvm::is_same<T, CXXOperatorCallExpr>::value || - llvm::is_same<T, CXXMethodDecl>::value), - unsupported_class_for_matcher); - TOOLING_COMPILE_ASSERT((llvm::is_same<ArgT, StringRef>::value), - argument_type_must_be_StringRef); + static_assert(std::is_same<T, CXXOperatorCallExpr>::value || + std::is_base_of<FunctionDecl, T>::value, + "unsupported class for matcher"); + static_assert(std::is_same<ArgT, StringRef>::value, + "argument type must be StringRef"); + public: explicit HasOverloadedOperatorNameMatcher(const StringRef Name) : SingleNodeMatcherInterface<T>(), Name(Name) {} - virtual bool matchesNode(const T &Node) const LLVM_OVERRIDE { + bool matchesNode(const T &Node) const override { return matchesSpecialized(Node); } @@ -570,7 +541,7 @@ private: /// \brief Returns true only if CXXMethodDecl represents an overloaded /// operator and has the given operator name. - bool matchesSpecialized(const CXXMethodDecl &Node) const { + bool matchesSpecialized(const FunctionDecl &Node) const { return Node.isOverloadedOperator() && getOperatorSpelling(Node.getOverloadedOperator()) == Name; } @@ -584,16 +555,15 @@ private: /// 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); + static_assert(std::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 { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { return matchesSpecialized(Node, Finder, Builder); } @@ -603,7 +573,7 @@ private: template <typename U> bool matchesSpecialized( const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, - typename llvm::enable_if<has_getDecl<U>, int>::type = 0) const { + typename std::enable_if<has_getDecl<U>::value, int>::type = 0) const { return matchesDecl(Node.getDecl(), Finder, Builder); } @@ -656,7 +626,7 @@ private: bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - return Node != NULL && InnerMatcher.matches(*Node, Finder, Builder); + return Node != nullptr && InnerMatcher.matches(*Node, Finder, Builder); } const Matcher<Decl> InnerMatcher; @@ -667,14 +637,14 @@ private: 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, Type>::value || - llvm::is_same<T, TypeLoc>::value || - llvm::is_same<T, NestedNameSpecifier>::value || - llvm::is_same<T, NestedNameSpecifierLoc>::value || - llvm::is_same<T, CXXCtorInitializer>::value); + std::is_same<T, Decl>::value || + std::is_same<T, Stmt>::value || + std::is_same<T, QualType>::value || + std::is_same<T, Type>::value || + std::is_same<T, TypeLoc>::value || + std::is_same<T, NestedNameSpecifier>::value || + std::is_same<T, NestedNameSpecifierLoc>::value || + std::is_same<T, CXXCtorInitializer>::value; }; template <typename T> const bool IsBaseType<T>::value; @@ -740,14 +710,13 @@ public: BoundNodesTreeBuilder *Builder, TraversalKind Traverse, BindKind Bind) { - TOOLING_COMPILE_ASSERT( - (llvm::is_base_of<Decl, T>::value || - llvm::is_base_of<Stmt, T>::value || - llvm::is_base_of<NestedNameSpecifier, T>::value || - llvm::is_base_of<NestedNameSpecifierLoc, T>::value || - llvm::is_base_of<TypeLoc, T>::value || - llvm::is_base_of<QualType, T>::value), - unsupported_type_for_recursive_matching); + static_assert(std::is_base_of<Decl, T>::value || + std::is_base_of<Stmt, T>::value || + std::is_base_of<NestedNameSpecifier, T>::value || + std::is_base_of<NestedNameSpecifierLoc, T>::value || + std::is_base_of<TypeLoc, T>::value || + std::is_base_of<QualType, T>::value, + "unsupported type for recursive matching"); return matchesChildOf(ast_type_traits::DynTypedNode::create(Node), Matcher, Builder, Traverse, Bind); } @@ -757,14 +726,13 @@ public: const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, BindKind Bind) { - TOOLING_COMPILE_ASSERT( - (llvm::is_base_of<Decl, T>::value || - llvm::is_base_of<Stmt, T>::value || - llvm::is_base_of<NestedNameSpecifier, T>::value || - llvm::is_base_of<NestedNameSpecifierLoc, T>::value || - llvm::is_base_of<TypeLoc, T>::value || - llvm::is_base_of<QualType, T>::value), - unsupported_type_for_recursive_matching); + static_assert(std::is_base_of<Decl, T>::value || + std::is_base_of<Stmt, T>::value || + std::is_base_of<NestedNameSpecifier, T>::value || + std::is_base_of<NestedNameSpecifierLoc, T>::value || + std::is_base_of<TypeLoc, T>::value || + std::is_base_of<QualType, T>::value, + "unsupported type for recursive matching"); return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node), Matcher, Builder, Bind); } @@ -775,9 +743,9 @@ public: const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) { - TOOLING_COMPILE_ASSERT((llvm::is_base_of<Decl, T>::value || - llvm::is_base_of<Stmt, T>::value), - only_Decl_or_Stmt_allowed_for_recursive_matching); + static_assert(std::is_base_of<Decl, T>::value || + std::is_base_of<Stmt, T>::value, + "only Decl or Stmt allowed for recursive matching"); return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node), Matcher, Builder, MatchMode); } @@ -820,7 +788,7 @@ struct TypeList { /// \brief The first type on the list. typedef T1 head; - /// \brief A sub list with the tail. ie everything but the head. + /// \brief A sublist with the tail. ie everything but the head. /// /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the /// end of the list. @@ -852,7 +820,7 @@ typedef TypeList<> EmptyTypeList; template <typename AnyTypeList, typename T> struct TypeListContainsSuperOf { static const bool value = - llvm::is_base_of<typename AnyTypeList::head, T>::value || + std::is_base_of<typename AnyTypeList::head, T>::value || TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value; }; template <typename T> @@ -952,8 +920,8 @@ public: typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes; template <typename T> operator Matcher<T>() const { - TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value), - right_polymorphic_conversion); + static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, + "right polymorphic conversion"); return Matcher<T>(new MatcherT<T>()); } }; @@ -970,8 +938,8 @@ public: template <typename T> operator Matcher<T>() const { - TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value), - right_polymorphic_conversion); + static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, + "right polymorphic conversion"); return Matcher<T>(new MatcherT<T, P1>(Param1)); } @@ -991,8 +959,8 @@ public: template <typename T> operator Matcher<T>() const { - TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value), - right_polymorphic_conversion); + static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, + "right polymorphic conversion"); return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2)); } @@ -1018,7 +986,7 @@ private: template <typename T> class TrueMatcher : public SingleNodeMatcherInterface<T> { public: - virtual bool matchesNode(const T &Node) const { + bool matchesNode(const T &Node) const override { return true; } }; @@ -1033,9 +1001,8 @@ public: IdMatcher(StringRef ID, const Matcher<T> &InnerMatcher) : ID(ID), InnerMatcher(InnerMatcher) {} - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { bool Result = InnerMatcher.matches(Node, Finder, Builder); if (Result) { Builder->setBinding(ID, &Node); @@ -1074,15 +1041,15 @@ public: /// 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); + static_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 { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { return Finder->matchesChildOf( Node, ChildMatcher, Builder, ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses, @@ -1100,15 +1067,15 @@ public: /// 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); + static_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 { + bool matches(const T& Node, ASTMatchFinder* Finder, + BoundNodesTreeBuilder* Builder) const override { return Finder->matchesChildOf( Node, ChildMatcher, Builder, ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses, @@ -1119,38 +1086,6 @@ private: const Matcher<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 { - // The 'unless' matcher will always discard the result: - // If the inner matcher doesn't match, unless returns true, - // but the inner matcher cannot have bound anything. - // If the inner matcher matches, the result is false, and - // any possible binding will be discarded. - // We still need to hand in all the bound nodes up to this - // point so the inner matcher can depend on bound nodes, - // and we need to actively discard the bound nodes, otherwise - // the inner matcher will reset the bound nodes if it doesn't - // match, but this would be inversed by 'unless'. - BoundNodesTreeBuilder Discard(*Builder); - return !InnerMatcher.matches(Node, Finder, &Discard); - } - -private: - const Matcher<T> InnerMatcher; -}; - /// \brief VariadicOperatorMatcher related types. /// @{ @@ -1165,22 +1100,18 @@ template <typename T> class VariadicOperatorMatcherInterface : public MatcherInterface<T> { public: VariadicOperatorMatcherInterface(VariadicOperatorFunction Func, - ArrayRef<const Matcher<T> *> InputMatchers) - : Func(Func) { - for (size_t i = 0, e = InputMatchers.size(); i != e; ++i) { - InnerMatchers.push_back(*InputMatchers[i]); - } - } + std::vector<DynTypedMatcher> InnerMatchers) + : Func(Func), InnerMatchers(std::move(InnerMatchers)) {} - virtual bool matches(const T &Node, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { return Func(ast_type_traits::DynTypedNode::create(Node), Finder, Builder, InnerMatchers); } private: const VariadicOperatorFunction Func; - std::vector<DynTypedMatcher> InnerMatchers; + const std::vector<DynTypedMatcher> InnerMatchers; }; /// \brief "No argument" placeholder to use as template paratemers. @@ -1192,46 +1123,55 @@ struct VariadicOperatorNoArg {}; /// Input matchers can have any type (including other polymorphic matcher /// types), and the actual Matcher<T> is generated on demand with an implicit /// coversion operator. -template <typename P1, typename P2, +template <typename P1, typename P2 = VariadicOperatorNoArg, typename P3 = VariadicOperatorNoArg, typename P4 = VariadicOperatorNoArg, - typename P5 = VariadicOperatorNoArg> + typename P5 = VariadicOperatorNoArg, + typename P6 = VariadicOperatorNoArg, + typename P7 = VariadicOperatorNoArg, + typename P8 = VariadicOperatorNoArg, + typename P9 = VariadicOperatorNoArg> class VariadicOperatorMatcher { public: VariadicOperatorMatcher(VariadicOperatorFunction Func, const P1 &Param1, - const P2 &Param2, + const P2 &Param2 = VariadicOperatorNoArg(), const P3 &Param3 = VariadicOperatorNoArg(), const P4 &Param4 = VariadicOperatorNoArg(), - const P5 &Param5 = VariadicOperatorNoArg()) + const P5 &Param5 = VariadicOperatorNoArg(), + const P6 &Param6 = VariadicOperatorNoArg(), + const P7 &Param7 = VariadicOperatorNoArg(), + const P8 &Param8 = VariadicOperatorNoArg(), + const P9 &Param9 = VariadicOperatorNoArg()) : Func(Func), Param1(Param1), Param2(Param2), Param3(Param3), - Param4(Param4), Param5(Param5) {} + Param4(Param4), Param5(Param5), Param6(Param6), Param7(Param7), + Param8(Param8), Param9(Param9) {} template <typename T> operator Matcher<T>() const { - Matcher<T> *Array[5]; - size_t Size = 0; - - addMatcher<T>(Param1, Array, Size); - addMatcher<T>(Param2, Array, Size); - addMatcher<T>(Param3, Array, Size); - addMatcher<T>(Param4, Array, Size); - addMatcher<T>(Param5, Array, Size); - Matcher<T> Result(new VariadicOperatorMatcherInterface<T>( - Func, ArrayRef<const Matcher<T> *>(Array, Size))); - for (size_t i = 0, e = Size; i != e; ++i) delete Array[i]; - return Result; + std::vector<DynTypedMatcher> Matchers; + addMatcher<T>(Param1, Matchers); + addMatcher<T>(Param2, Matchers); + addMatcher<T>(Param3, Matchers); + addMatcher<T>(Param4, Matchers); + addMatcher<T>(Param5, Matchers); + addMatcher<T>(Param6, Matchers); + addMatcher<T>(Param7, Matchers); + addMatcher<T>(Param8, Matchers); + addMatcher<T>(Param9, Matchers); + return Matcher<T>( + new VariadicOperatorMatcherInterface<T>(Func, std::move(Matchers))); } private: template <typename T> - static void addMatcher(const Matcher<T> &M, Matcher<T> **Array, - size_t &Size) { - Array[Size++] = new Matcher<T>(M); + static void addMatcher(const Matcher<T> &M, + std::vector<DynTypedMatcher> &Matchers) { + Matchers.push_back(M); } /// \brief Overload to ignore \c VariadicOperatorNoArg arguments. template <typename T> - static void addMatcher(VariadicOperatorNoArg, Matcher<T> **Array, - size_t &Size) {} + static void addMatcher(VariadicOperatorNoArg, + std::vector<DynTypedMatcher> &Matchers) {} const VariadicOperatorFunction Func; const P1 Param1; @@ -1239,40 +1179,100 @@ private: const P3 Param3; const P4 Param4; const P5 Param5; + const P6 Param6; + const P7 Param7; + const P8 Param8; + const P9 Param9; }; /// \brief Overloaded function object to generate VariadicOperatorMatcher /// objects from arbitrary matchers. /// -/// It supports 2-5 argument overloaded operator(). More can be added if needed. +/// It supports 1-9 argument overloaded operator(). More can be added if needed. +template <unsigned MinCount, unsigned MaxCount> struct VariadicOperatorMatcherFunc { VariadicOperatorFunction Func; + template <unsigned Count, typename T> + struct EnableIfValidArity + : public std::enable_if<MinCount <= Count && Count <= MaxCount, T> {}; + + template <typename M1> + typename EnableIfValidArity<1, VariadicOperatorMatcher<M1> >::type + operator()(const M1 &P1) const { + return VariadicOperatorMatcher<M1>(Func, P1); + } template <typename M1, typename M2> - VariadicOperatorMatcher<M1, M2> operator()(const M1 &P1, const M2 &P2) const { + typename EnableIfValidArity<2, VariadicOperatorMatcher<M1, M2> >::type + operator()(const M1 &P1, const M2 &P2) const { return VariadicOperatorMatcher<M1, M2>(Func, P1, P2); } template <typename M1, typename M2, typename M3> - VariadicOperatorMatcher<M1, M2, M3> operator()(const M1 &P1, const M2 &P2, - const M3 &P3) const { + typename EnableIfValidArity<3, VariadicOperatorMatcher<M1, M2, M3> >::type + operator()(const M1 &P1, const M2 &P2, const M3 &P3) const { return VariadicOperatorMatcher<M1, M2, M3>(Func, P1, P2, P3); } template <typename M1, typename M2, typename M3, typename M4> - VariadicOperatorMatcher<M1, M2, M3, M4> + typename EnableIfValidArity<4, VariadicOperatorMatcher<M1, M2, M3, M4> >::type operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) const { return VariadicOperatorMatcher<M1, M2, M3, M4>(Func, P1, P2, P3, P4); } template <typename M1, typename M2, typename M3, typename M4, typename M5> - VariadicOperatorMatcher<M1, M2, M3, M4, M5> + typename EnableIfValidArity< + 5, VariadicOperatorMatcher<M1, M2, M3, M4, M5> >::type operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) const { return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Func, P1, P2, P3, P4, P5); } + template <typename M1, typename M2, typename M3, typename M4, typename M5, + typename M6> + typename EnableIfValidArity< + 6, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6> >::type + operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, + const M5 &P5, const M6 &P6) const { + return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6>( + Func, P1, P2, P3, P4, P5, P6); + } + template <typename M1, typename M2, typename M3, typename M4, typename M5, + typename M6, typename M7> + typename EnableIfValidArity< + 7, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7> >::type + operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, + const M5 &P5, const M6 &P6, const M7 &P7) const { + return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7>( + Func, P1, P2, P3, P4, P5, P6, P7); + } + template <typename M1, typename M2, typename M3, typename M4, typename M5, + typename M6, typename M7, typename M8> + typename EnableIfValidArity< + 8, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8> >::type + operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, + const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8) const { + return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8>( + Func, P1, P2, P3, P4, P5, P6, P7, P8); + } + template <typename M1, typename M2, typename M3, typename M4, typename M5, + typename M6, typename M7, typename M8, typename M9> + typename EnableIfValidArity< + 9, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9> >::type + operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, + const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8, + const M9 &P9) const { + return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9>( + Func, P1, P2, P3, P4, P5, P6, P7, P8, P9); + } }; /// @} +/// \brief Matches nodes that do not match the provided matcher. +/// +/// Uses the variadic matcher interface, but fails if InnerMatchers.size()!=1. +bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, + ArrayRef<DynTypedMatcher> InnerMatchers); + /// \brief Matches nodes for which all provided matchers match. bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder, @@ -1293,12 +1293,22 @@ bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); +template <typename T> +inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const { + return Matcher<T>(new VariadicOperatorMatcherInterface<T>( + AllOfVariadicOperator, llvm::makeArrayRef(*this))); +} + /// \brief Creates a Matcher<T> that matches if all inner matchers match. template<typename T> BindableMatcher<T> makeAllOfComposite( ArrayRef<const Matcher<T> *> InnerMatchers) { + std::vector<DynTypedMatcher> DynMatchers; + for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { + DynMatchers.push_back(*InnerMatchers[i]); + } return BindableMatcher<T>(new VariadicOperatorMatcherInterface<T>( - AllOfVariadicOperator, InnerMatchers)); + AllOfVariadicOperator, std::move(DynMatchers))); } /// \brief Creates a Matcher<T> that matches if @@ -1320,15 +1330,15 @@ BindableMatcher<T> makeDynCastAllOfComposite( /// 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); + static_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 { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { return Finder->matchesDescendantOf( Node, DescendantMatcher, Builder, ASTMatchFinder::BK_First); } @@ -1343,15 +1353,15 @@ public: /// \c ParentT must be an AST base type. template <typename T, typename ParentT> class HasParentMatcher : public MatcherInterface<T> { - TOOLING_COMPILE_ASSERT(IsBaseType<ParentT>::value, - has_parent_only_accepts_base_type_matcher); + static_assert(IsBaseType<ParentT>::value, + "has parent only accepts base type matcher"); + public: explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher) : ParentMatcher(ParentMatcher) {} - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { return Finder->matchesAncestorOf( Node, ParentMatcher, Builder, ASTMatchFinder::AMM_ParentOnly); } @@ -1366,15 +1376,15 @@ public: /// \c AncestorT must be an AST base type. template <typename T, typename AncestorT> class HasAncestorMatcher : public MatcherInterface<T> { - TOOLING_COMPILE_ASSERT(IsBaseType<AncestorT>::value, - has_ancestor_only_accepts_base_type_matcher); + static_assert(IsBaseType<AncestorT>::value, + "has ancestor only accepts base type matcher"); + public: explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher) : AncestorMatcher(AncestorMatcher) {} - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { return Finder->matchesAncestorOf( Node, AncestorMatcher, Builder, ASTMatchFinder::AMM_All); } @@ -1391,16 +1401,16 @@ public: /// 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); + static_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 { + bool matches(const T& Node, ASTMatchFinder* Finder, + BoundNodesTreeBuilder* Builder) const override { return Finder->matchesDescendantOf(Node, DescendantMatcher, Builder, ASTMatchFinder::BK_All); } @@ -1413,17 +1423,17 @@ private: /// 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); + static_assert(std::is_base_of<CharacterLiteral, T>::value || + std::is_base_of<CXXBoolLiteralExpr, T>::value || + std::is_base_of<FloatingLiteral, T>::value || + std::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 { + bool matchesNode(const T &Node) const override { return Node.getValue() == ExpectedValue; } @@ -1478,9 +1488,8 @@ public: explicit LocMatcher(const Matcher<T> &InnerMatcher) : InnerMatcher(InnerMatcher) {} - virtual bool matches(const TLoc &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const TLoc &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { if (!Node) return false; return InnerMatcher.matches(*extract(Node), Finder, Builder); @@ -1503,9 +1512,8 @@ public: explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher) : InnerMatcher(InnerMatcher) {} - virtual bool matches(const TypeLoc &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const TypeLoc &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { if (!Node) return false; return InnerMatcher.matches(Node.getType(), Finder, Builder); @@ -1525,9 +1533,8 @@ public: QualType (T::*TraverseFunction)() const) : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { QualType NextNode = (Node.*TraverseFunction)(); if (NextNode.isNull()) return false; @@ -1549,9 +1556,8 @@ public: TypeLoc (T::*TraverseFunction)() const) : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { TypeLoc NextNode = (Node.*TraverseFunction)(); if (!NextNode) return false; @@ -1612,6 +1618,26 @@ TypeTraversePolymorphicMatcher< return Self(InnerMatchers); } +// FIXME: unify ClassTemplateSpecializationDecl and TemplateSpecializationType's +// APIs for accessing the template argument list. +inline ArrayRef<TemplateArgument> +getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) { + return D.getTemplateArgs().asArray(); +} + +inline ArrayRef<TemplateArgument> +getTemplateSpecializationArgs(const TemplateSpecializationType &T) { + return ArrayRef<TemplateArgument>(T.getArgs(), T.getNumArgs()); +} + +struct NotEqualsBoundNodePredicate { + bool operator()(const internal::BoundNodesMap &Nodes) const { + return Nodes.getNode(ID) != Node; + } + std::string ID; + ast_type_traits::DynTypedNode Node; +}; + } // end namespace internal } // end namespace ast_matchers } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h index b5d5303..563372a 100644 --- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -37,6 +37,25 @@ #ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H #define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H +/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { +/// defines a single-parameter function named DefineMatcher() that returns a +/// ReturnType object. +/// +/// The code between the curly braces has access to the following variables: +/// +/// Param: the parameter passed to the function; its type +/// is ParamType. +/// +/// The code should return an instance of ReturnType. +#define AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) \ + AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, Param, \ + 0) +#define AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, \ + Param, OverloadId) \ + inline ReturnType DefineMatcher(ParamType const &Param); \ + typedef ReturnType (&DefineMatcher##_Type##OverloadId)(ParamType const &); \ + inline ReturnType DefineMatcher(ParamType const &Param) + /// \brief AST_MATCHER(Type, DefineMatcher) { ... } /// defines a zero parameter function named DefineMatcher() that returns a /// Matcher<Type> object. @@ -53,8 +72,8 @@ class matcher_##DefineMatcher##Matcher : public MatcherInterface<Type> { \ public: \ explicit matcher_##DefineMatcher##Matcher() {} \ - virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ + bool matches(const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const override; \ }; \ } \ inline internal::Matcher<Type> DefineMatcher() { \ @@ -88,21 +107,21 @@ : public MatcherInterface<Type> { \ public: \ explicit matcher_##DefineMatcher##OverloadId##Matcher( \ - const ParamType &A##Param) \ + ParamType const &A##Param) \ : Param(A##Param) {} \ - virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ + bool matches(const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const override; \ \ private: \ - const ParamType Param; \ + ParamType const Param; \ }; \ } \ - inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) { \ + inline internal::Matcher<Type> DefineMatcher(ParamType const &Param) { \ return internal::makeMatcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \ } \ typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \ - const ParamType &Param); \ + ParamType const &Param); \ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const @@ -132,25 +151,25 @@ class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<Type> { \ public: \ - matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \ - const ParamType2 &A##Param2) \ + matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \ + ParamType2 const &A##Param2) \ : Param1(A##Param1), Param2(A##Param2) {} \ - virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ + bool matches(const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const override; \ \ private: \ - const ParamType1 Param1; \ - const ParamType2 Param2; \ + ParamType1 const Param1; \ + ParamType2 const Param2; \ }; \ } \ - inline internal::Matcher<Type> DefineMatcher(const ParamType1 &Param1, \ - const ParamType2 &Param2) { \ + inline internal::Matcher<Type> DefineMatcher(ParamType1 const &Param1, \ + ParamType2 const &Param2) { \ return internal::makeMatcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \ Param2)); \ } \ typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \ - const ParamType1 &Param1, const ParamType2 &Param2); \ + ParamType1 const &Param1, ParamType2 const &Param2); \ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const @@ -184,8 +203,8 @@ template <typename NodeType> \ class matcher_##DefineMatcher##Matcher : public MatcherInterface<NodeType> { \ public: \ - virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ + bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const override; \ }; \ } \ inline internal::PolymorphicMatcherWithParam0< \ @@ -221,18 +240,18 @@ : public MatcherInterface<NodeType> { \ public: \ explicit matcher_##DefineMatcher##OverloadId##Matcher( \ - const ParamType &A##Param) \ + ParamType const &A##Param) \ : Param(A##Param) {} \ - virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ + bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const override; \ \ private: \ - const ParamType Param; \ + ParamType const Param; \ }; \ } \ inline internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ - ReturnTypesF> DefineMatcher(const ParamType &Param) { \ + ReturnTypesF> DefineMatcher(ParamType const &Param) { \ return internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ ReturnTypesF>(Param); \ @@ -240,7 +259,7 @@ typedef internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ - const ParamType &Param); \ + ParamType const &Param); \ template <typename NodeType, typename ParamT> \ bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \ @@ -267,21 +286,21 @@ class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<NodeType> { \ public: \ - matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \ - const ParamType2 &A##Param2) \ + matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \ + ParamType2 const &A##Param2) \ : Param1(A##Param1), Param2(A##Param2) {} \ - virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ + bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const override; \ \ private: \ - const ParamType1 Param1; \ - const ParamType2 Param2; \ + ParamType1 const Param1; \ + ParamType2 const Param2; \ }; \ } \ inline internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ - ParamType2, ReturnTypesF> DefineMatcher(const ParamType1 &Param1, \ - const ParamType2 &Param2) { \ + ParamType2, ReturnTypesF> DefineMatcher(ParamType1 const &Param1, \ + ParamType2 const &Param2) { \ return internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ ParamType2, ReturnTypesF>(Param1, Param2); \ @@ -289,7 +308,7 @@ typedef internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ - const ParamType1 &Param1, const ParamType2 &Param2); \ + ParamType1 const &Param1, ParamType2 const &Param2); \ template <typename NodeType, typename ParamT1, typename ParamT2> \ bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ NodeType, ParamT1, ParamT2>::matches( \ diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h index aec0c0e..82a14f1 100644 --- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h +++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h @@ -15,15 +15,14 @@ #ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H #define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H -#include <string> -#include <vector> - #include "clang/ASTMatchers/Dynamic/VariantValue.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" +#include <string> +#include <vector> namespace clang { namespace ast_matchers { @@ -61,11 +60,12 @@ public: enum ErrorType { ET_None = 0, - ET_RegistryNotFound = 1, + ET_RegistryMatcherNotFound = 1, ET_RegistryWrongArgCount = 2, ET_RegistryWrongArgType = 3, ET_RegistryNotBindable = 4, ET_RegistryAmbiguousOverload = 5, + ET_RegistryValueNotFound = 6, ET_ParserStringError = 100, ET_ParserNoOpenParen = 101, diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h index bb6ac76..4045f57 100644 --- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h +++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h @@ -18,13 +18,14 @@ /// /// \code /// Grammar for the expressions supported: -/// <Expression> := <Literal> | <MatcherExpression> +/// <Expression> := <Literal> | <NamedValue> | <MatcherExpression> /// <Literal> := <StringLiteral> | <Unsigned> /// <StringLiteral> := "quoted string" /// <Unsigned> := [0-9]+ -/// <MatcherExpression> := <MatcherName>(<ArgumentList>) | -/// <MatcherName>(<ArgumentList>).bind(<StringLiteral>) -/// <MatcherName> := [a-zA-Z]+ +/// <NamedValue> := <Identifier> +/// <MatcherExpression> := <Identifier>(<ArgumentList>) | +/// <Identifier>(<ArgumentList>).bind(<StringLiteral>) +/// <Identifier> := [a-zA-Z]+ /// <ArgumentList> := <Expression> | <Expression>,<ArgumentList> /// \endcode /// @@ -34,6 +35,7 @@ #define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H #include "clang/ASTMatchers/Dynamic/Diagnostics.h" +#include "clang/ASTMatchers/Dynamic/Registry.h" #include "clang/ASTMatchers/Dynamic/VariantValue.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" @@ -61,11 +63,22 @@ public: public: virtual ~Sema(); + /// \brief Lookup a value by name. + /// + /// This can be used in the Sema layer to declare known constants or to + /// allow to split an expression in pieces. + /// + /// \param Name The name of the value to lookup. + /// + /// \return The named value. It could be any type that VariantValue + /// supports. An empty value means that the name is not recognized. + virtual VariantValue getNamedValue(StringRef Name); + /// \brief Process a matcher expression. /// /// All the arguments passed here have already been processed. /// - /// \param MatcherName The matcher name found by the parser. + /// \param Ctor A matcher constructor looked up by lookupMatcherCtor. /// /// \param NameRange The location of the name in the matcher source. /// Useful for error reporting. @@ -78,11 +91,36 @@ public: /// \return The matcher objects constructed by the processor, or a null /// matcher if an error occurred. In that case, \c Error will contain a /// description of the error. - virtual VariantMatcher actOnMatcherExpression(StringRef MatcherName, + virtual VariantMatcher actOnMatcherExpression(MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID, ArrayRef<ParserValue> Args, Diagnostics *Error) = 0; + + /// \brief Look up a matcher by name. + /// + /// \param MatcherName The matcher name found by the parser. + /// + /// \return The matcher constructor, or Optional<MatcherCtor>() if not + /// found. + virtual llvm::Optional<MatcherCtor> + lookupMatcherCtor(StringRef MatcherName) = 0; + }; + + /// \brief Sema implementation that uses the matcher registry to process the + /// tokens. + class RegistrySema : public Parser::Sema { + public: + virtual ~RegistrySema(); + + llvm::Optional<MatcherCtor> + lookupMatcherCtor(StringRef MatcherName) override; + + VariantMatcher actOnMatcherExpression(MatcherCtor Ctor, + const SourceRange &NameRange, + StringRef BindID, + ArrayRef<ParserValue> Args, + Diagnostics *Error) override; }; /// \brief Parse a matcher expression, creating matchers from the registry. @@ -129,19 +167,37 @@ public: static bool parseExpression(StringRef Code, Sema *S, VariantValue *Value, Diagnostics *Error); + /// \brief Complete an expression at the given offset. + /// + /// \return The list of completions, which may be empty if there are no + /// available completions or if an error occurred. + static std::vector<MatcherCompletion> + completeExpression(StringRef Code, unsigned CompletionOffset); + private: class CodeTokenizer; + struct ScopedContextEntry; struct TokenInfo; Parser(CodeTokenizer *Tokenizer, Sema *S, Diagnostics *Error); bool parseExpressionImpl(VariantValue *Value); - bool parseMatcherExpressionImpl(VariantValue *Value); + bool parseMatcherExpressionImpl(const TokenInfo &NameToken, + VariantValue *Value); + bool parseIdentifierPrefixImpl(VariantValue *Value); + + void addCompletion(const TokenInfo &CompToken, StringRef TypedText, + StringRef Decl); + void addExpressionCompletions(); CodeTokenizer *const Tokenizer; Sema *const S; Diagnostics *const Error; + + typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy; + ContextStackTy ContextStack; + std::vector<MatcherCompletion> Completions; }; } // namespace dynamic diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h index c113c14..faa9254 100644 --- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h +++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h @@ -21,20 +21,69 @@ #include "clang/ASTMatchers/Dynamic/VariantValue.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" namespace clang { namespace ast_matchers { namespace dynamic { +namespace internal { +class MatcherDescriptor; +} + +typedef const internal::MatcherDescriptor *MatcherCtor; + +struct MatcherCompletion { + MatcherCompletion() {} + MatcherCompletion(StringRef TypedText, StringRef MatcherDecl) + : TypedText(TypedText), MatcherDecl(MatcherDecl) {} + + /// \brief The text to type to select this matcher. + std::string TypedText; + + /// \brief The "declaration" of the matcher, with type information. + std::string MatcherDecl; + + bool operator==(const MatcherCompletion &Other) const { + return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl; + } +}; + class Registry { public: - /// \brief Construct a matcher from the registry by name. + /// \brief Look up a matcher in the registry by name, + /// + /// \return An opaque value which may be used to refer to the matcher + /// constructor, or Optional<MatcherCtor>() if not found. + static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName); + + /// \brief Compute the list of completions for \p Context. /// - /// Consult the registry of known matchers and construct the appropriate - /// matcher by name. + /// Each element of \p Context represents a matcher invocation, going from + /// outermost to innermost. Elements are pairs consisting of a reference to the + /// matcher constructor and the index of the next element in the argument list + /// of that matcher (or for the last element, the index of the completion + /// point in the argument list). An empty list requests completion for the + /// root matcher. + /// + /// The completions are ordered first by decreasing relevance, then + /// alphabetically. Relevance is determined by how closely the matcher's + /// type matches that of the context. For example, if the innermost matcher + /// takes a FunctionDecl matcher, the FunctionDecl matchers are returned + /// first, followed by the ValueDecl matchers, then NamedDecl, then Decl, then + /// polymorphic matchers. + /// + /// Matchers which are technically convertible to the innermost context but + /// which would match either all or no nodes are excluded. For example, + /// namedDecl and varDecl are excluded in a FunctionDecl context, because + /// those matchers would match respectively all or no nodes in such a context. + static std::vector<MatcherCompletion> + getCompletions(ArrayRef<std::pair<MatcherCtor, unsigned> > Context); + + /// \brief Construct a matcher from the registry. /// - /// \param MatcherName The name of the matcher to instantiate. + /// \param Ctor The matcher constructor to instantiate. /// /// \param NameRange The location of the name in the matcher source. /// Useful for error reporting. @@ -44,10 +93,10 @@ public: /// will return an error. /// /// \return The matcher object constructed if no error was found. - /// A null matcher if the matcher is not found, or if the number of - /// arguments or argument types do not match the signature. - /// In that case \c Error will contain the description of the error. - static VariantMatcher constructMatcher(StringRef MatcherName, + /// A null matcher if the number of arguments or argument types do not match + /// the signature. In that case \c Error will contain the description of + /// the error. + static VariantMatcher constructMatcher(MatcherCtor Ctor, const SourceRange &NameRange, ArrayRef<ParserValue> Args, Diagnostics *Error); @@ -58,7 +107,7 @@ public: /// matcher to the specified \c BindID. /// If the matcher is not bindable, it sets an error in \c Error and returns /// a null matcher. - static VariantMatcher constructBoundMatcher(StringRef MatcherName, + static VariantMatcher constructBoundMatcher(MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID, ArrayRef<ParserValue> Args, diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h index b9bc017..b25267b 100644 --- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h +++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h @@ -17,14 +17,13 @@ #ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H #define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H -#include <vector> - #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/Twine.h" -#include "llvm/Support/type_traits.h" +#include <memory> +#include <vector> namespace clang { namespace ast_matchers { @@ -50,7 +49,8 @@ class VariantMatcher { class MatcherOps { public: virtual ~MatcherOps(); - virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const = 0; + virtual bool canConstructFrom(const DynTypedMatcher &Matcher, + bool &IsExactMatch) const = 0; virtual void constructFrom(const DynTypedMatcher &Matcher) = 0; virtual void constructVariadicOperator( ast_matchers::internal::VariadicOperatorFunction Func, @@ -78,14 +78,15 @@ public: /// \brief Clones the provided matchers. /// /// They should be the result of a polymorphic matcher. - static VariantMatcher PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers); + static VariantMatcher + PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers); /// \brief Creates a 'variadic' operator matcher. /// /// It will bind to the appropriate type on getTypedMatcher<T>(). static VariantMatcher VariadicOperatorMatcher( ast_matchers::internal::VariadicOperatorFunction Func, - ArrayRef<VariantMatcher> Args); + std::vector<VariantMatcher> Args); /// \brief Makes the matcher the "null" matcher. void reset(); @@ -145,7 +146,10 @@ private: public: typedef ast_matchers::internal::Matcher<T> MatcherT; - virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const { + virtual bool canConstructFrom(const DynTypedMatcher &Matcher, + bool &IsExactMatch) const { + IsExactMatch = Matcher.getSupportedKind().isSame( + ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); return Matcher.canConvertTo<T>(); } @@ -156,34 +160,25 @@ private: virtual void constructVariadicOperator( ast_matchers::internal::VariadicOperatorFunction Func, ArrayRef<VariantMatcher> InnerMatchers) { - const size_t NumArgs = InnerMatchers.size(); - MatcherT **InnerArgs = new MatcherT *[NumArgs](); - bool HasError = false; - for (size_t i = 0; i != NumArgs; ++i) { + std::vector<DynTypedMatcher> DynMatchers; + for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { // Abort if any of the inner matchers can't be converted to // Matcher<T>. if (!InnerMatchers[i].hasTypedMatcher<T>()) { - HasError = true; - break; + return; } - InnerArgs[i] = new MatcherT(InnerMatchers[i].getTypedMatcher<T>()); + DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>()); } - if (!HasError) { - Out.reset(new MatcherT( - new ast_matchers::internal::VariadicOperatorMatcherInterface<T>( - Func, ArrayRef<const MatcherT *>(InnerArgs, NumArgs)))); - } - for (size_t i = 0; i != NumArgs; ++i) { - delete InnerArgs[i]; - } - delete[] InnerArgs; + Out.reset(new MatcherT( + new ast_matchers::internal::VariadicOperatorMatcherInterface<T>( + Func, DynMatchers))); } - bool hasMatcher() const { return Out.get() != NULL; } + bool hasMatcher() const { return Out.get() != nullptr; } const MatcherT &matcher() const { return *Out; } private: - OwningPtr<MatcherT> Out; + std::unique_ptr<MatcherT> Out; }; IntrusiveRefCntPtr<const Payload> Value; @@ -214,6 +209,10 @@ public: VariantValue(const std::string &String); VariantValue(const VariantMatcher &Matchers); + /// \brief Returns true iff this is not an empty value. + LLVM_EXPLICIT operator bool() const { return hasValue(); } + bool hasValue() const { return Type != VT_Nothing; } + /// \brief Unsigned value functions. bool isUnsigned() const; unsigned getUnsigned() const; diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h index 23a094a..36e07c2 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h @@ -18,8 +18,8 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" -#include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" +#include "clang/Analysis/AnalysisContext.h" #include "clang/Basic/SourceLocation.h" namespace clang { @@ -142,7 +142,7 @@ namespace consumed { TmpMapType TmpMap; public: - ConsumedStateMap() : Reachable(true), From(NULL) {} + ConsumedStateMap() : Reachable(true), From(nullptr) {} ConsumedStateMap(const ConsumedStateMap &Other) : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap), TmpMap() {} @@ -185,8 +185,8 @@ namespace consumed { /// \brief Set the consumed state of a given temporary value. void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State); - /// \brief Remove the variable from our state map. - void remove(const VarDecl *Var); + /// \brief Remove the temporary value from our state map. + void remove(const CXXBindTemporaryExpr *Tmp); /// \brief Tests to see if there is a mismatch in the states stored in two /// maps. @@ -201,9 +201,10 @@ namespace consumed { public: ConsumedBlockInfo() { } - + ~ConsumedBlockInfo() { llvm::DeleteContainerPointers(StateMapsArray); } + ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph) - : StateMapsArray(NumBlocks, 0), VisitOrder(NumBlocks, 0) { + : StateMapsArray(NumBlocks, nullptr), VisitOrder(NumBlocks, 0) { unsigned int VisitOrderCounter = 0; for (PostOrderCFGView::iterator BI = SortedGraph->begin(), BE = SortedGraph->end(); BI != BE; ++BI) { diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h index 2a806c8..6c6d923 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h @@ -17,9 +17,15 @@ #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/Analysis/DominatorInternals.h" -#include "llvm/Analysis/Dominators.h" -#include "llvm/IR/Module.h" +#include "llvm/Support/GenericDomTree.h" +#include "llvm/Support/GenericDomTreeConstruction.h" + +// FIXME: There is no good reason for the domtree to require a print method +// which accepts an LLVM Module, so remove this (and the method's argument that +// needs it) when that is fixed. +namespace llvm { +class Module; +} namespace clang { @@ -147,7 +153,7 @@ public: /// \brief This method converts the dominator tree to human readable form. /// - virtual void print(raw_ostream &OS, const llvm::Module* M= 0) const { + virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const { DT->print(OS); } @@ -155,11 +161,6 @@ private: CFG *cfg; }; -inline void WriteAsOperand(raw_ostream &OS, const CFGBlock *BB, - bool t) { - OS << "BB#" << BB->getBlockID(); -} - } // end namespace clang //===------------------------------------- diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h index 75d7963..5b8aafe 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h @@ -83,7 +83,7 @@ public: }; LengthModifier() - : Position(0), kind(None) {} + : Position(nullptr), kind(None) {} LengthModifier(const char *pos, Kind k) : Position(pos), kind(k) {} @@ -174,10 +174,11 @@ public: }; ConversionSpecifier(bool isPrintf = true) - : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {} + : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr), + kind(InvalidSpecifier) {} ConversionSpecifier(bool isPrintf, const char *pos, Kind k) - : IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {} + : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {} const char *getStart() const { return Position; @@ -231,10 +232,11 @@ private: const char *Name; bool Ptr; public: - ArgType(Kind k = UnknownTy, const char *n = 0) : K(k), Name(n), Ptr(false) {} - ArgType(QualType t, const char *n = 0) + ArgType(Kind k = UnknownTy, const char *n = nullptr) + : K(k), Name(n), Ptr(false) {} + ArgType(QualType t, const char *n = nullptr) : K(SpecificTy), T(t), Name(n), Ptr(false) {} - ArgType(CanQualType t) : K(SpecificTy), T(t), Name(0), Ptr(false) {} + ArgType(CanQualType t) : K(SpecificTy), T(t), Name(nullptr), Ptr(false) {} static ArgType Invalid() { return ArgType(InvalidTy); } bool isValid() const { return K != InvalidTy; } @@ -267,7 +269,7 @@ public: UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {} OptionalAmount(bool valid = true) - : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0), + : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0), UsesPositionalArg(0), UsesDotPrefix(0) {} bool isInvalid() const { @@ -394,7 +396,7 @@ class PrintfConversionSpecifier : public analyze_format_string::ConversionSpecifier { public: PrintfConversionSpecifier() - : ConversionSpecifier(true, 0, InvalidSpecifier) {} + : ConversionSpecifier(true, nullptr, InvalidSpecifier) {} PrintfConversionSpecifier(const char *pos, Kind k) : ConversionSpecifier(true, pos, k) {} @@ -530,7 +532,7 @@ class ScanfConversionSpecifier : public analyze_format_string::ConversionSpecifier { public: ScanfConversionSpecifier() - : ConversionSpecifier(false, 0, InvalidSpecifier) {} + : ConversionSpecifier(false, nullptr, InvalidSpecifier) {} ScanfConversionSpecifier(const char *pos, Kind k) : ConversionSpecifier(false, pos, k) {} @@ -577,7 +579,8 @@ public: ArgType getArgType(ASTContext &Ctx) const; - bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx); + bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt, + ASTContext &Ctx); void toString(raw_ostream &os) const; diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h index bbd2b02..7842271 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h @@ -38,7 +38,7 @@ public: bool equals(const LivenessValues &V) const; LivenessValues() - : liveStmts(0), liveDecls(0) {} + : liveStmts(nullptr), liveDecls(nullptr) {} LivenessValues(llvm::ImmutableSet<const Stmt *> LiveStmts, llvm::ImmutableSet<const VarDecl *> LiveDecls) diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h index 4e3244e..91bf51c 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h @@ -52,7 +52,7 @@ public: // make sure that Block is non-null. Moreover, the CFGBlock iterator will // occasionally hand out null pointers for pruned edges, so we catch those // here. - if (Block == 0) + if (!Block) return false; // if an edge is trivially false. if (VisitedBlockIDs.test(Block->getBlockID())) return false; @@ -76,14 +76,18 @@ private: BlockOrderTy BlockOrder; public: - typedef std::vector<const CFGBlock*>::reverse_iterator iterator; + typedef std::vector<const CFGBlock *>::reverse_iterator iterator; + typedef std::vector<const CFGBlock *>::const_reverse_iterator const_iterator; PostOrderCFGView(const CFG *cfg); iterator begin() { return Blocks.rbegin(); } iterator end() { return Blocks.rend(); } - bool empty() { return begin() == end(); } + const_iterator begin() const { return Blocks.rbegin(); } + const_iterator end() const { return Blocks.rend(); } + + bool empty() const { return begin() == end(); } struct BlockOrderCompare; friend struct BlockOrderCompare; diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h index 30c5b2d..90a6d01 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h @@ -27,6 +27,7 @@ namespace llvm { namespace clang { class AnalysisDeclContext; class CFGBlock; + class Preprocessor; } //===----------------------------------------------------------------------===// @@ -36,11 +37,22 @@ namespace clang { namespace clang { namespace reachable_code { +/// Classifications of unreachable code. +enum UnreachableKind { + UK_Return, + UK_Break, + UK_Loop_Increment, + UK_Other +}; + class Callback { virtual void anchor(); public: virtual ~Callback() {} - virtual void HandleUnreachable(SourceLocation L, SourceRange R1, + virtual void HandleUnreachable(UnreachableKind UK, + SourceLocation L, + SourceRange ConditionVal, + SourceRange R1, SourceRange R2) = 0; }; @@ -49,7 +61,8 @@ public: unsigned ScanReachableFromBlock(const CFGBlock *Start, llvm::BitVector &Reachable); -void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB); +void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP, + Callback &CB); }} // end namespace clang::reachable_code diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h index 5def3dd..b533c1d 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h @@ -39,7 +39,8 @@ enum ProtectedOperationKind { /// mutex. enum LockKind { LK_Shared, ///< Shared/reader lock of a mutex. - LK_Exclusive ///< Exclusive/writer lock of a mutex. + LK_Exclusive, ///< Exclusive/writer lock of a mutex. + LK_Generic ///< Can be either Shared or Exclusive }; /// This enum distinguishes between different ways to access (read or write) a @@ -72,27 +73,46 @@ public: virtual ~ThreadSafetyHandler(); /// Warn about lock expressions which fail to resolve to lockable objects. + /// \param Kind -- the capability's name parameter (role, mutex, etc). /// \param Loc -- the SourceLocation of the unresolved expression. - virtual void handleInvalidLockExp(SourceLocation Loc) {} + virtual void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) {} /// Warn about unlock function calls that do not have a prior matching lock /// expression. + /// \param Kind -- the capability's name parameter (role, mutex, etc). /// \param LockName -- A StringRef name for the lock expression, to be printed /// in the error message. /// \param Loc -- The SourceLocation of the Unlock - virtual void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) {} + virtual void handleUnmatchedUnlock(StringRef Kind, Name LockName, + SourceLocation Loc) {} + + /// Warn about an unlock function call that attempts to unlock a lock with + /// the incorrect lock kind. For instance, a shared lock being unlocked + /// exclusively, or vice versa. + /// \param LockName -- A StringRef name for the lock expression, to be printed + /// in the error message. + /// \param Kind -- the capability's name parameter (role, mutex, etc). + /// \param Expected -- the kind of lock expected. + /// \param Received -- the kind of lock received. + /// \param Loc -- The SourceLocation of the Unlock. + virtual void handleIncorrectUnlockKind(StringRef Kind, Name LockName, + LockKind Expected, LockKind Received, + SourceLocation Loc) {} /// Warn about lock function calls for locks which are already held. + /// \param Kind -- the capability's name parameter (role, mutex, etc). /// \param LockName -- A StringRef name for the lock expression, to be printed /// in the error message. /// \param Loc -- The location of the second lock expression. - virtual void handleDoubleLock(Name LockName, SourceLocation Loc) {} + virtual void handleDoubleLock(StringRef Kind, Name LockName, + SourceLocation Loc) {} /// Warn about situations where a mutex is sometimes held and sometimes not. /// The three situations are: /// 1. a mutex is locked on an "if" branch but not the "else" branch, /// 2, or a mutex is only held at the start of some loop iterations, /// 3. or when a mutex is locked but not unlocked inside a function. + /// \param Kind -- the capability's name parameter (role, mutex, etc). /// \param LockName -- A StringRef name for the lock expression, to be printed /// in the error message. /// \param LocLocked -- The location of the lock expression where the mutex is @@ -100,50 +120,56 @@ public: /// \param LocEndOfScope -- The location of the end of the scope where the /// mutex is no longer held /// \param LEK -- which of the three above cases we should warn for - virtual void handleMutexHeldEndOfScope(Name LockName, + virtual void handleMutexHeldEndOfScope(StringRef Kind, Name LockName, SourceLocation LocLocked, SourceLocation LocEndOfScope, - LockErrorKind LEK){} + LockErrorKind LEK) {} /// Warn when a mutex is held exclusively and shared at the same point. For /// example, if a mutex is locked exclusively during an if branch and shared /// during the else branch. + /// \param Kind -- the capability's name parameter (role, mutex, etc). /// \param LockName -- A StringRef name for the lock expression, to be printed /// in the error message. /// \param Loc1 -- The location of the first lock expression. /// \param Loc2 -- The location of the second lock expression. - virtual void handleExclusiveAndShared(Name LockName, SourceLocation Loc1, + virtual void handleExclusiveAndShared(StringRef Kind, Name LockName, + SourceLocation Loc1, SourceLocation Loc2) {} /// Warn when a protected operation occurs while no locks are held. + /// \param Kind -- the capability's name parameter (role, mutex, etc). /// \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 Loc -- The location of the protected operation. - virtual void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK, - AccessKind AK, SourceLocation Loc) {} + virtual void handleNoMutexHeld(StringRef Kind, const NamedDecl *D, + ProtectedOperationKind POK, AccessKind AK, + SourceLocation Loc) {} /// Warn when a protected operation occurs while the specific mutex protecting /// the operation is not locked. + /// \param Kind -- the capability's name parameter (role, mutex, etc). /// \param D -- The decl for the protected variable or function /// \param POK -- The kind of protected operation (e.g. variable access) /// \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, + virtual void handleMutexNotHeld(StringRef Kind, const NamedDecl *D, ProtectedOperationKind POK, Name LockName, LockKind LK, SourceLocation Loc, - Name *PossibleMatch=0) {} + Name *PossibleMatch = nullptr) {} /// Warn when a function is called while an excluded mutex is locked. For /// example, the mutex may be locked inside the function. + /// \param Kind -- the capability's name parameter (role, mutex, etc). /// \param FunName -- The name of the function /// \param LockName -- A StringRef name for the lock expression, to be printed /// in the error message. /// \param Loc -- The location of the function call. - virtual void handleFunExcludesLock(Name FunName, Name LockName, - SourceLocation Loc) {} + virtual void handleFunExcludesLock(StringRef Kind, Name FunName, + Name LockName, SourceLocation Loc) {} bool issueBetaWarnings() { return IssueBetaWarnings; } void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; } diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h new file mode 100644 index 0000000..09c614c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h @@ -0,0 +1,393 @@ +//===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Parts of thread safety analysis that are not specific to thread safety +// itself have been factored into classes here, where they can be potentially +// used by other analyses. Currently these include: +// +// * Generalize clang CFG visitors. +// * Conversion of the clang CFG to SSA form. +// * Translation of clang Exprs to TIL SExprs +// +// UNDER CONSTRUCTION. USE AT YOUR OWN RISK. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_THREAD_SAFETY_COMMON_H +#define LLVM_CLANG_THREAD_SAFETY_COMMON_H + +#include "clang/Analysis/Analyses/PostOrderCFGView.h" +#include "clang/Analysis/Analyses/ThreadSafetyTIL.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Basic/OperatorKinds.h" + +#include <memory> +#include <vector> + + +namespace clang { +namespace threadSafety { + +// This class defines the interface of a clang CFG Visitor. +// CFGWalker will invoke the following methods. +// Note that methods are not virtual; the visitor is templatized. +class CFGVisitor { + // Enter the CFG for Decl D, and perform any initial setup operations. + void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {} + + // Enter a CFGBlock. + void enterCFGBlock(const CFGBlock *B) {} + + // Returns true if this visitor implements handlePredecessor + bool visitPredecessors() { return true; } + + // Process a predecessor edge. + void handlePredecessor(const CFGBlock *Pred) {} + + // Process a successor back edge to a previously visited block. + void handlePredecessorBackEdge(const CFGBlock *Pred) {} + + // Called just before processing statements. + void enterCFGBlockBody(const CFGBlock *B) {} + + // Process an ordinary statement. + void handleStatement(const Stmt *S) {} + + // Process a destructor call + void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {} + + // Called after all statements have been handled. + void exitCFGBlockBody(const CFGBlock *B) {} + + // Return true + bool visitSuccessors() { return true; } + + // Process a successor edge. + void handleSuccessor(const CFGBlock *Succ) {} + + // Process a successor back edge to a previously visited block. + void handleSuccessorBackEdge(const CFGBlock *Succ) {} + + // Leave a CFGBlock. + void exitCFGBlock(const CFGBlock *B) {} + + // Leave the CFG, and perform any final cleanup operations. + void exitCFG(const CFGBlock *Last) {} +}; + + +// Walks the clang CFG, and invokes methods on a given CFGVisitor. +class CFGWalker { +public: + CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {} + + // Initialize the CFGWalker. This setup only needs to be done once, even + // if there are multiple passes over the CFG. + bool init(AnalysisDeclContext &AC) { + ACtx = &AC; + CFGraph = AC.getCFG(); + if (!CFGraph) + return false; + + // Ignore anonymous functions. + if (!dyn_cast_or_null<NamedDecl>(AC.getDecl())) + return false; + + SortedGraph = AC.getAnalysis<PostOrderCFGView>(); + if (!SortedGraph) + return false; + + return true; + } + + // Traverse the CFG, calling methods on V as appropriate. + template <class Visitor> + void walk(Visitor &V) { + PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph); + + V.enterCFG(CFGraph, getDecl(), &CFGraph->getEntry()); + + for (const auto *CurrBlock : *SortedGraph) { + VisitedBlocks.insert(CurrBlock); + + V.enterCFGBlock(CurrBlock); + + // Process predecessors, handling back edges last + if (V.visitPredecessors()) { + SmallVector<CFGBlock*, 4> BackEdges; + // Process successors + for (CFGBlock::const_pred_iterator SI = CurrBlock->pred_begin(), + SE = CurrBlock->pred_end(); + SI != SE; ++SI) { + if (*SI == nullptr) + continue; + + if (!VisitedBlocks.alreadySet(*SI)) { + BackEdges.push_back(*SI); + continue; + } + V.handlePredecessor(*SI); + } + + for (auto *Blk : BackEdges) + V.handlePredecessorBackEdge(Blk); + } + + V.enterCFGBlockBody(CurrBlock); + + // Process statements + for (const auto &BI : *CurrBlock) { + switch (BI.getKind()) { + case CFGElement::Statement: { + V.handleStatement(BI.castAs<CFGStmt>().getStmt()); + break; + } + case CFGElement::AutomaticObjectDtor: { + CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>(); + CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>( + AD.getDestructorDecl(ACtx->getASTContext())); + VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl()); + V.handleDestructorCall(VD, DD); + break; + } + default: + break; + } + } + + V.exitCFGBlockBody(CurrBlock); + + // Process successors, handling back edges first. + if (V.visitSuccessors()) { + SmallVector<CFGBlock*, 8> ForwardEdges; + + // Process successors + for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(), + SE = CurrBlock->succ_end(); + SI != SE; ++SI) { + if (*SI == nullptr) + continue; + + if (!VisitedBlocks.alreadySet(*SI)) { + ForwardEdges.push_back(*SI); + continue; + } + V.handleSuccessorBackEdge(*SI); + } + + for (auto *Blk : ForwardEdges) + V.handleSuccessor(Blk); + } + + V.exitCFGBlock(CurrBlock); + } + V.exitCFG(&CFGraph->getExit()); + } + + const CFG *getGraph() const { return CFGraph; } + CFG *getGraph() { return CFGraph; } + + const NamedDecl *getDecl() const { + return dyn_cast<NamedDecl>(ACtx->getDecl()); + } + + const PostOrderCFGView *getSortedGraph() const { return SortedGraph; } + +private: + CFG *CFGraph; + AnalysisDeclContext *ACtx; + PostOrderCFGView *SortedGraph; +}; + + +// Translate clang::Expr to til::SExpr. +class SExprBuilder { +public: + /// \brief Encapsulates the lexical context of a function call. The lexical + /// context includes the arguments to the call, including the implicit object + /// argument. When an attribute containing a mutex expression is attached to + /// a method, the expression may refer to formal parameters of the method. + /// Actual arguments must be substituted for formal parameters to derive + /// the appropriate mutex expression in the lexical context where the function + /// is called. PrevCtx holds the context in which the arguments themselves + /// should be evaluated; multiple calling contexts can be chained together + /// by the lock_returned attribute. + struct CallingContext { + const NamedDecl *AttrDecl; // The decl to which the attr is attached. + const Expr *SelfArg; // Implicit object argument -- e.g. 'this' + unsigned NumArgs; // Number of funArgs + const Expr *const *FunArgs; // Function arguments + CallingContext *Prev; // The previous context; or 0 if none. + bool SelfArrow; // is Self referred to with -> or .? + + CallingContext(const NamedDecl *D = nullptr, const Expr *S = nullptr, + unsigned N = 0, const Expr *const *A = nullptr, + CallingContext *P = nullptr) + : AttrDecl(D), SelfArg(S), NumArgs(N), FunArgs(A), Prev(P), + SelfArrow(false) + {} + }; + + SExprBuilder(til::MemRegionRef A) + : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr), + CurrentBlockInfo(nullptr) { + // FIXME: we don't always have a self-variable. + SelfVar = new (Arena) til::Variable(nullptr); + SelfVar->setKind(til::Variable::VK_SFun); + } + + // Translate a clang statement or expression to a TIL expression. + // Also performs substitution of variables; Ctx provides the context. + // Dispatches on the type of S. + til::SExpr *translate(const Stmt *S, CallingContext *Ctx); + til::SCFG *buildCFG(CFGWalker &Walker); + + til::SExpr *lookupStmt(const Stmt *S); + + til::BasicBlock *lookupBlock(const CFGBlock *B) { + return BlockMap[B->getBlockID()]; + } + + const til::SCFG *getCFG() const { return Scfg; } + til::SCFG *getCFG() { return Scfg; } + +private: + til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE, + CallingContext *Ctx) ; + til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx); + til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx); + til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx); + til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME, + CallingContext *Ctx); + til::SExpr *translateCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE, + CallingContext *Ctx); + til::SExpr *translateUnaryOperator(const UnaryOperator *UO, + CallingContext *Ctx); + til::SExpr *translateBinOp(til::TIL_BinaryOpcode Op, + const BinaryOperator *BO, + CallingContext *Ctx, bool Reverse = false); + til::SExpr *translateBinAssign(til::TIL_BinaryOpcode Op, + const BinaryOperator *BO, + CallingContext *Ctx, bool Assign = false); + til::SExpr *translateBinaryOperator(const BinaryOperator *BO, + CallingContext *Ctx); + til::SExpr *translateCastExpr(const CastExpr *CE, CallingContext *Ctx); + til::SExpr *translateArraySubscriptExpr(const ArraySubscriptExpr *E, + CallingContext *Ctx); + til::SExpr *translateConditionalOperator(const ConditionalOperator *C, + CallingContext *Ctx); + til::SExpr *translateBinaryConditionalOperator( + const BinaryConditionalOperator *C, CallingContext *Ctx); + + til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx); + + // Map from statements in the clang CFG to SExprs in the til::SCFG. + typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap; + + // Map from clang local variables to indices in a LVarDefinitionMap. + typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap; + + // Map from local variable indices to SSA variables (or constants). + typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair; + typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap; + + struct BlockInfo { + LVarDefinitionMap ExitMap; + bool HasBackEdges; + unsigned UnprocessedSuccessors; // Successors yet to be processed + unsigned ProcessedPredecessors; // Predecessors already processed + + BlockInfo() + : HasBackEdges(false), UnprocessedSuccessors(0), + ProcessedPredecessors(0) {} + BlockInfo(BlockInfo &&RHS) + : ExitMap(std::move(RHS.ExitMap)), + HasBackEdges(RHS.HasBackEdges), + UnprocessedSuccessors(RHS.UnprocessedSuccessors), + ProcessedPredecessors(RHS.ProcessedPredecessors) {} + + BlockInfo &operator=(BlockInfo &&RHS) { + if (this != &RHS) { + ExitMap = std::move(RHS.ExitMap); + HasBackEdges = RHS.HasBackEdges; + UnprocessedSuccessors = RHS.UnprocessedSuccessors; + ProcessedPredecessors = RHS.ProcessedPredecessors; + } + return *this; + } + + private: + BlockInfo(const BlockInfo &) LLVM_DELETED_FUNCTION; + void operator=(const BlockInfo &) LLVM_DELETED_FUNCTION; + }; + + // We implement the CFGVisitor API + friend class CFGWalker; + + void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First); + void enterCFGBlock(const CFGBlock *B); + bool visitPredecessors() { return true; } + void handlePredecessor(const CFGBlock *Pred); + void handlePredecessorBackEdge(const CFGBlock *Pred); + void enterCFGBlockBody(const CFGBlock *B); + void handleStatement(const Stmt *S); + void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD); + void exitCFGBlockBody(const CFGBlock *B); + bool visitSuccessors() { return true; } + void handleSuccessor(const CFGBlock *Succ); + void handleSuccessorBackEdge(const CFGBlock *Succ); + void exitCFGBlock(const CFGBlock *B); + void exitCFG(const CFGBlock *Last); + + void insertStmt(const Stmt *S, til::SExpr *E) { + SMap.insert(std::make_pair(S, E)); + } + til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD); + + til::SExpr *addStatement(til::SExpr *E, const Stmt *S, + const ValueDecl *VD = nullptr); + til::SExpr *lookupVarDecl(const ValueDecl *VD); + til::SExpr *addVarDecl(const ValueDecl *VD, til::SExpr *E); + til::SExpr *updateVarDecl(const ValueDecl *VD, til::SExpr *E); + + void makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E); + void mergeEntryMap(LVarDefinitionMap Map); + void mergeEntryMapBackEdge(); + void mergePhiNodesBackEdge(const CFGBlock *Blk); + +private: + til::MemRegionRef Arena; + til::Variable *SelfVar; // Variable to use for 'this'. May be null. + til::SCFG *Scfg; + + StatementMap SMap; // Map from Stmt to TIL Variables + LVarIndexMap LVarIdxMap; // Indices of clang local vars. + std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs. + std::vector<BlockInfo> BBInfo; // Extra information per BB. + // Indexed by clang BlockID. + std::unique_ptr<SExprBuilder::CallingContext> CallCtx; // Root calling context + + LVarDefinitionMap CurrentLVarMap; + std::vector<til::Variable*> CurrentArguments; + std::vector<til::Variable*> CurrentInstructions; + std::vector<til::Variable*> IncompleteArgs; + til::BasicBlock *CurrentBB; + BlockInfo *CurrentBlockInfo; +}; + + +// Dump an SCFG to llvm::errs(). +void printSCFG(CFGWalker &Walker); + + +} // end namespace threadSafety + +} // end namespace clang + +#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h new file mode 100644 index 0000000..c4f4b21 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h @@ -0,0 +1,108 @@ +//===- ThreadSafetyLogical.h -----------------------------------*- 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 representation for logical expressions with SExpr leaves +// that are used as part of fact-checking capability expressions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_THREAD_SAFETY_LOGICAL_H +#define LLVM_CLANG_THREAD_SAFETY_LOGICAL_H + +#include "clang/Analysis/Analyses/ThreadSafetyTIL.h" + +namespace clang { +namespace threadSafety { +namespace lexpr { + +class LExpr { +public: + enum Opcode { + Terminal, + And, + Or, + Not + }; + Opcode kind() const { return Kind; } + + /// \brief Logical implication. Returns true if the LExpr implies RHS, i.e. if + /// the LExpr holds, then RHS must hold. For example, (A & B) implies A. + inline bool implies(const LExpr *RHS) const; + +protected: + LExpr(Opcode Kind) : Kind(Kind) {} + +private: + Opcode Kind; +}; + +class Terminal : public LExpr { + til::SExprRef Expr; + +public: + Terminal(til::SExpr *Expr) : LExpr(LExpr::Terminal), Expr(Expr) {} + + const til::SExpr *expr() const { return Expr.get(); } + til::SExpr *expr() { return Expr.get(); } + + static bool classof(const LExpr *E) { return E->kind() == LExpr::Terminal; } +}; + +class BinOp : public LExpr { + LExpr *LHS, *RHS; + +protected: + BinOp(LExpr *LHS, LExpr *RHS, Opcode Code) : LExpr(Code), LHS(LHS), RHS(RHS) {} + +public: + const LExpr *left() const { return LHS; } + LExpr *left() { return LHS; } + + const LExpr *right() const { return RHS; } + LExpr *right() { return RHS; } +}; + +class And : public BinOp { +public: + And(LExpr *LHS, LExpr *RHS) : BinOp(LHS, RHS, LExpr::And) {} + + static bool classof(const LExpr *E) { return E->kind() == LExpr::And; } +}; + +class Or : public BinOp { +public: + Or(LExpr *LHS, LExpr *RHS) : BinOp(LHS, RHS, LExpr::Or) {} + + static bool classof(const LExpr *E) { return E->kind() == LExpr::Or; } +}; + +class Not : public LExpr { + LExpr *Exp; + +public: + Not(LExpr *Exp) : LExpr(LExpr::Not), Exp(Exp) {} + + const LExpr *exp() const { return Exp; } + LExpr *exp() { return Exp; } + + static bool classof(const LExpr *E) { return E->kind() == LExpr::Not; } +}; + +/// \brief Logical implication. Returns true if LHS implies RHS, i.e. if LHS +/// holds, then RHS must hold. For example, (A & B) implies A. +bool implies(const LExpr *LHS, const LExpr *RHS); + +bool LExpr::implies(const LExpr *RHS) const { + return lexpr::implies(this, RHS); +} + +} +} +} + +#endif // LLVM_CLANG_THREAD_SAFETY_LOGICAL_H + diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyOps.def b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyOps.def new file mode 100644 index 0000000..6ebc95d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyOps.def @@ -0,0 +1,54 @@ +//===- ThreadSafetyTIL.h ---------------------------------------*- 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 list of core opcodes for the Thread Safety +// Typed Intermediate language. Please see ThreadSafetyTIL.h for more +// information. +// +//===----------------------------------------------------------------------===// + + +TIL_OPCODE_DEF(Future) +TIL_OPCODE_DEF(Undefined) +TIL_OPCODE_DEF(Wildcard) + +TIL_OPCODE_DEF(Literal) +TIL_OPCODE_DEF(LiteralPtr) +TIL_OPCODE_DEF(Variable) +TIL_OPCODE_DEF(Function) +TIL_OPCODE_DEF(SFunction) +TIL_OPCODE_DEF(Code) +TIL_OPCODE_DEF(Field) + +TIL_OPCODE_DEF(Apply) +TIL_OPCODE_DEF(SApply) +TIL_OPCODE_DEF(Project) + +TIL_OPCODE_DEF(Call) +TIL_OPCODE_DEF(Alloc) +TIL_OPCODE_DEF(Load) +TIL_OPCODE_DEF(Store) +TIL_OPCODE_DEF(ArrayIndex) +TIL_OPCODE_DEF(ArrayAdd) + +TIL_OPCODE_DEF(UnaryOp) +TIL_OPCODE_DEF(BinaryOp) +TIL_OPCODE_DEF(Cast) + +TIL_OPCODE_DEF(SCFG) +TIL_OPCODE_DEF(BasicBlock) +TIL_OPCODE_DEF(Phi) +TIL_OPCODE_DEF(Goto) +TIL_OPCODE_DEF(Branch) + +// pseudo-terms +TIL_OPCODE_DEF(Identifier) +TIL_OPCODE_DEF(IfThenElse) +TIL_OPCODE_DEF(Let) + diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h new file mode 100644 index 0000000..8e4299e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -0,0 +1,1813 @@ +//===- ThreadSafetyTIL.h ---------------------------------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT in the llvm repository for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a simple Typed Intermediate Language, or TIL, that is used +// by the thread safety analysis (See ThreadSafety.cpp). The TIL is intended +// to be largely independent of clang, in the hope that the analysis can be +// reused for other non-C++ languages. All dependencies on clang/llvm should +// go in ThreadSafetyUtil.h. +// +// Thread safety analysis works by comparing mutex expressions, e.g. +// +// class A { Mutex mu; int dat GUARDED_BY(this->mu); } +// class B { A a; } +// +// void foo(B* b) { +// (*b).a.mu.lock(); // locks (*b).a.mu +// b->a.dat = 0; // substitute &b->a for 'this'; +// // requires lock on (&b->a)->mu +// (b->a.mu).unlock(); // unlocks (b->a.mu) +// } +// +// As illustrated by the above example, clang Exprs are not well-suited to +// represent mutex expressions directly, since there is no easy way to compare +// Exprs for equivalence. The thread safety analysis thus lowers clang Exprs +// into a simple intermediate language (IL). The IL supports: +// +// (1) comparisons for semantic equality of expressions +// (2) SSA renaming of variables +// (3) wildcards and pattern matching over expressions +// (4) hash-based expression lookup +// +// The TIL is currently very experimental, is intended only for use within +// the thread safety analysis, and is subject to change without notice. +// After the API stabilizes and matures, it may be appropriate to make this +// more generally available to other analyses. +// +// UNDER CONSTRUCTION. USE AT YOUR OWN RISK. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_THREAD_SAFETY_TIL_H +#define LLVM_CLANG_THREAD_SAFETY_TIL_H + +// All clang include dependencies for this file must be put in +// ThreadSafetyUtil.h. +#include "ThreadSafetyUtil.h" + +#include <stdint.h> +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <utility> + + +namespace clang { +namespace threadSafety { +namespace til { + + +enum TIL_Opcode { +#define TIL_OPCODE_DEF(X) COP_##X, +#include "ThreadSafetyOps.def" +#undef TIL_OPCODE_DEF +}; + +enum TIL_UnaryOpcode : unsigned char { + UOP_Minus, // - + UOP_BitNot, // ~ + UOP_LogicNot // ! +}; + +enum TIL_BinaryOpcode : unsigned char { + BOP_Mul, // * + BOP_Div, // / + BOP_Rem, // % + BOP_Add, // + + BOP_Sub, // - + BOP_Shl, // << + BOP_Shr, // >> + BOP_BitAnd, // & + BOP_BitXor, // ^ + BOP_BitOr, // | + BOP_Eq, // == + BOP_Neq, // != + BOP_Lt, // < + BOP_Leq, // <= + BOP_LogicAnd, // && + BOP_LogicOr // || +}; + +enum TIL_CastOpcode : unsigned char { + CAST_none = 0, + CAST_extendNum, // extend precision of numeric type + CAST_truncNum, // truncate precision of numeric type + CAST_toFloat, // convert to floating point type + CAST_toInt, // convert to integer type +}; + +const TIL_Opcode COP_Min = COP_Future; +const TIL_Opcode COP_Max = COP_Branch; +const TIL_UnaryOpcode UOP_Min = UOP_Minus; +const TIL_UnaryOpcode UOP_Max = UOP_LogicNot; +const TIL_BinaryOpcode BOP_Min = BOP_Mul; +const TIL_BinaryOpcode BOP_Max = BOP_LogicOr; +const TIL_CastOpcode CAST_Min = CAST_none; +const TIL_CastOpcode CAST_Max = CAST_toInt; + +StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op); +StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op); + + +// ValueTypes are data types that can actually be held in registers. +// All variables and expressions must have a vBNF_Nonealue type. +// Pointer types are further subdivided into the various heap-allocated +// types, such as functions, records, etc. +// Structured types that are passed by value (e.g. complex numbers) +// require special handling; they use BT_ValueRef, and size ST_0. +struct ValueType { + enum BaseType : unsigned char { + BT_Void = 0, + BT_Bool, + BT_Int, + BT_Float, + BT_String, // String literals + BT_Pointer, + BT_ValueRef + }; + + enum SizeType : unsigned char { + ST_0 = 0, + ST_1, + ST_8, + ST_16, + ST_32, + ST_64, + ST_128 + }; + + inline static SizeType getSizeType(unsigned nbytes); + + template <class T> + inline static ValueType getValueType(); + + ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS) + : Base(B), Size(Sz), Signed(S), VectSize(VS) + { } + + BaseType Base; + SizeType Size; + bool Signed; + unsigned char VectSize; // 0 for scalar, otherwise num elements in vector +}; + + +inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) { + switch (nbytes) { + case 1: return ST_8; + case 2: return ST_16; + case 4: return ST_32; + case 8: return ST_64; + case 16: return ST_128; + default: return ST_0; + } +} + + +template<> +inline ValueType ValueType::getValueType<void>() { + return ValueType(BT_Void, ST_0, false, 0); +} + +template<> +inline ValueType ValueType::getValueType<bool>() { + return ValueType(BT_Bool, ST_1, false, 0); +} + +template<> +inline ValueType ValueType::getValueType<int8_t>() { + return ValueType(BT_Int, ST_8, true, 0); +} + +template<> +inline ValueType ValueType::getValueType<uint8_t>() { + return ValueType(BT_Int, ST_8, false, 0); +} + +template<> +inline ValueType ValueType::getValueType<int16_t>() { + return ValueType(BT_Int, ST_16, true, 0); +} + +template<> +inline ValueType ValueType::getValueType<uint16_t>() { + return ValueType(BT_Int, ST_16, false, 0); +} + +template<> +inline ValueType ValueType::getValueType<int32_t>() { + return ValueType(BT_Int, ST_32, true, 0); +} + +template<> +inline ValueType ValueType::getValueType<uint32_t>() { + return ValueType(BT_Int, ST_32, false, 0); +} + +template<> +inline ValueType ValueType::getValueType<int64_t>() { + return ValueType(BT_Int, ST_64, true, 0); +} + +template<> +inline ValueType ValueType::getValueType<uint64_t>() { + return ValueType(BT_Int, ST_64, false, 0); +} + +template<> +inline ValueType ValueType::getValueType<float>() { + return ValueType(BT_Float, ST_32, true, 0); +} + +template<> +inline ValueType ValueType::getValueType<double>() { + return ValueType(BT_Float, ST_64, true, 0); +} + +template<> +inline ValueType ValueType::getValueType<long double>() { + return ValueType(BT_Float, ST_128, true, 0); +} + +template<> +inline ValueType ValueType::getValueType<StringRef>() { + return ValueType(BT_String, getSizeType(sizeof(StringRef)), false, 0); +} + +template<> +inline ValueType ValueType::getValueType<void*>() { + return ValueType(BT_Pointer, getSizeType(sizeof(void*)), false, 0); +} + + + +// Base class for AST nodes in the typed intermediate language. +class SExpr { +public: + TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); } + + // Subclasses of SExpr must define the following: + // + // This(const This& E, ...) { + // copy constructor: construct copy of E, with some additional arguments. + // } + // + // template <class V> + // typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + // traverse all subexpressions, following the traversal/rewriter interface. + // } + // + // template <class C> typename C::CType compare(CType* E, C& Cmp) { + // compare all subexpressions, following the comparator interface + // } + + void *operator new(size_t S, MemRegionRef &R) { + return ::operator new(S, R); + } + + // SExpr objects cannot be deleted. + // This declaration is public to workaround a gcc bug that breaks building + // with REQUIRES_EH=1. + void operator delete(void *) LLVM_DELETED_FUNCTION; + +protected: + SExpr(TIL_Opcode Op) : Opcode(Op), Reserved(0), Flags(0) {} + SExpr(const SExpr &E) : Opcode(E.Opcode), Reserved(0), Flags(E.Flags) {} + + const unsigned char Opcode; + unsigned char Reserved; + unsigned short Flags; + +private: + SExpr() LLVM_DELETED_FUNCTION; + + // SExpr objects must be created in an arena. + void *operator new(size_t) LLVM_DELETED_FUNCTION; +}; + + +// Class for owning references to SExprs. +// Includes attach/detach logic for counting variable references and lazy +// rewriting strategies. +class SExprRef { +public: + SExprRef() : Ptr(nullptr) { } + SExprRef(std::nullptr_t P) : Ptr(nullptr) { } + SExprRef(SExprRef &&R) : Ptr(R.Ptr) { R.Ptr = nullptr; } + + // Defined after Variable and Future, below. + inline SExprRef(SExpr *P); + inline ~SExprRef(); + + SExpr *get() { return Ptr; } + const SExpr *get() const { return Ptr; } + + SExpr *operator->() { return get(); } + const SExpr *operator->() const { return get(); } + + SExpr &operator*() { return *Ptr; } + const SExpr &operator*() const { return *Ptr; } + + bool operator==(const SExprRef &R) const { return Ptr == R.Ptr; } + bool operator!=(const SExprRef &R) const { return !operator==(R); } + bool operator==(const SExpr *P) const { return Ptr == P; } + bool operator!=(const SExpr *P) const { return !operator==(P); } + bool operator==(std::nullptr_t) const { return Ptr == nullptr; } + bool operator!=(std::nullptr_t) const { return Ptr != nullptr; } + + inline void reset(SExpr *E); + +private: + inline void attach(); + inline void detach(); + + SExpr *Ptr; +}; + + +// Contains various helper functions for SExprs. +namespace ThreadSafetyTIL { + inline bool isTrivial(const SExpr *E) { + unsigned Op = E->opcode(); + return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr; + } +} + +// Nodes which declare variables +class Function; +class SFunction; +class BasicBlock; +class Let; + + +// A named variable, e.g. "x". +// +// There are two distinct places in which a Variable can appear in the AST. +// A variable declaration introduces a new variable, and can occur in 3 places: +// Let-expressions: (Let (x = t) u) +// Functions: (Function (x : t) u) +// Self-applicable functions (SFunction (x) t) +// +// If a variable occurs in any other location, it is a reference to an existing +// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't +// allocate a separate AST node for variable references; a reference is just a +// pointer to the original declaration. +class Variable : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; } + + // Let-variable, function parameter, or self-variable + enum VariableKind { + VK_Let, + VK_LetBB, + VK_Fun, + VK_SFun + }; + + // These are defined after SExprRef contructor, below + inline Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr); + inline Variable(StringRef s, SExpr *D = nullptr); + inline Variable(const Variable &Vd, SExpr *D); + + VariableKind kind() const { return static_cast<VariableKind>(Flags); } + + const StringRef name() const { return Name; } + const clang::ValueDecl *clangDecl() const { return Cvdecl; } + + // Returns the definition (for let vars) or type (for parameter & self vars) + SExpr *definition() { return Definition.get(); } + const SExpr *definition() const { return Definition.get(); } + + void attachVar() const { ++NumUses; } + void detachVar() const { assert(NumUses > 0); --NumUses; } + + unsigned getID() const { return Id; } + unsigned getBlockID() const { return BlockID; } + + void setName(StringRef S) { Name = S; } + void setID(unsigned Bid, unsigned I) { + BlockID = static_cast<unsigned short>(Bid); + Id = static_cast<unsigned short>(I); + } + void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; } + void setDefinition(SExpr *E); + void setKind(VariableKind K) { Flags = K; } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + // This routine is only called for variable references. + return Vs.reduceVariableRef(this); + } + + template <class C> typename C::CType compare(Variable* E, C& Cmp) { + return Cmp.compareVariableRefs(this, E); + } + +private: + friend class Function; + friend class SFunction; + friend class BasicBlock; + friend class Let; + + StringRef Name; // The name of the variable. + SExprRef Definition; // The TIL type or definition + const clang::ValueDecl *Cvdecl; // The clang declaration for this variable. + + unsigned short BlockID; + unsigned short Id; + mutable unsigned NumUses; +}; + + +// Placeholder for an expression that has not yet been created. +// Used to implement lazy copy and rewriting strategies. +class Future : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Future; } + + enum FutureStatus { + FS_pending, + FS_evaluating, + FS_done + }; + + Future() : + SExpr(COP_Future), Status(FS_pending), Result(nullptr), Location(nullptr) + {} +private: + virtual ~Future() LLVM_DELETED_FUNCTION; +public: + + // Registers the location in the AST where this future is stored. + // Forcing the future will automatically update the AST. + static inline void registerLocation(SExprRef *Member) { + if (Future *F = dyn_cast_or_null<Future>(Member->get())) + F->Location = Member; + } + + // A lazy rewriting strategy should subclass Future and override this method. + virtual SExpr *create() { return nullptr; } + + // Return the result of this future if it exists, otherwise return null. + SExpr *maybeGetResult() { + return Result; + } + + // Return the result of this future; forcing it if necessary. + SExpr *result() { + switch (Status) { + case FS_pending: + force(); + return Result; + case FS_evaluating: + return nullptr; // infinite loop; illegal recursion. + case FS_done: + return Result; + } + } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + assert(Result && "Cannot traverse Future that has not been forced."); + return Vs.traverse(Result, Ctx); + } + + template <class C> typename C::CType compare(Future* E, C& Cmp) { + if (!Result || !E->Result) + return Cmp.comparePointers(this, E); + return Cmp.compare(Result, E->Result); + } + +private: + // Force the future. + inline void force(); + + FutureStatus Status; + SExpr *Result; + SExprRef *Location; +}; + + +inline void SExprRef::attach() { + if (!Ptr) + return; + + TIL_Opcode Op = Ptr->opcode(); + if (Op == COP_Variable) { + cast<Variable>(Ptr)->attachVar(); + } else if (Op == COP_Future) { + cast<Future>(Ptr)->registerLocation(this); + } +} + +inline void SExprRef::detach() { + if (Ptr && Ptr->opcode() == COP_Variable) { + cast<Variable>(Ptr)->detachVar(); + } +} + +inline SExprRef::SExprRef(SExpr *P) : Ptr(P) { + attach(); +} + +inline SExprRef::~SExprRef() { + detach(); +} + +inline void SExprRef::reset(SExpr *P) { + detach(); + Ptr = P; + attach(); +} + + +inline Variable::Variable(StringRef s, SExpr *D) + : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr), + BlockID(0), Id(0), NumUses(0) { + Flags = VK_Let; +} + +inline Variable::Variable(SExpr *D, const clang::ValueDecl *Cvd) + : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"), + Definition(D), Cvdecl(Cvd), BlockID(0), Id(0), NumUses(0) { + Flags = VK_Let; +} + +inline Variable::Variable(const Variable &Vd, SExpr *D) // rewrite constructor + : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl), + BlockID(0), Id(0), NumUses(0) { + Flags = Vd.kind(); +} + +inline void Variable::setDefinition(SExpr *E) { + Definition.reset(E); +} + +void Future::force() { + Status = FS_evaluating; + SExpr *R = create(); + Result = R; + if (Location) + Location->reset(R); + Status = FS_done; +} + + +// Placeholder for C++ expressions that cannot be represented in the TIL. +class Undefined : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; } + + Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {} + Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {} + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + return Vs.reduceUndefined(*this); + } + + template <class C> typename C::CType compare(Undefined* E, C& Cmp) { + return Cmp.comparePointers(Cstmt, E->Cstmt); + } + +private: + const clang::Stmt *Cstmt; +}; + + +// Placeholder for a wildcard that matches any other expression. +class Wildcard : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; } + + Wildcard() : SExpr(COP_Wildcard) {} + Wildcard(const Wildcard &W) : SExpr(W) {} + + template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + return Vs.reduceWildcard(*this); + } + + template <class C> typename C::CType compare(Wildcard* E, C& Cmp) { + return Cmp.trueResult(); + } +}; + + +template <class T> class LiteralT; + +// Base class for literal values. +class Literal : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; } + + Literal(const clang::Expr *C) + : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C) + { } + Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT), Cexpr(nullptr) {} + Literal(const Literal &L) : SExpr(L), ValType(L.ValType), Cexpr(L.Cexpr) {} + + // The clang expression for this literal. + const clang::Expr *clangExpr() const { return Cexpr; } + + ValueType valueType() const { return ValType; } + + template<class T> const LiteralT<T>& as() const { + return *static_cast<const LiteralT<T>*>(this); + } + template<class T> LiteralT<T>& as() { + return *static_cast<LiteralT<T>*>(this); + } + + template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx); + + template <class C> typename C::CType compare(Literal* E, C& Cmp) { + // TODO -- use value, not pointer equality + return Cmp.comparePointers(Cexpr, E->Cexpr); + } + +private: + const ValueType ValType; + const clang::Expr *Cexpr; +}; + + +// Derived class for literal values, which stores the actual value. +template<class T> +class LiteralT : public Literal { +public: + LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) { } + LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) { } + + T value() const { return Val;} + T& value() { return Val; } + +private: + T Val; +}; + + + +template <class V> +typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) { + if (Cexpr) + return Vs.reduceLiteral(*this); + + switch (ValType.Base) { + case ValueType::BT_Void: + break; + case ValueType::BT_Bool: + return Vs.reduceLiteralT(as<bool>()); + case ValueType::BT_Int: { + switch (ValType.Size) { + case ValueType::ST_8: + if (ValType.Signed) + return Vs.reduceLiteralT(as<int8_t>()); + else + return Vs.reduceLiteralT(as<uint8_t>()); + case ValueType::ST_16: + if (ValType.Signed) + return Vs.reduceLiteralT(as<int16_t>()); + else + return Vs.reduceLiteralT(as<uint16_t>()); + case ValueType::ST_32: + if (ValType.Signed) + return Vs.reduceLiteralT(as<int32_t>()); + else + return Vs.reduceLiteralT(as<uint32_t>()); + case ValueType::ST_64: + if (ValType.Signed) + return Vs.reduceLiteralT(as<int64_t>()); + else + return Vs.reduceLiteralT(as<uint64_t>()); + default: + break; + } + } + case ValueType::BT_Float: { + switch (ValType.Size) { + case ValueType::ST_32: + return Vs.reduceLiteralT(as<float>()); + case ValueType::ST_64: + return Vs.reduceLiteralT(as<double>()); + default: + break; + } + } + case ValueType::BT_String: + return Vs.reduceLiteralT(as<StringRef>()); + case ValueType::BT_Pointer: + return Vs.reduceLiteralT(as<void*>()); + case ValueType::BT_ValueRef: + break; + } + return Vs.reduceLiteral(*this); +} + + +// Literal pointer to an object allocated in memory. +// At compile time, pointer literals are represented by symbolic names. +class LiteralPtr : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; } + + LiteralPtr(const clang::ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {} + LiteralPtr(const LiteralPtr &R) : SExpr(R), Cvdecl(R.Cvdecl) {} + + // The clang declaration for the value that this pointer points to. + const clang::ValueDecl *clangDecl() const { return Cvdecl; } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + return Vs.reduceLiteralPtr(*this); + } + + template <class C> typename C::CType compare(LiteralPtr* E, C& Cmp) { + return Cmp.comparePointers(Cvdecl, E->Cvdecl); + } + +private: + const clang::ValueDecl *Cvdecl; +}; + + +// A function -- a.k.a. lambda abstraction. +// Functions with multiple arguments are created by currying, +// e.g. (function (x: Int) (function (y: Int) (add x y))) +class Function : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Function; } + + Function(Variable *Vd, SExpr *Bd) + : SExpr(COP_Function), VarDecl(Vd), Body(Bd) { + Vd->setKind(Variable::VK_Fun); + } + Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor + : SExpr(F), VarDecl(Vd), Body(Bd) { + Vd->setKind(Variable::VK_Fun); + } + + Variable *variableDecl() { return VarDecl; } + const Variable *variableDecl() const { return VarDecl; } + + SExpr *body() { return Body.get(); } + const SExpr *body() const { return Body.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + // This is a variable declaration, so traverse the definition. + auto E0 = Vs.traverse(VarDecl->Definition, Vs.typeCtx(Ctx)); + // Tell the rewriter to enter the scope of the function. + Variable *Nvd = Vs.enterScope(*VarDecl, E0); + auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx)); + Vs.exitScope(*VarDecl); + return Vs.reduceFunction(*this, Nvd, E1); + } + + template <class C> typename C::CType compare(Function* E, C& Cmp) { + typename C::CType Ct = + Cmp.compare(VarDecl->definition(), E->VarDecl->definition()); + if (Cmp.notTrue(Ct)) + return Ct; + Cmp.enterScope(variableDecl(), E->variableDecl()); + Ct = Cmp.compare(body(), E->body()); + Cmp.leaveScope(); + return Ct; + } + +private: + Variable *VarDecl; + SExprRef Body; +}; + + +// A self-applicable function. +// A self-applicable function can be applied to itself. It's useful for +// implementing objects and late binding +class SFunction : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; } + + SFunction(Variable *Vd, SExpr *B) + : SExpr(COP_SFunction), VarDecl(Vd), Body(B) { + assert(Vd->Definition == nullptr); + Vd->setKind(Variable::VK_SFun); + Vd->Definition.reset(this); + } + SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor + : SExpr(F), VarDecl(Vd), Body(B) { + assert(Vd->Definition == nullptr); + Vd->setKind(Variable::VK_SFun); + Vd->Definition.reset(this); + } + + Variable *variableDecl() { return VarDecl; } + const Variable *variableDecl() const { return VarDecl; } + + SExpr *body() { return Body.get(); } + const SExpr *body() const { return Body.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + // A self-variable points to the SFunction itself. + // A rewrite must introduce the variable with a null definition, and update + // it after 'this' has been rewritten. + Variable *Nvd = Vs.enterScope(*VarDecl, nullptr); + auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx)); + Vs.exitScope(*VarDecl); + // A rewrite operation will call SFun constructor to set Vvd->Definition. + return Vs.reduceSFunction(*this, Nvd, E1); + } + + template <class C> typename C::CType compare(SFunction* E, C& Cmp) { + Cmp.enterScope(variableDecl(), E->variableDecl()); + typename C::CType Ct = Cmp.compare(body(), E->body()); + Cmp.leaveScope(); + return Ct; + } + +private: + Variable *VarDecl; + SExprRef Body; +}; + + +// A block of code -- e.g. the body of a function. +class Code : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Code; } + + Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {} + Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor + : SExpr(C), ReturnType(T), Body(B) {} + + SExpr *returnType() { return ReturnType.get(); } + const SExpr *returnType() const { return ReturnType.get(); } + + SExpr *body() { return Body.get(); } + const SExpr *body() const { return Body.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx)); + auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx)); + return Vs.reduceCode(*this, Nt, Nb); + } + + template <class C> typename C::CType compare(Code* E, C& Cmp) { + typename C::CType Ct = Cmp.compare(returnType(), E->returnType()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(body(), E->body()); + } + +private: + SExprRef ReturnType; + SExprRef Body; +}; + + +// A typed, writable location in memory +class Field : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Field; } + + Field(SExpr *R, SExpr *B) : SExpr(COP_Field), Range(R), Body(B) {} + Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor + : SExpr(C), Range(R), Body(B) {} + + SExpr *range() { return Range.get(); } + const SExpr *range() const { return Range.get(); } + + SExpr *body() { return Body.get(); } + const SExpr *body() const { return Body.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx)); + auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx)); + return Vs.reduceField(*this, Nr, Nb); + } + + template <class C> typename C::CType compare(Field* E, C& Cmp) { + typename C::CType Ct = Cmp.compare(range(), E->range()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(body(), E->body()); + } + +private: + SExprRef Range; + SExprRef Body; +}; + + +// Apply an argument to a function +class Apply : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; } + + Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {} + Apply(const Apply &A, SExpr *F, SExpr *Ar) // rewrite constructor + : SExpr(A), Fun(F), Arg(Ar) + {} + + SExpr *fun() { return Fun.get(); } + const SExpr *fun() const { return Fun.get(); } + + SExpr *arg() { return Arg.get(); } + const SExpr *arg() const { return Arg.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx)); + auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx)); + return Vs.reduceApply(*this, Nf, Na); + } + + template <class C> typename C::CType compare(Apply* E, C& Cmp) { + typename C::CType Ct = Cmp.compare(fun(), E->fun()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(arg(), E->arg()); + } + +private: + SExprRef Fun; + SExprRef Arg; +}; + + +// Apply a self-argument to a self-applicable function +class SApply : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; } + + SApply(SExpr *Sf, SExpr *A = nullptr) : SExpr(COP_SApply), Sfun(Sf), Arg(A) {} + SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor + : SExpr(A), Sfun(Sf), Arg(Ar) {} + + SExpr *sfun() { return Sfun.get(); } + const SExpr *sfun() const { return Sfun.get(); } + + SExpr *arg() { return Arg.get() ? Arg.get() : Sfun.get(); } + const SExpr *arg() const { return Arg.get() ? Arg.get() : Sfun.get(); } + + bool isDelegation() const { return Arg == nullptr; } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx)); + typename V::R_SExpr Na = Arg.get() ? Vs.traverse(Arg, Vs.subExprCtx(Ctx)) + : nullptr; + return Vs.reduceSApply(*this, Nf, Na); + } + + template <class C> typename C::CType compare(SApply* E, C& Cmp) { + typename C::CType Ct = Cmp.compare(sfun(), E->sfun()); + if (Cmp.notTrue(Ct) || (!arg() && !E->arg())) + return Ct; + return Cmp.compare(arg(), E->arg()); + } + +private: + SExprRef Sfun; + SExprRef Arg; +}; + + +// Project a named slot from a C++ struct or class. +class Project : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Project; } + + Project(SExpr *R, StringRef SName) + : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr) + { } + Project(SExpr *R, clang::ValueDecl *Cvd) + : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd) + { } + Project(const Project &P, SExpr *R) + : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl) + { } + + SExpr *record() { return Rec.get(); } + const SExpr *record() const { return Rec.get(); } + + const clang::ValueDecl *clangValueDecl() const { return Cvdecl; } + + StringRef slotName() const { + if (Cvdecl) + return Cvdecl->getName(); + else + return SlotName; + } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx)); + return Vs.reduceProject(*this, Nr); + } + + template <class C> typename C::CType compare(Project* E, C& Cmp) { + typename C::CType Ct = Cmp.compare(record(), E->record()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.comparePointers(Cvdecl, E->Cvdecl); + } + +private: + SExprRef Rec; + StringRef SlotName; + clang::ValueDecl *Cvdecl; +}; + + +// Call a function (after all arguments have been applied). +class Call : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Call; } + + Call(SExpr *T, const clang::CallExpr *Ce = nullptr) + : SExpr(COP_Call), Target(T), Cexpr(Ce) {} + Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {} + + SExpr *target() { return Target.get(); } + const SExpr *target() const { return Target.get(); } + + const clang::CallExpr *clangCallExpr() const { return Cexpr; } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nt = Vs.traverse(Target, Vs.subExprCtx(Ctx)); + return Vs.reduceCall(*this, Nt); + } + + template <class C> typename C::CType compare(Call* E, C& Cmp) { + return Cmp.compare(target(), E->target()); + } + +private: + SExprRef Target; + const clang::CallExpr *Cexpr; +}; + + +// Allocate memory for a new value on the heap or stack. +class Alloc : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Call; } + + enum AllocKind { + AK_Stack, + AK_Heap + }; + + Alloc(SExpr *D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) { Flags = K; } + Alloc(const Alloc &A, SExpr *Dt) : SExpr(A), Dtype(Dt) { Flags = A.kind(); } + + AllocKind kind() const { return static_cast<AllocKind>(Flags); } + + SExpr *dataType() { return Dtype.get(); } + const SExpr *dataType() const { return Dtype.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx)); + return Vs.reduceAlloc(*this, Nd); + } + + template <class C> typename C::CType compare(Alloc* E, C& Cmp) { + typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(dataType(), E->dataType()); + } + +private: + SExprRef Dtype; +}; + + +// Load a value from memory. +class Load : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Load; } + + Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {} + Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {} + + SExpr *pointer() { return Ptr.get(); } + const SExpr *pointer() const { return Ptr.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx)); + return Vs.reduceLoad(*this, Np); + } + + template <class C> typename C::CType compare(Load* E, C& Cmp) { + return Cmp.compare(pointer(), E->pointer()); + } + +private: + SExprRef Ptr; +}; + + +// Store a value to memory. +// Source is a pointer, destination is the value to store. +class Store : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Store; } + + Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {} + Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {} + + SExpr *destination() { return Dest.get(); } // Address to store to + const SExpr *destination() const { return Dest.get(); } + + SExpr *source() { return Source.get(); } // Value to store + const SExpr *source() const { return Source.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Np = Vs.traverse(Dest, Vs.subExprCtx(Ctx)); + auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx)); + return Vs.reduceStore(*this, Np, Nv); + } + + template <class C> typename C::CType compare(Store* E, C& Cmp) { + typename C::CType Ct = Cmp.compare(destination(), E->destination()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(source(), E->source()); + } + +private: + SExprRef Dest; + SExprRef Source; +}; + + +// If p is a reference to an array, then first(p) is a reference to the first +// element. The usual array notation p[i] becomes first(p + i). +class ArrayIndex : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; } + + ArrayIndex(SExpr *A, SExpr *N) : SExpr(COP_ArrayIndex), Array(A), Index(N) {} + ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N) + : SExpr(E), Array(A), Index(N) {} + + SExpr *array() { return Array.get(); } + const SExpr *array() const { return Array.get(); } + + SExpr *index() { return Index.get(); } + const SExpr *index() const { return Index.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx)); + auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx)); + return Vs.reduceArrayIndex(*this, Na, Ni); + } + + template <class C> typename C::CType compare(ArrayIndex* E, C& Cmp) { + typename C::CType Ct = Cmp.compare(array(), E->array()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(index(), E->index()); + } + +private: + SExprRef Array; + SExprRef Index; +}; + + +// Pointer arithmetic, restricted to arrays only. +// If p is a reference to an array, then p + n, where n is an integer, is +// a reference to a subarray. +class ArrayAdd : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; } + + ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {} + ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N) + : SExpr(E), Array(A), Index(N) {} + + SExpr *array() { return Array.get(); } + const SExpr *array() const { return Array.get(); } + + SExpr *index() { return Index.get(); } + const SExpr *index() const { return Index.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx)); + auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx)); + return Vs.reduceArrayAdd(*this, Na, Ni); + } + + template <class C> typename C::CType compare(ArrayAdd* E, C& Cmp) { + typename C::CType Ct = Cmp.compare(array(), E->array()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(index(), E->index()); + } + +private: + SExprRef Array; + SExprRef Index; +}; + + +// Simple unary operation -- e.g. !, ~, etc. +class UnaryOp : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; } + + UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) { + Flags = Op; + } + UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U), Expr0(E) { Flags = U.Flags; } + + TIL_UnaryOpcode unaryOpcode() const { + return static_cast<TIL_UnaryOpcode>(Flags); + } + + SExpr *expr() { return Expr0.get(); } + const SExpr *expr() const { return Expr0.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx)); + return Vs.reduceUnaryOp(*this, Ne); + } + + template <class C> typename C::CType compare(UnaryOp* E, C& Cmp) { + typename C::CType Ct = + Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(expr(), E->expr()); + } + +private: + SExprRef Expr0; +}; + + +// Simple binary operation -- e.g. +, -, etc. +class BinaryOp : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; } + + BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1) + : SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) { + Flags = Op; + } + BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1) + : SExpr(B), Expr0(E0), Expr1(E1) { + Flags = B.Flags; + } + + TIL_BinaryOpcode binaryOpcode() const { + return static_cast<TIL_BinaryOpcode>(Flags); + } + + SExpr *expr0() { return Expr0.get(); } + const SExpr *expr0() const { return Expr0.get(); } + + SExpr *expr1() { return Expr1.get(); } + const SExpr *expr1() const { return Expr1.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx)); + auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx)); + return Vs.reduceBinaryOp(*this, Ne0, Ne1); + } + + template <class C> typename C::CType compare(BinaryOp* E, C& Cmp) { + typename C::CType Ct = + Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode()); + if (Cmp.notTrue(Ct)) + return Ct; + Ct = Cmp.compare(expr0(), E->expr0()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(expr1(), E->expr1()); + } + +private: + SExprRef Expr0; + SExprRef Expr1; +}; + + +// Cast expression +class Cast : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; } + + Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; } + Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; } + + TIL_CastOpcode castOpcode() const { + return static_cast<TIL_CastOpcode>(Flags); + } + + SExpr *expr() { return Expr0.get(); } + const SExpr *expr() const { return Expr0.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx)); + return Vs.reduceCast(*this, Ne); + } + + template <class C> typename C::CType compare(Cast* E, C& Cmp) { + typename C::CType Ct = + Cmp.compareIntegers(castOpcode(), E->castOpcode()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(expr(), E->expr()); + } + +private: + SExprRef Expr0; +}; + + +class SCFG; + + +class Phi : public SExpr { +public: + // TODO: change to SExprRef + typedef SimpleArray<SExpr *> ValArray; + + // In minimal SSA form, all Phi nodes are MultiVal. + // During conversion to SSA, incomplete Phi nodes may be introduced, which + // are later determined to be SingleVal, and are thus redundant. + enum Status { + PH_MultiVal = 0, // Phi node has multiple distinct values. (Normal) + PH_SingleVal, // Phi node has one distinct value, and can be eliminated + PH_Incomplete // Phi node is incomplete + }; + + static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; } + + Phi() : SExpr(COP_Phi) {} + Phi(MemRegionRef A, unsigned Nvals) : SExpr(COP_Phi), Values(A, Nvals) {} + Phi(const Phi &P, ValArray &&Vs) : SExpr(P), Values(std::move(Vs)) {} + + const ValArray &values() const { return Values; } + ValArray &values() { return Values; } + + Status status() const { return static_cast<Status>(Flags); } + void setStatus(Status s) { Flags = s; } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + typename V::template Container<typename V::R_SExpr> + Nvs(Vs, Values.size()); + + for (auto *Val : Values) { + Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) ); + } + return Vs.reducePhi(*this, Nvs); + } + + template <class C> typename C::CType compare(Phi *E, C &Cmp) { + // TODO: implement CFG comparisons + return Cmp.comparePointers(this, E); + } + +private: + ValArray Values; +}; + + +// A basic block is part of an SCFG, and can be treated as a function in +// continuation passing style. It consists of a sequence of phi nodes, which +// are "arguments" to the function, followed by a sequence of instructions. +// Both arguments and instructions define new variables. It ends with a +// branch or goto to another basic block in the same SCFG. +class BasicBlock : public SExpr { +public: + typedef SimpleArray<Variable*> VarArray; + typedef SimpleArray<BasicBlock*> BlockArray; + + static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; } + + explicit BasicBlock(MemRegionRef A, BasicBlock* P = nullptr) + : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0), + Parent(P), Terminator(nullptr) + { } + BasicBlock(BasicBlock &B, VarArray &&As, VarArray &&Is, SExpr *T) + : SExpr(COP_BasicBlock), Arena(B.Arena), CFGPtr(nullptr), BlockID(0), + Parent(nullptr), Args(std::move(As)), Instrs(std::move(Is)), + Terminator(T) + { } + + unsigned blockID() const { return BlockID; } + unsigned numPredecessors() const { return Predecessors.size(); } + + const SCFG* cfg() const { return CFGPtr; } + SCFG* cfg() { return CFGPtr; } + + const BasicBlock *parent() const { return Parent; } + BasicBlock *parent() { return Parent; } + + const VarArray &arguments() const { return Args; } + VarArray &arguments() { return Args; } + + const VarArray &instructions() const { return Instrs; } + VarArray &instructions() { return Instrs; } + + const BlockArray &predecessors() const { return Predecessors; } + BlockArray &predecessors() { return Predecessors; } + + const SExpr *terminator() const { return Terminator.get(); } + SExpr *terminator() { return Terminator.get(); } + + void setBlockID(unsigned i) { BlockID = i; } + void setParent(BasicBlock *P) { Parent = P; } + void setTerminator(SExpr *E) { Terminator.reset(E); } + + // Add a new argument. V must define a phi-node. + void addArgument(Variable *V) { + V->setKind(Variable::VK_LetBB); + Args.reserveCheck(1, Arena); + Args.push_back(V); + } + // Add a new instruction. + void addInstruction(Variable *V) { + V->setKind(Variable::VK_LetBB); + Instrs.reserveCheck(1, Arena); + Instrs.push_back(V); + } + // Add a new predecessor, and return the phi-node index for it. + // Will add an argument to all phi-nodes, initialized to nullptr. + unsigned addPredecessor(BasicBlock *Pred); + + // Reserve space for Nargs arguments. + void reserveArguments(unsigned Nargs) { Args.reserve(Nargs, Arena); } + + // Reserve space for Nins instructions. + void reserveInstructions(unsigned Nins) { Instrs.reserve(Nins, Arena); } + + // Reserve space for NumPreds predecessors, including space in phi nodes. + void reservePredecessors(unsigned NumPreds); + + // Return the index of BB, or Predecessors.size if BB is not a predecessor. + unsigned findPredecessorIndex(const BasicBlock *BB) const { + auto I = std::find(Predecessors.cbegin(), Predecessors.cend(), BB); + return std::distance(Predecessors.cbegin(), I); + } + + // Set id numbers for variables. + void renumberVars(); + + template <class V> + typename V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx) { + typename V::template Container<Variable*> Nas(Vs, Args.size()); + typename V::template Container<Variable*> Nis(Vs, Instrs.size()); + + // Entering the basic block should do any scope initialization. + Vs.enterBasicBlock(*this); + + for (auto *A : Args) { + auto Ne = Vs.traverse(A->Definition, Vs.subExprCtx(Ctx)); + Variable *Nvd = Vs.enterScope(*A, Ne); + Nas.push_back(Nvd); + } + for (auto *I : Instrs) { + auto Ne = Vs.traverse(I->Definition, Vs.subExprCtx(Ctx)); + Variable *Nvd = Vs.enterScope(*I, Ne); + Nis.push_back(Nvd); + } + auto Nt = Vs.traverse(Terminator, Ctx); + + // Exiting the basic block should handle any scope cleanup. + Vs.exitBasicBlock(*this); + + return Vs.reduceBasicBlock(*this, Nas, Nis, Nt); + } + + template <class C> typename C::CType compare(BasicBlock *E, C &Cmp) { + // TODO: implement CFG comparisons + return Cmp.comparePointers(this, E); + } + +private: + friend class SCFG; + + MemRegionRef Arena; + + SCFG *CFGPtr; // The CFG that contains this block. + unsigned BlockID; // unique id for this BB in the containing CFG + BasicBlock *Parent; // The parent block is the enclosing lexical scope. + // The parent dominates this block. + BlockArray Predecessors; // Predecessor blocks in the CFG. + VarArray Args; // Phi nodes. One argument per predecessor. + VarArray Instrs; // Instructions. + SExprRef Terminator; // Branch or Goto +}; + + +// An SCFG is a control-flow graph. It consists of a set of basic blocks, each +// of which terminates in a branch to another basic block. There is one +// entry point, and one exit point. +class SCFG : public SExpr { +public: + typedef SimpleArray<BasicBlock *> BlockArray; + typedef BlockArray::iterator iterator; + typedef BlockArray::const_iterator const_iterator; + + static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; } + + SCFG(MemRegionRef A, unsigned Nblocks) + : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks), + Entry(nullptr), Exit(nullptr) { + Entry = new (A) BasicBlock(A, nullptr); + Exit = new (A) BasicBlock(A, Entry); + auto *V = new (A) Variable(new (A) Phi()); + Exit->addArgument(V); + add(Entry); + add(Exit); + } + SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba + : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)), + Entry(nullptr), Exit(nullptr) { + // TODO: set entry and exit! + } + + iterator begin() { return Blocks.begin(); } + iterator end() { return Blocks.end(); } + + const_iterator begin() const { return cbegin(); } + const_iterator end() const { return cend(); } + + const_iterator cbegin() const { return Blocks.cbegin(); } + const_iterator cend() const { return Blocks.cend(); } + + const BasicBlock *entry() const { return Entry; } + BasicBlock *entry() { return Entry; } + const BasicBlock *exit() const { return Exit; } + BasicBlock *exit() { return Exit; } + + inline void add(BasicBlock *BB) { + assert(BB->CFGPtr == nullptr || BB->CFGPtr == this); + BB->setBlockID(Blocks.size()); + BB->CFGPtr = this; + Blocks.reserveCheck(1, Arena); + Blocks.push_back(BB); + } + + void setEntry(BasicBlock *BB) { Entry = BB; } + void setExit(BasicBlock *BB) { Exit = BB; } + + // Set varable ids in all blocks. + void renumberVars(); + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + Vs.enterCFG(*this); + typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size()); + for (auto *B : Blocks) { + Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) ); + } + Vs.exitCFG(*this); + return Vs.reduceSCFG(*this, Bbs); + } + + template <class C> typename C::CType compare(SCFG *E, C &Cmp) { + // TODO -- implement CFG comparisons + return Cmp.comparePointers(this, E); + } + +private: + MemRegionRef Arena; + BlockArray Blocks; + BasicBlock *Entry; + BasicBlock *Exit; +}; + + +class Goto : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; } + + Goto(BasicBlock *B, unsigned I) + : SExpr(COP_Goto), TargetBlock(B), Index(I) {} + Goto(const Goto &G, BasicBlock *B, unsigned I) + : SExpr(COP_Goto), TargetBlock(B), Index(I) {} + + const BasicBlock *targetBlock() const { return TargetBlock; } + BasicBlock *targetBlock() { return TargetBlock; } + + unsigned index() const { return Index; } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock); + return Vs.reduceGoto(*this, Ntb); + } + + template <class C> typename C::CType compare(Goto *E, C &Cmp) { + // TODO -- implement CFG comparisons + return Cmp.comparePointers(this, E); + } + +private: + BasicBlock *TargetBlock; + unsigned Index; // Index into Phi nodes of target block. +}; + + +class Branch : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; } + + Branch(SExpr *C, BasicBlock *T, BasicBlock *E, unsigned TI, unsigned EI) + : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E), + ThenIndex(TI), ElseIndex(EI) + {} + Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E, + unsigned TI, unsigned EI) + : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E), + ThenIndex(TI), ElseIndex(EI) + {} + + const SExpr *condition() const { return Condition; } + SExpr *condition() { return Condition; } + + const BasicBlock *thenBlock() const { return ThenBlock; } + BasicBlock *thenBlock() { return ThenBlock; } + + const BasicBlock *elseBlock() const { return ElseBlock; } + BasicBlock *elseBlock() { return ElseBlock; } + + unsigned thenIndex() const { return ThenIndex; } + unsigned elseIndex() const { return ElseIndex; } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx)); + BasicBlock *Ntb = Vs.reduceBasicBlockRef(ThenBlock); + BasicBlock *Nte = Vs.reduceBasicBlockRef(ElseBlock); + return Vs.reduceBranch(*this, Nc, Ntb, Nte); + } + + template <class C> typename C::CType compare(Branch *E, C &Cmp) { + // TODO -- implement CFG comparisons + return Cmp.comparePointers(this, E); + } + +private: + SExpr *Condition; + BasicBlock *ThenBlock; + BasicBlock *ElseBlock; + unsigned ThenIndex; + unsigned ElseIndex; +}; + + +// An identifier, e.g. 'foo' or 'x'. +// This is a pseduo-term; it will be lowered to a variable or projection. +class Identifier : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; } + + Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) { } + Identifier(const Identifier& I) : SExpr(I), Name(I.Name) { } + + StringRef name() const { return Name; } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + return Vs.reduceIdentifier(*this); + } + + template <class C> typename C::CType compare(Identifier* E, C& Cmp) { + return Cmp.compareStrings(name(), E->name()); + } + +private: + StringRef Name; +}; + + +// An if-then-else expression. +// This is a pseduo-term; it will be lowered to a branch in a CFG. +class IfThenElse : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; } + + IfThenElse(SExpr *C, SExpr *T, SExpr *E) + : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E) + { } + IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E) + : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E) + { } + + SExpr *condition() { return Condition.get(); } // Address to store to + const SExpr *condition() const { return Condition.get(); } + + SExpr *thenExpr() { return ThenExpr.get(); } // Value to store + const SExpr *thenExpr() const { return ThenExpr.get(); } + + SExpr *elseExpr() { return ElseExpr.get(); } // Value to store + const SExpr *elseExpr() const { return ElseExpr.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx)); + auto Nt = Vs.traverse(ThenExpr, Vs.subExprCtx(Ctx)); + auto Ne = Vs.traverse(ElseExpr, Vs.subExprCtx(Ctx)); + return Vs.reduceIfThenElse(*this, Nc, Nt, Ne); + } + + template <class C> typename C::CType compare(IfThenElse* E, C& Cmp) { + typename C::CType Ct = Cmp.compare(condition(), E->condition()); + if (Cmp.notTrue(Ct)) + return Ct; + Ct = Cmp.compare(thenExpr(), E->thenExpr()); + if (Cmp.notTrue(Ct)) + return Ct; + return Cmp.compare(elseExpr(), E->elseExpr()); + } + +private: + SExprRef Condition; + SExprRef ThenExpr; + SExprRef ElseExpr; +}; + + +// A let-expression, e.g. let x=t; u. +// This is a pseduo-term; it will be lowered to instructions in a CFG. +class Let : public SExpr { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Let; } + + Let(Variable *Vd, SExpr *Bd) : SExpr(COP_Let), VarDecl(Vd), Body(Bd) { + Vd->setKind(Variable::VK_Let); + } + Let(const Let &L, Variable *Vd, SExpr *Bd) : SExpr(L), VarDecl(Vd), Body(Bd) { + Vd->setKind(Variable::VK_Let); + } + + Variable *variableDecl() { return VarDecl; } + const Variable *variableDecl() const { return VarDecl; } + + SExpr *body() { return Body.get(); } + const SExpr *body() const { return Body.get(); } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + // This is a variable declaration, so traverse the definition. + auto E0 = Vs.traverse(VarDecl->Definition, Vs.subExprCtx(Ctx)); + // Tell the rewriter to enter the scope of the let variable. + Variable *Nvd = Vs.enterScope(*VarDecl, E0); + auto E1 = Vs.traverse(Body, Ctx); + Vs.exitScope(*VarDecl); + return Vs.reduceLet(*this, Nvd, E1); + } + + template <class C> typename C::CType compare(Let* E, C& Cmp) { + typename C::CType Ct = + Cmp.compare(VarDecl->definition(), E->VarDecl->definition()); + if (Cmp.notTrue(Ct)) + return Ct; + Cmp.enterScope(variableDecl(), E->variableDecl()); + Ct = Cmp.compare(body(), E->body()); + Cmp.leaveScope(); + return Ct; + } + +private: + Variable *VarDecl; + SExprRef Body; +}; + + + +SExpr *getCanonicalVal(SExpr *E); +void simplifyIncompleteArg(Variable *V, til::Phi *Ph); + + +} // end namespace til +} // end namespace threadSafety +} // end namespace clang + +#endif // LLVM_CLANG_THREAD_SAFETY_TIL_H diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h new file mode 100644 index 0000000..bc1490b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h @@ -0,0 +1,936 @@ +//===- ThreadSafetyTraverse.h ----------------------------------*- 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 framework for doing generic traversals and rewriting +// operations over the Thread Safety TIL. +// +// UNDER CONSTRUCTION. USE AT YOUR OWN RISK. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H +#define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H + +#include "ThreadSafetyTIL.h" + +namespace clang { +namespace threadSafety { +namespace til { + +// Defines an interface used to traverse SExprs. Traversals have been made as +// generic as possible, and are intended to handle any kind of pass over the +// AST, e.g. visiters, copying, non-destructive rewriting, destructive +// (in-place) rewriting, hashing, typing, etc. +// +// Traversals implement the functional notion of a "fold" operation on SExprs. +// Each SExpr class provides a traverse method, which does the following: +// * e->traverse(v): +// // compute a result r_i for each subexpression e_i +// for (i = 1..n) r_i = v.traverse(e_i); +// // combine results into a result for e, where X is the class of e +// return v.reduceX(*e, r_1, .. r_n). +// +// A visitor can control the traversal by overriding the following methods: +// * v.traverse(e): +// return v.traverseByCase(e), which returns v.traverseX(e) +// * v.traverseX(e): (X is the class of e) +// return e->traverse(v). +// * v.reduceX(*e, r_1, .. r_n): +// compute a result for a node of type X +// +// The reduceX methods control the kind of traversal (visitor, copy, etc.). +// They are defined in derived classes. +// +// Class R defines the basic interface types (R_SExpr). +template <class Self, class R> +class Traversal { +public: + Self *self() { return static_cast<Self *>(this); } + + // Traverse an expression -- returning a result of type R_SExpr. + // Override this method to do something for every expression, regardless + // of which kind it is. + typename R::R_SExpr traverse(SExprRef &E, typename R::R_Ctx Ctx) { + return traverse(E.get(), Ctx); + } + + typename R::R_SExpr traverse(SExpr *E, typename R::R_Ctx Ctx) { + return traverseByCase(E, Ctx); + } + + // Helper method to call traverseX(e) on the appropriate type. + typename R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx) { + switch (E->opcode()) { +#define TIL_OPCODE_DEF(X) \ + case COP_##X: \ + return self()->traverse##X(cast<X>(E), Ctx); +#include "ThreadSafetyOps.def" +#undef TIL_OPCODE_DEF + } + } + +// Traverse e, by static dispatch on the type "X" of e. +// Override these methods to do something for a particular kind of term. +#define TIL_OPCODE_DEF(X) \ + typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) { \ + return e->traverse(*self(), Ctx); \ + } +#include "ThreadSafetyOps.def" +#undef TIL_OPCODE_DEF +}; + + +// Base class for simple reducers that don't much care about the context. +class SimpleReducerBase { +public: + enum TraversalKind { + TRV_Normal, + TRV_Decl, + TRV_Lazy, + TRV_Type + }; + + // R_Ctx defines a "context" for the traversal, which encodes information + // about where a term appears. This can be used to encoding the + // "current continuation" for CPS transforms, or other information. + typedef TraversalKind R_Ctx; + + // Create context for an ordinary subexpression. + R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; } + + // Create context for a subexpression that occurs in a declaration position + // (e.g. function body). + R_Ctx declCtx(R_Ctx Ctx) { return TRV_Decl; } + + // Create context for a subexpression that occurs in a position that + // should be reduced lazily. (e.g. code body). + R_Ctx lazyCtx(R_Ctx Ctx) { return TRV_Lazy; } + + // Create context for a subexpression that occurs in a type position. + R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; } +}; + + +// Base class for traversals that rewrite an SExpr to another SExpr. +class CopyReducerBase : public SimpleReducerBase { +public: + // R_SExpr is the result type for a traversal. + // A copy or non-destructive rewrite returns a newly allocated term. + typedef SExpr *R_SExpr; + typedef BasicBlock *R_BasicBlock; + + // Container is a minimal interface used to store results when traversing + // SExprs of variable arity, such as Phi, Goto, and SCFG. + template <class T> class Container { + public: + // Allocate a new container with a capacity for n elements. + Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {} + + // Push a new element onto the container. + void push_back(T E) { Elems.push_back(E); } + + SimpleArray<T> Elems; + }; + + CopyReducerBase(MemRegionRef A) : Arena(A) {} + +protected: + MemRegionRef Arena; +}; + + +// Implements a traversal that makes a deep copy of an SExpr. +// The default behavior of reduce##X(...) is to create a copy of the original. +// Subclasses can override reduce##X to implement non-destructive rewriting +// passes. +template<class Self> +class CopyReducer : public Traversal<Self, CopyReducerBase>, + public CopyReducerBase { +public: + CopyReducer(MemRegionRef A) : CopyReducerBase(A) {} + +public: + R_SExpr reduceNull() { + return nullptr; + } + // R_SExpr reduceFuture(...) is never used. + + R_SExpr reduceUndefined(Undefined &Orig) { + return new (Arena) Undefined(Orig); + } + R_SExpr reduceWildcard(Wildcard &Orig) { + return new (Arena) Wildcard(Orig); + } + + R_SExpr reduceLiteral(Literal &Orig) { + return new (Arena) Literal(Orig); + } + template<class T> + R_SExpr reduceLiteralT(LiteralT<T> &Orig) { + return new (Arena) LiteralT<T>(Orig); + } + R_SExpr reduceLiteralPtr(LiteralPtr &Orig) { + return new (Arena) LiteralPtr(Orig); + } + + R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) { + return new (Arena) Function(Orig, Nvd, E0); + } + R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) { + return new (Arena) SFunction(Orig, Nvd, E0); + } + R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) { + return new (Arena) Code(Orig, E0, E1); + } + R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) { + return new (Arena) Field(Orig, E0, E1); + } + + R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) { + return new (Arena) Apply(Orig, E0, E1); + } + R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) { + return new (Arena) SApply(Orig, E0, E1); + } + R_SExpr reduceProject(Project &Orig, R_SExpr E0) { + return new (Arena) Project(Orig, E0); + } + R_SExpr reduceCall(Call &Orig, R_SExpr E0) { + return new (Arena) Call(Orig, E0); + } + + R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { + return new (Arena) Alloc(Orig, E0); + } + R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { + return new (Arena) Load(Orig, E0); + } + R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { + return new (Arena) Store(Orig, E0, E1); + } + R_SExpr reduceArrayIndex(ArrayIndex &Orig, R_SExpr E0, R_SExpr E1) { + return new (Arena) ArrayIndex(Orig, E0, E1); + } + R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) { + return new (Arena) ArrayAdd(Orig, E0, E1); + } + R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { + return new (Arena) UnaryOp(Orig, E0); + } + R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) { + return new (Arena) BinaryOp(Orig, E0, E1); + } + R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { + return new (Arena) Cast(Orig, E0); + } + + R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) { + return nullptr; // FIXME: implement CFG rewriting + } + R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As, + Container<Variable *> &Is, R_SExpr T) { + return nullptr; // FIXME: implement CFG rewriting + } + R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) { + return new (Arena) Phi(Orig, std::move(As.Elems)); + } + R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) { + return new (Arena) Goto(Orig, B, 0); // FIXME: set index + } + R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) { + return new (Arena) Branch(O, C, B0, B1, 0, 0); // FIXME: set indices + } + + R_SExpr reduceIdentifier(Identifier &Orig) { + return new (Arena) Identifier(Orig); + } + R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) { + return new (Arena) IfThenElse(Orig, C, T, E); + } + R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) { + return new (Arena) Let(Orig, Nvd, B); + } + + // Create a new variable from orig, and push it onto the lexical scope. + Variable *enterScope(Variable &Orig, R_SExpr E0) { + return new (Arena) Variable(Orig, E0); + } + // Exit the lexical scope of orig. + void exitScope(const Variable &Orig) {} + + void enterCFG(SCFG &Cfg) {} + void exitCFG(SCFG &Cfg) {} + void enterBasicBlock(BasicBlock &BB) {} + void exitBasicBlock(BasicBlock &BB) {} + + // Map Variable references to their rewritten definitions. + Variable *reduceVariableRef(Variable *Ovd) { return Ovd; } + + // Map BasicBlock references to their rewritten definitions. + BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; } +}; + + +class SExprCopier : public CopyReducer<SExprCopier> { +public: + typedef SExpr *R_SExpr; + + SExprCopier(MemRegionRef A) : CopyReducer(A) { } + + // Create a copy of e in region a. + static SExpr *copy(SExpr *E, MemRegionRef A) { + SExprCopier Copier(A); + return Copier.traverse(E, TRV_Normal); + } +}; + + + +// Base class for visit traversals. +class VisitReducerBase : public SimpleReducerBase { +public: + // A visitor returns a bool, representing success or failure. + typedef bool R_SExpr; + typedef bool R_BasicBlock; + + // A visitor "container" is a single bool, which accumulates success. + template <class T> class Container { + public: + Container(VisitReducerBase &S, unsigned N) : Success(true) {} + void push_back(bool E) { Success = Success && E; } + + bool Success; + }; +}; + + +// Implements a traversal that visits each subexpression, and returns either +// true or false. +template <class Self> +class VisitReducer : public Traversal<Self, VisitReducerBase>, + public VisitReducerBase { +public: + VisitReducer() {} + +public: + R_SExpr reduceNull() { return true; } + R_SExpr reduceUndefined(Undefined &Orig) { return true; } + R_SExpr reduceWildcard(Wildcard &Orig) { return true; } + + R_SExpr reduceLiteral(Literal &Orig) { return true; } + template<class T> + R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; } + R_SExpr reduceLiteralPtr(Literal &Orig) { return true; } + + R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) { + return Nvd && E0; + } + R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) { + return Nvd && E0; + } + R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) { + return E0 && E1; + } + R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) { + return E0 && E1; + } + R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) { + return E0 && E1; + } + R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) { + return E0 && E1; + } + R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; } + R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; } + R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; } + R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; } + R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } + R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) { + return E0 && E1; + } + R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) { + return E0 && E1; + } + R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; } + R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) { + return E0 && E1; + } + R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; } + + R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) { + return Bbs.Success; + } + R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As, + Container<Variable *> &Is, R_SExpr T) { + return (As.Success && Is.Success && T); + } + R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) { + return As.Success; + } + R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) { + return true; + } + R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) { + return C; + } + + R_SExpr reduceIdentifier(Identifier &Orig) { + return true; + } + R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) { + return C && T && E; + } + R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) { + return Nvd && B; + } + + Variable *enterScope(Variable &Orig, R_SExpr E0) { return &Orig; } + void exitScope(const Variable &Orig) {} + void enterCFG(SCFG &Cfg) {} + void exitCFG(SCFG &Cfg) {} + void enterBasicBlock(BasicBlock &BB) {} + void exitBasicBlock(BasicBlock &BB) {} + + Variable *reduceVariableRef (Variable *Ovd) { return Ovd; } + BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; } + +public: + bool traverse(SExpr *E, TraversalKind K = TRV_Normal) { + Success = Success && this->traverseByCase(E); + return Success; + } + + static bool visit(SExpr *E) { + Self Visitor; + return Visitor.traverse(E, TRV_Normal); + } + +private: + bool Success; +}; + + +// Basic class for comparison operations over expressions. +template <typename Self> +class Comparator { +protected: + Self *self() { return reinterpret_cast<Self *>(this); } + +public: + bool compareByCase(SExpr *E1, SExpr* E2) { + switch (E1->opcode()) { +#define TIL_OPCODE_DEF(X) \ + case COP_##X: \ + return cast<X>(E1)->compare(cast<X>(E2), *self()); +#include "ThreadSafetyOps.def" +#undef TIL_OPCODE_DEF + } + } +}; + + +class EqualsComparator : public Comparator<EqualsComparator> { +public: + // Result type for the comparison, e.g. bool for simple equality, + // or int for lexigraphic comparison (-1, 0, 1). Must have one value which + // denotes "true". + typedef bool CType; + + CType trueResult() { return true; } + bool notTrue(CType ct) { return !ct; } + + bool compareIntegers(unsigned i, unsigned j) { return i == j; } + bool compareStrings (StringRef s, StringRef r) { return s == r; } + bool comparePointers(const void* P, const void* Q) { return P == Q; } + + bool compare(SExpr *E1, SExpr* E2) { + if (E1->opcode() != E2->opcode()) + return false; + return compareByCase(E1, E2); + } + + // TODO -- handle alpha-renaming of variables + void enterScope(Variable* V1, Variable* V2) { } + void leaveScope() { } + + bool compareVariableRefs(Variable* V1, Variable* V2) { + return V1 == V2; + } + + static bool compareExprs(SExpr *E1, SExpr* E2) { + EqualsComparator Eq; + return Eq.compare(E1, E2); + } +}; + + +// Pretty printer for TIL expressions +template <typename Self, typename StreamType> +class PrettyPrinter { +private: + bool Verbose; // Print out additional information + bool Cleanup; // Omit redundant decls. + +public: + PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { } + + static void print(SExpr *E, StreamType &SS) { + Self printer; + printer.printSExpr(E, SS, Prec_MAX); + } + +protected: + Self *self() { return reinterpret_cast<Self *>(this); } + + void newline(StreamType &SS) { + SS << "\n"; + } + + // TODO: further distinguish between binary operations. + static const unsigned Prec_Atom = 0; + static const unsigned Prec_Postfix = 1; + static const unsigned Prec_Unary = 2; + static const unsigned Prec_Binary = 3; + static const unsigned Prec_Other = 4; + static const unsigned Prec_Decl = 5; + static const unsigned Prec_MAX = 6; + + // Return the precedence of a given node, for use in pretty printing. + unsigned precedence(SExpr *E) { + switch (E->opcode()) { + case COP_Future: return Prec_Atom; + case COP_Undefined: return Prec_Atom; + case COP_Wildcard: return Prec_Atom; + + case COP_Literal: return Prec_Atom; + case COP_LiteralPtr: return Prec_Atom; + case COP_Variable: return Prec_Atom; + case COP_Function: return Prec_Decl; + case COP_SFunction: return Prec_Decl; + case COP_Code: return Prec_Decl; + case COP_Field: return Prec_Decl; + + case COP_Apply: return Prec_Postfix; + case COP_SApply: return Prec_Postfix; + case COP_Project: return Prec_Postfix; + + case COP_Call: return Prec_Postfix; + case COP_Alloc: return Prec_Other; + case COP_Load: return Prec_Postfix; + case COP_Store: return Prec_Other; + case COP_ArrayIndex: return Prec_Postfix; + case COP_ArrayAdd: return Prec_Postfix; + + case COP_UnaryOp: return Prec_Unary; + case COP_BinaryOp: return Prec_Binary; + case COP_Cast: return Prec_Unary; + + case COP_SCFG: return Prec_Decl; + case COP_BasicBlock: return Prec_MAX; + case COP_Phi: return Prec_Atom; + case COP_Goto: return Prec_Atom; + case COP_Branch: return Prec_Atom; + + case COP_Identifier: return Prec_Atom; + case COP_IfThenElse: return Prec_Other; + case COP_Let: return Prec_Decl; + } + return Prec_MAX; + } + + void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) { + if (!BB) { + SS << "BB_null"; + return; + } + SS << "BB_"; + SS << BB->blockID(); + SS << ":"; + SS << index; + } + + void printSExpr(SExpr *E, StreamType &SS, unsigned P) { + if (!E) { + self()->printNull(SS); + return; + } + if (self()->precedence(E) > P) { + // Wrap expr in () if necessary. + SS << "("; + self()->printSExpr(E, SS, Prec_MAX); + SS << ")"; + return; + } + + switch (E->opcode()) { +#define TIL_OPCODE_DEF(X) \ + case COP_##X: \ + self()->print##X(cast<X>(E), SS); \ + return; +#include "ThreadSafetyOps.def" +#undef TIL_OPCODE_DEF + } + } + + void printNull(StreamType &SS) { + SS << "#null"; + } + + void printFuture(Future *E, StreamType &SS) { + self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom); + } + + void printUndefined(Undefined *E, StreamType &SS) { + SS << "#undefined"; + } + + void printWildcard(Wildcard *E, StreamType &SS) { + SS << "_"; + } + + template<class T> + void printLiteralT(LiteralT<T> *E, StreamType &SS) { + SS << E->value(); + } + + void printLiteralT(LiteralT<uint8_t> *E, StreamType &SS) { + SS << "'" << E->value() << "'"; + } + + void printLiteral(Literal *E, StreamType &SS) { + if (E->clangExpr()) { + SS << getSourceLiteralString(E->clangExpr()); + return; + } + else { + ValueType VT = E->valueType(); + switch (VT.Base) { + case ValueType::BT_Void: { + SS << "void"; + return; + } + case ValueType::BT_Bool: { + if (E->as<bool>().value()) + SS << "true"; + else + SS << "false"; + return; + } + case ValueType::BT_Int: { + switch (VT.Size) { + case ValueType::ST_8: + if (VT.Signed) + printLiteralT(&E->as<int8_t>(), SS); + else + printLiteralT(&E->as<uint8_t>(), SS); + return; + case ValueType::ST_16: + if (VT.Signed) + printLiteralT(&E->as<int16_t>(), SS); + else + printLiteralT(&E->as<uint16_t>(), SS); + return; + case ValueType::ST_32: + if (VT.Signed) + printLiteralT(&E->as<int32_t>(), SS); + else + printLiteralT(&E->as<uint32_t>(), SS); + return; + case ValueType::ST_64: + if (VT.Signed) + printLiteralT(&E->as<int64_t>(), SS); + else + printLiteralT(&E->as<uint64_t>(), SS); + return; + default: + break; + } + break; + } + case ValueType::BT_Float: { + switch (VT.Size) { + case ValueType::ST_32: + printLiteralT(&E->as<float>(), SS); + return; + case ValueType::ST_64: + printLiteralT(&E->as<double>(), SS); + return; + default: + break; + } + break; + } + case ValueType::BT_String: { + SS << "\""; + printLiteralT(&E->as<StringRef>(), SS); + SS << "\""; + return; + } + case ValueType::BT_Pointer: { + SS << "#ptr"; + return; + } + case ValueType::BT_ValueRef: { + SS << "#vref"; + return; + } + } + } + SS << "#lit"; + } + + void printLiteralPtr(LiteralPtr *E, StreamType &SS) { + SS << E->clangDecl()->getNameAsString(); + } + + void printVariable(Variable *V, StreamType &SS, bool IsVarDecl = false) { + if (!IsVarDecl && Cleanup) { + SExpr* E = getCanonicalVal(V); + if (E != V) { + printSExpr(E, SS, Prec_Atom); + return; + } + } + if (V->kind() == Variable::VK_LetBB) + SS << V->name() << V->getBlockID() << "_" << V->getID(); + else + SS << V->name() << V->getID(); + } + + void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) { + switch (sugared) { + default: + SS << "\\("; // Lambda + break; + case 1: + SS << "("; // Slot declarations + break; + case 2: + SS << ", "; // Curried functions + break; + } + self()->printVariable(E->variableDecl(), SS, true); + SS << ": "; + self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX); + + SExpr *B = E->body(); + if (B && B->opcode() == COP_Function) + self()->printFunction(cast<Function>(B), SS, 2); + else { + SS << ")"; + self()->printSExpr(B, SS, Prec_Decl); + } + } + + void printSFunction(SFunction *E, StreamType &SS) { + SS << "@"; + self()->printVariable(E->variableDecl(), SS, true); + SS << " "; + self()->printSExpr(E->body(), SS, Prec_Decl); + } + + void printCode(Code *E, StreamType &SS) { + SS << ": "; + self()->printSExpr(E->returnType(), SS, Prec_Decl-1); + SS << " -> "; + self()->printSExpr(E->body(), SS, Prec_Decl); + } + + void printField(Field *E, StreamType &SS) { + SS << ": "; + self()->printSExpr(E->range(), SS, Prec_Decl-1); + SS << " = "; + self()->printSExpr(E->body(), SS, Prec_Decl); + } + + void printApply(Apply *E, StreamType &SS, bool sugared = false) { + SExpr *F = E->fun(); + if (F->opcode() == COP_Apply) { + printApply(cast<Apply>(F), SS, true); + SS << ", "; + } else { + self()->printSExpr(F, SS, Prec_Postfix); + SS << "("; + } + self()->printSExpr(E->arg(), SS, Prec_MAX); + if (!sugared) + SS << ")$"; + } + + void printSApply(SApply *E, StreamType &SS) { + self()->printSExpr(E->sfun(), SS, Prec_Postfix); + if (E->isDelegation()) { + SS << "@("; + self()->printSExpr(E->arg(), SS, Prec_MAX); + SS << ")"; + } + } + + void printProject(Project *E, StreamType &SS) { + self()->printSExpr(E->record(), SS, Prec_Postfix); + SS << "."; + SS << E->slotName(); + } + + void printCall(Call *E, StreamType &SS) { + SExpr *T = E->target(); + if (T->opcode() == COP_Apply) { + self()->printApply(cast<Apply>(T), SS, true); + SS << ")"; + } + else { + self()->printSExpr(T, SS, Prec_Postfix); + SS << "()"; + } + } + + void printAlloc(Alloc *E, StreamType &SS) { + SS << "new "; + self()->printSExpr(E->dataType(), SS, Prec_Other-1); + } + + void printLoad(Load *E, StreamType &SS) { + self()->printSExpr(E->pointer(), SS, Prec_Postfix); + SS << "^"; + } + + void printStore(Store *E, StreamType &SS) { + self()->printSExpr(E->destination(), SS, Prec_Other-1); + SS << " := "; + self()->printSExpr(E->source(), SS, Prec_Other-1); + } + + void printArrayIndex(ArrayIndex *E, StreamType &SS) { + self()->printSExpr(E->array(), SS, Prec_Postfix); + SS << "["; + self()->printSExpr(E->index(), SS, Prec_MAX); + SS << "]"; + } + + void printArrayAdd(ArrayAdd *E, StreamType &SS) { + self()->printSExpr(E->array(), SS, Prec_Postfix); + SS << " + "; + self()->printSExpr(E->index(), SS, Prec_Atom); + } + + void printUnaryOp(UnaryOp *E, StreamType &SS) { + SS << getUnaryOpcodeString(E->unaryOpcode()); + self()->printSExpr(E->expr(), SS, Prec_Unary); + } + + void printBinaryOp(BinaryOp *E, StreamType &SS) { + self()->printSExpr(E->expr0(), SS, Prec_Binary-1); + SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " "; + self()->printSExpr(E->expr1(), SS, Prec_Binary-1); + } + + void printCast(Cast *E, StreamType &SS) { + SS << "%"; + self()->printSExpr(E->expr(), SS, Prec_Unary); + } + + void printSCFG(SCFG *E, StreamType &SS) { + SS << "CFG {\n"; + for (auto BBI : *E) { + printBasicBlock(BBI, SS); + } + SS << "}"; + newline(SS); + } + + void printBasicBlock(BasicBlock *E, StreamType &SS) { + SS << "BB_" << E->blockID() << ":"; + if (E->parent()) + SS << " BB_" << E->parent()->blockID(); + newline(SS); + for (auto *A : E->arguments()) { + SS << "let "; + self()->printVariable(A, SS, true); + SS << " = "; + self()->printSExpr(A->definition(), SS, Prec_MAX); + SS << ";"; + newline(SS); + } + for (auto *I : E->instructions()) { + if (I->definition()->opcode() != COP_Store) { + SS << "let "; + self()->printVariable(I, SS, true); + SS << " = "; + } + self()->printSExpr(I->definition(), SS, Prec_MAX); + SS << ";"; + newline(SS); + } + SExpr *T = E->terminator(); + if (T) { + self()->printSExpr(T, SS, Prec_MAX); + SS << ";"; + newline(SS); + } + newline(SS); + } + + void printPhi(Phi *E, StreamType &SS) { + SS << "phi("; + if (E->status() == Phi::PH_SingleVal) + self()->printSExpr(E->values()[0], SS, Prec_MAX); + else { + unsigned i = 0; + for (auto V : E->values()) { + if (i++ > 0) + SS << ", "; + self()->printSExpr(V, SS, Prec_MAX); + } + } + SS << ")"; + } + + void printGoto(Goto *E, StreamType &SS) { + SS << "goto "; + printBlockLabel(SS, E->targetBlock(), E->index()); + } + + void printBranch(Branch *E, StreamType &SS) { + SS << "branch ("; + self()->printSExpr(E->condition(), SS, Prec_MAX); + SS << ") "; + printBlockLabel(SS, E->thenBlock(), E->thenIndex()); + SS << " "; + printBlockLabel(SS, E->elseBlock(), E->elseIndex()); + } + + void printIdentifier(Identifier *E, StreamType &SS) { + SS << E->name(); + } + + void printIfThenElse(IfThenElse *E, StreamType &SS) { + SS << "if ("; + printSExpr(E->condition(), SS, Prec_MAX); + SS << ") then "; + printSExpr(E->thenExpr(), SS, Prec_Other); + SS << " else "; + printSExpr(E->elseExpr(), SS, Prec_Other); + } + + void printLet(Let *E, StreamType &SS) { + SS << "let "; + printVariable(E->variableDecl(), SS, true); + SS << " = "; + printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1); + SS << "; "; + printSExpr(E->body(), SS, Prec_Decl-1); + } +}; + + +} // end namespace til +} // end namespace threadSafety +} // end namespace clang + +#endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h new file mode 100644 index 0000000..31200a3 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h @@ -0,0 +1,316 @@ +//===- ThreadSafetyUtil.h --------------------------------------*- 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 some basic utility classes for use by ThreadSafetyTIL.h +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_THREAD_SAFETY_UTIL_H +#define LLVM_CLANG_THREAD_SAFETY_UTIL_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" +#include "clang/AST/ExprCXX.h" + +#include <cassert> +#include <cstddef> +#include <vector> +#include <utility> + +namespace clang { +namespace threadSafety { +namespace til { + +// Simple wrapper class to abstract away from the details of memory management. +// SExprs are allocated in pools, and deallocated all at once. +class MemRegionRef { +private: + union AlignmentType { + double d; + void *p; + long double dd; + long long ii; + }; + +public: + MemRegionRef() : Allocator(nullptr) {} + MemRegionRef(llvm::BumpPtrAllocator *A) : Allocator(A) {} + + void *allocate(size_t Sz) { + return Allocator->Allocate(Sz, llvm::AlignOf<AlignmentType>::Alignment); + } + + template <typename T> T *allocateT() { return Allocator->Allocate<T>(); } + + template <typename T> T *allocateT(size_t NumElems) { + return Allocator->Allocate<T>(NumElems); + } + +private: + llvm::BumpPtrAllocator *Allocator; +}; + + +} // end namespace til +} // end namespace threadSafety +} // end namespace clang + + +inline void *operator new(size_t Sz, + clang::threadSafety::til::MemRegionRef &R) { + return R.allocate(Sz); +} + + +namespace clang { +namespace threadSafety { + +std::string getSourceLiteralString(const clang::Expr *CE); + +using llvm::StringRef; +using clang::SourceLocation; + +namespace til { + + +// A simple fixed size array class that does not manage its own memory, +// suitable for use with bump pointer allocation. +template <class T> class SimpleArray { +public: + SimpleArray() : Data(nullptr), Size(0), Capacity(0) {} + SimpleArray(T *Dat, size_t Cp, size_t Sz = 0) + : Data(Dat), Size(Sz), Capacity(Cp) {} + SimpleArray(MemRegionRef A, size_t Cp) + : Data(Cp == 0 ? nullptr : A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {} + SimpleArray(SimpleArray<T> &&A) + : Data(A.Data), Size(A.Size), Capacity(A.Capacity) { + A.Data = nullptr; + A.Size = 0; + A.Capacity = 0; + } + + SimpleArray &operator=(SimpleArray &&RHS) { + if (this != &RHS) { + Data = RHS.Data; + Size = RHS.Size; + Capacity = RHS.Capacity; + + RHS.Data = nullptr; + RHS.Size = RHS.Capacity = 0; + } + return *this; + } + + // Reserve space for at least Ncp items, reallocating if necessary. + void reserve(size_t Ncp, MemRegionRef A) { + if (Ncp <= Capacity) + return; + T *Odata = Data; + Data = A.allocateT<T>(Ncp); + Capacity = Ncp; + memcpy(Data, Odata, sizeof(T) * Size); + return; + } + + // Reserve space for at least N more items. + void reserveCheck(size_t N, MemRegionRef A) { + if (Capacity == 0) + reserve(u_max(InitialCapacity, N), A); + else if (Size + N < Capacity) + reserve(u_max(Size + N, Capacity * 2), A); + } + + typedef T *iterator; + typedef const T *const_iterator; + + size_t size() const { return Size; } + size_t capacity() const { return Capacity; } + + T &operator[](unsigned i) { + assert(i < Size && "Array index out of bounds."); + return Data[i]; + } + const T &operator[](unsigned i) const { + assert(i < Size && "Array index out of bounds."); + return Data[i]; + } + + iterator begin() { return Data; } + iterator end() { return Data + Size; } + + const_iterator cbegin() const { return Data; } + const_iterator cend() const { return Data + Size; } + + void push_back(const T &Elem) { + assert(Size < Capacity); + Data[Size++] = Elem; + } + + void setValues(unsigned Sz, const T& C) { + assert(Sz <= Capacity); + Size = Sz; + for (unsigned i = 0; i < Sz; ++i) { + Data[i] = C; + } + } + + template <class Iter> unsigned append(Iter I, Iter E) { + size_t Osz = Size; + size_t J = Osz; + for (; J < Capacity && I != E; ++J, ++I) + Data[J] = *I; + Size = J; + return J - Osz; + } + +private: + // std::max is annoying here, because it requires a reference, + // thus forcing InitialCapacity to be initialized outside the .h file. + size_t u_max(size_t i, size_t j) { return (i < j) ? j : i; } + + static const size_t InitialCapacity = 4; + + SimpleArray(const SimpleArray<T> &A) LLVM_DELETED_FUNCTION; + + T *Data; + size_t Size; + size_t Capacity; +}; + +} // end namespace til + + +// A copy on write vector. +// The vector can be in one of three states: +// * invalid -- no operations are permitted. +// * read-only -- read operations are permitted. +// * writable -- read and write operations are permitted. +// The init(), destroy(), and makeWritable() methods will change state. +template<typename T> +class CopyOnWriteVector { + class VectorData { + public: + VectorData() : NumRefs(1) { } + VectorData(const VectorData &VD) : NumRefs(1), Vect(VD.Vect) { } + + unsigned NumRefs; + std::vector<T> Vect; + }; + + // No copy constructor or copy assignment. Use clone() with move assignment. + CopyOnWriteVector(const CopyOnWriteVector &V) LLVM_DELETED_FUNCTION; + void operator=(const CopyOnWriteVector &V) LLVM_DELETED_FUNCTION; + +public: + CopyOnWriteVector() : Data(nullptr) {} + CopyOnWriteVector(CopyOnWriteVector &&V) : Data(V.Data) { V.Data = nullptr; } + ~CopyOnWriteVector() { destroy(); } + + // Returns true if this holds a valid vector. + bool valid() const { return Data; } + + // Returns true if this vector is writable. + bool writable() const { return Data && Data->NumRefs == 1; } + + // If this vector is not valid, initialize it to a valid vector. + void init() { + if (!Data) { + Data = new VectorData(); + } + } + + // Destroy this vector; thus making it invalid. + void destroy() { + if (!Data) + return; + if (Data->NumRefs <= 1) + delete Data; + else + --Data->NumRefs; + Data = nullptr; + } + + // Make this vector writable, creating a copy if needed. + void makeWritable() { + if (!Data) { + Data = new VectorData(); + return; + } + if (Data->NumRefs == 1) + return; // already writeable. + --Data->NumRefs; + Data = new VectorData(*Data); + } + + // Create a lazy copy of this vector. + CopyOnWriteVector clone() { return CopyOnWriteVector(Data); } + + CopyOnWriteVector &operator=(CopyOnWriteVector &&V) { + destroy(); + Data = V.Data; + V.Data = nullptr; + return *this; + } + + typedef typename std::vector<T>::const_iterator const_iterator; + + const std::vector<T> &elements() const { return Data->Vect; } + + const_iterator begin() const { return elements().cbegin(); } + const_iterator end() const { return elements().cend(); } + + const T& operator[](unsigned i) const { return elements()[i]; } + + unsigned size() const { return Data ? elements().size() : 0; } + + // Return true if V and this vector refer to the same data. + bool sameAs(const CopyOnWriteVector &V) const { return Data == V.Data; } + + // Clear vector. The vector must be writable. + void clear() { + assert(writable() && "Vector is not writable!"); + Data->Vect.clear(); + } + + // Push a new element onto the end. The vector must be writable. + void push_back(const T &Elem) { + assert(writable() && "Vector is not writable!"); + Data->Vect.push_back(Elem); + } + + // Gets a mutable reference to the element at index(i). + // The vector must be writable. + T& elem(unsigned i) { + assert(writable() && "Vector is not writable!"); + return Data->Vect[i]; + } + + // Drops elements from the back until the vector has size i. + void downsize(unsigned i) { + assert(writable() && "Vector is not writable!"); + Data->Vect.erase(Data->Vect.begin() + i, Data->Vect.end()); + } + +private: + CopyOnWriteVector(VectorData *D) : Data(D) { + if (!Data) + return; + ++Data->NumRefs; + } + + VectorData *Data; +}; + + +} // end namespace threadSafety +} // end namespace clang + +#endif // LLVM_CLANG_THREAD_SAFETY_UTIL_H diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h index b6f183d..08e3354 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h @@ -19,8 +19,8 @@ #include "clang/Analysis/CFG.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/Allocator.h" +#include <memory> namespace clang { @@ -69,16 +69,16 @@ class AnalysisDeclContext { const Decl * const D; - OwningPtr<CFG> cfg, completeCFG; - OwningPtr<CFGStmtMap> cfgStmtMap; + std::unique_ptr<CFG> cfg, completeCFG; + std::unique_ptr<CFGStmtMap> cfgStmtMap; CFG::BuildOptions cfgBuildOptions; CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; bool builtCFG, builtCompleteCFG; - OwningPtr<ParentMap> PM; - OwningPtr<PseudoConstantAnalysis> PCA; - OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA; + std::unique_ptr<ParentMap> PM; + std::unique_ptr<PseudoConstantAnalysis> PCA; + std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA; llvm::BumpPtrAllocator A; @@ -252,7 +252,7 @@ public: virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; void dumpStack(raw_ostream &OS, StringRef Indent = "") const; - LLVM_ATTRIBUTE_USED void dumpStack() const; + void dumpStack() const; public: static void ProfileCommon(llvm::FoldingSetNodeID &ID, @@ -287,11 +287,11 @@ public: const CFGBlock *getCallSiteBlock() const { return Block; } /// Return true if the current LocationContext has no caller context. - virtual bool inTopFrame() const { return getParent() == 0; } + bool inTopFrame() const override { return getParent() == nullptr; } unsigned getIndex() const { return Index; } - void Profile(llvm::FoldingSetNodeID &ID); + void Profile(llvm::FoldingSetNodeID &ID) override; static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s, @@ -317,7 +317,7 @@ class ScopeContext : public LocationContext { public: ~ScopeContext() {} - void Profile(llvm::FoldingSetNodeID &ID); + void Profile(llvm::FoldingSetNodeID &ID) override; static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s) { @@ -349,7 +349,7 @@ public: const void *getContextData() const { return ContextData; } - void Profile(llvm::FoldingSetNodeID &ID); + void Profile(llvm::FoldingSetNodeID &ID) override; static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, const LocationContext *parent, const BlockDecl *bd, @@ -409,7 +409,8 @@ public: bool addInitializers = false, bool addTemporaryDtors = false, bool synthesizeBodies = false, - bool addStaticInitBranches = false); + bool addStaticInitBranches = false, + bool addCXXNewAllocator = true); ~AnalysisDeclContextManager(); @@ -437,7 +438,8 @@ public: // Get the top level stack frame. const StackFrameContext *getStackFrame(const Decl *D) { - return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0); + return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr, + 0); } // Get a stack frame with parent. diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h index 14b7ab8..891fb90 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h @@ -21,13 +21,14 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" #include <bitset> #include <cassert> #include <iterator> +#include <memory> namespace clang { class CXXDestructorDecl; @@ -45,6 +46,8 @@ namespace clang { class ASTContext; class CXXRecordDecl; class CXXDeleteExpr; + class CXXNewExpr; + class BinaryOperator; /// CFGElement - Represents a top-level expression in a basic block. class CFGElement { @@ -53,6 +56,7 @@ public: // main kind Statement, Initializer, + NewAllocator, // dtor kind AutomaticObjectDtor, DeleteDtor, @@ -68,9 +72,11 @@ protected: llvm::PointerIntPair<void *, 2> Data1; llvm::PointerIntPair<void *, 2> Data2; - CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0) + CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr) : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), - Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {} + Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) { + assert(getKind() == kind); + } CFGElement() {} public: @@ -141,12 +147,31 @@ private: } }; +/// CFGNewAllocator - Represents C++ allocator call. +class CFGNewAllocator : public CFGElement { +public: + explicit CFGNewAllocator(const CXXNewExpr *S) + : CFGElement(NewAllocator, S) {} + + // Get the new expression. + const CXXNewExpr *getAllocatorExpr() const { + return static_cast<CXXNewExpr *>(Data1.getPointer()); + } + +private: + friend class CFGElement; + CFGNewAllocator() {} + static bool isKind(const CFGElement &elem) { + return elem.getKind() == NewAllocator; + } +}; + /// CFGImplicitDtor - Represents C++ object destructor implicitly generated /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { protected: CFGImplicitDtor() {} - CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0) + CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr) : CFGElement(kind, data1, data2) { assert(kind >= DTOR_BEGIN && kind <= DTOR_END); } @@ -237,7 +262,7 @@ private: class CFGMemberDtor : public CFGImplicitDtor { public: CFGMemberDtor(const FieldDecl *field) - : CFGImplicitDtor(MemberDtor, field, 0) {} + : CFGImplicitDtor(MemberDtor, field, nullptr) {} const FieldDecl *getFieldDecl() const { return static_cast<const FieldDecl*>(Data1.getPointer()); @@ -256,7 +281,7 @@ private: class CFGTemporaryDtor : public CFGImplicitDtor { public: CFGTemporaryDtor(CXXBindTemporaryExpr *expr) - : CFGImplicitDtor(TemporaryDtor, expr, 0) {} + : CFGImplicitDtor(TemporaryDtor, expr, nullptr) {} const CXXBindTemporaryExpr *getBindTemporaryExpr() const { return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer()); @@ -388,9 +413,64 @@ class CFGBlock { /// of the CFG. unsigned BlockID; +public: + /// This class represents a potential adjacent block in the CFG. It encodes + /// whether or not the block is actually reachable, or can be proved to be + /// trivially unreachable. For some cases it allows one to encode scenarios + /// where a block was substituted because the original (now alternate) block + /// is unreachable. + class AdjacentBlock { + enum Kind { + AB_Normal, + AB_Unreachable, + AB_Alternate + }; + + CFGBlock *ReachableBlock; + llvm::PointerIntPair<CFGBlock*, 2> UnreachableBlock; + + public: + /// Construct an AdjacentBlock with a possibly unreachable block. + AdjacentBlock(CFGBlock *B, bool IsReachable); + + /// Construct an AdjacentBlock with a reachable block and an alternate + /// unreachable block. + AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock); + + /// Get the reachable block, if one exists. + CFGBlock *getReachableBlock() const { + return ReachableBlock; + } + + /// Get the potentially unreachable block. + CFGBlock *getPossiblyUnreachableBlock() const { + return UnreachableBlock.getPointer(); + } + + /// Provide an implicit conversion to CFGBlock* so that + /// AdjacentBlock can be substituted for CFGBlock*. + operator CFGBlock*() const { + return getReachableBlock(); + } + + CFGBlock& operator *() const { + return *getReachableBlock(); + } + + CFGBlock* operator ->() const { + return getReachableBlock(); + } + + bool isReachable() const { + Kind K = (Kind) UnreachableBlock.getInt(); + return K == AB_Normal || K == AB_Alternate; + } + }; + +private: /// Predecessors/Successors - Keep track of the predecessor / successor /// CFG blocks. - typedef BumpVector<CFGBlock*> AdjacentBlocks; + typedef BumpVector<AdjacentBlock> AdjacentBlocks; AdjacentBlocks Preds; AdjacentBlocks Succs; @@ -410,7 +490,7 @@ class CFGBlock { public: explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent) - : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL), + : Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr), BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false), Parent(parent) {} ~CFGBlock() {} @@ -480,9 +560,11 @@ public: class FilterOptions { public: FilterOptions() { + IgnoreNullPredecessors = 1; IgnoreDefaultsWithCoveredEnums = 0; } + unsigned IgnoreNullPredecessors : 1; unsigned IgnoreDefaultsWithCoveredEnums : 1; }; @@ -495,11 +577,14 @@ public: IMPL I, E; const FilterOptions F; const CFGBlock *From; - public: + public: explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, - const CFGBlock *from, - const FilterOptions &f) - : I(i), E(e), F(f), From(from) {} + const CFGBlock *from, + const FilterOptions &f) + : I(i), E(e), F(f), From(from) { + while (hasMore() && Filter(*I)) + ++I; + } bool hasMore() const { return I != E; } @@ -531,7 +616,7 @@ public: // Manipulation of block contents - void setTerminator(Stmt *Statement) { Terminator = Statement; } + void setTerminator(CFGTerminator Term) { Terminator = Term; } void setLabel(Stmt *Statement) { Label = Statement; } void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; } void setHasNoReturnElement() { HasNoReturnElement = true; } @@ -539,10 +624,10 @@ public: CFGTerminator getTerminator() { return Terminator; } const CFGTerminator getTerminator() const { return Terminator; } - Stmt *getTerminatorCondition(); + Stmt *getTerminatorCondition(bool StripParens = true); - const Stmt *getTerminatorCondition() const { - return const_cast<CFGBlock*>(this)->getTerminatorCondition(); + const Stmt *getTerminatorCondition(bool StripParens = true) const { + return const_cast<CFGBlock*>(this)->getTerminatorCondition(StripParens); } const Stmt *getLoopTarget() const { return LoopTarget; } @@ -556,17 +641,19 @@ public: CFG *getParent() const { return Parent; } + void dump() const; + void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const; void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO, bool ShowColors) const; void printTerminator(raw_ostream &OS, const LangOptions &LO) const; - - void addSuccessor(CFGBlock *Block, BumpVectorContext &C) { - if (Block) - Block->Preds.push_back(this, C); - Succs.push_back(Block, C); + void printAsOperand(raw_ostream &OS, bool /*PrintType*/) { + OS << "BB#" << getBlockID(); } + /// Adds a (potentially unreachable) successor block to the current block. + void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C); + void appendStmt(Stmt *statement, BumpVectorContext &C) { Elements.push_back(CFGStmt(statement), C); } @@ -576,6 +663,11 @@ public: Elements.push_back(CFGInitializer(initializer), C); } + void appendNewAllocator(CXXNewExpr *NE, + BumpVectorContext &C) { + Elements.push_back(CFGNewAllocator(NE), C); + } + void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) { Elements.push_back(CFGBaseDtor(BS), C); } @@ -601,7 +693,8 @@ public: // the elements beginning at the last position in prepared space. iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, BumpVectorContext &C) { - return iterator(Elements.insert(I.base(), Cnt, CFGAutomaticObjDtor(0, 0), C)); + return iterator(Elements.insert(I.base(), Cnt, + CFGAutomaticObjDtor(nullptr, 0), C)); } iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) { *I = CFGAutomaticObjDtor(VD, S); @@ -609,6 +702,17 @@ public: } }; +/// \brief CFGCallback defines methods that should be called when a logical +/// operator error is found when building the CFG. +class CFGCallback { +public: + CFGCallback() {} + virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {} + virtual void compareBitwiseEquality(const BinaryOperator *B, + bool isAlwaysTrue) {} + virtual ~CFGCallback() {} +}; + /// CFG - Represents a source-level, intra-procedural CFG that represents the /// control-flow of a Stmt. The Stmt can represent an entire function body, /// or a single expression. A CFG will always contain one empty block that @@ -627,13 +731,14 @@ public: public: typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs; ForcedBlkExprs **forcedBlkExprs; - + CFGCallback *Observer; bool PruneTriviallyFalseEdges; bool AddEHEdges; bool AddInitializers; bool AddImplicitDtors; bool AddTemporaryDtors; bool AddStaticInitBranches; + bool AddCXXNewAllocator; bool alwaysAdd(const Stmt *stmt) const { return alwaysAddMask[stmt->getStmtClass()]; @@ -650,12 +755,11 @@ public: } BuildOptions() - : forcedBlkExprs(0), PruneTriviallyFalseEdges(true) - ,AddEHEdges(false) - ,AddInitializers(false) - ,AddImplicitDtors(false) - ,AddTemporaryDtors(false) - ,AddStaticInitBranches(false) {} + : forcedBlkExprs(nullptr), Observer(nullptr), + PruneTriviallyFalseEdges(true), AddEHEdges(false), + AddInitializers(false), AddImplicitDtors(false), + AddTemporaryDtors(false), AddStaticInitBranches(false), + AddCXXNewAllocator(false) {} }; /// \brief Provides a custom implementation of the iterator class to have the @@ -845,8 +949,9 @@ public: // Internal: constructors and data. //===--------------------------------------------------------------------===// - CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0), - Blocks(BlkBVC, 10) {} + CFG() + : Entry(nullptr), Exit(nullptr), IndirectGotoBlock(nullptr), NumBlockIDs(0), + Blocks(BlkBVC, 10) {} llvm::BumpPtrAllocator& getAllocator() { return BlkBVC.getAllocator(); diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h deleted file mode 100644 index c611ea2..0000000 --- a/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ /dev/null @@ -1,342 +0,0 @@ -//===--- DataflowSolver.h - Skeleton Dataflow Analysis Code -----*- 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 skeleton code for implementing dataflow analyses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER -#define LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER - -#include "functional" // STL -#include "clang/Analysis/CFG.h" -#include "clang/Analysis/FlowSensitive/DataflowValues.h" -#include "clang/Analysis/ProgramPoint.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" - -namespace clang { - -//===----------------------------------------------------------------------===// -/// DataflowWorkListTy - Data structure representing the worklist used for -/// dataflow algorithms. -//===----------------------------------------------------------------------===// - -class DataflowWorkListTy { - llvm::DenseMap<const CFGBlock*, unsigned char> BlockSet; - SmallVector<const CFGBlock *, 10> BlockQueue; -public: - /// enqueue - Add a block to the worklist. Blocks already on the - /// worklist are not added a second time. - void enqueue(const CFGBlock *B) { - unsigned char &x = BlockSet[B]; - if (x == 1) - return; - x = 1; - BlockQueue.push_back(B); - } - - /// dequeue - Remove a block from the worklist. - const CFGBlock *dequeue() { - assert(!BlockQueue.empty()); - const CFGBlock *B = BlockQueue.pop_back_val(); - BlockSet[B] = 0; - return B; - } - - /// isEmpty - Return true if the worklist is empty. - bool isEmpty() const { return BlockQueue.empty(); } -}; - -//===----------------------------------------------------------------------===// -// BlockItrTraits - Traits classes that allow transparent iteration -// over successors/predecessors of a block depending on the direction -// of our dataflow analysis. -//===----------------------------------------------------------------------===// - -namespace dataflow { -template<typename Tag> struct ItrTraits {}; - -template <> struct ItrTraits<forward_analysis_tag> { - typedef CFGBlock::const_pred_iterator PrevBItr; - typedef CFGBlock::const_succ_iterator NextBItr; - typedef CFGBlock::const_iterator StmtItr; - - static PrevBItr PrevBegin(const CFGBlock *B) { return B->pred_begin(); } - static PrevBItr PrevEnd(const CFGBlock *B) { return B->pred_end(); } - - static NextBItr NextBegin(const CFGBlock *B) { return B->succ_begin(); } - static NextBItr NextEnd(const CFGBlock *B) { return B->succ_end(); } - - static StmtItr StmtBegin(const CFGBlock *B) { return B->begin(); } - static StmtItr StmtEnd(const CFGBlock *B) { return B->end(); } - - static BlockEdge PrevEdge(const CFGBlock *B, const CFGBlock *Prev) { - return BlockEdge(Prev, B, 0); - } - - static BlockEdge NextEdge(const CFGBlock *B, const CFGBlock *Next) { - return BlockEdge(B, Next, 0); - } -}; - -template <> struct ItrTraits<backward_analysis_tag> { - typedef CFGBlock::const_succ_iterator PrevBItr; - typedef CFGBlock::const_pred_iterator NextBItr; - typedef CFGBlock::const_reverse_iterator StmtItr; - - static PrevBItr PrevBegin(const CFGBlock *B) { return B->succ_begin(); } - static PrevBItr PrevEnd(const CFGBlock *B) { return B->succ_end(); } - - static NextBItr NextBegin(const CFGBlock *B) { return B->pred_begin(); } - static NextBItr NextEnd(const CFGBlock *B) { return B->pred_end(); } - - static StmtItr StmtBegin(const CFGBlock *B) { return B->rbegin(); } - static StmtItr StmtEnd(const CFGBlock *B) { return B->rend(); } - - static BlockEdge PrevEdge(const CFGBlock *B, const CFGBlock *Prev) { - return BlockEdge(B, Prev, 0); - } - - static BlockEdge NextEdge(const CFGBlock *B, const CFGBlock *Next) { - return BlockEdge(Next, B, 0); - } -}; -} // end namespace dataflow - -//===----------------------------------------------------------------------===// -/// DataflowSolverTy - Generic dataflow solver. -//===----------------------------------------------------------------------===// - -template <typename _DFValuesTy, // Usually a subclass of DataflowValues - typename _TransferFuncsTy, - typename _MergeOperatorTy, - typename _Equal = std::equal_to<typename _DFValuesTy::ValTy> > -class DataflowSolver { - - //===----------------------------------------------------===// - // Type declarations. - //===----------------------------------------------------===// - -public: - typedef _DFValuesTy DFValuesTy; - typedef _TransferFuncsTy TransferFuncsTy; - typedef _MergeOperatorTy MergeOperatorTy; - - typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag; - typedef typename _DFValuesTy::ValTy ValTy; - typedef typename _DFValuesTy::EdgeDataMapTy EdgeDataMapTy; - typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy; - - typedef dataflow::ItrTraits<AnalysisDirTag> ItrTraits; - typedef typename ItrTraits::NextBItr NextBItr; - typedef typename ItrTraits::PrevBItr PrevBItr; - typedef typename ItrTraits::StmtItr StmtItr; - - //===----------------------------------------------------===// - // External interface: constructing and running the solver. - //===----------------------------------------------------===// - -public: - DataflowSolver(DFValuesTy& d) : D(d), TF(d.getAnalysisData()) {} - ~DataflowSolver() {} - - /// runOnCFG - Computes dataflow values for all blocks in a CFG. - void runOnCFG(CFG& cfg, bool recordStmtValues = false) { - // Set initial dataflow values and boundary conditions. - D.InitializeValues(cfg); - // Solve the dataflow equations. This will populate D.EdgeDataMap - // with dataflow values. - SolveDataflowEquations(cfg, recordStmtValues); - } - - /// runOnBlock - Computes dataflow values for a given block. This - /// should usually be invoked only after previously computing - /// dataflow values using runOnCFG, as runOnBlock is intended to - /// only be used for querying the dataflow values within a block - /// with and Observer object. - void runOnBlock(const CFGBlock *B, bool recordStmtValues) { - BlockDataMapTy& M = D.getBlockDataMap(); - typename BlockDataMapTy::iterator I = M.find(B); - - if (I != M.end()) { - TF.getVal().copyValues(I->second); - ProcessBlock(B, recordStmtValues, AnalysisDirTag()); - } - } - - void runOnBlock(const CFGBlock &B, bool recordStmtValues) { - runOnBlock(&B, recordStmtValues); - } - void runOnBlock(CFG::iterator &I, bool recordStmtValues) { - runOnBlock(*I, recordStmtValues); - } - void runOnBlock(CFG::const_iterator &I, bool recordStmtValues) { - runOnBlock(*I, recordStmtValues); - } - - void runOnAllBlocks(const CFG& cfg, bool recordStmtValues = false) { - for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I) - runOnBlock(I, recordStmtValues); - } - - //===----------------------------------------------------===// - // Internal solver logic. - //===----------------------------------------------------===// - -private: - - /// SolveDataflowEquations - Perform the actual worklist algorithm - /// to compute dataflow values. - void SolveDataflowEquations(CFG& cfg, bool recordStmtValues) { - EnqueueBlocksOnWorklist(cfg, AnalysisDirTag()); - - while (!WorkList.isEmpty()) { - const CFGBlock *B = WorkList.dequeue(); - ProcessMerge(cfg, B); - ProcessBlock(B, recordStmtValues, AnalysisDirTag()); - UpdateEdges(cfg, B, TF.getVal()); - } - } - - void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::forward_analysis_tag) { - // Enqueue all blocks to ensure the dataflow values are computed - // for every block. Not all blocks are guaranteed to reach the exit block. - for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I) - WorkList.enqueue(&**I); - } - - void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::backward_analysis_tag) { - // Enqueue all blocks to ensure the dataflow values are computed - // for every block. Not all blocks are guaranteed to reach the exit block. - // Enqueue in reverse order since that will more likely match with - // the order they should ideally processed by the dataflow algorithm. - for (CFG::reverse_iterator I=cfg.rbegin(), E=cfg.rend(); I!=E; ++I) - WorkList.enqueue(&**I); - } - - void ProcessMerge(CFG& cfg, const CFGBlock *B) { - ValTy& V = TF.getVal(); - TF.SetTopValue(V); - - // Merge dataflow values from all predecessors of this block. - MergeOperatorTy Merge; - - EdgeDataMapTy& M = D.getEdgeDataMap(); - bool firstMerge = true; - bool noEdges = true; - for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){ - - CFGBlock *PrevBlk = *I; - - if (!PrevBlk) - continue; - - typename EdgeDataMapTy::iterator EI = - M.find(ItrTraits::PrevEdge(B, PrevBlk)); - - if (EI != M.end()) { - noEdges = false; - if (firstMerge) { - firstMerge = false; - V.copyValues(EI->second); - } - else - Merge(V, EI->second); - } - } - - bool isInitialized = true; - typename BlockDataMapTy::iterator BI = D.getBlockDataMap().find(B); - if(BI == D.getBlockDataMap().end()) { - isInitialized = false; - BI = D.getBlockDataMap().insert( std::make_pair(B,ValTy()) ).first; - } - // If no edges have been found, it means this is the first time the solver - // has been called on block B, we copy the initialization values (if any) - // as current value for V (which will be used as edge data) - if(noEdges && isInitialized) - Merge(V, BI->second); - - // Set the data for the block. - BI->second.copyValues(V); - } - - /// ProcessBlock - Process the transfer functions for a given block. - void ProcessBlock(const CFGBlock *B, bool recordStmtValues, - dataflow::forward_analysis_tag) { - - TF.setCurrentBlock(B); - - for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) { - CFGElement El = *I; - if (const CFGStmt *S = El.getAs<CFGStmt>()) - ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag()); - } - - TF.VisitTerminator(const_cast<CFGBlock*>(B)); - } - - void ProcessBlock(const CFGBlock *B, bool recordStmtValues, - dataflow::backward_analysis_tag) { - - TF.setCurrentBlock(B); - - TF.VisitTerminator(const_cast<CFGBlock*>(B)); - - for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) { - CFGElement El = *I; - if (const CFGStmt *S = El.getAs<CFGStmt>()) - ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag()); - } - } - - void ProcessStmt(const Stmt *S, bool record, dataflow::forward_analysis_tag) { - if (record) D.getStmtDataMap()[S] = TF.getVal(); - TF.BlockStmt_Visit(const_cast<Stmt*>(S)); - } - - void ProcessStmt(const Stmt *S, bool record, dataflow::backward_analysis_tag){ - TF.BlockStmt_Visit(const_cast<Stmt*>(S)); - if (record) D.getStmtDataMap()[S] = TF.getVal(); - } - - /// UpdateEdges - After processing the transfer functions for a - /// block, update the dataflow value associated with the block's - /// outgoing/incoming edges (depending on whether we do a - // forward/backward analysis respectively) - void UpdateEdges(CFG& cfg, const CFGBlock *B, ValTy& V) { - for (NextBItr I=ItrTraits::NextBegin(B), E=ItrTraits::NextEnd(B); I!=E; ++I) - if (CFGBlock *NextBlk = *I) - UpdateEdgeValue(ItrTraits::NextEdge(B, NextBlk),V, NextBlk); - } - - /// UpdateEdgeValue - Update the value associated with a given edge. - void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock *TargetBlock) { - EdgeDataMapTy& M = D.getEdgeDataMap(); - typename EdgeDataMapTy::iterator I = M.find(E); - - if (I == M.end()) { // First computed value for this edge? - M[E].copyValues(V); - WorkList.enqueue(TargetBlock); - } - else if (!_Equal()(V,I->second)) { - I->second.copyValues(V); - WorkList.enqueue(TargetBlock); - } - } - -private: - DFValuesTy& D; - DataflowWorkListTy WorkList; - TransferFuncsTy TF; -}; - -} // end namespace clang -#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h index 333329d..57324d0 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h @@ -77,9 +77,9 @@ protected: ProgramPoint(const void *P, Kind k, const LocationContext *l, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : Data1(P), - Data2(0, (((unsigned) k) >> 0) & 0x3), + Data2(nullptr, (((unsigned) k) >> 0) & 0x3), L(l, (((unsigned) k) >> 2) & 0x3), Tag(tag, (((unsigned) k) >> 4) & 0x3) { assert(getKind() == k); @@ -91,7 +91,7 @@ protected: const void *P2, Kind k, const LocationContext *l, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : Data1(P1), Data2(P2, (((unsigned) k) >> 0) & 0x3), L(l, (((unsigned) k) >> 2) & 0x3), @@ -193,7 +193,7 @@ public: class BlockEntrance : public ProgramPoint { public: BlockEntrance(const CFGBlock *B, const LocationContext *L, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : ProgramPoint(B, BlockEntranceKind, L, tag) { assert(B && "BlockEntrance requires non-null block"); } @@ -263,7 +263,7 @@ private: class PreStmt : public StmtPoint { public: PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag, - const Stmt *SubStmt = 0) + const Stmt *SubStmt = nullptr) : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {} const Stmt *getSubStmt() const { return (const Stmt*) getData2(); } @@ -280,17 +280,17 @@ class PostStmt : public StmtPoint { protected: PostStmt() {} PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : StmtPoint(S, data, k, L, tag) {} public: - explicit PostStmt(const Stmt *S, Kind k, - const LocationContext *L, const ProgramPointTag *tag = 0) - : StmtPoint(S, NULL, k, L, tag) {} + explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L, + const ProgramPointTag *tag = nullptr) + : StmtPoint(S, nullptr, k, L, tag) {} explicit PostStmt(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = 0) - : StmtPoint(S, NULL, PostStmtKind, L, tag) {} + const ProgramPointTag *tag = nullptr) + : StmtPoint(S, nullptr, PostStmtKind, L, tag) {} private: friend class ProgramPoint; @@ -304,7 +304,7 @@ private: class PostCondition : public PostStmt { public: PostCondition(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : PostStmt(S, PostConditionKind, L, tag) {} private: @@ -320,7 +320,7 @@ protected: LocationCheck() {} LocationCheck(const Stmt *S, const LocationContext *L, ProgramPoint::Kind K, const ProgramPointTag *tag) - : StmtPoint(S, NULL, K, L, tag) {} + : StmtPoint(S, nullptr, K, L, tag) {} private: friend class ProgramPoint; @@ -333,7 +333,7 @@ private: class PreLoad : public LocationCheck { public: PreLoad(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : LocationCheck(S, L, PreLoadKind, tag) {} private: @@ -347,7 +347,7 @@ private: class PreStore : public LocationCheck { public: PreStore(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : LocationCheck(S, L, PreStoreKind, tag) {} private: @@ -361,7 +361,7 @@ private: class PostLoad : public PostStmt { public: PostLoad(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : PostStmt(S, PostLoadKind, L, tag) {} private: @@ -379,9 +379,9 @@ public: /// \param Loc can be used to store the information about the location /// used in the form it was uttered in the code. PostStore(const Stmt *S, const LocationContext *L, const void *Loc, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : PostStmt(S, PostStoreKind, L, tag) { - assert(getData2() == 0); + assert(getData2() == nullptr); setData2(Loc); } @@ -402,7 +402,7 @@ private: class PostLValue : public PostStmt { public: PostLValue(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = 0) + const ProgramPointTag *tag = nullptr) : PostStmt(S, PostLValueKind, L, tag) {} private: @@ -418,8 +418,8 @@ private: class PreStmtPurgeDeadSymbols : public StmtPoint { public: PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = 0) - : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { } + const ProgramPointTag *tag = nullptr) + : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { } private: friend class ProgramPoint; @@ -434,8 +434,8 @@ private: class PostStmtPurgeDeadSymbols : public StmtPoint { public: PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = 0) - : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { } + const ProgramPointTag *tag = nullptr) + : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { } private: friend class ProgramPoint; @@ -527,8 +527,8 @@ private: /// 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) + PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L, + const ProgramPointTag *Tag = nullptr) : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {} private: @@ -544,8 +544,8 @@ private: /// 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) + PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L, + const ProgramPointTag *Tag = nullptr) : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {} private: @@ -562,7 +562,7 @@ class CallEnter : public ProgramPoint { public: CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, const LocationContext *callerCtx) - : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {} + : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {} const Stmt *getCallExpr() const { return static_cast<const Stmt *>(getData1()); @@ -593,7 +593,7 @@ class CallExitBegin : public ProgramPoint { public: // CallExitBegin uses the callee's location context. CallExitBegin(const StackFrameContext *L) - : ProgramPoint(0, CallExitBeginKind, L, 0) {} + : ProgramPoint(nullptr, CallExitBeginKind, L, nullptr) {} private: friend class ProgramPoint; @@ -610,7 +610,7 @@ public: // CallExitEnd uses the caller's location context. CallExitEnd(const StackFrameContext *CalleeCtx, const LocationContext *CallerCtx) - : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, 0) {} + : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {} const StackFrameContext *getCalleeContext() const { return static_cast<const StackFrameContext *>(getData1()); @@ -629,7 +629,8 @@ private: class EpsilonPoint : public ProgramPoint { public: EpsilonPoint(const LocationContext *L, const void *Data1, - const void *Data2 = 0, const ProgramPointTag *tag = 0) + const void *Data2 = nullptr, + const ProgramPointTag *tag = nullptr) : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {} const void *getData() const { return getData1(); } @@ -647,7 +648,7 @@ private: /// description and potentially other information. class ProgramPointTag { public: - ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {} + ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {} virtual ~ProgramPointTag(); virtual StringRef getTagDescription() const = 0; @@ -658,12 +659,12 @@ protected: private: const void *TagKind; }; - + class SimpleProgramPointTag : public ProgramPointTag { - std::string desc; + std::string Desc; public: - SimpleProgramPointTag(StringRef description); - StringRef getTagDescription() const; + SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg); + StringRef getTagDescription() const override; }; } // end namespace clang @@ -676,13 +677,13 @@ template <> struct DenseMapInfo<clang::ProgramPoint> { static inline clang::ProgramPoint getEmptyKey() { uintptr_t x = reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; - return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); + return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr); } static inline clang::ProgramPoint getTombstoneKey() { uintptr_t x = reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; - return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); + return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr); } static unsigned getHashValue(const clang::ProgramPoint &Loc) { diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h index 387e779..6d0427b 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h @@ -55,12 +55,12 @@ class BumpVector { public: // Default ctor - Initialize to empty. explicit BumpVector(BumpVectorContext &C, unsigned N) - : Begin(NULL), End(NULL), Capacity(NULL) { + : Begin(nullptr), End(nullptr), Capacity(nullptr) { reserve(C, N); } ~BumpVector() { - if (llvm::is_class<T>::value) { + if (std::is_class<T>::value) { // Destroy the constructed elements in the vector. destroy_range(Begin, End); } @@ -130,7 +130,7 @@ public: } void clear() { - if (llvm::is_class<T>::value) { + if (std::is_class<T>::value) { destroy_range(Begin, End); } End = Begin; @@ -223,7 +223,7 @@ void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) { T *NewElts = C.getAllocator().template Allocate<T>(NewCapacity); // Copy the elements over. - if (llvm::is_class<T>::value) { + if (std::is_class<T>::value) { std::uninitialized_copy(Begin, End, NewElts); // Destroy the original elements. destroy_range(Begin, End); diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ABI.h b/contrib/llvm/tools/clang/include/clang/Basic/ABI.h index 3b3d59e..9e8ef2e 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/ABI.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/ABI.h @@ -186,10 +186,10 @@ struct ThunkInfo { /// an ABI-specific comparator. const CXXMethodDecl *Method; - ThunkInfo() : Method(0) { } + ThunkInfo() : Method(nullptr) { } ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return, - const CXXMethodDecl *Method = 0) + const CXXMethodDecl *Method = nullptr) : This(This), Return(Return), Method(Method) {} friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) { @@ -197,7 +197,9 @@ struct ThunkInfo { LHS.Method == RHS.Method; } - bool isEmpty() const { return This.isEmpty() && Return.isEmpty() && Method == 0; } + bool isEmpty() const { + return This.isEmpty() && Return.isEmpty() && Method == nullptr; + } }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td index 8c3bdba..704a375 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td @@ -7,6 +7,54 @@ // //===----------------------------------------------------------------------===// +// The documentation is organized by category. Attributes can have category- +// specific documentation that is collated within the larger document. +class DocumentationCategory<string name> { + string Name = name; + code Content = [{}]; +} +def DocCatFunction : DocumentationCategory<"Function Attributes">; +def DocCatVariable : DocumentationCategory<"Variable Attributes">; +def DocCatType : DocumentationCategory<"Type Attributes">; +def DocCatStmt : DocumentationCategory<"Statement Attributes">; +// Attributes listed under the Undocumented category do not generate any public +// documentation. Ideally, this category should be used for internal-only +// attributes which contain no spellings. +def DocCatUndocumented : DocumentationCategory<"Undocumented">; + +class DocDeprecated<string replacement = ""> { + // If the Replacement field is empty, no replacement will be listed with the + // documentation. Otherwise, the documentation will specify the attribute has + // been superseded by this replacement. + string Replacement = replacement; +} + +// Specifies the documentation to be associated with the given category. +class Documentation { + DocumentationCategory Category; + code Content; + + // If the heading is empty, one may be picked automatically. If the attribute + // only has one spelling, no heading is required as the attribute's sole + // spelling is sufficient. If all spellings are semantically common, the + // heading will be the semantic spelling. If the spellings are not + // semantically common and no heading is provided, an error will be emitted. + string Heading = ""; + + // When set, specifies that the attribute is deprecated and can optionally + // specify a replacement attribute. + DocDeprecated Deprecated; +} + +// Specifies that the attribute is explicitly undocumented. This can be a +// helpful placeholder for the attribute while working on the implementation, +// but should not be used once feature work has been completed. +def Undocumented : Documentation { + let Category = DocCatUndocumented; +} + +include "clang/Basic/AttrDocs.td" + // An attribute's subject is whatever it appertains to. In this file, it is // more accurately a list of things that an attribute can appertain to. All // Decls and Stmts are possibly AttrSubjects (even though the syntax may not @@ -19,29 +67,63 @@ include "clang/Basic/StmtNodes.td" // A subset-subject is an AttrSubject constrained to operate only on some subset // of that subject. // -// The description is used in output messages to specify what the subject -// represents. FIXME: Deal with translation issues. -// // The code fragment is a boolean expression that will confirm that the subject // meets the requirements; the subject will have the name S, and will have the // type specified by the base. It should be a simple boolean expression. -class SubsetSubject<AttrSubject base, string description, code check> - : AttrSubject { +class SubsetSubject<AttrSubject base, code check> : AttrSubject { AttrSubject Base = base; - string Description = description; code CheckCode = check; } // This is the type of a variable which C++11 allows alignas(...) to appertain // to. -def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable", +def NormalVar : SubsetSubject<Var, [{S->getStorageClass() != VarDecl::Register && S->getKind() != Decl::ImplicitParam && S->getKind() != Decl::ParmVar && S->getKind() != Decl::NonTypeTemplateParm}]>; -def NonBitField : SubsetSubject<Field, "non-bit field", +def NonBitField : SubsetSubject<Field, [{!S->isBitField()}]>; +def ObjCInstanceMethod : SubsetSubject<ObjCMethod, + [{S->isInstanceMethod()}]>; + +def ObjCInterfaceDeclInitMethod : SubsetSubject<ObjCMethod, + [{S->getMethodFamily() == OMF_init && + (isa<ObjCInterfaceDecl>(S->getDeclContext()) || + (isa<ObjCCategoryDecl>(S->getDeclContext()) && + cast<ObjCCategoryDecl>(S->getDeclContext())->IsClassExtension()))}]>; + +def Struct : SubsetSubject<Record, + [{!S->isUnion()}]>; + +def TLSVar : SubsetSubject<Var, + [{S->getTLSKind() != 0}]>; + +def SharedVar : SubsetSubject<Var, + [{S->hasGlobalStorage() && !S->getTLSKind()}]>; + +def GlobalVar : SubsetSubject<Var, + [{S->hasGlobalStorage()}]>; + +// FIXME: this hack is needed because DeclNodes.td defines the base Decl node +// type to be a class, not a definition. This makes it impossible to create an +// attribute subject which accepts a Decl. Normally, this is not a problem, +// because the attribute can have no Subjects clause to accomplish this. But in +// the case of a SubsetSubject, there's no way to express it without this hack. +def DeclBase : AttrSubject; +def FunctionLike : SubsetSubject<DeclBase, + [{S->getFunctionType(false) != NULL}]>; + +// HasFunctionProto is a more strict version of FunctionLike, so it should +// never be specified in a Subjects list along with FunctionLike (due to the +// inclusive nature of subject testing). +def HasFunctionProto : SubsetSubject<DeclBase, + [{(S->getFunctionType(true) != NULL && + isa<FunctionProtoType>(S->getFunctionType())) || + isa<ObjCMethodDecl>(S) || + isa<BlockDecl>(S)}]>; + // A single argument to an attribute class Argument<string name, bit optional> { string Name = name; @@ -56,7 +138,6 @@ class ExprArgument<string name, bit opt = 0> : Argument<name, opt>; class FunctionArgument<string name, bit opt = 0> : Argument<name, opt>; class TypeArgument<string name, bit opt = 0> : Argument<name, opt>; class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>; -class SourceLocArgument<string name, bit opt = 0> : Argument<name, opt>; class VariadicUnsignedArgument<string name> : Argument<name, 1>; class VariadicExprArgument<string name> : Argument<name, 1>; @@ -68,6 +149,11 @@ class VersionArgument<string name, bit opt = 0> : Argument<name, opt>; // be dependent. class AlignedArgument<string name, bit opt = 0> : Argument<name, opt>; +// A bool argument with a default value +class DefaultBoolArgument<string name, bit default> : BoolArgument<name, 1> { + bit Default = default; +} + // An integer argument with a default value class DefaultIntArgument<string name, int default> : IntArgument<name, 1> { int Default = default; @@ -95,6 +181,7 @@ class VariadicEnumArgument<string name, string type, list<string> values, class Spelling<string name, string variety> { string Name = name; string Variety = variety; + bit KnownToGCC; } class GNU<string name> : Spelling<name, "GNU">; @@ -103,17 +190,62 @@ class CXX11<string namespace, string name> : Spelling<name, "CXX11"> { string Namespace = namespace; } class Keyword<string name> : Spelling<name, "Keyword">; +class Pragma<string namespace, string name> : Spelling<name, "Pragma"> { + string Namespace = namespace; +} + +// The GCC spelling implies GNU<name, "GNU"> and CXX11<"gnu", name> and also +// sets KnownToGCC to 1. This spelling should be used for any GCC-compatible +// attributes. +class GCC<string name> : Spelling<name, "GCC"> { + let KnownToGCC = 1; +} class Accessor<string name, list<Spelling> spellings> { string Name = name; list<Spelling> Spellings = spellings; } +class SubjectDiag<bit warn> { + bit Warn = warn; +} +def WarnDiag : SubjectDiag<1>; +def ErrorDiag : SubjectDiag<0>; + +class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag, + string customDiag = ""> { + list<AttrSubject> Subjects = subjects; + SubjectDiag Diag = diag; + string CustomDiag = customDiag; +} + +class LangOpt<string name> { + string Name = name; +} +def MicrosoftExt : LangOpt<"MicrosoftExt">; +def Borland : LangOpt<"Borland">; +def CUDA : LangOpt<"CUDA">; + +// Defines targets for target-specific attributes. The list of strings should +// specify architectures for which the target applies, based off the ArchType +// enumeration in Triple.h. +class TargetArch<list<string> arches> { + list<string> Arches = arches; + list<string> OSes; +} +def TargetARM : TargetArch<["arm", "thumb"]>; +def TargetMSP430 : TargetArch<["msp430"]>; +def TargetX86 : TargetArch<["x86"]>; +def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> { + let OSes = ["Win32"]; +} +def TargetMips : TargetArch<["mips", "mipsel"]>; + class Attr { // The various ways in which an attribute can be spelled in source list<Spelling> Spellings; // The things to which an attribute can appertain - list<AttrSubject> Subjects; + SubjectList Subjects; // The arguments allowed on an attribute list<Argument> Args = []; // Accessors which should be generated for the attribute. @@ -131,28 +263,55 @@ class Attr { 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; // Set to true if the attribute's parsing does not match its semantic // content. Eg) It parses 3 args, but semantically takes 4 args. Opts out of // common attribute error checking. bit HasCustomParsing = 0; + // Set to true if all of the attribute's arguments should be parsed in an + // unevaluated context. + bit ParseArgumentsAsUnevaluated = 0; + // Set to true if this attribute can be duplicated on a subject when merging + // attributes. By default, attributes are not merged. + bit DuplicatesAllowedWhileMerging = 0; + // Lists language options, one of which is required to be true for the + // attribute to be applicable. If empty, no language options are required. + list<LangOpt> LangOpts = []; // Any additional text that should be included verbatim in the class. code AdditionalMembers = [{}]; + // Any documentation that should be associated with the attribute. Since an + // attribute may be documented under multiple categories, more than one + // Documentation entry may be listed. + list<Documentation> Documentation; } /// A type attribute is not processed on a declaration or a statement. class TypeAttr : Attr { + // By default, type attributes do not get an AST node. let ASTNode = 0; } /// An inheritable attribute is inherited by later redeclarations. class InheritableAttr : Attr; -/// A target-specific attribute that is meant to be processed via -/// TargetAttributesSema::ProcessDeclAttribute. This class is meant to be used -/// as a mixin with InheritableAttr or Attr depending on the attribute's needs. -class TargetSpecificAttr; +/// A target-specific attribute. This class is meant to be used as a mixin +/// with InheritableAttr or Attr depending on the attribute's needs. +class TargetSpecificAttr<TargetArch target> { + TargetArch Target = target; + // Attributes are generally required to have unique spellings for their names + // so that the parser can determine what kind of attribute it has parsed. + // However, target-specific attributes are special in that the attribute only + // "exists" for a given target. So two target-specific attributes can share + // the same name when they exist in different targets. To support this, a + // Kind can be explicitly specified for a target-specific attribute. This + // corresponds to the AttributeList::AT_* enum that is generated and it + // should contain a shared value between the attributes. + // + // Target-specific attributes which use this feature should ensure that the + // spellings match exactly betweeen the attributes, and if the arguments or + // subjects differ, should specify HasCustomParsing = 1 and implement their + // own parsing and semantic handling requirements as-needed. + string ParseKind; +} /// An inheritable parameter attribute is inherited by later /// redeclarations, even when it's written on a parameter. @@ -163,6 +322,7 @@ class IgnoredAttr : Attr { let Ignored = 1; let ASTNode = 0; let SemaHandler = 0; + let Documentation = [Undocumented]; } // @@ -172,66 +332,77 @@ class IgnoredAttr : Attr { def AddressSpace : TypeAttr { let Spellings = [GNU<"address_space">]; let Args = [IntArgument<"AddressSpace">]; + let Documentation = [Undocumented]; } def Alias : Attr { - let Spellings = [GNU<"alias">, CXX11<"gnu", "alias">]; + let Spellings = [GCC<"alias">]; let Args = [StringArgument<"Aliasee">]; + let Documentation = [Undocumented]; } def Aligned : InheritableAttr { - let Spellings = [GNU<"aligned">, Declspec<"align">, CXX11<"gnu", "aligned">, - Keyword<"alignas">, Keyword<"_Alignas">]; - let Subjects = [NonBitField, NormalVar, Tag]; + let Spellings = [GCC<"aligned">, Declspec<"align">, Keyword<"alignas">, + Keyword<"_Alignas">]; +// let Subjects = SubjectList<[NonBitField, NormalVar, Tag]>; let Args = [AlignedArgument<"Alignment", 1>]; - let Accessors = [Accessor<"isGNU", [GNU<"aligned">, CXX11<"gnu","aligned">]>, + let Accessors = [Accessor<"isGNU", [GCC<"aligned">]>, Accessor<"isC11", [Keyword<"_Alignas">]>, Accessor<"isAlignas", [Keyword<"alignas">, Keyword<"_Alignas">]>, Accessor<"isDeclspec",[Declspec<"align">]>]; + let Documentation = [Undocumented]; } def AlignMac68k : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; let SemaHandler = 0; -} - -def AllocSize : InheritableAttr { - let Spellings = [GNU<"alloc_size">, CXX11<"gnu", "alloc_size">]; - let Args = [VariadicUnsignedArgument<"Args">]; + let Documentation = [Undocumented]; } def AlwaysInline : InheritableAttr { - let Spellings = [GNU<"always_inline">, CXX11<"gnu", "always_inline">]; + let Spellings = [GCC<"always_inline">, Keyword<"__forceinline">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def TLSModel : InheritableAttr { - let Spellings = [GNU<"tls_model">, CXX11<"gnu", "tls_model">]; - let Subjects = [Var]; + let Spellings = [GCC<"tls_model">]; + let Subjects = SubjectList<[TLSVar], ErrorDiag, "ExpectedTLSVar">; let Args = [StringArgument<"Model">]; + let Documentation = [TLSModelDocs]; } def AnalyzerNoReturn : InheritableAttr { let Spellings = [GNU<"analyzer_noreturn">]; + let Documentation = [Undocumented]; } def Annotate : InheritableParamAttr { let Spellings = [GNU<"annotate">]; let Args = [StringArgument<"Annotation">]; + let Documentation = [Undocumented]; } -def ARMInterrupt : InheritableAttr, TargetSpecificAttr { +def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> { + // NOTE: If you add any additional spellings, MSP430Interrupt's spellings + // must match. let Spellings = [GNU<"interrupt">]; let Args = [EnumArgument<"Interrupt", "InterruptType", ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""], ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", "Generic"], 1>]; + let ParseKind = "Interrupt"; + let HasCustomParsing = 1; + let Documentation = [ARMInterruptDocs]; } def AsmLabel : InheritableAttr { - let Spellings = []; + let Spellings = [Keyword<"asm">, Keyword<"__asm__">]; let Args = [StringArgument<"Label">]; let SemaHandler = 0; + let Documentation = [Undocumented]; } def Availability : InheritableAttr { @@ -247,11 +418,15 @@ def Availability : InheritableAttr { .Default(llvm::StringRef()); } }]; let HasCustomParsing = 1; + let DuplicatesAllowedWhileMerging = 1; +// let Subjects = SubjectList<[Named]>; + let Documentation = [AvailabilityDocs]; } def Blocks : InheritableAttr { let Spellings = [GNU<"blocks">]; let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>]; + let Documentation = [Undocumented]; } def Bounded : IgnoredAttr { @@ -259,14 +434,15 @@ def Bounded : IgnoredAttr { } def CarriesDependency : InheritableParamAttr { - let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">, - CXX11<"std","carries_dependency">]; - let Subjects = [ParmVar, Function]; + let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">]; + let Subjects = SubjectList<[ParmVar, ObjCMethod, Function], ErrorDiag>; + let Documentation = [CarriesDependencyDocs]; } def CDecl : InheritableAttr { - let Spellings = [GNU<"cdecl">, CXX11<"gnu", "cdecl">, Keyword<"__cdecl">, - Keyword<"_cdecl">]; + let Spellings = [GCC<"cdecl">, Keyword<"__cdecl">, Keyword<"_cdecl">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [Undocumented]; } // cf_audited_transfer indicates that the given function has been @@ -275,7 +451,8 @@ def CDecl : InheritableAttr { // '#pragma clang arc_cf_code_audited' rather than explicitly. def CFAuditedTransfer : InheritableAttr { let Spellings = [GNU<"cf_audited_transfer">]; - let Subjects = [Function]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [Undocumented]; } // cf_unknown_transfer is an explicit opt-out of cf_audited_transfer. @@ -283,386 +460,623 @@ def CFAuditedTransfer : InheritableAttr { // transfer semantics. def CFUnknownTransfer : InheritableAttr { let Spellings = [GNU<"cf_unknown_transfer">]; - let Subjects = [Function]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [Undocumented]; } def CFReturnsRetained : InheritableAttr { let Spellings = [GNU<"cf_returns_retained">]; - let Subjects = [ObjCMethod, Function]; +// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; + let Documentation = [Undocumented]; } def CFReturnsNotRetained : InheritableAttr { let Spellings = [GNU<"cf_returns_not_retained">]; - let Subjects = [ObjCMethod, Function]; +// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; + let Documentation = [Undocumented]; } def CFConsumed : InheritableParamAttr { let Spellings = [GNU<"cf_consumed">]; - let Subjects = [ParmVar]; + let Subjects = SubjectList<[ParmVar]>; + let Documentation = [Undocumented]; } def Cleanup : InheritableAttr { - let Spellings = [GNU<"cleanup">, CXX11<"gnu", "cleanup">]; + let Spellings = [GCC<"cleanup">]; let Args = [FunctionArgument<"FunctionDecl">]; + let Subjects = SubjectList<[Var]>; + let Documentation = [Undocumented]; } def Cold : InheritableAttr { - let Spellings = [GNU<"cold">, CXX11<"gnu", "cold">]; + let Spellings = [GCC<"cold">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def Common : InheritableAttr { - let Spellings = [GNU<"common">, CXX11<"gnu", "common">]; + let Spellings = [GCC<"common">]; + let Subjects = SubjectList<[Var]>; + let Documentation = [Undocumented]; } def Const : InheritableAttr { - let Spellings = [GNU<"const">, GNU<"__const">, - CXX11<"gnu", "const">, CXX11<"gnu", "__const">]; + let Spellings = [GCC<"const">, GCC<"__const">]; + let Documentation = [Undocumented]; } def Constructor : InheritableAttr { - let Spellings = [GNU<"constructor">, CXX11<"gnu", "constructor">]; - let Args = [IntArgument<"Priority", 1>]; + let Spellings = [GCC<"constructor">]; + let Args = [DefaultIntArgument<"Priority", 65535>]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def CUDAConstant : InheritableAttr { let Spellings = [GNU<"constant">]; + let Subjects = SubjectList<[Var]>; + let LangOpts = [CUDA]; + let Documentation = [Undocumented]; } def CUDADevice : InheritableAttr { let Spellings = [GNU<"device">]; + let Subjects = SubjectList<[Function, Var]>; + let LangOpts = [CUDA]; + let Documentation = [Undocumented]; } def CUDAGlobal : InheritableAttr { let Spellings = [GNU<"global">]; + let Subjects = SubjectList<[Function]>; + let LangOpts = [CUDA]; + let Documentation = [Undocumented]; } def CUDAHost : InheritableAttr { let Spellings = [GNU<"host">]; + let Subjects = SubjectList<[Function]>; + let LangOpts = [CUDA]; + let Documentation = [Undocumented]; } def CUDALaunchBounds : InheritableAttr { let Spellings = [GNU<"launch_bounds">]; let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>]; + let LangOpts = [CUDA]; + let Subjects = SubjectList<[ObjCMethod, FunctionLike], WarnDiag, + "ExpectedFunctionOrMethod">; + // An AST node is created for this attribute, but is not used by other parts + // of the compiler. However, this node needs to exist in the AST because + // non-LLVM backends may be relying on the attribute's presence. + let Documentation = [Undocumented]; } def CUDAShared : InheritableAttr { let Spellings = [GNU<"shared">]; + let Subjects = SubjectList<[Var]>; + let LangOpts = [CUDA]; + let Documentation = [Undocumented]; } def C11NoReturn : InheritableAttr { let Spellings = [Keyword<"_Noreturn">]; - let Subjects = [Function]; + let Subjects = SubjectList<[Function], ErrorDiag>; let SemaHandler = 0; + let Documentation = [C11NoReturnDocs]; } def CXX11NoReturn : InheritableAttr { - let Spellings = [CXX11<"","noreturn">, CXX11<"std","noreturn">]; - let Subjects = [Function]; + let Spellings = [CXX11<"","noreturn">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [CXX11NoReturnDocs]; } def OpenCLKernel : InheritableAttr { let Spellings = [Keyword<"__kernel">, Keyword<"kernel">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [Undocumented]; } +// This attribute is both a type attribute, and a declaration attribute (for +// parameter variables). def OpenCLImageAccess : Attr { - let Spellings = [GNU<"opencl_image_access">]; - let Args = [IntArgument<"Access">]; + let Spellings = [Keyword<"__read_only">, Keyword<"read_only">, + Keyword<"__write_only">, Keyword<"write_only">, + Keyword<"__read_write">, Keyword<"read_write">]; + let Subjects = SubjectList<[ParmVar], ErrorDiag>; + let Accessors = [Accessor<"isReadOnly", [Keyword<"__read_only">, + Keyword<"read_only">]>, + Accessor<"isReadWrite", [Keyword<"__read_write">, + Keyword<"read_write">]>, + Accessor<"isWriteOnly", [Keyword<"__write_only">, + Keyword<"write_only">]>]; + let Documentation = [Undocumented]; +} + +def OpenCLPrivateAddressSpace : TypeAttr { + let Spellings = [Keyword<"__private">, Keyword<"private">]; + let Documentation = [Undocumented]; +} + +def OpenCLGlobalAddressSpace : TypeAttr { + let Spellings = [Keyword<"__global">, Keyword<"global">]; + let Documentation = [Undocumented]; +} + +def OpenCLLocalAddressSpace : TypeAttr { + let Spellings = [Keyword<"__local">, Keyword<"local">]; + let Documentation = [Undocumented]; +} + +def OpenCLConstantAddressSpace : TypeAttr { + let Spellings = [Keyword<"__constant">, Keyword<"constant">]; + let Documentation = [Undocumented]; } def Deprecated : InheritableAttr { - let Spellings = [GNU<"deprecated">, - CXX11<"gnu", "deprecated">, CXX11<"","deprecated">]; + let Spellings = [GCC<"deprecated">, Declspec<"deprecated">, + CXX11<"","deprecated">]; let Args = [StringArgument<"Message", 1>]; + let Documentation = [Undocumented]; } def Destructor : InheritableAttr { - let Spellings = [GNU<"destructor">, CXX11<"gnu", "destructor">]; - let Args = [IntArgument<"Priority", 1>]; + let Spellings = [GCC<"destructor">]; + let Args = [DefaultIntArgument<"Priority", 65535>]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; +} + +def EnableIf : InheritableAttr { + let Spellings = [GNU<"enable_if">]; + let Subjects = SubjectList<[Function]>; + let Args = [ExprArgument<"Cond">, StringArgument<"Message">]; + let TemplateDependent = 1; + let Documentation = [EnableIfDocs]; } def ExtVectorType : Attr { let Spellings = [GNU<"ext_vector_type">]; + let Subjects = SubjectList<[TypedefName], ErrorDiag>; let Args = [ExprArgument<"NumElements">]; let ASTNode = 0; + let Documentation = [Undocumented]; } def FallThrough : Attr { let Spellings = [CXX11<"clang", "fallthrough">]; - let Subjects = [NullStmt]; +// let Subjects = [NullStmt]; + let Documentation = [FallthroughDocs]; } def FastCall : InheritableAttr { - let Spellings = [GNU<"fastcall">, CXX11<"gnu", "fastcall">, - Keyword<"__fastcall">, Keyword<"_fastcall">]; + let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">, + Keyword<"_fastcall">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [Undocumented]; } def Final : InheritableAttr { let Spellings = [Keyword<"final">, Keyword<"sealed">]; let Accessors = [Accessor<"isSpelledAsSealed", [Keyword<"sealed">]>]; let SemaHandler = 0; + let Documentation = [Undocumented]; } def MinSize : InheritableAttr { let Spellings = [GNU<"minsize">]; - let Subjects = [Function]; + let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>; + let Documentation = [Undocumented]; +} + +def Flatten : InheritableAttr { + let Spellings = [GCC<"flatten">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [FlattenDocs]; } def Format : InheritableAttr { - let Spellings = [GNU<"format">, CXX11<"gnu", "format">]; + let Spellings = [GCC<"format">]; let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">, IntArgument<"FirstArg">]; + let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto], WarnDiag, + "ExpectedFunction">; + let Documentation = [FormatDocs]; } def FormatArg : InheritableAttr { - let Spellings = [GNU<"format_arg">, CXX11<"gnu", "format_arg">]; + let Spellings = [GCC<"format_arg">]; let Args = [IntArgument<"FormatIdx">]; + let Subjects = SubjectList<[ObjCMethod, HasFunctionProto], WarnDiag, + "ExpectedFunction">; + let Documentation = [Undocumented]; } def GNUInline : InheritableAttr { - let Spellings = [GNU<"gnu_inline">, CXX11<"gnu", "gnu_inline">]; + let Spellings = [GCC<"gnu_inline">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def Hot : InheritableAttr { - let Spellings = [GNU<"hot">, CXX11<"gnu", "hot">]; + let Spellings = [GCC<"hot">]; + let Subjects = SubjectList<[Function]>; + // An AST node is created for this attribute, but not actually used beyond + // semantic checking for mutual exclusion with the Cold attribute. + let Documentation = [Undocumented]; } def IBAction : InheritableAttr { let Spellings = [GNU<"ibaction">]; + let Subjects = SubjectList<[ObjCInstanceMethod], WarnDiag, + "ExpectedObjCInstanceMethod">; + // An AST node is created for this attribute, but is not used by other parts + // of the compiler. However, this node needs to exist in the AST because + // external tools rely on it. + let Documentation = [Undocumented]; } def IBOutlet : InheritableAttr { let Spellings = [GNU<"iboutlet">]; +// let Subjects = [ObjCIvar, ObjCProperty]; + let Documentation = [Undocumented]; } def IBOutletCollection : InheritableAttr { let Spellings = [GNU<"iboutletcollection">]; let Args = [TypeArgument<"Interface", 1>]; +// let Subjects = [ObjCIvar, ObjCProperty]; + let Documentation = [Undocumented]; } def Malloc : InheritableAttr { - let Spellings = [GNU<"malloc">, CXX11<"gnu", "malloc">]; + let Spellings = [GCC<"malloc">]; +// let Subjects = [Function]; + let Documentation = [Undocumented]; } def MaxFieldAlignment : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; let Args = [UnsignedArgument<"Alignment">]; let SemaHandler = 0; + let Documentation = [Undocumented]; } def MayAlias : InheritableAttr { - let Spellings = [GNU<"may_alias">, CXX11<"gnu", "may_alias">]; + // FIXME: this is a type attribute in GCC, but a declaration attribute here. + let Spellings = [GCC<"may_alias">]; + let Documentation = [Undocumented]; } def MSABI : InheritableAttr { - let Spellings = [GNU<"ms_abi">, CXX11<"gnu", "ms_abi">]; + let Spellings = [GCC<"ms_abi">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [Undocumented]; } -def MSP430Interrupt : InheritableAttr, TargetSpecificAttr { - let Spellings = []; +def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> { + // NOTE: If you add any additional spellings, ARMInterrupt's spellings must + // match. + let Spellings = [GNU<"interrupt">]; let Args = [UnsignedArgument<"Number">]; - let SemaHandler = 0; + let ParseKind = "Interrupt"; + let HasCustomParsing = 1; + let Documentation = [Undocumented]; } -def Mips16 : InheritableAttr, TargetSpecificAttr { - let Spellings = [GNU<"mips16">, CXX11<"gnu", "mips16">]; - let Subjects = [Function]; +def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips> { + let Spellings = [GCC<"mips16">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [Undocumented]; } def Mode : Attr { - let Spellings = [GNU<"mode">, CXX11<"gnu", "mode">]; + let Spellings = [GCC<"mode">]; let Args = [IdentifierArgument<"Mode">]; + let Documentation = [Undocumented]; } def Naked : InheritableAttr { - let Spellings = [GNU<"naked">, CXX11<"gnu", "naked">]; + let Spellings = [GCC<"naked">, Declspec<"naked">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def NeonPolyVectorType : TypeAttr { let Spellings = [GNU<"neon_polyvector_type">]; let Args = [IntArgument<"NumElements">]; + let Documentation = [Undocumented]; } def NeonVectorType : TypeAttr { let Spellings = [GNU<"neon_vector_type">]; let Args = [IntArgument<"NumElements">]; + let Documentation = [Undocumented]; } def ReturnsTwice : InheritableAttr { - let Spellings = [GNU<"returns_twice">, CXX11<"gnu", "returns_twice">]; + let Spellings = [GCC<"returns_twice">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def NoCommon : InheritableAttr { - let Spellings = [GNU<"nocommon">, CXX11<"gnu", "nocommon">]; + let Spellings = [GCC<"nocommon">]; + let Subjects = SubjectList<[Var]>; + let Documentation = [Undocumented]; } def NoDebug : InheritableAttr { let Spellings = [GNU<"nodebug">]; + let Documentation = [Undocumented]; +} + +def NoDuplicate : InheritableAttr { + let Spellings = [GNU<"noduplicate">, CXX11<"clang", "noduplicate">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [NoDuplicateDocs]; } def NoInline : InheritableAttr { - let Spellings = [GNU<"noinline">, CXX11<"gnu", "noinline">]; + let Spellings = [GCC<"noinline">, Declspec<"noinline">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; +} + +def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> { + let Spellings = [GCC<"nomips16">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [Undocumented]; } -def NoMips16 : InheritableAttr, TargetSpecificAttr { - let Spellings = [GNU<"nomips16">, CXX11<"gnu", "nomips16">]; - let Subjects = [Function]; +def NoSplitStack : InheritableAttr { + let Spellings = [GCC<"no_split_stack">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [NoSplitStackDocs]; } def NonNull : InheritableAttr { - let Spellings = [GNU<"nonnull">, CXX11<"gnu", "nonnull">]; + let Spellings = [GCC<"nonnull">]; + let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag, + "ExpectedFunctionMethodOrParameter">; let Args = [VariadicUnsignedArgument<"Args">]; let AdditionalMembers = [{bool isNonNull(unsigned idx) const { - for (args_iterator i = args_begin(), e = args_end(); - i != e; ++i) - if (*i == idx) + for (const auto &V : args()) + if (V == idx) return true; return false; } }]; + let Documentation = [Undocumented]; +} + +def ReturnsNonNull : InheritableAttr { + let Spellings = [GCC<"returns_nonnull">]; + let Subjects = SubjectList<[ObjCMethod, Function], WarnDiag, + "ExpectedFunctionOrMethod">; + let Documentation = [Undocumented]; } def NoReturn : InheritableAttr { - let Spellings = [GNU<"noreturn">, CXX11<"gnu", "noreturn">]; + let Spellings = [GCC<"noreturn">, Declspec<"noreturn">]; // FIXME: Does GCC allow this on the function instead? - let Subjects = [Function]; + let Documentation = [Undocumented]; } def NoInstrumentFunction : InheritableAttr { - let Spellings = [GNU<"no_instrument_function">, - CXX11<"gnu", "no_instrument_function">]; - let Subjects = [Function]; + let Spellings = [GCC<"no_instrument_function">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def NoThrow : InheritableAttr { - let Spellings = [GNU<"nothrow">, CXX11<"gnu", "nothrow">]; -} - -def NSBridged : InheritableAttr { - let Spellings = [GNU<"ns_bridged">]; - let Subjects = [Record]; - let Args = [IdentifierArgument<"BridgedType", 1>]; + let Spellings = [GCC<"nothrow">, Declspec<"nothrow">]; + let Documentation = [Undocumented]; } def ObjCBridge : InheritableAttr { let Spellings = [GNU<"objc_bridge">]; - let Subjects = [Record]; - let Args = [IdentifierArgument<"BridgedType", 1>]; + let Subjects = SubjectList<[Record], ErrorDiag>; + let Args = [IdentifierArgument<"BridgedType">]; + let Documentation = [Undocumented]; +} + +def ObjCBridgeMutable : InheritableAttr { + let Spellings = [GNU<"objc_bridge_mutable">]; + let Subjects = SubjectList<[Record], ErrorDiag>; + let Args = [IdentifierArgument<"BridgedType">]; + let Documentation = [Undocumented]; +} + +def ObjCBridgeRelated : InheritableAttr { + let Spellings = [GNU<"objc_bridge_related">]; + let Subjects = SubjectList<[Record], ErrorDiag>; + let Args = [IdentifierArgument<"RelatedClass">, + IdentifierArgument<"ClassMethod">, + IdentifierArgument<"InstanceMethod">]; + let HasCustomParsing = 1; + let Documentation = [Undocumented]; } def NSReturnsRetained : InheritableAttr { let Spellings = [GNU<"ns_returns_retained">]; - let Subjects = [ObjCMethod, Function]; +// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; + let Documentation = [Undocumented]; } def NSReturnsNotRetained : InheritableAttr { let Spellings = [GNU<"ns_returns_not_retained">]; - let Subjects = [ObjCMethod, Function]; +// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; + let Documentation = [Undocumented]; } def NSReturnsAutoreleased : InheritableAttr { let Spellings = [GNU<"ns_returns_autoreleased">]; - let Subjects = [ObjCMethod, Function]; +// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; + let Documentation = [Undocumented]; } def NSConsumesSelf : InheritableAttr { let Spellings = [GNU<"ns_consumes_self">]; - let Subjects = [ObjCMethod]; + let Subjects = SubjectList<[ObjCMethod]>; + let Documentation = [Undocumented]; } def NSConsumed : InheritableParamAttr { let Spellings = [GNU<"ns_consumed">]; - let Subjects = [ParmVar]; + let Subjects = SubjectList<[ParmVar]>; + let Documentation = [Undocumented]; } def ObjCException : InheritableAttr { let Spellings = [GNU<"objc_exception">]; + let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; + let Documentation = [Undocumented]; } def ObjCMethodFamily : InheritableAttr { let Spellings = [GNU<"objc_method_family">]; - let Subjects = [ObjCMethod]; + let Subjects = SubjectList<[ObjCMethod], ErrorDiag>; let Args = [EnumArgument<"Family", "FamilyKind", ["none", "alloc", "copy", "init", "mutableCopy", "new"], ["OMF_None", "OMF_alloc", "OMF_copy", "OMF_init", "OMF_mutableCopy", "OMF_new"]>]; + let Documentation = [ObjCMethodFamilyDocs]; } def ObjCNSObject : InheritableAttr { let Spellings = [GNU<"NSObject">]; + let Documentation = [Undocumented]; } def ObjCPreciseLifetime : InheritableAttr { let Spellings = [GNU<"objc_precise_lifetime">]; - let Subjects = [Var]; + let Subjects = SubjectList<[Var], ErrorDiag>; + let Documentation = [Undocumented]; } def ObjCReturnsInnerPointer : InheritableAttr { let Spellings = [GNU<"objc_returns_inner_pointer">]; - let Subjects = [ObjCMethod, ObjCProperty]; + let Subjects = SubjectList<[ObjCMethod, ObjCProperty], ErrorDiag>; + let Documentation = [Undocumented]; } def ObjCRequiresSuper : InheritableAttr { let Spellings = [GNU<"objc_requires_super">]; - let Subjects = [ObjCMethod]; + let Subjects = SubjectList<[ObjCMethod], ErrorDiag>; + let Documentation = [ObjCRequiresSuperDocs]; } def ObjCRootClass : InheritableAttr { let Spellings = [GNU<"objc_root_class">]; - let Subjects = [ObjCInterface]; + let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; + let Documentation = [Undocumented]; +} + +def ObjCExplicitProtocolImpl : InheritableAttr { + let Spellings = [GNU<"objc_protocol_requires_explicit_implementation">]; + let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>; + let Documentation = [Undocumented]; +} + +def ObjCDesignatedInitializer : Attr { + let Spellings = [GNU<"objc_designated_initializer">]; + let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag, + "ExpectedObjCInterfaceDeclInitMethod">; + let Documentation = [Undocumented]; +} + +def ObjCRuntimeName : Attr { + let Spellings = [GNU<"objc_runtime_name">]; + let Subjects = SubjectList<[ObjCInterface, ObjCProtocol], ErrorDiag>; + let Args = [StringArgument<"MetadataName">]; + let Documentation = [ObjCRuntimeNameDocs]; +} + +def OptimizeNone : InheritableAttr { + let Spellings = [GNU<"optnone">, CXX11<"clang", "optnone">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; + let Documentation = [OptnoneDocs]; } def Overloadable : Attr { let Spellings = [GNU<"overloadable">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [OverloadableDocs]; } def Override : InheritableAttr { - let Spellings = []; + let Spellings = [Keyword<"override">]; let SemaHandler = 0; + let Documentation = [Undocumented]; } def Ownership : InheritableAttr { 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"]>, - StringArgument<"Module">, VariadicUnsignedArgument<"Args">]; - let HasCustomParsing = 1; + let Accessors = [Accessor<"isHolds", [GNU<"ownership_holds">]>, + Accessor<"isReturns", [GNU<"ownership_returns">]>, + Accessor<"isTakes", [GNU<"ownership_takes">]>]; + let AdditionalMembers = [{ + enum OwnershipKind { Holds, Returns, Takes }; + OwnershipKind getOwnKind() const { + return isHolds() ? Holds : + isTakes() ? Takes : + Returns; + } + }]; + let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">]; + let Subjects = SubjectList<[HasFunctionProto], WarnDiag, "ExpectedFunction">; + let Documentation = [Undocumented]; } def Packed : InheritableAttr { - let Spellings = [GNU<"packed">, CXX11<"gnu", "packed">]; + let Spellings = [GCC<"packed">]; +// let Subjects = [Tag, Field]; + let Documentation = [Undocumented]; } def PnaclCall : InheritableAttr { let Spellings = [GNU<"pnaclcall">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [Undocumented]; } def IntelOclBicc : InheritableAttr { let Spellings = [GNU<"intel_ocl_bicc">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [Undocumented]; } def Pcs : InheritableAttr { - let Spellings = [GNU<"pcs">, CXX11<"gnu", "pcs">]; + let Spellings = [GCC<"pcs">]; let Args = [EnumArgument<"PCS", "PCSType", ["aapcs", "aapcs-vfp"], ["AAPCS", "AAPCS_VFP"]>]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [PcsDocs]; } def Pure : InheritableAttr { - let Spellings = [GNU<"pure">, CXX11<"gnu", "pure">]; + let Spellings = [GCC<"pure">]; + let Documentation = [Undocumented]; } -def Regparm : InheritableAttr { - let Spellings = [GNU<"regparm">, CXX11<"gnu", "regparm">]; +def Regparm : TypeAttr { + let Spellings = [GCC<"regparm">]; let Args = [UnsignedArgument<"NumParams">]; + let Documentation = [Undocumented]; } def ReqdWorkGroupSize : InheritableAttr { let Spellings = [GNU<"reqd_work_group_size">]; let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">, UnsignedArgument<"ZDim">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [Undocumented]; } def WorkGroupSizeHint : InheritableAttr { @@ -670,102 +1084,137 @@ def WorkGroupSizeHint : InheritableAttr { let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">, UnsignedArgument<"ZDim">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [Undocumented]; } def InitPriority : InheritableAttr { let Spellings = [GNU<"init_priority">]; let Args = [UnsignedArgument<"Priority">]; + let Subjects = SubjectList<[Var], ErrorDiag>; + let Documentation = [Undocumented]; } def Section : InheritableAttr { - let Spellings = [GNU<"section">, CXX11<"gnu", "section">]; + let Spellings = [GCC<"section">, Declspec<"allocate">]; let Args = [StringArgument<"Name">]; + let Subjects = SubjectList<[Function, GlobalVar, + ObjCMethod, ObjCProperty], ErrorDiag, + "ExpectedFunctionGlobalVarMethodOrProperty">; + let Documentation = [SectionDocs]; } def Sentinel : InheritableAttr { - let Spellings = [GNU<"sentinel">, CXX11<"gnu", "sentinel">]; + let Spellings = [GCC<"sentinel">]; let Args = [DefaultIntArgument<"Sentinel", 0>, DefaultIntArgument<"NullPos", 0>]; +// let Subjects = SubjectList<[Function, ObjCMethod, Block, Var]>; + let Documentation = [Undocumented]; } def StdCall : InheritableAttr { - let Spellings = [GNU<"stdcall">, CXX11<"gnu", "stdcall">, - Keyword<"__stdcall">, Keyword<"_stdcall">]; + let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [Undocumented]; } def SysVABI : InheritableAttr { - let Spellings = [GNU<"sysv_abi">, CXX11<"gnu", "sysv_abi">]; + let Spellings = [GCC<"sysv_abi">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [Undocumented]; } def ThisCall : InheritableAttr { - let Spellings = [GNU<"thiscall">, CXX11<"gnu", "thiscall">, - Keyword<"__thiscall">, Keyword<"_thiscall">]; + let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">, + Keyword<"_thiscall">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [Undocumented]; } def Pascal : InheritableAttr { let Spellings = [GNU<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [Undocumented]; } def TransparentUnion : InheritableAttr { - let Spellings = [GNU<"transparent_union">, CXX11<"gnu", "transparent_union">]; + let Spellings = [GCC<"transparent_union">]; +// let Subjects = SubjectList<[Record, TypedefName]>; + let Documentation = [Undocumented]; } def Unavailable : InheritableAttr { let Spellings = [GNU<"unavailable">]; let Args = [StringArgument<"Message", 1>]; + let Documentation = [Undocumented]; } def ArcWeakrefUnavailable : InheritableAttr { let Spellings = [GNU<"objc_arc_weak_reference_unavailable">]; - let Subjects = [ObjCInterface]; + let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; + let Documentation = [Undocumented]; } def ObjCGC : TypeAttr { let Spellings = [GNU<"objc_gc">]; let Args = [IdentifierArgument<"Kind">]; + let Documentation = [Undocumented]; } def ObjCOwnership : InheritableAttr { let Spellings = [GNU<"objc_ownership">]; let Args = [IdentifierArgument<"Kind">]; let ASTNode = 0; + let Documentation = [Undocumented]; } def ObjCRequiresPropertyDefs : InheritableAttr { let Spellings = [GNU<"objc_requires_property_definitions">]; - let Subjects = [ObjCInterface]; + let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; + let Documentation = [Undocumented]; } def Unused : InheritableAttr { - let Spellings = [GNU<"unused">, CXX11<"gnu", "unused">]; + let Spellings = [GCC<"unused">]; + let Subjects = SubjectList<[Var, ObjCIvar, Type, Label, Field, ObjCMethod, + FunctionLike], WarnDiag, + "ExpectedVariableFunctionOrLabel">; + let Documentation = [Undocumented]; } def Used : InheritableAttr { - let Spellings = [GNU<"used">, CXX11<"gnu", "used">]; + let Spellings = [GCC<"used">]; + let Documentation = [Undocumented]; } def Uuid : InheritableAttr { - let Spellings = [GNU<"uuid">]; + let Spellings = [Declspec<"uuid">]; let Args = [StringArgument<"Guid">]; - let Subjects = [CXXRecord]; +// let Subjects = SubjectList<[CXXRecord]>; + let LangOpts = [MicrosoftExt, Borland]; + let Documentation = [Undocumented]; } def VectorSize : TypeAttr { - let Spellings = [GNU<"vector_size">, CXX11<"gnu", "vector_size">]; + let Spellings = [GCC<"vector_size">]; let Args = [ExprArgument<"NumBytes">]; + let Documentation = [Undocumented]; } def VecTypeHint : InheritableAttr { let Spellings = [GNU<"vec_type_hint">]; let Args = [TypeArgument<"TypeHint">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [Undocumented]; } def Visibility : InheritableAttr { let Clone = 0; - let Spellings = [GNU<"visibility">, CXX11<"gnu", "visibility">]; + let Spellings = [GCC<"visibility">]; let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], ["Default", "Hidden", "Hidden", "Protected"]>]; + let Documentation = [Undocumented]; } def TypeVisibility : InheritableAttr { @@ -774,80 +1223,227 @@ def TypeVisibility : InheritableAttr { let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], ["Default", "Hidden", "Hidden", "Protected"]>]; +// let Subjects = [Tag, ObjCInterface, Namespace]; + let Documentation = [Undocumented]; } def VecReturn : InheritableAttr { let Spellings = [GNU<"vecreturn">]; - let Subjects = [CXXRecord]; + let Subjects = SubjectList<[CXXRecord], ErrorDiag>; + let Documentation = [Undocumented]; } def WarnUnused : InheritableAttr { let Spellings = [GNU<"warn_unused">]; - let Subjects = [Record]; + let Subjects = SubjectList<[Record]>; + let Documentation = [Undocumented]; } def WarnUnusedResult : InheritableAttr { - let Spellings = [GNU<"warn_unused_result">, - CXX11<"clang", "warn_unused_result">, - CXX11<"gnu", "warn_unused_result">]; + let Spellings = [GCC<"warn_unused_result">, + CXX11<"clang", "warn_unused_result">]; + let Subjects = SubjectList<[ObjCMethod, CXXRecord, FunctionLike], WarnDiag, + "ExpectedFunctionMethodOrClass">; + let Documentation = [Undocumented]; } def Weak : InheritableAttr { - let Spellings = [GNU<"weak">, CXX11<"gnu", "weak">]; + let Spellings = [GCC<"weak">]; + let Subjects = SubjectList<[Var, Function, CXXRecord]>; + let Documentation = [Undocumented]; } def WeakImport : InheritableAttr { let Spellings = [GNU<"weak_import">]; + let Documentation = [Undocumented]; } def WeakRef : InheritableAttr { - let Spellings = [GNU<"weakref">, CXX11<"gnu", "weakref">]; + let Spellings = [GCC<"weakref">]; // A WeakRef that has an argument is treated as being an AliasAttr let Args = [StringArgument<"Aliasee", 1>]; + let Subjects = SubjectList<[Var, Function], ErrorDiag>; + let Documentation = [Undocumented]; } -def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr { - let Spellings = []; +def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetX86> { + let Spellings = [GNU<"force_align_arg_pointer">]; + // Technically, this appertains to a FunctionDecl, but the target-specific + // code silently allows anything function-like (such as typedefs or function + // pointers), but does not apply the attribute to them. + let Documentation = [Undocumented]; } // Attribute to disable AddressSanitizer (or equivalent) checks. def NoSanitizeAddress : InheritableAttr { - let Spellings = [GNU<"no_address_safety_analysis">, - GNU<"no_sanitize_address">, - CXX11<"gnu", "no_address_safety_analysis">, - CXX11<"gnu", "no_sanitize_address">]; + let Spellings = [GCC<"no_address_safety_analysis">, + GCC<"no_sanitize_address">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [NoSanitizeAddressDocs]; } // Attribute to disable ThreadSanitizer checks. def NoSanitizeThread : InheritableAttr { let Spellings = [GNU<"no_sanitize_thread">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [NoSanitizeThreadDocs]; } // Attribute to disable MemorySanitizer checks. def NoSanitizeMemory : InheritableAttr { let Spellings = [GNU<"no_sanitize_memory">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [NoSanitizeMemoryDocs]; } // C/C++ Thread safety attributes (e.g. for deadlock, data race checking) def GuardedVar : InheritableAttr { let Spellings = [GNU<"guarded_var">]; + let Subjects = SubjectList<[Field, SharedVar], WarnDiag, + "ExpectedFieldOrGlobalVar">; + let Documentation = [Undocumented]; } def PtGuardedVar : InheritableAttr { let Spellings = [GNU<"pt_guarded_var">]; + let Subjects = SubjectList<[Field, SharedVar], WarnDiag, + "ExpectedFieldOrGlobalVar">; + let Documentation = [Undocumented]; } def Lockable : InheritableAttr { let Spellings = [GNU<"lockable">]; + let Subjects = SubjectList<[Record]>; + let Documentation = [Undocumented]; + let ASTNode = 0; // Replaced by Capability } def ScopedLockable : InheritableAttr { let Spellings = [GNU<"scoped_lockable">]; + let Subjects = SubjectList<[Record]>; + let Documentation = [Undocumented]; +} + +def Capability : InheritableAttr { + let Spellings = [GNU<"capability">, CXX11<"clang", "capability">, + GNU<"shared_capability">, + CXX11<"clang", "shared_capability">]; + let Subjects = SubjectList<[Struct, TypedefName], ErrorDiag, + "ExpectedStructOrTypedef">; + let Args = [StringArgument<"Name">]; + let Accessors = [Accessor<"isShared", + [GNU<"shared_capability">, + CXX11<"clang","shared_capability">]>]; + let Documentation = [Undocumented]; + let AdditionalMembers = [{ + bool isMutex() const { return getName().equals_lower("mutex"); } + bool isRole() const { return getName().equals_lower("role"); } + }]; +} + +def AssertCapability : InheritableAttr { + let Spellings = [GNU<"assert_capability">, + CXX11<"clang", "assert_capability">, + GNU<"assert_shared_capability">, + CXX11<"clang", "assert_shared_capability">]; + let Subjects = SubjectList<[Function]>; + let LateParsed = 1; + let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Args = [ExprArgument<"Expr">]; + let Accessors = [Accessor<"isShared", + [GNU<"assert_shared_capability">, + CXX11<"clang", "assert_shared_capability">]>]; + let Documentation = [AssertCapabilityDocs]; +} + +def AcquireCapability : InheritableAttr { + let Spellings = [GNU<"acquire_capability">, + CXX11<"clang", "acquire_capability">, + GNU<"acquire_shared_capability">, + CXX11<"clang", "acquire_shared_capability">, + GNU<"exclusive_lock_function">, + GNU<"shared_lock_function">]; + let Subjects = SubjectList<[Function]>; + let LateParsed = 1; + let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Args = [VariadicExprArgument<"Args">]; + let Accessors = [Accessor<"isShared", + [GNU<"acquire_shared_capability">, + CXX11<"clang", "acquire_shared_capability">, + GNU<"shared_lock_function">]>]; + let Documentation = [AcquireCapabilityDocs]; +} + +def TryAcquireCapability : InheritableAttr { + let Spellings = [GNU<"try_acquire_capability">, + CXX11<"clang", "try_acquire_capability">, + GNU<"try_acquire_shared_capability">, + CXX11<"clang", "try_acquire_shared_capability">]; + let Subjects = SubjectList<[Function], + ErrorDiag>; + let LateParsed = 1; + let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; + let Accessors = [Accessor<"isShared", + [GNU<"try_acquire_shared_capability">, + CXX11<"clang", "try_acquire_shared_capability">]>]; + let Documentation = [TryAcquireCapabilityDocs]; +} + +def ReleaseCapability : InheritableAttr { + let Spellings = [GNU<"release_capability">, + CXX11<"clang", "release_capability">, + GNU<"release_shared_capability">, + CXX11<"clang", "release_shared_capability">, + GNU<"release_generic_capability">, + CXX11<"clang", "release_generic_capability">, + GNU<"unlock_function">]; + let Subjects = SubjectList<[Function]>; + let LateParsed = 1; + let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Args = [VariadicExprArgument<"Args">]; + let Accessors = [Accessor<"isShared", + [GNU<"release_shared_capability">, + CXX11<"clang", "release_shared_capability">]>, + Accessor<"isGeneric", + [GNU<"release_generic_capability">, + CXX11<"clang", "release_generic_capability">, + GNU<"unlock_function">]>]; + let Documentation = [ReleaseCapabilityDocs]; +} + +def RequiresCapability : InheritableAttr { + let Spellings = [GNU<"requires_capability">, + CXX11<"clang", "requires_capability">, + GNU<"exclusive_locks_required">, + GNU<"requires_shared_capability">, + CXX11<"clang", "requires_shared_capability">, + GNU<"shared_locks_required">]; + let Args = [VariadicExprArgument<"Args">]; + let LateParsed = 1; + let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Function]>; + let Accessors = [Accessor<"isShared", [GNU<"requires_shared_capability">, + GNU<"shared_locks_required">, + CXX11<"clang","requires_shared_capability">]>]; + let Documentation = [Undocumented]; } def NoThreadSafetyAnalysis : InheritableAttr { let Spellings = [GNU<"no_thread_safety_analysis">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def GuardedBy : InheritableAttr { @@ -855,6 +1451,11 @@ def GuardedBy : InheritableAttr { let Args = [ExprArgument<"Arg">]; let LateParsed = 1; let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Field, SharedVar], WarnDiag, + "ExpectedFieldOrGlobalVar">; + let Documentation = [Undocumented]; } def PtGuardedBy : InheritableAttr { @@ -862,6 +1463,11 @@ def PtGuardedBy : InheritableAttr { let Args = [ExprArgument<"Arg">]; let LateParsed = 1; let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Field, SharedVar], WarnDiag, + "ExpectedFieldOrGlobalVar">; + let Documentation = [Undocumented]; } def AcquiredAfter : InheritableAttr { @@ -869,6 +1475,11 @@ def AcquiredAfter : InheritableAttr { let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Field, SharedVar], WarnDiag, + "ExpectedFieldOrGlobalVar">; + let Documentation = [Undocumented]; } def AcquiredBefore : InheritableAttr { @@ -876,20 +1487,11 @@ def AcquiredBefore : InheritableAttr { let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; -} - -def ExclusiveLockFunction : InheritableAttr { - let Spellings = [GNU<"exclusive_lock_function">]; - let Args = [VariadicExprArgument<"Args">]; - let LateParsed = 1; - let TemplateDependent = 1; -} - -def SharedLockFunction : InheritableAttr { - let Spellings = [GNU<"shared_lock_function">]; - let Args = [VariadicExprArgument<"Args">]; - let LateParsed = 1; - let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Field, SharedVar], WarnDiag, + "ExpectedFieldOrGlobalVar">; + let Documentation = [Undocumented]; } def AssertExclusiveLock : InheritableAttr { @@ -897,6 +1499,10 @@ def AssertExclusiveLock : InheritableAttr { let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def AssertSharedLock : InheritableAttr { @@ -904,6 +1510,10 @@ def AssertSharedLock : InheritableAttr { let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } // The first argument is an integer or boolean value specifying the return value @@ -913,6 +1523,10 @@ def ExclusiveTrylockFunction : InheritableAttr { let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } // The first argument is an integer or boolean value specifying the return value @@ -922,13 +1536,10 @@ def SharedTrylockFunction : InheritableAttr { let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; -} - -def UnlockFunction : InheritableAttr { - let Spellings = [GNU<"unlock_function">]; - let Args = [VariadicExprArgument<"Args">]; - let LateParsed = 1; - let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def LockReturned : InheritableAttr { @@ -936,6 +1547,9 @@ def LockReturned : InheritableAttr { let Args = [ExprArgument<"Arg">]; let LateParsed = 1; let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } def LocksExcluded : InheritableAttr { @@ -943,70 +1557,78 @@ def LocksExcluded : InheritableAttr { let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; -} - -def ExclusiveLocksRequired : InheritableAttr { - let Spellings = [GNU<"exclusive_locks_required">]; - let Args = [VariadicExprArgument<"Args">]; - let LateParsed = 1; - let TemplateDependent = 1; -} - -def SharedLocksRequired : InheritableAttr { - let Spellings = [GNU<"shared_locks_required">]; - let Args = [VariadicExprArgument<"Args">]; - let LateParsed = 1; - let TemplateDependent = 1; + let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; } // C/C++ consumed attributes. def Consumable : InheritableAttr { let Spellings = [GNU<"consumable">]; - let Subjects = [CXXRecord]; + let Subjects = SubjectList<[CXXRecord]>; let Args = [EnumArgument<"DefaultState", "ConsumedState", ["unknown", "consumed", "unconsumed"], ["Unknown", "Consumed", "Unconsumed"]>]; + let Documentation = [ConsumableDocs]; +} + +def ConsumableAutoCast : InheritableAttr { + let Spellings = [GNU<"consumable_auto_cast_state">]; + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [Undocumented]; +} + +def ConsumableSetOnRead : InheritableAttr { + let Spellings = [GNU<"consumable_set_state_on_read">]; + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [Undocumented]; } def CallableWhen : InheritableAttr { let Spellings = [GNU<"callable_when">]; - let Subjects = [CXXMethod]; - let Args = [VariadicEnumArgument<"CallableState", "ConsumedState", + let Subjects = SubjectList<[CXXMethod]>; + let Args = [VariadicEnumArgument<"CallableStates", "ConsumedState", ["unknown", "consumed", "unconsumed"], ["Unknown", "Consumed", "Unconsumed"]>]; + let Documentation = [CallableWhenDocs]; } def ParamTypestate : InheritableAttr { let Spellings = [GNU<"param_typestate">]; - let Subjects = [ParmVar]; + let Subjects = SubjectList<[ParmVar]>; let Args = [EnumArgument<"ParamState", "ConsumedState", ["unknown", "consumed", "unconsumed"], ["Unknown", "Consumed", "Unconsumed"]>]; + let Documentation = [ParamTypestateDocs]; } def ReturnTypestate : InheritableAttr { let Spellings = [GNU<"return_typestate">]; - let Subjects = [Function, ParmVar]; + let Subjects = SubjectList<[Function, ParmVar]>; let Args = [EnumArgument<"State", "ConsumedState", ["unknown", "consumed", "unconsumed"], ["Unknown", "Consumed", "Unconsumed"]>]; + let Documentation = [ReturnTypestateDocs]; } def SetTypestate : InheritableAttr { let Spellings = [GNU<"set_typestate">]; - let Subjects = [CXXMethod]; + let Subjects = SubjectList<[CXXMethod]>; let Args = [EnumArgument<"NewState", "ConsumedState", ["unknown", "consumed", "unconsumed"], ["Unknown", "Consumed", "Unconsumed"]>]; + let Documentation = [SetTypestateDocs]; } def TestTypestate : InheritableAttr { let Spellings = [GNU<"test_typestate">]; - let Subjects = [CXXMethod]; + let Subjects = SubjectList<[CXXMethod]>; let Args = [EnumArgument<"TestState", "ConsumedState", ["consumed", "unconsumed"], ["Consumed", "Unconsumed"]>]; + let Documentation = [TestTypestateDocs]; } // Type safety attributes for `void *' pointers and type tags. @@ -1018,8 +1640,8 @@ def ArgumentWithTypeTag : InheritableAttr { UnsignedArgument<"ArgumentIdx">, UnsignedArgument<"TypeTagIdx">, BoolArgument<"IsPointer">]; - let Subjects = [Function]; let HasCustomParsing = 1; + let Documentation = [ArgumentWithTypeTagDocs, PointerWithTypeTagDocs]; } def TypeTagForDatatype : InheritableAttr { @@ -1028,8 +1650,9 @@ def TypeTagForDatatype : InheritableAttr { TypeArgument<"MatchingCType">, BoolArgument<"LayoutCompatible">, BoolArgument<"MustBeNull">]; - let Subjects = [Var]; +// let Subjects = SubjectList<[Var], ErrorDiag>; let HasCustomParsing = 1; + let Documentation = [TypeTagForDatatypeDocs]; } // Microsoft-related attributes @@ -1039,65 +1662,211 @@ def MsProperty : IgnoredAttr { } def MsStruct : InheritableAttr { - let Spellings = [Declspec<"ms_struct">]; + let Spellings = [GCC<"ms_struct">]; + let Subjects = SubjectList<[Record]>; + let Documentation = [Undocumented]; } -def DLLExport : InheritableAttr, TargetSpecificAttr { - let Spellings = [Declspec<"dllexport">]; +def DLLExport : InheritableAttr, TargetSpecificAttr<TargetWindows> { + let Spellings = [Declspec<"dllexport">, GCC<"dllexport">]; + let Subjects = SubjectList<[Function, Var, CXXRecord]>; + let Documentation = [Undocumented]; } -def DLLImport : InheritableAttr, TargetSpecificAttr { - let Spellings = [Declspec<"dllimport">]; -} - -def ForceInline : InheritableAttr { - let Spellings = [Keyword<"__forceinline">]; +def DLLImport : InheritableAttr, TargetSpecificAttr<TargetWindows> { + let Spellings = [Declspec<"dllimport">, GCC<"dllimport">]; + let Subjects = SubjectList<[Function, Var, CXXRecord]>; + let Documentation = [Undocumented]; } def SelectAny : InheritableAttr { let Spellings = [Declspec<"selectany">]; + let LangOpts = [MicrosoftExt]; + let Documentation = [Undocumented]; } -def Win64 : InheritableAttr { +def Thread : Attr { + let Spellings = [Declspec<"thread">]; + let LangOpts = [MicrosoftExt]; + let Documentation = [ThreadDocs]; + let Subjects = SubjectList<[Var]>; +} + +def Win64 : IgnoredAttr { let Spellings = [Keyword<"__w64">]; + let LangOpts = [MicrosoftExt]; } def Ptr32 : TypeAttr { let Spellings = [Keyword<"__ptr32">]; + let Documentation = [Undocumented]; } def Ptr64 : TypeAttr { let Spellings = [Keyword<"__ptr64">]; + let Documentation = [Undocumented]; } def SPtr : TypeAttr { let Spellings = [Keyword<"__sptr">]; + let Documentation = [Undocumented]; } def UPtr : TypeAttr { let Spellings = [Keyword<"__uptr">]; -} - -class MSInheritanceAttr : InheritableAttr; - -def SingleInheritance : MSInheritanceAttr { - let Spellings = [Keyword<"__single_inheritance">]; -} + let Documentation = [Undocumented]; +} + +def MSInheritance : InheritableAttr { + let LangOpts = [MicrosoftExt]; + let Args = [DefaultBoolArgument<"BestCase", 1>]; + let Spellings = [Keyword<"__single_inheritance">, + Keyword<"__multiple_inheritance">, + Keyword<"__virtual_inheritance">, + Keyword<"__unspecified_inheritance">]; + let AdditionalMembers = [{ + static bool hasVBPtrOffsetField(Spelling Inheritance) { + return Inheritance == Keyword_unspecified_inheritance; + } + + // Only member pointers to functions need a this adjustment, since it can be + // combined with the field offset for data pointers. + static bool hasNVOffsetField(bool IsMemberFunction, Spelling Inheritance) { + return IsMemberFunction && Inheritance >= Keyword_multiple_inheritance; + } + + static bool hasVBTableOffsetField(Spelling Inheritance) { + return Inheritance >= Keyword_virtual_inheritance; + } + + static bool hasOnlyOneField(bool IsMemberFunction, + Spelling Inheritance) { + if (IsMemberFunction) + return Inheritance <= Keyword_single_inheritance; + return Inheritance <= Keyword_multiple_inheritance; + } + }]; + let Documentation = [MSInheritanceDocs]; +} + +def MSVtorDisp : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. + let Spellings = []; + let Args = [UnsignedArgument<"vdm">]; + let SemaHandler = 0; -def MultipleInheritance : MSInheritanceAttr { - let Spellings = [Keyword<"__multiple_inheritance">]; -} + let AdditionalMembers = [{ + enum Mode { + Never, + ForVBaseOverride, + ForVFTable + }; -def VirtualInheritance : MSInheritanceAttr { - let Spellings = [Keyword<"__virtual_inheritance">]; + Mode getVtorDispMode() const { return Mode(vdm); } + }]; + let Documentation = [Undocumented]; } -// This attribute doesn't have any spellings, but we can apply it implicitly to -// incomplete types that lack any of the other attributes. -def UnspecifiedInheritance : MSInheritanceAttr { - let Spellings = []; +def InitSeg : Attr { + let Spellings = [Pragma<"", "init_seg">]; + let Args = [StringArgument<"Section">]; + let SemaHandler = 0; + let Documentation = [InitSegDocs]; + let AdditionalMembers = [{ + void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const { + OS << '(' << getSection() << ')'; + } + }]; } def Unaligned : IgnoredAttr { let Spellings = [Keyword<"__unaligned">]; } + +def LoopHint : Attr { + /// vectorize: vectorizes loop operations if 'value != 0'. + /// vectorize_width: vectorize loop operations with width 'value'. + /// interleave: interleave multiple loop iterations if 'value != 0'. + /// interleave_count: interleaves 'value' loop interations. + /// unroll: unroll loop if 'value != 0'. + /// unroll_count: unrolls loop 'value' times. + + let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">]; + + /// State of the loop optimization specified by the spelling. + let Args = [EnumArgument<"Option", "OptionType", + ["vectorize", "vectorize_width", "interleave", "interleave_count", + "unroll", "unroll_count"], + ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount", + "Unroll", "UnrollCount"]>, + DefaultIntArgument<"Value", 1>]; + + let AdditionalMembers = [{ + static StringRef getOptionName(int Option) { + switch(Option) { + case Vectorize: return "vectorize"; + case VectorizeWidth: return "vectorize_width"; + case Interleave: return "interleave"; + case InterleaveCount: return "interleave_count"; + case Unroll: return "unroll"; + case UnrollCount: return "unroll_count"; + } + llvm_unreachable("Unhandled LoopHint option."); + } + + static StringRef getValueName(int Value) { + if (Value) + return "enable"; + return "disable"; + } + + void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const { + unsigned SpellingIndex = getSpellingListIndex(); + if (SpellingIndex == Pragma_unroll) { + // String "unroll" of "#pragma unroll" is already emitted as the + // pragma name. + if (option == UnrollCount) + printArgument(OS); + OS << "\n"; + return; + } + assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling"); + OS << getOptionName(option); + printArgument(OS); + OS << "\n"; + } + + // Prints the loop hint argument including the enclosing parentheses to OS. + void printArgument(raw_ostream &OS) const { + OS << "("; + if (option == VectorizeWidth || option == InterleaveCount || + option == UnrollCount) + OS << value; + else if (value) + OS << "enable"; + else + OS << "disable"; + OS << ")"; + } + + // Return a string suitable for identifying this attribute in diagnostics. + std::string getDiagnosticName() const { + std::string DiagnosticName; + llvm::raw_string_ostream OS(DiagnosticName); + unsigned SpellingIndex = getSpellingListIndex(); + if (SpellingIndex == Pragma_unroll && option == Unroll) + OS << "#pragma unroll"; + else if (SpellingIndex == Pragma_unroll && option == UnrollCount) { + OS << "#pragma unroll"; + printArgument(OS); + } else { + assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling"); + OS << getOptionName(option); + printArgument(OS); + } + return OS.str(); + } + }]; + + let Documentation = [LoopHintDocs, UnrollHintDocs]; +} diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td new file mode 100644 index 0000000..e6d6a33 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td @@ -0,0 +1,1105 @@ +//==--- AttrDocs.td - Attribute documentation ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +def GlobalDocumentation { + code Intro =[{.. + ------------------------------------------------------------------- + NOTE: This file is automatically generated by running clang-tblgen + -gen-attr-docs. Do not edit this file by hand!! + ------------------------------------------------------------------- + +=================== +Attributes in Clang +=================== +.. contents:: + :local: + +Introduction +============ + +This page lists the attributes currently supported by Clang. +}]; +} + +def SectionDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``section`` attribute allows you to specify a specific section a +global variable or function should be in after translation. + }]; + let Heading = "section (gnu::section, __declspec(allocate))"; +} + +def InitSegDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The attribute applied by ``pragma init_seg()`` controls the section into +which global initialization function pointers are emitted. It is only +available with ``-fms-extensions``. Typically, this function pointer is +emitted into ``.CRT$XCU`` on Windows. The user can change the order of +initialization by using a different section name with the same +``.CRT$XC`` prefix and a suffix that sorts lexicographically before or +after the standard ``.CRT$XCU`` sections. See the init_seg_ +documentation on MSDN for more information. + +.. _init_seg: http://msdn.microsoft.com/en-us/library/7977wcck(v=vs.110).aspx + }]; +} + +def TLSModelDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``tls_model`` attribute allows you to specify which thread-local storage +model to use. It accepts the following strings: + +* global-dynamic +* local-dynamic +* initial-exec +* local-exec + +TLS models are mutually exclusive. + }]; +} + +def ThreadDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``__declspec(thread)`` attribute declares a variable with thread local +storage. It is available under the ``-fms-extensions`` flag for MSVC +compatibility. Documentation for the Visual C++ attribute is available on MSDN_. + +.. _MSDN: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx + +In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the +GNU ``__thread`` keyword. The variable must not have a destructor and must have +a constant initializer, if any. The attribute only applies to variables +declared with static storage duration, such as globals, class static data +members, and static locals. + }]; +} + +def CarriesDependencyDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``carries_dependency`` attribute specifies dependency propagation into and +out of functions. + +When specified on a function or Objective-C method, the ``carries_dependency`` +attribute means that the return value carries a dependency out of the function, +so that the implementation need not constrain ordering upon return from that +function. Implementations of the function and its caller may choose to preserve +dependencies instead of emitting memory ordering instructions such as fences. + +Note, this attribute does not change the meaning of the program, but may result +in generation of more efficient code. + }]; +} + +def C11NoReturnDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +A function declared as ``_Noreturn`` shall not return to its caller. The +compiler will generate a diagnostic for a function declared as ``_Noreturn`` +that appears to be capable of returning to its caller. + }]; +} + +def CXX11NoReturnDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +A function declared as ``[[noreturn]]`` shall not return to its caller. The +compiler will generate a diagnostic for a function declared as ``[[noreturn]]`` +that appears to be capable of returning to its caller. + }]; +} + +def AssertCapabilityDocs : Documentation { + let Category = DocCatFunction; + let Heading = "assert_capability (assert_shared_capability, clang::assert_capability, clang::assert_shared_capability)"; + let Content = [{ +Marks a function that dynamically tests whether a capability is held, and halts +the program if it is not held. + }]; +} + +def AcquireCapabilityDocs : Documentation { + let Category = DocCatFunction; + let Heading = "acquire_capability (acquire_shared_capability, clang::acquire_capability, clang::acquire_shared_capability)"; + let Content = [{ +Marks a function as acquiring a capability. + }]; +} + +def TryAcquireCapabilityDocs : Documentation { + let Category = DocCatFunction; + let Heading = "try_acquire_capability (try_acquire_shared_capability, clang::try_acquire_capability, clang::try_acquire_shared_capability)"; + let Content = [{ +Marks a function that attempts to acquire a capability. This function may fail to +actually acquire the capability; they accept a Boolean value determining +whether acquiring the capability means success (true), or failing to acquire +the capability means success (false). + }]; +} + +def ReleaseCapabilityDocs : Documentation { + let Category = DocCatFunction; + let Heading = "release_capability (release_shared_capability, clang::release_capability, clang::release_shared_capability)"; + let Content = [{ +Marks a function as releasing a capability. + }]; +} +def EnableIfDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``enable_if`` attribute can be placed on function declarations to control +which overload is selected based on the values of the function's arguments. +When combined with the ``overloadable`` attribute, this feature is also +available in C. + +.. code-block:: c++ + + int isdigit(int c); + int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF"))); + + void foo(char c) { + isdigit(c); + isdigit(10); + isdigit(-10); // results in a compile-time error. + } + +The enable_if attribute takes two arguments, the first is an expression written +in terms of the function parameters, the second is a string explaining why this +overload candidate could not be selected to be displayed in diagnostics. The +expression is part of the function signature for the purposes of determining +whether it is a redeclaration (following the rules used when determining +whether a C++ template specialization is ODR-equivalent), but is not part of +the type. + +The enable_if expression is evaluated as if it were the body of a +bool-returning constexpr function declared with the arguments of the function +it is being applied to, then called with the parameters at the call site. If the +result is false or could not be determined through constant expression +evaluation, then this overload will not be chosen and the provided string may +be used in a diagnostic if the compile fails as a result. + +Because the enable_if expression is an unevaluated context, there are no global +state changes, nor the ability to pass information from the enable_if +expression to the function body. For example, suppose we want calls to +strnlen(strbuf, maxlen) to resolve to strnlen_chk(strbuf, maxlen, size of +strbuf) only if the size of strbuf can be determined: + +.. code-block:: c++ + + __attribute__((always_inline)) + static inline size_t strnlen(const char *s, size_t maxlen) + __attribute__((overloadable)) + __attribute__((enable_if(__builtin_object_size(s, 0) != -1))), + "chosen when the buffer size is known but 'maxlen' is not"))) + { + return strnlen_chk(s, maxlen, __builtin_object_size(s, 0)); + } + +Multiple enable_if attributes may be applied to a single declaration. In this +case, the enable_if expressions are evaluated from left to right in the +following manner. First, the candidates whose enable_if expressions evaluate to +false or cannot be evaluated are discarded. If the remaining candidates do not +share ODR-equivalent enable_if expressions, the overload resolution is +ambiguous. Otherwise, enable_if overload resolution continues with the next +enable_if attribute on the candidates that have not been discarded and have +remaining enable_if attributes. In this way, we pick the most specific +overload out of a number of viable overloads using enable_if. + +.. code-block:: c++ + + void f() __attribute__((enable_if(true, ""))); // #1 + void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, ""))); // #2 + + void g(int i, int j) __attribute__((enable_if(i, ""))); // #1 + void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true))); // #2 + +In this example, a call to f() is always resolved to #2, as the first enable_if +expression is ODR-equivalent for both declarations, but #1 does not have another +enable_if expression to continue evaluating, so the next round of evaluation has +only a single candidate. In a call to g(1, 1), the call is ambiguous even though +#2 has more enable_if attributes, because the first enable_if expressions are +not ODR-equivalent. + +Query for this feature with ``__has_attribute(enable_if)``. + }]; +} + +def OverloadableDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang provides support for C++ function overloading in C. Function overloading +in C is introduced using the ``overloadable`` attribute. For example, one +might provide several overloaded versions of a ``tgsin`` function that invokes +the appropriate standard function computing the sine of a value with ``float``, +``double``, or ``long double`` precision: + +.. code-block:: c + + #include <math.h> + float __attribute__((overloadable)) tgsin(float x) { return sinf(x); } + double __attribute__((overloadable)) tgsin(double x) { return sin(x); } + long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); } + +Given these declarations, one can call ``tgsin`` with a ``float`` value to +receive a ``float`` result, with a ``double`` to receive a ``double`` result, +etc. Function overloading in C follows the rules of C++ function overloading +to pick the best overload given the call arguments, with a few C-specific +semantics: + +* Conversion from ``float`` or ``double`` to ``long double`` is ranked as a + floating-point promotion (per C99) rather than as a floating-point conversion + (as in C++). + +* A conversion from a pointer of type ``T*`` to a pointer of type ``U*`` is + considered a pointer conversion (with conversion rank) if ``T`` and ``U`` are + compatible types. + +* A conversion from type ``T`` to a value of type ``U`` is permitted if ``T`` + and ``U`` are compatible types. This conversion is given "conversion" rank. + +The declaration of ``overloadable`` functions is restricted to function +declarations and definitions. Most importantly, if any function with a given +name is given the ``overloadable`` attribute, then all function declarations +and definitions with that name (and in that scope) must have the +``overloadable`` attribute. This rule even applies to redeclarations of +functions whose original declaration had the ``overloadable`` attribute, e.g., + +.. code-block:: c + + int f(int) __attribute__((overloadable)); + float f(float); // error: declaration of "f" must have the "overloadable" attribute + + int g(int) __attribute__((overloadable)); + int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute + +Functions marked ``overloadable`` must have prototypes. Therefore, the +following code is ill-formed: + +.. code-block:: c + + int h() __attribute__((overloadable)); // error: h does not have a prototype + +However, ``overloadable`` functions are allowed to use a ellipsis even if there +are no named parameters (as is permitted in C++). This feature is particularly +useful when combined with the ``unavailable`` attribute: + +.. code-block:: c++ + + void honeypot(...) __attribute__((overloadable, unavailable)); // calling me is an error + +Functions declared with the ``overloadable`` attribute have their names mangled +according to the same rules as C++ function names. For example, the three +``tgsin`` functions in our motivating example get the mangled names +``_Z5tgsinf``, ``_Z5tgsind``, and ``_Z5tgsine``, respectively. There are two +caveats to this use of name mangling: + +* Future versions of Clang may change the name mangling of functions overloaded + in C, so you should not depend on an specific mangling. To be completely + safe, we strongly urge the use of ``static inline`` with ``overloadable`` + functions. + +* The ``overloadable`` attribute has almost no meaning when used in C++, + because names will already be mangled and functions are already overloadable. + However, when an ``overloadable`` function occurs within an ``extern "C"`` + linkage specification, it's name *will* be mangled in the same way as it + would in C. + +Query for this feature with ``__has_extension(attribute_overloadable)``. + }]; +} + +def ObjCMethodFamilyDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Many methods in Objective-C have conventional meanings determined by their +selectors. It is sometimes useful to be able to mark a method as having a +particular conventional meaning despite not having the right selector, or as +not having the conventional meaning that its selector would suggest. For these +use cases, we provide an attribute to specifically describe the "method family" +that a method belongs to. + +**Usage**: ``__attribute__((objc_method_family(X)))``, where ``X`` is one of +``none``, ``alloc``, ``copy``, ``init``, ``mutableCopy``, or ``new``. This +attribute can only be placed at the end of a method declaration: + +.. code-block:: objc + + - (NSString *)initMyStringValue __attribute__((objc_method_family(none))); + +Users who do not wish to change the conventional meaning of a method, and who +merely want to document its non-standard retain and release semantics, should +use the retaining behavior attributes (``ns_returns_retained``, +``ns_returns_not_retained``, etc). + +Query for this feature with ``__has_attribute(objc_method_family)``. + }]; +} + +def NoDuplicateDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``noduplicate`` attribute can be placed on function declarations to control +whether function calls to this function can be duplicated or not as a result of +optimizations. This is required for the implementation of functions with +certain special requirements, like the OpenCL "barrier" function, that might +need to be run concurrently by all the threads that are executing in lockstep +on the hardware. For example this attribute applied on the function +"nodupfunc" in the code below avoids that: + +.. code-block:: c + + void nodupfunc() __attribute__((noduplicate)); + // Setting it as a C++11 attribute is also valid + // void nodupfunc() [[clang::noduplicate]]; + void foo(); + void bar(); + + nodupfunc(); + if (a > n) { + foo(); + } else { + bar(); + } + +gets possibly modified by some optimizations into code similar to this: + +.. code-block:: c + + if (a > n) { + nodupfunc(); + foo(); + } else { + nodupfunc(); + bar(); + } + +where the call to "nodupfunc" is duplicated and sunk into the two branches +of the condition. + }]; +} + +def NoSplitStackDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``no_split_stack`` attribute disables the emission of the split stack +preamble for a particular function. It has no effect if ``-fsplit-stack`` +is not specified. + }]; +} + +def ObjCRequiresSuperDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Some Objective-C classes allow a subclass to override a particular method in a +parent class but expect that the overriding method also calls the overridden +method in the parent class. For these cases, we provide an attribute to +designate that a method requires a "call to ``super``" in the overriding +method in the subclass. + +**Usage**: ``__attribute__((objc_requires_super))``. This attribute can only +be placed at the end of a method declaration: + +.. code-block:: objc + + - (void)foo __attribute__((objc_requires_super)); + +This attribute can only be applied the method declarations within a class, and +not a protocol. Currently this attribute does not enforce any placement of +where the call occurs in the overriding method (such as in the case of +``-dealloc`` where the call must appear at the end). It checks only that it +exists. + +Note that on both OS X and iOS that the Foundation framework provides a +convenience macro ``NS_REQUIRES_SUPER`` that provides syntactic sugar for this +attribute: + +.. code-block:: objc + + - (void)foo NS_REQUIRES_SUPER; + +This macro is conditionally defined depending on the compiler's support for +this attribute. If the compiler does not support the attribute the macro +expands to nothing. + +Operationally, when a method has this annotation the compiler will warn if the +implementation of an override in a subclass does not call super. For example: + +.. code-block:: objc + + warning: method possibly missing a [super AnnotMeth] call + - (void) AnnotMeth{}; + ^ + }]; +} + +def ObjCRuntimeNameDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +By default, the Objective-C interface or protocol identifier is used +in the metadata name for that object. The `objc_runtime_name` +attribute allows annotated interfaces or protocols to use the +specified string argument in the object's metadata name instead of the +default name. + +**Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute +can only be placed before an @protocol or @interface declaration: + +.. code-block:: objc + + __attribute__((objc_runtime_name("MyLocalName"))) + @interface Message + @end + + }]; +} + +def AvailabilityDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``availability`` attribute can be placed on declarations to describe the +lifecycle of that declaration relative to operating system versions. Consider +the function declaration for a hypothetical function ``f``: + +.. code-block:: c++ + + void f(void) __attribute__((availability(macosx,introduced=10.4,deprecated=10.6,obsoleted=10.7))); + +The availability attribute states that ``f`` was introduced in Mac OS X 10.4, +deprecated in Mac OS X 10.6, and obsoleted in Mac OS X 10.7. This information +is used by Clang to determine when it is safe to use ``f``: for example, if +Clang is instructed to compile code for Mac OS X 10.5, a call to ``f()`` +succeeds. If Clang is instructed to compile code for Mac OS X 10.6, the call +succeeds but Clang emits a warning specifying that the function is deprecated. +Finally, if Clang is instructed to compile code for Mac OS X 10.7, the call +fails because ``f()`` is no longer available. + +The availability attribute is a comma-separated list starting with the +platform name and then including clauses specifying important milestones in the +declaration's lifetime (in any order) along with additional information. Those +clauses can be: + +introduced=\ *version* + The first version in which this declaration was introduced. + +deprecated=\ *version* + The first version in which this declaration was deprecated, meaning that + users should migrate away from this API. + +obsoleted=\ *version* + The first version in which this declaration was obsoleted, meaning that it + was removed completely and can no longer be used. + +unavailable + This declaration is never available on this platform. + +message=\ *string-literal* + Additional message text that Clang will provide when emitting a warning or + error about use of a deprecated or obsoleted declaration. Useful to direct + users to replacement APIs. + +Multiple availability attributes can be placed on a declaration, which may +correspond to different platforms. Only the availability attribute with the +platform corresponding to the target platform will be used; any others will be +ignored. If no availability attribute specifies availability for the current +target platform, the availability attributes are ignored. Supported platforms +are: + +``ios`` + Apple's iOS operating system. The minimum deployment target is specified by + the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*`` + command-line arguments. + +``macosx`` + Apple's Mac OS X operating system. The minimum deployment target is + specified by the ``-mmacosx-version-min=*version*`` command-line argument. + +A declaration can be used even when deploying back to a platform version prior +to when the declaration was introduced. When this happens, the declaration is +`weakly linked +<https://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html>`_, +as if the ``weak_import`` attribute were added to the declaration. A +weakly-linked declaration may or may not be present a run-time, and a program +can determine whether the declaration is present by checking whether the +address of that declaration is non-NULL. + +If there are multiple declarations of the same entity, the availability +attributes must either match on a per-platform basis or later +declarations must not have availability attributes for that +platform. For example: + +.. code-block:: c + + void g(void) __attribute__((availability(macosx,introduced=10.4))); + void g(void) __attribute__((availability(macosx,introduced=10.4))); // okay, matches + void g(void) __attribute__((availability(ios,introduced=4.0))); // okay, adds a new platform + void g(void); // okay, inherits both macosx and ios availability from above. + void g(void) __attribute__((availability(macosx,introduced=10.5))); // error: mismatch + +When one method overrides another, the overriding method can be more widely available than the overridden method, e.g.,: + +.. code-block:: objc + + @interface A + - (id)method __attribute__((availability(macosx,introduced=10.4))); + - (id)method2 __attribute__((availability(macosx,introduced=10.4))); + @end + + @interface B : A + - (id)method __attribute__((availability(macosx,introduced=10.3))); // okay: method moved into base class later + - (id)method __attribute__((availability(macosx,introduced=10.5))); // error: this method was available via the base class in 10.4 + @end + }]; +} + +def FallthroughDocs : Documentation { + let Category = DocCatStmt; + let Content = [{ +The ``clang::fallthrough`` attribute is used along with the +``-Wimplicit-fallthrough`` argument to annotate intentional fall-through +between switch labels. It can only be applied to a null statement placed at a +point of execution between any statement and the next switch label. It is +common to mark these places with a specific comment, but this attribute is +meant to replace comments with a more strict annotation, which can be checked +by the compiler. This attribute doesn't change semantics of the code and can +be used wherever an intended fall-through occurs. It is designed to mimic +control-flow statements like ``break;``, so it can be placed in most places +where ``break;`` can, but only if there are no statements on the execution path +between it and the next switch label. + +Here is an example: + +.. code-block:: c++ + + // compile with -Wimplicit-fallthrough + switch (n) { + case 22: + case 33: // no warning: no statements between case labels + f(); + case 44: // warning: unannotated fall-through + g(); + [[clang::fallthrough]]; + case 55: // no warning + if (x) { + h(); + break; + } + else { + i(); + [[clang::fallthrough]]; + } + case 66: // no warning + p(); + [[clang::fallthrough]]; // warning: fallthrough annotation does not + // directly precede case label + q(); + case 77: // warning: unannotated fall-through + r(); + } + }]; +} + +def ARMInterruptDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on +ARM targets. This attribute may be attached to a function definition and +instructs the backend to generate appropriate function entry/exit code so that +it can be used directly as an interrupt service routine. + +The parameter passed to the interrupt attribute is optional, but if +provided it must be a string literal with one of the following values: "IRQ", +"FIQ", "SWI", "ABORT", "UNDEF". + +The semantics are as follows: + +- If the function is AAPCS, Clang instructs the backend to realign the stack to + 8 bytes on entry. This is a general requirement of the AAPCS at public + interfaces, but may not hold when an exception is taken. Doing this allows + other AAPCS functions to be called. +- If the CPU is M-class this is all that needs to be done since the architecture + itself is designed in such a way that functions obeying the normal AAPCS ABI + constraints are valid exception handlers. +- If the CPU is not M-class, the prologue and epilogue are modified to save all + non-banked registers that are used, so that upon return the user-mode state + will not be corrupted. Note that to avoid unnecessary overhead, only + general-purpose (integer) registers are saved in this way. If VFP operations + are needed, that state must be saved manually. + + Specifically, interrupt kinds other than "FIQ" will save all core registers + except "lr" and "sp". "FIQ" interrupts will save r0-r7. +- If the CPU is not M-class, the return instruction is changed to one of the + canonical sequences permitted by the architecture for exception return. Where + possible the function itself will make the necessary "lr" adjustments so that + the "preferred return address" is selected. + + Unfortunately the compiler is unable to make this guarantee for an "UNDEF" + handler, where the offset from "lr" to the preferred return address depends on + the execution state of the code which generated the exception. In this case + a sequence equivalent to "movs pc, lr" will be used. + }]; +} + +def PcsDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +On ARM targets, this can attribute can be used to select calling conventions, +similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and +"aapcs-vfp". + }]; +} + +def DocCatConsumed : DocumentationCategory<"Consumed Annotation Checking"> { + let Content = [{ +Clang supports additional attributes for checking basic resource management +properties, specifically for unique objects that have a single owning reference. +The following attributes are currently supported, although **the implementation +for these annotations is currently in development and are subject to change.** + }]; +} + +def SetTypestateDocs : Documentation { + let Category = DocCatConsumed; + let Content = [{ +Annotate methods that transition an object into a new state with +``__attribute__((set_typestate(new_state)))``. The new state must be +unconsumed, consumed, or unknown. + }]; +} + +def CallableWhenDocs : Documentation { + let Category = DocCatConsumed; + let Content = [{ +Use ``__attribute__((callable_when(...)))`` to indicate what states a method +may be called in. Valid states are unconsumed, consumed, or unknown. Each +argument to this attribute must be a quoted string. E.g.: + +``__attribute__((callable_when("unconsumed", "unknown")))`` + }]; +} + +def TestTypestateDocs : Documentation { + let Category = DocCatConsumed; + let Content = [{ +Use ``__attribute__((test_typestate(tested_state)))`` to indicate that a method +returns true if the object is in the specified state.. + }]; +} + +def ParamTypestateDocs : Documentation { + let Category = DocCatConsumed; + let Content = [{ +This attribute specifies expectations about function parameters. Calls to an +function with annotated parameters will issue a warning if the corresponding +argument isn't in the expected state. The attribute is also used to set the +initial state of the parameter when analyzing the function's body. + }]; +} + +def ReturnTypestateDocs : Documentation { + let Category = DocCatConsumed; + let Content = [{ +The ``return_typestate`` attribute can be applied to functions or parameters. +When applied to a function the attribute specifies the state of the returned +value. The function's body is checked to ensure that it always returns a value +in the specified state. On the caller side, values returned by the annotated +function are initialized to the given state. + +When applied to a function parameter it modifies the state of an argument after +a call to the function returns. The function's body is checked to ensure that +the parameter is in the expected state before returning. + }]; +} + +def ConsumableDocs : Documentation { + let Category = DocCatConsumed; + let Content = [{ +Each ``class`` that uses any of the typestate annotations must first be marked +using the ``consumable`` attribute. Failure to do so will result in a warning. + +This attribute accepts a single parameter that must be one of the following: +``unknown``, ``consumed``, or ``unconsumed``. + }]; +} + +def NoSanitizeAddressDocs : Documentation { + let Category = DocCatFunction; + // This function has multiple distinct spellings, and so it requires a custom + // heading to be specified. The most common spelling is sufficient. + let Heading = "no_sanitize_address (no_address_safety_analysis, gnu::no_address_safety_analysis, gnu::no_sanitize_address)"; + let Content = [{ +.. _langext-address_sanitizer: + +Use ``__attribute__((no_sanitize_address))`` on a function declaration to +specify that address safety instrumentation (e.g. AddressSanitizer) should +not be applied to that function. + }]; +} + +def NoSanitizeThreadDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +.. _langext-thread_sanitizer: + +Use ``__attribute__((no_sanitize_thread))`` on a function declaration to +specify that checks for data races on plain (non-atomic) memory accesses should +not be inserted by ThreadSanitizer. The function is still instrumented by the +tool to avoid false positives and provide meaningful stack traces. + }]; +} + +def NoSanitizeMemoryDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +.. _langext-memory_sanitizer: + +Use ``__attribute__((no_sanitize_memory))`` on a function declaration to +specify that checks for uninitialized memory should not be inserted +(e.g. by MemorySanitizer). The function may still be instrumented by the tool +to avoid false positives in other places. + }]; +} + +def DocCatTypeSafety : DocumentationCategory<"Type Safety Checking"> { + let Content = [{ +Clang supports additional attributes to enable checking type safety properties +that can't be enforced by the C type system. Use cases include: + +* MPI library implementations, where these attributes enable checking that + the buffer type matches the passed ``MPI_Datatype``; +* for HDF5 library there is a similar use case to MPI; +* checking types of variadic functions' arguments for functions like + ``fcntl()`` and ``ioctl()``. + +You can detect support for these attributes with ``__has_attribute()``. For +example: + +.. code-block:: c++ + + #if defined(__has_attribute) + # if __has_attribute(argument_with_type_tag) && \ + __has_attribute(pointer_with_type_tag) && \ + __has_attribute(type_tag_for_datatype) + # define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx))) + /* ... other macros ... */ + # endif + #endif + + #if !defined(ATTR_MPI_PWT) + # define ATTR_MPI_PWT(buffer_idx, type_idx) + #endif + + int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + ATTR_MPI_PWT(1,3); + }]; +} + +def ArgumentWithTypeTagDocs : Documentation { + let Category = DocCatTypeSafety; + let Heading = "argument_with_type_tag"; + let Content = [{ +Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx, +type_tag_idx)))`` on a function declaration to specify that the function +accepts a type tag that determines the type of some other argument. +``arg_kind`` is an identifier that should be used when annotating all +applicable type tags. + +This attribute is primarily useful for checking arguments of variadic functions +(``pointer_with_type_tag`` can be used in most non-variadic cases). + +For example: + +.. code-block:: c++ + + int fcntl(int fd, int cmd, ...) + __attribute__(( argument_with_type_tag(fcntl,3,2) )); + }]; +} + +def PointerWithTypeTagDocs : Documentation { + let Category = DocCatTypeSafety; + let Heading = "pointer_with_type_tag"; + let Content = [{ +Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))`` +on a function declaration to specify that the function accepts a type tag that +determines the pointee type of some other pointer argument. + +For example: + +.. code-block:: c++ + + int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + }]; +} + +def TypeTagForDatatypeDocs : Documentation { + let Category = DocCatTypeSafety; + let Content = [{ +Clang supports annotating type tags of two forms. + +* **Type tag that is an expression containing a reference to some declared + identifier.** Use ``__attribute__((type_tag_for_datatype(kind, type)))`` on a + declaration with that identifier: + + .. code-block:: c++ + + extern struct mpi_datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )); + #define MPI_INT ((MPI_Datatype) &mpi_datatype_int) + +* **Type tag that is an integral literal.** Introduce a ``static const`` + variable with a corresponding initializer value and attach + ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration, + for example: + + .. code-block:: c++ + + #define MPI_INT ((MPI_Datatype) 42) + static const MPI_Datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )) = 42 + +The attribute also accepts an optional third argument that determines how the +expression is compared to the type tag. There are two supported flags: + +* ``layout_compatible`` will cause types to be compared according to + layout-compatibility rules (C++11 [class.mem] p 17, 18). This is + implemented to support annotating types like ``MPI_DOUBLE_INT``. + + For example: + + .. code-block:: c++ + + /* In mpi.h */ + struct internal_mpi_double_int { double d; int i; }; + extern struct mpi_datatype mpi_datatype_double_int + __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, layout_compatible) )); + + #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int) + + /* In user code */ + struct my_pair { double a; int b; }; + struct my_pair *buffer; + MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning + + struct my_int_pair { int a; int b; } + struct my_int_pair *buffer2; + MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning: actual buffer element + // type 'struct my_int_pair' + // doesn't match specified MPI_Datatype + +* ``must_be_null`` specifies that the expression should be a null pointer + constant, for example: + + .. code-block:: c++ + + /* In mpi.h */ + extern struct mpi_datatype mpi_datatype_null + __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) )); + + #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null) + + /* In user code */ + MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL + // was specified but buffer + // is not a null pointer + }]; +} + +def FlattenDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``flatten`` attribute causes calls within the attributed function to +be inlined unless it is impossible to do so, for example if the body of the +callee is unavailable or if the callee has the ``noinline`` attribute. + }]; +} + +def FormatDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ + +Clang supports the ``format`` attribute, which indicates that the function +accepts a ``printf`` or ``scanf``-like format string and corresponding +arguments or a ``va_list`` that contains these arguments. + +Please see `GCC documentation about format attribute +<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ to find details +about attribute syntax. + +Clang implements two kinds of checks with this attribute. + +#. Clang checks that the function with the ``format`` attribute is called with + a format string that uses format specifiers that are allowed, and that + arguments match the format string. This is the ``-Wformat`` warning, it is + on by default. + +#. Clang checks that the format string argument is a literal string. This is + the ``-Wformat-nonliteral`` warning, it is off by default. + + Clang implements this mostly the same way as GCC, but there is a difference + for functions that accept a ``va_list`` argument (for example, ``vprintf``). + GCC does not emit ``-Wformat-nonliteral`` warning for calls to such + functions. Clang does not warn if the format string comes from a function + parameter, where the function is annotated with a compatible attribute, + otherwise it warns. For example: + + .. code-block:: c + + __attribute__((__format__ (__scanf__, 1, 3))) + void foo(const char* s, char *buf, ...) { + va_list ap; + va_start(ap, buf); + + vprintf(s, ap); // warning: format string is not a string literal + } + + In this case we warn because ``s`` contains a format string for a + ``scanf``-like function, but it is passed to a ``printf``-like function. + + If the attribute is removed, clang still warns, because the format string is + not a string literal. + + Another example: + + .. code-block:: c + + __attribute__((__format__ (__printf__, 1, 3))) + void foo(const char* s, char *buf, ...) { + va_list ap; + va_start(ap, buf); + + vprintf(s, ap); // warning + } + + In this case Clang does not warn because the format string ``s`` and + the corresponding arguments are annotated. If the arguments are + incorrect, the caller of ``foo`` will receive a warning. + }]; +} + +def MSInheritanceDocs : Documentation { + let Category = DocCatType; + let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance"; + let Content = [{ +This collection of keywords is enabled under ``-fms-extensions`` and controls +the pointer-to-member representation used on ``*-*-win32`` targets. + +The ``*-*-win32`` targets utilize a pointer-to-member representation which +varies in size and alignment depending on the definition of the underlying +class. + +However, this is problematic when a forward declaration is only available and +no definition has been made yet. In such cases, Clang is forced to utilize the +most general representation that is available to it. + +These keywords make it possible to use a pointer-to-member representation other +than the most general one regardless of whether or not the definition will ever +be present in the current translation unit. + +This family of keywords belong between the ``class-key`` and ``class-name``: + +.. code-block:: c++ + + struct __single_inheritance S; + int S::*i; + struct S {}; + +This keyword can be applied to class templates but only has an effect when used +on full specializations: + +.. code-block:: c++ + + template <typename T, typename U> struct __single_inheritance A; // warning: inheritance model ignored on primary template + template <typename T> struct __multiple_inheritance A<T, T>; // warning: inheritance model ignored on partial specialization + template <> struct __single_inheritance A<int, float>; + +Note that choosing an inheritance model less general than strictly necessary is +an error: + +.. code-block:: c++ + + struct __multiple_inheritance S; // error: inheritance model does not match definition + int S::*i; + struct S {}; +}]; +} + +def OptnoneDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``optnone`` attribute suppresses essentially all optimizations +on a function or method, regardless of the optimization level applied to +the compilation unit as a whole. This is particularly useful when you +need to debug a particular function, but it is infeasible to build the +entire application without optimization. Avoiding optimization on the +specified function can improve the quality of the debugging information +for that function. + +This attribute is incompatible with the ``always_inline`` attribute. + }]; +} + +def LoopHintDocs : Documentation { + let Category = DocCatStmt; + let Content = [{ +The ``#pragma clang loop`` directive allows loop optimization hints to be +specified for the subsequent loop. The directive allows vectorization, +interleaving, and unrolling to be enabled or disabled. Vector width as well +as interleave and unrolling count can be manually specified. See +`language extensions +<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_ +for details. + }]; +} + +def UnrollHintDocs : Documentation { + let Category = DocCatStmt; + let Content = [{ +Loop unrolling optimization hints can be specified with ``#pragma unroll``. The +pragma is placed immediately before a for, while, do-while, or c++11 range-based +for loop. + +Specifying ``#pragma unroll`` without a parameter directs the loop unroller to +attempt to fully unroll the loop if the trip count is known at compile time: + +.. code-block:: c++ + + #pragma unroll + for (...) { + ... + } + +Specifying the optional parameter, ``#pragma unroll _value_``, directs the +unroller to unroll the loop ``_value_`` times. The parameter may optionally be +enclosed in parentheses: + +.. code-block:: c++ + + #pragma unroll 16 + for (...) { + ... + } + + #pragma unroll(16) + for (...) { + ... + } + +``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to +``#pragma clang loop unroll(enable)`` and ``#pragma clang loop +unroll_count(_value_)`` respectively. See `language extensions +<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_ +for further details including limitations of the unroll hints. + }]; +} + diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h index 7c4e2c7..150a30e 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h @@ -24,7 +24,6 @@ enum Kind { #define ATTR(X) X, #define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X, #define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = X, -#define LAST_MS_INHERITANCE_ATTR(X) X, LAST_MS_INHERITANCE = X, #include "clang/Basic/AttrList.inc" NUM_ATTRS }; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h new file mode 100644 index 0000000..5783b3b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h @@ -0,0 +1,41 @@ +//===--- Attributes.h - Attributes header -----------------------*- 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_BASIC_ATTRIBUTES_H +#define LLVM_CLANG_BASIC_ATTRIBUTES_H + +#include "llvm/ADT/Triple.h" +#include "clang/Basic/LangOptions.h" + +namespace clang { + +class IdentifierInfo; + +enum class AttrSyntax { + /// Is the attribute identifier generally known for any syntax? + Generic, + /// Is the identifier known as a GNU-style attribute? + GNU, + /// Is the identifier known as a __declspec-style attribute? + Declspec, + // Is the identifier known as a C++-style attribute? + CXX, + // Is the identifier known as a pragma attribute? + Pragma +}; + +/// \brief Return true if we recognize and implement the attribute specified by +/// the given information. +bool hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, + const IdentifierInfo *Attr, const llvm::Triple &T, + const LangOptions &LangOpts); + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_ATTRIBUTES_H diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def index 55c6ed7..e705382 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def @@ -50,6 +50,7 @@ // L -> long (e.g. Li for 'long int') // LL -> long long // LLL -> __int128_t (e.g. LLLi) +// W -> int64_t // S -> signed // U -> unsigned // I -> Required to constant fold to an integer constant expression. @@ -72,7 +73,7 @@ // be followed by ':headername:' to state which header this function // comes from. // i -> this is a runtime library implemented function without the -// '__builtin_' prefix. It will be implemented in compiter-rt or libgcc. +// '__builtin_' prefix. It will be implemented in compiler-rt or libgcc. // p:N: -> this is a printf-like function whose Nth argument is the format // string. // P:N: -> similar to the p:N: attribute, but the function is like vprintf @@ -444,6 +445,7 @@ BUILTIN(__builtin_strstr, "c*cC*cC*", "nF") BUILTIN(__builtin_return_address, "v*IUi", "n") BUILTIN(__builtin_extract_return_addr, "v*v*", "n") BUILTIN(__builtin_frame_address, "v*IUi", "n") +BUILTIN(__builtin___clear_cache, "vc*c*", "n") BUILTIN(__builtin_flt_rounds, "i", "nc") BUILTIN(__builtin_setjmp, "iv**", "j") BUILTIN(__builtin_longjmp, "vv**i", "r") @@ -677,8 +679,16 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn") // Microsoft builtins. These are only active with -fms-extensions. LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(__noop, "v.", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES) // C99 library functions // C99 stdlib.h @@ -726,11 +736,16 @@ LIBBUILTIN(vscanf, "icC*Ra", "fS:0:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vfscanf, "iP*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vsscanf, "icC*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES) // C99 +// In some systems setjmp is a macro that expands to _setjmp. We undefine +// it here to avoid having two identical LIBBUILTIN entries. #undef setjmp LIBBUILTIN(setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES) // Non-C library functions, active in GNU mode only. +// Functions with (returns_twice) attribute (marked as "j") are still active in +// all languages, because losing this attribute would result in miscompilation +// when these functions are used in non-GNU mode. PR16138. LIBBUILTIN(alloca, "v*z", "f", "stdlib.h", ALL_GNU_LANGUAGES) // POSIX string.h LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h", ALL_GNU_LANGUAGES) @@ -749,18 +764,16 @@ LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_GNU_LANGUAGES) LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_GNU_LANGUAGES) // POSIX unistd.h LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_GNU_LANGUAGES) -LIBBUILTIN(vfork, "p", "fj", "unistd.h", ALL_GNU_LANGUAGES) +LIBBUILTIN(vfork, "p", "fj", "unistd.h", ALL_LANGUAGES) // POSIX setjmp.h -// In some systems setjmp is a macro that expands to _setjmp. We undefine -// it here to avoid having two identical LIBBUILTIN entries. -LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES) -LIBBUILTIN(__sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_GNU_LANGUAGES) -LIBBUILTIN(sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_GNU_LANGUAGES) -LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES) -LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES) -LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES) -LIBBUILTIN(getcontext, "iK*", "fj", "setjmp.h", ALL_GNU_LANGUAGES) +LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) +LIBBUILTIN(__sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES) +LIBBUILTIN(sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES) +LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) +LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) +LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) +LIBBUILTIN(getcontext, "iK*", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h", ALL_GNU_LANGUAGES) LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h", ALL_GNU_LANGUAGES) @@ -1137,6 +1150,21 @@ LIBBUILTIN(ctanh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ctanhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ctanhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +// __sinpi and friends are OS X specific library functions, but otherwise much +// like the standard (non-complex) sin (etc). +LIBBUILTIN(__sinpi, "dd", "fne", "math.h", ALL_LANGUAGES) +LIBBUILTIN(__sinpif, "ff", "fne", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(__cospi, "dd", "fne", "math.h", ALL_LANGUAGES) +LIBBUILTIN(__cospif, "ff", "fne", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(__tanpi, "dd", "fne", "math.h", ALL_LANGUAGES) +LIBBUILTIN(__tanpif, "ff", "fne", "math.h", ALL_LANGUAGES) + +// Similarly, __exp10 is OS X only +LIBBUILTIN(__exp10, "dd", "fne", "math.h", ALL_LANGUAGES) +LIBBUILTIN(__exp10f, "ff", "fne", "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) @@ -1179,6 +1207,8 @@ BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n") // Clang builtins (not available in GCC). BUILTIN(__builtin_addressof, "v*v&", "nct") +BUILTIN(__builtin_operator_new, "v*z", "c") +BUILTIN(__builtin_operator_delete, "vv*", "n") #undef BUILTIN #undef LIBBUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h index 9756f21..f9d30e4 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h @@ -94,53 +94,53 @@ public: /// \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; + return strchr(GetRecord(ID).Attributes, 'c') != nullptr; } /// \brief Return true if we know this builtin never throws an exception. bool isNoThrow(unsigned ID) const { - return strchr(GetRecord(ID).Attributes, 'n') != 0; + return strchr(GetRecord(ID).Attributes, 'n') != nullptr; } /// \brief Return true if we know this builtin never returns. bool isNoReturn(unsigned ID) const { - return strchr(GetRecord(ID).Attributes, 'r') != 0; + return strchr(GetRecord(ID).Attributes, 'r') != nullptr; } /// \brief Return true if we know this builtin can return twice. bool isReturnsTwice(unsigned ID) const { - return strchr(GetRecord(ID).Attributes, 'j') != 0; + return strchr(GetRecord(ID).Attributes, 'j') != nullptr; } /// \brief Returns true if this builtin does not perform the side-effects /// of its arguments. bool isUnevaluated(unsigned ID) const { - return strchr(GetRecord(ID).Attributes, 'u') != 0; + return strchr(GetRecord(ID).Attributes, 'u') != nullptr; } /// \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; + return strchr(GetRecord(ID).Attributes, 'F') != nullptr; } /// \brief Determines whether this builtin is a predefined libc/libm /// function, such as "malloc", where we know the signature a /// priori. bool isPredefinedLibFunction(unsigned ID) const { - return strchr(GetRecord(ID).Attributes, 'f') != 0; + return strchr(GetRecord(ID).Attributes, 'f') != nullptr; } /// \brief Determines whether this builtin is a predefined compiler-rt/libgcc /// function, such as "__clear_cache", where we know the signature a /// priori. bool isPredefinedRuntimeFunction(unsigned ID) const { - return strchr(GetRecord(ID).Attributes, 'i') != 0; + return strchr(GetRecord(ID).Attributes, 'i') != nullptr; } /// \brief Determines whether this builtin has custom typechecking. bool hasCustomTypechecking(unsigned ID) const { - return strchr(GetRecord(ID).Attributes, 't') != 0; + return strchr(GetRecord(ID).Attributes, 't') != nullptr; } /// \brief Completely forget that the given ID was ever considered a builtin, @@ -168,7 +168,7 @@ public: /// /// Such functions can be const when the MathErrno lang option is disabled. bool isConstWithoutErrno(unsigned ID) const { - return strchr(GetRecord(ID).Attributes, 'e') != 0; + return strchr(GetRecord(ID).Attributes, 'e') != nullptr; } private: @@ -177,6 +177,10 @@ private: /// \brief Is this builtin supported according to the given language options? bool BuiltinIsSupported(const Builtin::Info &BuiltinInfo, const LangOptions &LangOpts); + + /// \brief Helper function for isPrintfLike and isScanfLike. + bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg, + const char *Fmt) const; }; } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def index aafd202..695ecf9 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def @@ -1,4 +1,4 @@ -//===-- BuiltinsAArch64.def - AArch64 Builtin function database -*- C++ -*-===// +//==- BuiltinsAArch64.def - AArch64 Builtin function database ----*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -16,10 +16,38 @@ // In libgcc BUILTIN(__clear_cache, "vv*v*", "i") -// NEON -#define GET_NEON_AARCH64_BUILTINS -#include "clang/Basic/arm_neon.inc" -#undef GET_NEON_AARCH64_BUILTINS -#undef GET_NEON_BUILTINS + +BUILTIN(__builtin_arm_ldrex, "v.", "t") +BUILTIN(__builtin_arm_ldaex, "v.", "t") +BUILTIN(__builtin_arm_strex, "i.", "t") +BUILTIN(__builtin_arm_stlex, "i.", "t") +BUILTIN(__builtin_arm_clrex, "v", "") + +// Bit manipulation +BUILTIN(__builtin_arm_rbit, "UiUi", "nc") +BUILTIN(__builtin_arm_rbit64, "LUiLUi", "nc") + +// HINT +BUILTIN(__builtin_arm_nop, "v", "") +BUILTIN(__builtin_arm_yield, "v", "") +BUILTIN(__builtin_arm_wfe, "v", "") +BUILTIN(__builtin_arm_wfi, "v", "") +BUILTIN(__builtin_arm_sev, "v", "") +BUILTIN(__builtin_arm_sevl, "v", "") + +// CRC32 +BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc") +BUILTIN(__builtin_arm_crc32cb, "UiUiUc", "nc") +BUILTIN(__builtin_arm_crc32h, "UiUiUs", "nc") +BUILTIN(__builtin_arm_crc32ch, "UiUiUs", "nc") +BUILTIN(__builtin_arm_crc32w, "UiUiUi", "nc") +BUILTIN(__builtin_arm_crc32cw, "UiUiUi", "nc") +BUILTIN(__builtin_arm_crc32d, "UiUiLUi", "nc") +BUILTIN(__builtin_arm_crc32cd, "UiUiLUi", "nc") + +// Memory barrier +BUILTIN(__builtin_arm_dmb, "vUi", "nc") +BUILTIN(__builtin_arm_dsb, "vUi", "nc") +BUILTIN(__builtin_arm_isb, "vUi", "nc") #undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def index 21bb892..2e5eac6 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def @@ -14,6 +14,10 @@ // The format of this database matches clang/Basic/Builtins.def. +#if defined(BUILTIN) && !defined(LANGBUILTIN) +# define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) +#endif + // In libgcc BUILTIN(__clear_cache, "vv*v*", "i") BUILTIN(__builtin_thread_pointer, "v*", "") @@ -24,12 +28,17 @@ BUILTIN(__builtin_arm_qsub, "iii", "nc") BUILTIN(__builtin_arm_ssat, "iiUi", "nc") BUILTIN(__builtin_arm_usat, "UiUiUi", "nc") +// Bit manipulation +BUILTIN(__builtin_arm_rbit, "UiUi", "nc") + // Store and load exclusive BUILTIN(__builtin_arm_ldrexd, "LLUiv*", "") BUILTIN(__builtin_arm_strexd, "iLLUiv*", "") BUILTIN(__builtin_arm_ldrex, "v.", "t") +BUILTIN(__builtin_arm_ldaex, "v.", "t") BUILTIN(__builtin_arm_strex, "i.", "t") +BUILTIN(__builtin_arm_stlex, "i.", "t") BUILTIN(__builtin_arm_clrex, "v", "") // VFP @@ -59,15 +68,33 @@ BUILTIN(__builtin_arm_crc32d, "UiUiLLUi", "nc") BUILTIN(__builtin_arm_crc32cd, "UiUiLLUi", "nc") // HINT +BUILTIN(__builtin_arm_nop, "v", "") +BUILTIN(__builtin_arm_yield, "v", "") +BUILTIN(__builtin_arm_wfe, "v", "") +BUILTIN(__builtin_arm_wfi, "v", "") +BUILTIN(__builtin_arm_sev, "v", "") BUILTIN(__builtin_arm_sevl, "v", "") // Data barrier BUILTIN(__builtin_arm_dmb, "vUi", "nc") BUILTIN(__builtin_arm_dsb, "vUi", "nc") +BUILTIN(__builtin_arm_isb, "vUi", "nc") + +// MSVC +LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES) -// NEON -#define GET_NEON_BUILTINS -#include "clang/Basic/arm_neon.inc" -#undef GET_NEON_BUILTINS +LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__ldrexd, "WiCDWi*", "", ALL_MS_LANGUAGES) +LANGBUILTIN(_MoveFromCoprocessor, "UiUiUiUiUiUi", "", ALL_MS_LANGUAGES) +LANGBUILTIN(_MoveFromCoprocessor2, "UiUiUiUiUiUi", "", ALL_MS_LANGUAGES) +LANGBUILTIN(_MoveToCoprocessor, "vUiUiUiUiUiUi", "", ALL_MS_LANGUAGES) +LANGBUILTIN(_MoveToCoprocessor2, "vUiUiUiUiUiUi", "", ALL_MS_LANGUAGES) #undef BUILTIN +#undef LANGBUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsMips.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsMips.def index e435d52..2d217f7 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsMips.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsMips.def @@ -783,15 +783,15 @@ BUILTIN(__builtin_msa_shf_b, "V16cV16cIUi", "nc") BUILTIN(__builtin_msa_shf_h, "V8sV8sIUi", "nc") BUILTIN(__builtin_msa_shf_w, "V4iV4iIUi", "nc") -BUILTIN(__builtin_msa_sld_b, "V16cV16cUi", "nc") -BUILTIN(__builtin_msa_sld_h, "V8sV8sUi", "nc") -BUILTIN(__builtin_msa_sld_w, "V4iV4iUi", "nc") -BUILTIN(__builtin_msa_sld_d, "V2LLiV2LLiUi", "nc") - -BUILTIN(__builtin_msa_sldi_b, "V16cV16cIUi", "nc") -BUILTIN(__builtin_msa_sldi_h, "V8sV8sIUi", "nc") -BUILTIN(__builtin_msa_sldi_w, "V4iV4iIUi", "nc") -BUILTIN(__builtin_msa_sldi_d, "V2LLiV2LLiIUi", "nc") +BUILTIN(__builtin_msa_sld_b, "V16cV16cV16cUi", "nc") +BUILTIN(__builtin_msa_sld_h, "V8sV8sV8sUi", "nc") +BUILTIN(__builtin_msa_sld_w, "V4iV4iV4iUi", "nc") +BUILTIN(__builtin_msa_sld_d, "V2LLiV2LLiV2LLiUi", "nc") + +BUILTIN(__builtin_msa_sldi_b, "V16cV16cV16cIUi", "nc") +BUILTIN(__builtin_msa_sldi_h, "V8sV8sV8sIUi", "nc") +BUILTIN(__builtin_msa_sldi_w, "V4iV4iV4iIUi", "nc") +BUILTIN(__builtin_msa_sldi_d, "V2LLiV2LLiV2LLiIUi", "nc") BUILTIN(__builtin_msa_sll_b, "V16cV16cV16c", "nc") BUILTIN(__builtin_msa_sll_h, "V8sV8sV8s", "nc") diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def new file mode 100644 index 0000000..7800ae69 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def @@ -0,0 +1,21 @@ +//===--- BuiltinsNEON.def - NEON 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 NEON-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. + +#define GET_NEON_BUILTINS +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_BUILTINS + +#undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsR600.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsR600.def new file mode 100644 index 0000000..49135cc --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsR600.def @@ -0,0 +1,32 @@ +//==- BuiltinsR600.def - R600 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 R600-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. + +BUILTIN(__builtin_amdgpu_div_scale, "dddbb*", "n") +BUILTIN(__builtin_amdgpu_div_scalef, "fffbb*", "n") +BUILTIN(__builtin_amdgpu_div_fmas, "dddd", "nc") +BUILTIN(__builtin_amdgpu_div_fmasf, "ffff", "nc") +BUILTIN(__builtin_amdgpu_div_fixup, "dddd", "nc") +BUILTIN(__builtin_amdgpu_div_fixupf, "ffff", "nc") +BUILTIN(__builtin_amdgpu_trig_preop, "ddi", "nc") +BUILTIN(__builtin_amdgpu_trig_preopf, "ffi", "nc") +BUILTIN(__builtin_amdgpu_rcp, "dd", "nc") +BUILTIN(__builtin_amdgpu_rcpf, "ff", "nc") +BUILTIN(__builtin_amdgpu_rsq, "dd", "nc") +BUILTIN(__builtin_amdgpu_rsqf, "ff", "nc") +BUILTIN(__builtin_amdgpu_rsq_clamped, "dd", "nc") +BUILTIN(__builtin_amdgpu_rsq_clampedf, "ff", "nc") + +#undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def index 51397fa..1f377a8 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def @@ -59,6 +59,7 @@ BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc") // All MMX instructions will be generated via builtins. Any MMX vector // types (<1 x i64>, <2 x i32>, etc.) that aren't used by these builtins will be // expanded by the back-end. +BUILTIN(_mm_prefetch, "vcC*i", "nc") BUILTIN(__builtin_ia32_emms, "v", "") BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "") BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "") @@ -452,9 +453,6 @@ BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "") BUILTIN(__builtin_ia32_movmskps256, "iV8f", "") BUILTIN(__builtin_ia32_vzeroall, "v", "") BUILTIN(__builtin_ia32_vzeroupper, "v", "") -BUILTIN(__builtin_ia32_vbroadcastss, "V4ffC*", "") -BUILTIN(__builtin_ia32_vbroadcastsd256, "V4ddC*", "") -BUILTIN(__builtin_ia32_vbroadcastss256, "V8ffC*", "") BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "") BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "") BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "") @@ -759,5 +757,8 @@ BUILTIN(__builtin_ia32_xbegin, "i", "") BUILTIN(__builtin_ia32_xend, "v", "") BUILTIN(__builtin_ia32_xabort, "vIc", "") BUILTIN(__builtin_ia32_xtest, "i", "") +BUILTIN(__builtin_ia32_rdpmc, "ULLii", "") +BUILTIN(__builtin_ia32_rdtsc, "ULLi", "") +BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "") #undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h index c057bdf..a7b2ba2 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h @@ -21,20 +21,23 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/Support/type_traits.h" +#include "llvm/ADT/iterator_range.h" #include <list> #include <vector> namespace clang { - class DiagnosticConsumer; + class DeclContext; class DiagnosticBuilder; + class DiagnosticConsumer; + class DiagnosticErrorTrap; class DiagnosticOptions; class IdentifierInfo; - class DeclContext; class LangOptions; class Preprocessor; - class DiagnosticErrorTrap; class StoredDiagnostic; + namespace tok { + enum TokenKind : unsigned short; + } /// \brief Annotates a diagnostic with some code that should be /// inserted, removed, or replaced to fix the problem. @@ -129,35 +132,34 @@ public: /// the user. DiagnosticsEngine is tied to one translation unit and one /// SourceManager. class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { + DiagnosticsEngine(const DiagnosticsEngine &) LLVM_DELETED_FUNCTION; + void operator=(const DiagnosticsEngine &) LLVM_DELETED_FUNCTION; + public: /// \brief The level of the diagnostic, after it has been through mapping. enum Level { Ignored = DiagnosticIDs::Ignored, Note = DiagnosticIDs::Note, + Remark = DiagnosticIDs::Remark, Warning = DiagnosticIDs::Warning, Error = DiagnosticIDs::Error, Fatal = DiagnosticIDs::Fatal }; - /// \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_tokenkind, ///< enum TokenKind : 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> + ak_qualtype_pair, ///< pair<QualType, QualType> + ak_attr ///< Attr * }; /// \brief Represents on argument value, which is a union discriminated @@ -181,7 +183,7 @@ private: // 0 -> no limit. unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation // backtrace stack, 0 -> no limit. - ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? + diag::Severity ExtBehavior; // Map extensions to warnings or errors? IntrusiveRefCntPtr<DiagnosticIDs> Diags; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; DiagnosticConsumer *Client; @@ -191,7 +193,7 @@ private: /// \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. + /// bits are the mapping (an instance of diag::Severity), 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. @@ -200,19 +202,18 @@ private: /// the state so that we know what is the diagnostic state at any given /// source location. class DiagState { - llvm::DenseMap<unsigned, DiagnosticMappingInfo> DiagMap; + llvm::DenseMap<unsigned, DiagnosticMapping> DiagMap; public: - typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::iterator - iterator; - typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::const_iterator - const_iterator; + typedef llvm::DenseMap<unsigned, DiagnosticMapping>::iterator iterator; + typedef llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator + const_iterator; - void setMappingInfo(diag::kind Diag, DiagnosticMappingInfo Info) { + void setMapping(diag::kind Diag, DiagnosticMapping Info) { DiagMap[Diag] = Info; } - DiagnosticMappingInfo &getOrAddMappingInfo(diag::kind Diag); + DiagnosticMapping &getOrAddMapping(diag::kind Diag); const_iterator begin() const { return DiagMap.begin(); } const_iterator end() const { return DiagMap.end(); } @@ -308,17 +309,15 @@ private: /// /// 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 - /// can use this information to avoid redundancy across arguments. + /// The PrevArgs array indicates the previous arguments formatted for this + /// diagnostic. Implementations of this function can use this information to + /// avoid redundancy across arguments. /// /// This is a hack to avoid a layering violation between libbasic and libsema. typedef void (*ArgToStringFnTy)( ArgumentKind Kind, intptr_t Val, - const char *Modifier, unsigned ModifierLen, - const char *Argument, unsigned ArgumentLen, - const ArgumentValue *PrevArgs, - unsigned NumPrevArgs, + StringRef Modifier, StringRef Argument, + ArrayRef<ArgumentValue> PrevArgs, SmallVectorImpl<char> &Output, void *Cookie, ArrayRef<intptr_t> QualTypeVals); @@ -336,11 +335,18 @@ private: /// \brief Second string argument for the delayed diagnostic. std::string DelayedDiagArg2; + /// \brief Optional flag value. + /// + /// Some flags accept values, for instance: -Wframe-larger-than=<value> and + /// -Rpass=<value>. The content of this string is emitted after the flag name + /// and '='. + std::string FlagValue; + public: explicit DiagnosticsEngine( const IntrusiveRefCntPtr<DiagnosticIDs> &Diags, DiagnosticOptions *DiagOpts, - DiagnosticConsumer *client = 0, + DiagnosticConsumer *client = nullptr, bool ShouldOwnClient = true); ~DiagnosticsEngine(); @@ -351,6 +357,14 @@ public: /// \brief Retrieve the diagnostic options. DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; } + typedef llvm::iterator_range<DiagState::const_iterator> diag_mapping_range; + + /// \brief Get the current set of diagnostic mappings. + diag_mapping_range getDiagnosticMappings() const { + const DiagState &DS = *GetCurDiagState(); + return diag_mapping_range(DS.begin(), DS.end()); + } + DiagnosticConsumer *getClient() { return Client; } const DiagnosticConsumer *getClient() const { return Client; } @@ -364,7 +378,7 @@ public: return Client; } - bool hasSourceManager() const { return SourceMgr != 0; } + bool hasSourceManager() const { return SourceMgr != nullptr; } SourceManager &getSourceManager() const { assert(SourceMgr && "SourceManager not set!"); return *SourceMgr; @@ -501,10 +515,8 @@ public: /// 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; } + void setExtensionHandlingBehavior(diag::Severity H) { ExtBehavior = H; } + diag::Severity getExtensionHandlingBehavior() const { return ExtBehavior; } /// \brief Counter bumped when an __extension__ block is/ encountered. /// @@ -522,8 +534,7 @@ public: /// /// \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); + void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc); /// \brief Change an entire diagnostic group (e.g. "unknown-pragmas") to /// have the specified mapping. @@ -531,15 +542,14 @@ public: /// \returns true (and ignores the request) if "Group" was unknown, false /// otherwise. /// + /// \param Flavor The flavor of group to affect. -Rfoo does not affect the + /// state of the -Wfoo group and vice versa. + /// /// \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. - void setDiagnosticWarningAsError(diag::kind Diag, bool Enabled); + bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group, + diag::Severity Map, + SourceLocation Loc = SourceLocation()); /// \brief Set the warning-as-error flag for the given diagnostic group. /// @@ -548,11 +558,6 @@ public: /// \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. - 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. @@ -560,12 +565,13 @@ public: /// \returns True if the given group is unknown, false otherwise. bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled); - /// \brief Add the specified mapping to all diagnostics. + /// \brief Add the specified mapping to all diagnostics of the specified + /// flavor. /// /// 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()); + void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map, + SourceLocation Loc = SourceLocation()); bool hasErrorOccurred() const { return ErrorOccurred; } @@ -587,25 +593,29 @@ public: this->NumWarnings = NumWarnings; } - /// \brief Return an ID for a diagnostic with the specified message and level. + /// \brief Return an ID for a diagnostic with the specified format string and + /// level. /// /// If this is the first request for this diagnostic, it is registered and /// created, otherwise the existing ID is returned. - unsigned getCustomDiagID(Level L, StringRef Message) { - return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message); + /// + /// \param FormatString A fixed diagnostic format string that will be hashed + /// and mapped to a unique DiagID. + template <unsigned N> + unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) { + return Diags->getCustomDiagID((DiagnosticIDs::Level)L, + StringRef(FormatString, N - 1)); } /// \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, - const ArgumentValue *PrevArgs, unsigned NumPrevArgs, + StringRef Modifier, StringRef Argument, + ArrayRef<ArgumentValue> PrevArgs, SmallVectorImpl<char> &Output, ArrayRef<intptr_t> QualTypeVals) const { - ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, - PrevArgs, NumPrevArgs, Output, ArgToStringCookie, - QualTypeVals); + ArgToStringFn(Kind, Val, Modifier, Argument, PrevArgs, Output, + ArgToStringCookie, QualTypeVals); } void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { @@ -627,10 +637,27 @@ public: // DiagnosticsEngine classification and reporting interfaces. // + /// \brief Determine whether the diagnostic is known to be ignored. + /// + /// This can be used to opportunistically avoid expensive checks when it's + /// known for certain that the diagnostic has been suppressed at the + /// specified location \p Loc. + /// + /// \param Loc The source location we are interested in finding out the + /// diagnostic state. Can be null in order to query the latest state. + bool isIgnored(unsigned DiagID, SourceLocation Loc) const { + return Diags->getDiagnosticSeverity(DiagID, Loc, *this) == + diag::Severity::Ignored; + } + /// \brief Based on the way the client configured the DiagnosticsEngine /// object, classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticConsumer. /// + /// To preserve invariant assumptions, this function should not be used to + /// influence parse or semantic analysis actions. Instead consider using + /// \c isIgnored(). + /// /// \param Loc The source location we are interested in finding out the /// diagnostic state. Can be null in order to query the latest state. Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const { @@ -680,6 +707,9 @@ public: /// \brief Clear out the current diagnostic. void Clear() { CurDiagID = ~0U; } + /// \brief Return the value associated with this diagnostic flag. + StringRef getFlagValue() const { return FlagValue; } + private: /// \brief Report the delayed diagnostic. void ReportDelayed(); @@ -711,20 +741,10 @@ private: /// diagnostic with more than that almost certainly has to be simplified /// anyway. MaxArguments = 10, - - /// \brief The maximum number of ranges we can hold. - MaxRanges = 10, - - /// \brief The maximum number of ranges we can hold. - MaxFixItHints = 10 }; /// \brief The number of entries in Arguments. signed char NumDiagArgs; - /// \brief The number of ranges in the DiagRanges array. - unsigned char NumDiagRanges; - /// \brief The number of hints in the DiagFixItHints array. - unsigned char NumDiagFixItHints; /// \brief Specifies whether an argument is in DiagArgumentsStr or /// in DiagArguments. @@ -747,25 +767,25 @@ private: intptr_t DiagArgumentsVal[MaxArguments]; /// \brief The list of ranges added to this diagnostic. - CharSourceRange DiagRanges[MaxRanges]; + SmallVector<CharSourceRange, 8> DiagRanges; /// \brief If valid, provides a hint with some code to insert, remove, /// or modify at a particular position. - FixItHint DiagFixItHints[MaxFixItHints]; + SmallVector<FixItHint, 8> DiagFixItHints; - DiagnosticMappingInfo makeMappingInfo(diag::Mapping Map, SourceLocation L) { + DiagnosticMapping makeUserMapping(diag::Severity Map, SourceLocation L) { bool isPragma = L.isValid(); - DiagnosticMappingInfo MappingInfo = DiagnosticMappingInfo::Make( - Map, /*IsUser=*/true, isPragma); + DiagnosticMapping Mapping = + DiagnosticMapping::Make(Map, /*IsUser=*/true, isPragma); // If this is a pragma mapping, then set the diagnostic mapping flags so // that we override command line options. if (isPragma) { - MappingInfo.setNoWarningAsError(true); - MappingInfo.setNoErrorAsFatal(true); + Mapping.setNoWarningAsError(true); + Mapping.setNoErrorAsFatal(true); } - return MappingInfo; + return Mapping; } /// \brief Used to report a diagnostic that is finally fully formed. @@ -848,7 +868,7 @@ public: /// for example. class DiagnosticBuilder { mutable DiagnosticsEngine *DiagObj; - mutable unsigned NumArgs, NumRanges, NumFixits; + mutable unsigned NumArgs; /// \brief Status variable indicating if this diagnostic is still active. /// @@ -863,15 +883,15 @@ class DiagnosticBuilder { void operator=(const DiagnosticBuilder &) LLVM_DELETED_FUNCTION; friend class DiagnosticsEngine; - + DiagnosticBuilder() - : DiagObj(0), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(false), - IsForceEmit(false) { } + : DiagObj(nullptr), NumArgs(0), IsActive(false), IsForceEmit(false) {} explicit DiagnosticBuilder(DiagnosticsEngine *diagObj) - : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true), - IsForceEmit(false) { + : DiagObj(diagObj), NumArgs(0), IsActive(true), IsForceEmit(false) { assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!"); + diagObj->DiagRanges.clear(); + diagObj->DiagFixItHints.clear(); } friend class PartialDiagnostic; @@ -879,13 +899,11 @@ class DiagnosticBuilder { protected: void FlushCounts() { DiagObj->NumDiagArgs = NumArgs; - DiagObj->NumDiagRanges = NumRanges; - DiagObj->NumDiagFixItHints = NumFixits; } /// \brief Clear out the current diagnostic. void Clear() const { - DiagObj = 0; + DiagObj = nullptr; IsActive = false; IsForceEmit = false; } @@ -927,8 +945,6 @@ public: IsForceEmit = D.IsForceEmit; D.Clear(); NumArgs = D.NumArgs; - NumRanges = D.NumRanges; - NumFixits = D.NumFixits; } /// \brief Retrieve an empty diagnostic builder. @@ -974,27 +990,32 @@ public: void AddSourceRange(const CharSourceRange &R) const { assert(isActive() && "Clients must not add to cleared diagnostic!"); - assert(NumRanges < DiagnosticsEngine::MaxRanges && - "Too many arguments to diagnostic!"); - DiagObj->DiagRanges[NumRanges++] = R; + DiagObj->DiagRanges.push_back(R); } void AddFixItHint(const FixItHint &Hint) const { assert(isActive() && "Clients must not add to cleared diagnostic!"); - assert(NumFixits < DiagnosticsEngine::MaxFixItHints && - "Too many arguments to diagnostic!"); - DiagObj->DiagFixItHints[NumFixits++] = Hint; + DiagObj->DiagFixItHints.push_back(Hint); } - bool hasMaxRanges() const { - return NumRanges == DiagnosticsEngine::MaxRanges; - } + void addFlagValue(StringRef V) const { DiagObj->FlagValue = V; } +}; - bool hasMaxFixItHints() const { - return NumFixits == DiagnosticsEngine::MaxFixItHints; - } +struct AddFlagValue { + explicit AddFlagValue(StringRef V) : Val(V) {} + StringRef Val; }; +/// \brief Register a value for the flag in the current diagnostic. This +/// value will be shown as the suffix "=value" after the flag name. It is +/// useful in cases where the diagnostic flag accepts values (e.g., +/// -Rpass or -Wframe-larger-than). +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const AddFlagValue V) { + DB.addFlagValue(V.Val); + return DB; +} + inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, StringRef S) { DB.AddString(S); @@ -1013,7 +1034,13 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) { return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) { +// We use enable_if here to prevent that this overload is selected for +// pointers or other arguments that are implicitly convertible to bool. +template <typename T> +inline +typename std::enable_if<std::is_same<T, bool>::value, + const DiagnosticBuilder &>::type +operator<<(const DiagnosticBuilder &DB, T I) { DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); return DB; } @@ -1025,6 +1052,12 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, } inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + tok::TokenKind I) { + DB.AddTaggedVal(static_cast<unsigned>(I), DiagnosticsEngine::ak_tokenkind); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const IdentifierInfo *II) { DB.AddTaggedVal(reinterpret_cast<intptr_t>(II), DiagnosticsEngine::ak_identifierinfo); @@ -1037,14 +1070,14 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, // match. template<typename T> inline -typename llvm::enable_if<llvm::is_same<T, DeclContext>, - const DiagnosticBuilder &>::type +typename std::enable_if<std::is_same<T, DeclContext>::value, + const DiagnosticBuilder &>::type operator<<(const DiagnosticBuilder &DB, T *DC) { DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC), DiagnosticsEngine::ak_declcontext); return DB; } - + inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const SourceRange &R) { DB.AddSourceRange(CharSourceRange::getTokenRange(R)); @@ -1052,11 +1085,18 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, } inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + ArrayRef<SourceRange> Ranges) { + for (const SourceRange &R: Ranges) + DB.AddSourceRange(CharSourceRange::getTokenRange(R)); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const CharSourceRange &R) { DB.AddSourceRange(R); return DB; } - + inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const FixItHint &Hint) { if (!Hint.isNull()) @@ -1065,12 +1105,14 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, } inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc, - unsigned DiagID){ + unsigned DiagID) { assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!"); CurDiagLoc = Loc; CurDiagID = DiagID; + FlagValue.clear(); return DiagnosticBuilder(this); } + inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { return Report(SourceLocation(), DiagID); } @@ -1159,22 +1201,22 @@ public: /// \brief Return the number of source ranges associated with this diagnostic. unsigned getNumRanges() const { - return DiagObj->NumDiagRanges; + return DiagObj->DiagRanges.size(); } /// \pre Idx < getNumRanges() const CharSourceRange &getRange(unsigned Idx) const { - assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!"); + assert(Idx < getNumRanges() && "Invalid diagnostic range index!"); return DiagObj->DiagRanges[Idx]; } /// \brief Return an array reference for this diagnostic's ranges. ArrayRef<CharSourceRange> getRanges() const { - return llvm::makeArrayRef(DiagObj->DiagRanges, DiagObj->NumDiagRanges); + return DiagObj->DiagRanges; } unsigned getNumFixItHints() const { - return DiagObj->NumDiagFixItHints; + return DiagObj->DiagFixItHints.size(); } const FixItHint &getFixItHint(unsigned Idx) const { @@ -1182,8 +1224,8 @@ public: return DiagObj->DiagFixItHints[Idx]; } - const FixItHint *getFixItHints() const { - return getNumFixItHints()? DiagObj->DiagFixItHints : 0; + ArrayRef<FixItHint> getFixItHints() const { + return DiagObj->DiagFixItHints; } /// \brief Format this diagnostic into a string, substituting the @@ -1279,7 +1321,7 @@ public: /// \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) {} + const Preprocessor *PP = nullptr) {} /// \brief Callback to inform the diagnostic client that processing /// of a source file has ended. @@ -1312,7 +1354,7 @@ public: class IgnoringDiagConsumer : public DiagnosticConsumer { virtual void anchor(); void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info) { + const Diagnostic &Info) override { // Just ignore it. } }; @@ -1328,11 +1370,11 @@ public: virtual ~ForwardingDiagnosticConsumer(); - virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info); - virtual void clear(); + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override; + void clear() override; - virtual bool IncludeInDiagnosticCounts() const; + bool IncludeInDiagnosticCounts() const override; }; // Struct used for sending info about how a type should be printed. @@ -1351,6 +1393,13 @@ struct TemplateDiffTypes { /// attribute. The character itself will be not be printed. const char ToggleHighlight = 127; + +/// ProcessWarningOptions - Initialize the diagnostic client and process the +/// warning options specified on the command line. +void ProcessWarningOptions(DiagnosticsEngine &Diags, + const DiagnosticOptions &Opts, + bool ReportDiags = true); + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td index 2616548..48cbf09 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td @@ -12,16 +12,20 @@ // //===----------------------------------------------------------------------===// -// Define the diagnostic mappings. -class DiagMapping; -def MAP_IGNORE : DiagMapping; -def MAP_WARNING : DiagMapping; -def MAP_ERROR : DiagMapping; -def MAP_FATAL : DiagMapping; +// Define the diagnostic severities. +class Severity<string N> { + string Name = N; +} +def SEV_Ignored : Severity<"Ignored">; +def SEV_Remark : Severity<"Remark">; +def SEV_Warning : Severity<"Warning">; +def SEV_Error : Severity<"Error">; +def SEV_Fatal : Severity<"Fatal">; // Define the diagnostic classes. class DiagClass; def CLASS_NOTE : DiagClass; +def CLASS_REMARK : DiagClass; def CLASS_WARNING : DiagClass; def CLASS_EXTENSION : DiagClass; def CLASS_ERROR : DiagClass; @@ -57,7 +61,7 @@ include "DiagnosticGroups.td" // All diagnostics emitted by the compiler are an indirect subclass of this. -class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> { +class Diagnostic<string text, DiagClass DC, Severity defaultmapping> { /// Component is specified by the file with a big let directive. string Component = ?; string Text = text; @@ -65,8 +69,8 @@ class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> { SFINAEResponse SFINAE = SFINAE_Suppress; bit AccessControl = 0; bit WarningNoWerror = 0; - bit WarningShowInSystemHeader = 0; - DiagMapping DefaultMapping = defaultmapping; + bit ShowInSystemHeader = 0; + Severity DefaultSeverity = defaultmapping; DiagGroup Group; string CategoryName = ""; } @@ -81,24 +85,33 @@ class AccessControl { SFINAEResponse SFINAE = SFINAE_AccessControl; } +class ShowInSystemHeader { + bit ShowInSystemHeader = 1; +} + +class SuppressInSystemHeader { + bit ShowInSystemHeader = 0; +} + // FIXME: ExtWarn and Extension should also be SFINAEFailure by default. -class Error<string str> : Diagnostic<str, CLASS_ERROR, MAP_ERROR>, SFINAEFailure; -class Warning<string str> : Diagnostic<str, CLASS_WARNING, MAP_WARNING>; -class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_IGNORE>; -class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_WARNING>; -class Note<string str> : Diagnostic<str, CLASS_NOTE, MAP_FATAL/*ignored*/>; +class Error<string str> : Diagnostic<str, CLASS_ERROR, SEV_Error>, SFINAEFailure { + bit ShowInSystemHeader = 1; +} +class Warning<string str> : Diagnostic<str, CLASS_WARNING, SEV_Warning>; +class Remark<string str> : Diagnostic<str, CLASS_REMARK, SEV_Ignored>; +class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Ignored>; +class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Warning>; +class Note<string str> : Diagnostic<str, CLASS_NOTE, SEV_Fatal/*ignored*/>; -class DefaultIgnore { DiagMapping DefaultMapping = MAP_IGNORE; } -class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; } -class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; } -class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; } +class DefaultIgnore { Severity DefaultSeverity = SEV_Ignored; } +class DefaultWarn { Severity DefaultSeverity = SEV_Warning; } +class DefaultError { Severity DefaultSeverity = SEV_Error; } +class DefaultFatal { Severity DefaultSeverity = SEV_Fatal; } class DefaultWarnNoWerror { bit WarningNoWerror = 1; } -class DefaultWarnShowInSystemHeader { - bit WarningShowInSystemHeader = 1; -} +class DefaultRemark { Severity DefaultSeverity = SEV_Remark; } // Definitions for Diagnostics. include "DiagnosticASTKinds.td" diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td index 113e564..8d5a1c7 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -89,6 +89,9 @@ def note_constexpr_call_limit_exceeded : Note< "constexpr evaluation hit maximum call limit">; def note_constexpr_step_limit_exceeded : Note< "constexpr evaluation hit maximum step limit; possible infinite loop?">; +def note_constexpr_this : Note< + "%select{|implicit }0use of 'this' pointer is only allowed within the " + "evaluation of a call to a 'constexpr' member function">; def note_constexpr_lifetime_ended : Note< "%select{read of|assignment to|increment of|decrement of}0 " "%select{temporary|variable}1 whose lifetime has ended">; @@ -138,6 +141,7 @@ def note_constexpr_calls_suppressed : Note< "(skipping %0 call%s0 in backtrace; use -fconstexpr-backtrace-limit=0 to " "see all)">; def note_constexpr_call_here : Note<"in call to '%0'">; + def warn_integer_constant_overflow : Warning< "overflow in expression; result is %0 with type %1">, InGroup<DiagGroup<"integer-overflow">>; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td index a02fbdf..37b8569 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td @@ -8,3 +8,4 @@ //===----------------------------------------------------------------------===// class CatInlineAsm : DiagCategory<"Inline Assembly Issue">; +class CatBackend : DiagCategory<"Backend Issue">; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td index 49781fe..6dc8b27 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td @@ -11,7 +11,7 @@ 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. +// knows that we didn't parse something as they might expect. def warn_doc_html_start_tag_expected_quoted_string : Warning< "expected quoted string after equals sign">, @@ -41,6 +41,10 @@ def warn_doc_html_start_end_mismatch : Warning< def note_doc_html_end_tag : Note< "end tag">; +def warn_doc_html_missing_end_tag : Warning< + "HTML tag '%0' requires an end tag">, + InGroup<DocumentationHTML>, DefaultIgnore; + // Commands def warn_doc_block_command_empty_paragraph : Warning< diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td index c54bafc..b3c77b8 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -30,7 +30,7 @@ def note_type_being_defined : Note< "definition of %0 is not complete until the closing '}'">; /// note_matching - this is used as a continuation of a previous diagnostic, /// e.g. to specify the '(' when we expected a ')'. -def note_matching : Note<"to match this '%0'">; +def note_matching : Note<"to match this %0">; def note_using : Note<"using">; def note_possibility : Note<"one possibility">; @@ -40,7 +40,6 @@ def note_also_found : Note<"also found">; let CategoryName = "Lexical or Preprocessor Issue" in { -def err_expected_colon : Error<"expected ':'">; def err_expected_colon_after_setter_name : Error< "method name referenced in property setter attribute " "must end with ':'">; @@ -60,6 +59,10 @@ def err_invalid_numeric_udl : Error< let CategoryName = "Parse Issue" in { +def err_expected : Error<"expected %0">; +def err_expected_either : Error<"expected %0 or %1">; +def err_expected_after : Error<"expected %1 after %0">; + def err_param_redefinition : Error<"redefinition of parameter %0">; def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">; def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">, @@ -101,8 +104,9 @@ def warn_cxx98_compat_longlong : Warning< InGroup<CXX98CompatPedantic>, DefaultIgnore; def err_integer_too_large : Error< "integer constant is larger than the largest unsigned integer type">; -def warn_integer_too_large_for_signed : Warning< - "integer constant is larger than the largest signed integer type">; +def ext_integer_too_large_for_signed : ExtWarn< + "integer constant is larger than the largest signed integer type">, + InGroup<DiagGroup<"implicitly-unsigned-literal">>; // Sema && AST def note_invalid_subexpr_in_const_expr : Note< @@ -114,7 +118,6 @@ def err_target_unknown_triple : Error< "unknown target triple '%0', please use -triple or -arch">; def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; def err_target_unknown_abi : Error<"unknown target ABI '%0'">; -def err_target_unknown_cxxabi : Error<"unknown C++ ABI '%0'">; def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">; def err_target_unsupported_fpmath : Error< "the '%0' unit is not supported with this instruction set">; @@ -133,4 +136,14 @@ def err_unable_to_make_temp : Error< // Modules def err_module_file_conflict : Error<"module '%0' found in both '%1' and '%2'">; +// TransformActions +// TODO: Use a custom category name to distinguish rewriter errors. +def err_mt_message : Error<"[rewriter] %0">, SuppressInSystemHeader; +def warn_mt_message : Warning<"[rewriter] %0">; +def note_mt_message : Note<"[rewriter] %0">; + +// ARCMigrate +def warn_arcmt_nsalloc_realloc : Warning<"[rewriter] call returns pointer to GC managed memory; it will become unmanaged in ARC">; +def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to be used with an object with ownership other than __unsafe_unretained">; + } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td index b489807..cd26a6a 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -17,9 +17,13 @@ def err_drv_unsupported_option_argument : Error< "unsupported argument '%1' to option '%0'">; def err_drv_unknown_stdin_type : Error< "-E or -x required when input is from standard input">; +def err_drv_unknown_stdin_type_clang_cl : Error< + "use /Tc or /Tp to set input type for standard input">; def err_drv_unknown_language : Error<"language not recognized: '%0'">; def err_drv_invalid_arch_name : Error< "invalid arch name '%0'">; +def err_drv_invalid_linker_name : Error< + "invalid linker name in argument '%0'">; def err_drv_invalid_rtlib_name : Error< "invalid runtime library name in argument '%0'">; def err_drv_unsupported_rtlib_for_platform : Error< @@ -80,6 +84,9 @@ def err_drv_invalid_libcxx_deployment : Error< def err_drv_malformed_sanitizer_blacklist : Error< "malformed sanitizer blacklist: '%0'">; +def err_target_unsupported_arch + : Error<"the target architecture '%0' is not supported by the target '%1'">; + def err_drv_I_dash_not_supported : Error< "'%0' not supported, please use -iquote instead">; def err_drv_unknown_argument : Error<"unknown argument: '%0'">; @@ -109,11 +116,14 @@ def err_drv_unknown_objc_runtime : Error< "unknown or ill-formed Objective-C runtime '%0'">; def err_drv_emit_llvm_link : Error< "-emit-llvm cannot be used when linking">; -def err_drv_unknown_toolchain : Error< - "cannot recognize the type of the toolchain">; +def err_drv_optimization_remark_pattern : Error< + "%0 in '%1'">; +def err_drv_no_neon_modifier : Error<"[no]neon is not accepted as modifier, please use [no]simd instead">; def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>; -def warn_drv_optimization_value : Warning<"optimization level '%0' is unsupported; using '%1%2' instead">, +def warn_drv_optimization_value : Warning<"optimization level '%0' is not supported; using '%1%2' instead">, + InGroup<InvalidCommandLineArgument>; +def warn_ignored_gcc_optimization : Warning<"optimization flag '%0' is not supported">, InGroup<InvalidCommandLineArgument>; def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">; @@ -132,12 +142,8 @@ def warn_drv_unused_argument : Warning< def warn_drv_empty_joined_argument : Warning< "joined argument expects additional value: '%0'">, InGroup<UnusedCommandLineArgument>; -def warn_drv_unused_sanitizer : Warning<"'%0' is ignored in absence of '%1'">, - InGroup<UnusedSanitizeArgument>; def warn_drv_clang_unsupported : Warning< "the clang compiler does not support '%0'">; -def warn_drv_deprecated_arg : Warning< - "argument '%0' is deprecated, use '%1' instead">, InGroup<Deprecated>; def warn_drv_assuming_mfloat_abi_is : Warning< "unknown platform, assuming -mfloat-abi=%0">; def warn_ignoring_ftabstop_value : Warning< @@ -154,6 +160,8 @@ def warn_drv_pch_not_first_include : Warning< "precompiled header '%0' was ignored because '%1' is not first '-include'">; def warn_missing_sysroot : Warning<"no such sysroot directory: '%0'">, InGroup<DiagGroup<"missing-sysroot">>; +def warn_debug_compression_unavailable : Warning<"cannot compress debug sections (zlib not installed)">, + InGroup<DiagGroup<"debug-compression-unavailable">>; def note_drv_command_failed_diag_msg : Note< "diagnostic msg: %0">; @@ -164,4 +172,11 @@ def err_analyzer_config_no_value : Error< "analyzer-config option '%0' has a key but no value">; def err_analyzer_config_multiple_values : Error< "analyzer-config option '%0' should contain only one '='">; + +def err_drv_modules_validate_once_requires_timestamp : Error< + "option '-fmodules-validate-once-per-build-session' requires " + "'-fbuild-session-timestamp=<seconds since Epoch>'">; + +def warn_drv_invoking_fallback : Warning<"falling back to %0">, + InGroup<Fallback>; } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td index bcf3c41..ae704c4 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +class BackendInfo : CatBackend, ShowInSystemHeader; + let Component = "Frontend" in { def err_fe_error_opening : Error<"error opening '%0': %1">; @@ -14,13 +16,35 @@ def err_fe_error_reading : Error<"error reading '%0'">; def err_fe_error_reading_stdin : Error<"error reading stdin: %0">; def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; -// Error generated by the backend. def err_fe_inline_asm : Error<"%0">, CatInlineAsm; +def warn_fe_inline_asm : Warning<"%0">, CatInlineAsm, InGroup<BackendInlineAsm>; +def note_fe_inline_asm : Note<"%0">, CatInlineAsm; def note_fe_inline_asm_here : Note<"instantiated into assembly here">; def err_fe_cannot_link_module : Error<"cannot link module '%0': %1">, DefaultFatal; +def warn_fe_frame_larger_than : Warning<"stack frame size of %0 bytes in %q1">, + BackendInfo, InGroup<BackendFrameLargerThanEQ>; +def warn_fe_backend_frame_larger_than: Warning<"%0">, + BackendInfo, InGroup<BackendFrameLargerThanEQ>; +def err_fe_backend_frame_larger_than: Error<"%0">, BackendInfo; +def note_fe_backend_frame_larger_than: Note<"%0">, BackendInfo; + +def warn_fe_backend_plugin: Warning<"%0">, BackendInfo, InGroup<BackendPlugin>; +def err_fe_backend_plugin: Error<"%0">, BackendInfo; +def remark_fe_backend_plugin: Remark<"%0">, BackendInfo, InGroup<RemarkBackendPlugin>; +def note_fe_backend_plugin: Note<"%0">, BackendInfo; +def remark_fe_backend_optimization_remark : Remark<"%0">, BackendInfo, + InGroup<BackendOptimizationRemark>; +def remark_fe_backend_optimization_remark_missed : Remark<"%0">, BackendInfo, + InGroup<BackendOptimizationRemarkMissed>; +def remark_fe_backend_optimization_remark_analysis : Remark<"%0">, BackendInfo, + InGroup<BackendOptimizationRemarkAnalysis>; +def warn_fe_backend_optimization_failure : Warning<"%0">, BackendInfo, + InGroup<BackendOptimizationFailure>, DefaultWarn; +def note_fe_backend_optimization_remark_invalid_loc : Note<"could " + "not determine the original source location for %0:%1:%2">; def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; @@ -77,6 +101,8 @@ def err_verify_missing_end : Error< "cannot find end ('}}') of expected %0">; def err_verify_invalid_content : Error< "invalid expected %0: %1">; +def err_verify_missing_regex : Error< + "cannot find start of regex ('{{') in %0">; def err_verify_inconsistent_diags : Error< "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: " "%2">; @@ -100,17 +126,8 @@ def err_relocatable_without_isysroot : Error< "must specify system root with -isysroot when building a relocatable " "PCH file">; -def warn_unknown_warning_option : Warning< - "unknown warning option '%0'">, - InGroup<UnknownWarningOption>; -def warn_unknown_negative_warning_option : Warning< - "unknown warning option '%0'">, - InGroup<UnknownWarningOption>; -def warn_unknown_warning_option_suggest : Warning< - "unknown warning option '%0'; did you mean '%1'?">, - InGroup<UnknownWarningOption>; -def warn_unknown_negative_warning_option_suggest : Warning< - "unknown warning option '%0'; did you mean '%1'?">, +def warn_unknown_diag_option : Warning< + "unknown %select{warning|remark}0 option '%1'%select{|; did you mean '%3'?}2">, InGroup<UnknownWarningOption>; def warn_unknown_warning_specifier : Warning< "unknown %0 warning specifier: '%1'">, @@ -138,6 +155,10 @@ def warn_missing_submodule : Warning<"missing submodule '%0'">, InGroup<IncompleteUmbrella>; def err_module_unavailable : Error< "module '%0' %select{is incompatible with|requires}1 feature '%2'">; +def err_module_header_missing : Error< + "%select{|umbrella }0header '%1' not found">; +def err_module_cannot_create_includes : Error< + "cannot create includes file for module %0: %1">; def warn_module_config_macro_undef : Warning< "%select{definition|#undef}0 of configuration macro '%1' has no effect on " "the import of '%2'; pass '%select{-D%1=...|-U%1}0' on the command line " @@ -145,4 +166,11 @@ def warn_module_config_macro_undef : Warning< InGroup<ConfigMacros>; def note_module_def_undef_here : Note< "macro was %select{defined|#undef'd}0 here">; +def remark_module_build : Remark<"building module '%0' as '%1'">, + InGroup<DiagGroup<"module-build">>; + +def err_missing_vfs_overlay_file : Error< + "virtual filesystem overlay file '%0' not found">, DefaultFatal; +def err_invalid_vfs_overlay : Error< + "invalid virtual filesystem overlay file '%0'">, DefaultFatal; } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td index b0d0216..58dee48 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td @@ -18,7 +18,7 @@ def Implicit : DiagGroup<"implicit", [ // Empty DiagGroups are recognized by clang but ignored. def : DiagGroup<"abi">; -def : DiagGroup<"address">; +def AbsoluteValue : DiagGroup<"absolute-value">; def AddressOfTemporary : DiagGroup<"address-of-temporary">; def : DiagGroup<"aggregate-return">; def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">; @@ -37,14 +37,21 @@ def ConstantConversion : def LiteralConversion : DiagGroup<"literal-conversion">; def StringConversion : DiagGroup<"string-conversion">; def SignConversion : DiagGroup<"sign-conversion">; -def BoolConversion : DiagGroup<"bool-conversion">; +def PointerBoolConversion : DiagGroup<"pointer-bool-conversion">; +def UndefinedBoolConversion : DiagGroup<"undefined-bool-conversion">; +def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion, + UndefinedBoolConversion]>; def IntConversion : DiagGroup<"int-conversion">; def EnumConversion : DiagGroup<"enum-conversion">; +def FloatConversion : DiagGroup<"float-conversion">; +def EnumTooLarge : DiagGroup<"enum-too-large">; def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">; def NullConversion : DiagGroup<"null-conversion">; def ImplicitConversionFloatingPointToBool : DiagGroup<"implicit-conversion-floating-point-to-bool">; +def ObjCLiteralConversion : DiagGroup<"objc-literal-conversion">; def BadArrayNewLength : DiagGroup<"bad-array-new-length">; +def MacroRedefined : DiagGroup<"macro-redefined">; def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">; def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">; def C99Compat : DiagGroup<"c99-compat">; @@ -71,16 +78,17 @@ def CXX11CompatDeprecatedWritableStr : DiagGroup<"c++11-compat-deprecated-writable-strings">; def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">; +def UnavailableDeclarations : DiagGroup<"unavailable-declarations">; def DeprecatedImplementations :DiagGroup<"deprecated-implementations">; def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">; def DeprecatedRegister : DiagGroup<"deprecated-register">; def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings", [CXX11CompatDeprecatedWritableStr]>; -// FIXME: Why are DeprecatedImplementations and DeprecatedWritableStr -// not in this group? +// FIXME: Why is DeprecatedImplementations not in this group? def Deprecated : DiagGroup<"deprecated", [DeprecatedDeclarations, DeprecatedIncrementBool, - DeprecatedRegister]>, + DeprecatedRegister, + DeprecatedWritableStr]>, DiagCategory<"Deprecations">; def : DiagGroup<"disabled-optimization">; @@ -113,6 +121,9 @@ def FormatZeroLength : DiagGroup<"format-zero-length">; def CXXPre1yCompat : DiagGroup<"c++98-c++11-compat">; def CXXPre1yCompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic", [CXXPre1yCompat]>; +def CXXPre1zCompat : DiagGroup<"c++98-c++11-c++14-compat">; +def CXXPre1zCompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic", + [CXXPre1zCompat]>; def CXX98CompatBindToTemporaryCopy : DiagGroup<"c++98-compat-bind-to-temporary-copy">; @@ -125,11 +136,13 @@ def CXX98Compat : DiagGroup<"c++98-compat", [CXX98CompatBindToTemporaryCopy, CXX98CompatLocalTypeTemplateArgs, CXX98CompatUnnamedTypeTemplateArgs, - CXXPre1yCompat]>; + CXXPre1yCompat, + CXXPre1zCompat]>; // Warnings for C++11 features which are Extensions in C++98 mode. def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", [CXX98Compat, - CXXPre1yCompatPedantic]>; + CXXPre1yCompatPedantic, + CXXPre1zCompatPedantic]>; def CXX11Narrowing : DiagGroup<"c++11-narrowing">; @@ -149,10 +162,16 @@ def CXX11Compat : DiagGroup<"c++11-compat", [CXX11Narrowing, CXX11CompatReservedUserDefinedLiteral, CXX11CompatDeprecatedWritableStr, - CXXPre1yCompat]>; + CXXPre1yCompat, + CXXPre1zCompat]>; def : DiagGroup<"c++0x-compat", [CXX11Compat]>; def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic", - [CXXPre1yCompatPedantic]>; + [CXXPre1yCompatPedantic, + CXXPre1zCompatPedantic]>; + +def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>; +def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic", + [CXXPre1zCompatPedantic]>; def : DiagGroup<"effc++">; def DivZero : DiagGroup<"division-by-zero">; @@ -168,9 +187,11 @@ def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">; def DanglingElse: DiagGroup<"dangling-else">; def DanglingField : DiagGroup<"dangling-field">; def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">; +def InfiniteRecursion : DiagGroup<"infinite-recursion">; def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">; def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; def : DiagGroup<"import">; +def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">; def IncompatiblePointerTypesDiscardsQualifiers : DiagGroup<"incompatible-pointer-types-discards-qualifiers">; def IncompatiblePointerTypes @@ -178,6 +199,10 @@ def IncompatiblePointerTypes [IncompatiblePointerTypesDiscardsQualifiers]>; def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">; def IncompleteModule : DiagGroup<"incomplete-module", [IncompleteUmbrella]>; +def NonModularIncludeInFrameworkModule + : DiagGroup<"non-modular-include-in-framework-module">; +def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module", + [NonModularIncludeInFrameworkModule]>; def InvalidNoreturn : DiagGroup<"invalid-noreturn">; def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">; def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">; @@ -214,24 +239,28 @@ def NullDereference : DiagGroup<"null-dereference">; def InitializerOverrides : DiagGroup<"initializer-overrides">; def NonNull : DiagGroup<"nonnull">; def NonPODVarargs : DiagGroup<"non-pod-varargs">; +def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>; def : DiagGroup<"nonportable-cfstrings">; def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; def OveralignedType : DiagGroup<"over-aligned">; -def : DiagGroup<"old-style-cast">; +def OldStyleCast : 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 OperatorNewReturnsNull : DiagGroup<"new-returns-null">; def OverlengthStrings : DiagGroup<"overlength-strings">; def OverloadedVirtual : DiagGroup<"overloaded-virtual">; def PrivateExtern : DiagGroup<"private-extern">; def SelTypeCast : DiagGroup<"cast-of-sel-type">; +def FunctionDefInObjCContainer : DiagGroup<"function-def-in-objc-container">; def BadFunctionCast : DiagGroup<"bad-function-cast">; def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">; def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">; def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">; +def ObjCDesignatedInit : DiagGroup<"objc-designated-initializers">; def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">; def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">; def ObjCInvalidIBOutletProperty : DiagGroup<"invalid-iboutlet">; @@ -242,8 +271,7 @@ def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">; def Packed : DiagGroup<"packed">; def Padded : DiagGroup<"padded">; def PointerArith : DiagGroup<"pointer-arith">; -def PoundWarning : DiagGroup<"#warnings">, - DiagCategory<"#warning Directive">; +def PoundWarning : DiagGroup<"#warnings">; def PoundPragmaMessage : DiagGroup<"#pragma-messages">, DiagCategory<"#pragma message Directive">; def : DiagGroup<"pointer-to-int-cast">; @@ -275,12 +303,19 @@ def StaticLocalInInline : DiagGroup<"static-local-in-inline">; def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">; def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>; def GNUStatementExpression : DiagGroup<"gnu-statement-expression">; +def StringCompare : DiagGroup<"string-compare">; def StringPlusInt : DiagGroup<"string-plus-int">; def StringPlusChar : DiagGroup<"string-plus-char">; def StrncatSize : DiagGroup<"strncat-size">; def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">; +def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">; +def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">; +def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">; def TautologicalCompare : DiagGroup<"tautological-compare", - [TautologicalOutOfRangeCompare]>; + [TautologicalOutOfRangeCompare, + TautologicalPointerCompare, + TautologicalOverlapCompare, + TautologicalUndefinedCompare]>; def HeaderHygiene : DiagGroup<"header-hygiene">; def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">; def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">; @@ -315,6 +350,7 @@ def : DiagGroup<"strict-prototypes">; def StrictSelector : DiagGroup<"strict-selector-match">; def MethodDuplicate : DiagGroup<"duplicate-method-match">; def CoveredSwitchDefault : DiagGroup<"covered-switch-default">; +def SwitchBool : DiagGroup<"switch-bool">; def SwitchEnum : DiagGroup<"switch-enum">; def Switch : DiagGroup<"switch">; def ImplicitFallthroughPerFunction : @@ -334,17 +370,19 @@ def UninitializedStaticSelfInit : DiagGroup<"static-self-init">; def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes, UninitializedStaticSelfInit]>; def UnknownPragmas : DiagGroup<"unknown-pragmas">; +def IgnoredPragmas : DiagGroup<"ignored-pragmas">; +def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas]>; def UnknownWarningOption : DiagGroup<"unknown-warning-option">; def NSobjectAttribute : DiagGroup<"NSObject-attribute">; -def UnknownAttributes : DiagGroup<"attributes">; +def UnknownAttributes : DiagGroup<"unknown-attributes">; def IgnoredAttributes : DiagGroup<"ignored-attributes">; +def Attributes : DiagGroup<"attributes", [UnknownAttributes, + IgnoredAttributes]>; def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", [CXX98CompatUnnamedTypeTemplateArgs]>; def UnsupportedFriend : DiagGroup<"unsupported-friend">; def UnusedArgument : DiagGroup<"unused-argument">; -def UnusedSanitizeArgument : DiagGroup<"unused-sanitize-argument">; -def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument", - [UnusedSanitizeArgument]>; +def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument">; def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument">; def UnusedComparison : DiagGroup<"unused-comparison">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; @@ -364,7 +402,6 @@ def UnusedVariable : DiagGroup<"unused-variable", def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">; def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">; def UserDefinedLiterals : DiagGroup<"user-defined-literals">; -def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">; def Reorder : DiagGroup<"reorder">; def UndeclaredSelector : DiagGroup<"undeclared-selector">; def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">; @@ -385,6 +422,7 @@ def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak", [ARCRepeatedUseOfWeakMaybe]>; def ObjCBridge : DiagGroup<"bridge-cast">; +def DeallocInCategory:DiagGroup<"dealloc-in-category">; def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">; def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>; def Protocol : DiagGroup<"protocol">; @@ -400,16 +438,48 @@ def Visibility : DiagGroup<"visibility">; def ZeroLengthArray : DiagGroup<"zero-length-array">; def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">; def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">; +def Fallback : DiagGroup<"fallback">; + +// This covers both the deprecated case (in C++98) +// and the extension case (in C++11 onwards). +def WritableStrings : DiagGroup<"writable-strings", [DeprecatedWritableStr]>; // GCC calls -Wdeprecated-writable-strings -Wwrite-strings. -def GCCWriteStrings : DiagGroup<"write-strings" , [DeprecatedWritableStr]>; +// +// Bizarrely, this warning flag enables -fconst-strings in C. This is +// GCC-compatible, but really weird. +// +// FIXME: Should this affect C++11 (where this is an error, +// not just deprecated) or not? +def GCCWriteStrings : DiagGroup<"write-strings" , [WritableStrings]>; def CharSubscript : DiagGroup<"char-subscripts">; def LargeByValueCopy : DiagGroup<"large-by-value-copy">; def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">; +// Unreachable code warning groups. +// +// The goal is make -Wunreachable-code on by default, in -Wall, or at +// least actively used, with more noisy versions of the warning covered +// under separate flags. +// +def UnreachableCodeLoopIncrement : DiagGroup<"unreachable-code-loop-increment">; +def UnreachableCode : DiagGroup<"unreachable-code", + [UnreachableCodeLoopIncrement]>; +def UnreachableCodeBreak : DiagGroup<"unreachable-code-break">; +def UnreachableCodeReturn : DiagGroup<"unreachable-code-return">; +def UnreachableCodeAggressive : DiagGroup<"unreachable-code-aggressive", + [UnreachableCode, + UnreachableCodeBreak, + UnreachableCodeReturn]>; + // Aggregation warning settings. +// Populate -Waddress with warnings from other groups. +def : DiagGroup<"address", [PointerBoolConversion, + StringCompare, + TautologicalPointerCompare]>; + // -Widiomatic-parentheses contains warnings about 'idiomatic' // missing parentheses; it is off by default. We do not include it // in -Wparentheses because most users who use -Wparentheses explicitly @@ -435,11 +505,13 @@ def Conversion : DiagGroup<"conversion", [BoolConversion, ConstantConversion, EnumConversion, + FloatConversion, Shorten64To32, IntConversion, LiteralConversion, NonLiteralNullConversion, // (1-1)->pointer (etc) NullConversion, // NULL->non-pointer + ObjCLiteralConversion, SignConversion, StringConversion]>, DiagCategory<"Value Conversion Issue">; @@ -461,7 +533,7 @@ def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull, FormatSecurity, FormatY2K, FormatInvalidSpecifier]>, DiagCategory<"Format String Issue">; -def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>; +def FormatNonLiteral : DiagGroup<"format-nonliteral">; def Format2 : DiagGroup<"format=2", [FormatNonLiteral, FormatSecurity, FormatY2K]>; @@ -502,6 +574,7 @@ def Most : DiagGroup<"most", [ Unused, VolatileRegisterVar, ObjCMissingSuperCalls, + ObjCDesignatedInit, OverloadedVirtual, PrivateExtern, SelTypeCast, @@ -524,7 +597,7 @@ def Consumed : DiagGroup<"consumed">; // 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]>; +def : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>; // Warnings enabled by -pedantic. This is magically filled in by TableGen. def Pedantic : DiagGroup<"pedantic">; @@ -555,6 +628,10 @@ def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11LongLong]>; // earlier C++ versions. def CXX1y : DiagGroup<"c++1y-extensions">; +// A warning group for warnings about using C++1z features as extensions in +// earlier C++ versions. +def CXX1z : DiagGroup<"c++1z-extensions">; + def : DiagGroup<"c++0x-extensions", [CXX11]>; def DelegatingCtorCycles : DiagGroup<"delegating-ctor-cycles">; @@ -608,8 +685,6 @@ def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [ ObjCStringComparison ]>; -def ObjCLiteralMissingAtSign : DiagGroup<"objc-literal-missing-atsign">; - // Inline ASM warnings. def ASMOperandWidths : DiagGroup<"asm-operand-widths">; def ASM : DiagGroup<"asm", [ @@ -618,3 +693,23 @@ def ASM : DiagGroup<"asm", [ // OpenMP warnings. def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">; +def OpenMPClauses : DiagGroup<"openmp-clauses">; +def OpenMPLoopForm : DiagGroup<"openmp-loop-form">; + +// Backend warnings. +def BackendInlineAsm : DiagGroup<"inline-asm">; +def BackendFrameLargerThanEQ : DiagGroup<"frame-larger-than=">; +def BackendPlugin : DiagGroup<"backend-plugin">; +def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">; +def BackendOptimizationRemark : DiagGroup<"pass">; +def BackendOptimizationRemarkMissed : DiagGroup<"pass-missed">; +def BackendOptimizationRemarkAnalysis : DiagGroup<"pass-analysis">; +def BackendOptimizationFailure : DiagGroup<"pass-failed">; + +// Instrumentation based profiling warnings. +def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">; +def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">; + +// A warning group for warnings about code that clang accepts when +// compiling CUDA C/C++ but which is not compatible with the CUDA spec. +def CudaCompat : DiagGroup<"cuda-compat">; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h index 56e30fb..bfb0f0d 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h @@ -56,49 +56,53 @@ namespace clang { }; /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs - /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR - /// (emit as an error). It allows clients to map errors to - /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this - /// one). - enum Mapping { + /// to either Ignore (nothing), Remark (emit a remark), Warning + /// (emit a warning) or Error (emit as an error). It allows clients to + /// map ERRORs to Error or Fatal (stop emitting diagnostics after this one). + enum class Severity { // 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. + Ignored = 1, ///< Do not present this diagnostic, ignore it. + Remark = 2, ///< Present this diagnostic as a remark. + Warning = 3, ///< Present this diagnostic as a warning. + Error = 4, ///< Present this diagnostic as an error. + Fatal = 5 ///< Present this diagnostic as a fatal error. + }; + + /// Flavors of diagnostics we can emit. Used to filter for a particular + /// kind of diagnostic (for instance, for -W/-R flags). + enum class Flavor { + WarningOrError, ///< A diagnostic that indicates a problem or potential + ///< problem. Can be made fatal by -Werror. + Remark ///< A diagnostic that indicates normal progress through + ///< compilation. }; } -class DiagnosticMappingInfo { - unsigned Mapping : 3; +class DiagnosticMapping { + unsigned Severity : 3; unsigned IsUser : 1; unsigned IsPragma : 1; - unsigned HasShowInSystemHeader : 1; unsigned HasNoWarningAsError : 1; unsigned HasNoErrorAsFatal : 1; public: - static DiagnosticMappingInfo Make(diag::Mapping Mapping, bool IsUser, - bool IsPragma) { - DiagnosticMappingInfo Result; - Result.Mapping = Mapping; + static DiagnosticMapping Make(diag::Severity Severity, bool IsUser, + bool IsPragma) { + DiagnosticMapping Result; + Result.Severity = (unsigned)Severity; Result.IsUser = IsUser; Result.IsPragma = IsPragma; - Result.HasShowInSystemHeader = 0; Result.HasNoWarningAsError = 0; Result.HasNoErrorAsFatal = 0; return Result; } - diag::Mapping getMapping() const { return diag::Mapping(Mapping); } - void setMapping(diag::Mapping Value) { Mapping = Value; } + diag::Severity getSeverity() const { return (diag::Severity)Severity; } + void setSeverity(diag::Severity Value) { Severity = (unsigned)Value; } bool isUser() const { return IsUser; } bool isPragma() const { return IsPragma; } - bool hasShowInSystemHeader() const { return HasShowInSystemHeader; } - void setShowInSystemHeader(bool Value) { HasShowInSystemHeader = Value; } - bool hasNoWarningAsError() const { return HasNoWarningAsError; } void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; } @@ -113,7 +117,7 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> { public: /// \brief The level of the diagnostic, after it has been through mapping. enum Level { - Ignored, Note, Warning, Error, Fatal + Ignored, Note, Remark, Warning, Error, Fatal }; private: @@ -124,11 +128,16 @@ public: DiagnosticIDs(); ~DiagnosticIDs(); - /// \brief Return an ID for a diagnostic with the specified message and level. + /// \brief Return an ID for a diagnostic with the specified format string and + /// level. /// /// If this is the first request for this diagnostic, it is registered and /// created, otherwise the existing ID is returned. - unsigned getCustomDiagID(Level L, StringRef Message); + + // FIXME: Replace this function with a create-only facilty like + // createCustomDiagIDFromFormatString() to enforce safe usage. At the time of + // writing, nearly all callers of this function were invalid. + unsigned getCustomDiagID(Level L, StringRef FormatString); //===--------------------------------------------------------------------===// // Diagnostic classification and reporting interfaces. @@ -228,15 +237,16 @@ public: /// /// \param[out] Diags - On return, the diagnostics in the group. /// \returns \c true if the given group is unknown, \c false otherwise. - bool getDiagnosticsInGroup(StringRef Group, + bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, SmallVectorImpl<diag::kind> &Diags) const; /// \brief Get the set of all diagnostic IDs. - void getAllDiagnostics(SmallVectorImpl<diag::kind> &Diags) const; + void getAllDiagnostics(diag::Flavor Flavor, + SmallVectorImpl<diag::kind> &Diags) const; - /// \brief Get the warning option with the closest edit distance to the given - /// group name. - static StringRef getNearestWarningOption(StringRef Group); + /// \brief Get the diagnostic option with the closest edit distance to the + /// given group name. + static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group); private: /// \brief Classify the specified diagnostic ID into a Level, consumable by @@ -247,15 +257,13 @@ private: /// /// \param Loc The source location for which we are interested in finding out /// the diagnostic state. Can be null in order to query the latest state. - DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, - const DiagnosticsEngine &Diag) const; - - /// \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; + DiagnosticIDs::Level + getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, + const DiagnosticsEngine &Diag) const LLVM_READONLY; + + diag::Severity + getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, + const DiagnosticsEngine &Diag) const LLVM_READONLY; /// \brief Used to report a diagnostic that is finally fully formed. /// diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td index 871f5f6..86def87 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -151,7 +151,8 @@ def warn_ucn_not_valid_in_c89_literal : ExtWarn< // Literal def ext_nonstandard_escape : Extension< "use of non-standard escape character '\\%0'">; -def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">; +def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">, + InGroup<DiagGroup<"unknown-escape-sequence">>; def err_invalid_decimal_digit : Error<"invalid digit '%0' in decimal constant">; def err_invalid_binary_digit : Error<"invalid digit '%0' in binary constant">; def err_invalid_octal_digit : Error<"invalid digit '%0' in octal constant">; @@ -244,9 +245,9 @@ def err_invalid_pth_file : Error< // Preprocessor Diagnostics //===----------------------------------------------------------------------===// -let CategoryName = "User Defined Issues" in { +let CategoryName = "User-Defined Issue" in { def pp_hash_warning : Warning<"%0">, - InGroup<PoundWarning>, DefaultWarnShowInSystemHeader; + InGroup<PoundWarning>, ShowInSystemHeader; def err_pp_hash_error : Error<"%0">; } @@ -300,6 +301,9 @@ def ext_pp_import_directive : Extension<"#import is a language extension">, InGroup<DiagGroup<"import-preprocessor-directive-pedantic">>; def err_pp_import_directive_ms : Error< "#import of type library is an unsupported Microsoft feature">; +def ext_pp_include_search_ms : ExtWarn< + "#include resolved using non-portable MSVC search rules as: %0">, + InGroup<DiagGroup<"msvc-include">>; def ext_pp_ident_directive : Extension<"#ident is a language extension">; def ext_pp_include_next_directive : Extension< @@ -312,7 +316,7 @@ def ext_pp_extra_tokens_at_eol : ExtWarn< 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_pp_macro_redef : ExtWarn<"%0 macro redefined">, InGroup<MacroRedefined>; def ext_variadic_macro : Extension<"variadic macros are a C99 feature">, InGroup<VariadicMacros>; def warn_cxx98_compat_variadic_macro : Warning< @@ -349,7 +353,7 @@ def err_pp_error_opening_file : Error< def err_pp_empty_filename : Error<"empty filename">; def err_pp_include_too_deep : Error<"#include nested too deeply">; def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">; -def err_pp_macro_not_identifier : Error<"macro names must be identifiers">; +def err_pp_macro_not_identifier : Error<"macro name must be an identifier">; def err_pp_missing_macro_name : Error<"macro name missing">; def err_pp_missing_rparen_in_macro_def : Error< "missing ')' in macro parameter list">; @@ -375,10 +379,7 @@ def err_pp_expected_value_in_expr : Error<"expected value in expression">; def err_pp_expected_rparen : Error<"expected ')' in preprocessor expression">; def err_pp_expected_eol : Error< "expected end of line in preprocessor expression">; -def err_pp_defined_requires_identifier : Error< - "operator 'defined' requires an identifier">; -def err_pp_missing_lparen : Error<"missing '(' after '%0'">; -def err_pp_missing_rparen : Error<"missing ')' after '%0'">; +def err_pp_expected_after : Error<"missing %1 after %0">; def err_pp_colon_without_question : Error<"':' without preceding '?'">; def err_pp_division_by_zero : Error< "division by zero in preprocessor expression">; @@ -400,6 +401,9 @@ def warn_has_warning_invalid_option : ExtWarn<"__has_warning expected option name (e.g. \"-Wundef\")">, InGroup<MalformedWarningCheck>; +def err_pp_identifier_arg_not_identifier : Error< + "cannot convert %0 token to an identifier">; + def warn_pragma_include_alias_mismatch_angle : ExtWarn<"angle-bracketed include <%0> cannot be aliased to double-quoted " "include \"%1\"">, InGroup<UnknownPragmas>; @@ -435,7 +439,8 @@ def err_pragma_message_malformed : Error< def err_pragma_push_pop_macro_malformed : Error< "pragma %0 requires a parenthesized string">; def warn_pragma_pop_macro_no_push : Warning< - "pragma pop_macro could not pop '%0', no matching push_macro">; + "pragma pop_macro could not pop '%0', no matching push_macro">, + InGroup<IgnoredPragmas>; def warn_pragma_message : Warning<"%0">, InGroup<PoundPragmaMessage>, DefaultWarnNoWerror; def err_pragma_message : Error<"%0">; @@ -470,7 +475,7 @@ def warn_pragma_diagnostic_unknown_warning : InGroup<UnknownPragmas>; // - #pragma __debug def warn_pragma_debug_unexpected_command : Warning< - "unexpected debug command '%0'">; + "unexpected debug command '%0'">, InGroup<IgnoredPragmas>; def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">; def err_paste_at_start : Error< @@ -491,11 +496,13 @@ def err_too_few_args_in_macro_invoc : Error< "too few arguments provided to function-like macro invocation">; def err_pp_bad_paste : Error< "pasting formed '%0', an invalid preprocessing token">; -def err_pp_bad_paste_ms : Warning< +def ext_pp_bad_paste_ms : ExtWarn< "pasting formed '%0', an invalid preprocessing token">, DefaultError, InGroup<DiagGroup<"invalid-token-paste">>; def err_pp_operator_used_as_macro_name : Error< - "C++ operator '%0' cannot be used as a macro name">; + "C++ operator %0 (aka %1) used as a macro name">; +def ext_pp_operator_used_as_macro_name : Extension< + "C++ operator %0 (aka %1) used as a macro name">, InGroup<Microsoft>; def err_pp_illegal_floating_literal : Error< "floating point literal in preprocessor expression">; def err_pp_line_requires_integer : Error< @@ -535,6 +542,10 @@ def err_pp_include_in_arc_cf_code_audited : Error< def err_pp_eof_in_arc_cf_code_audited : Error< "'#pragma clang arc_cf_code_audited' was not ended within this file">; +def warn_pp_date_time : Warning< + "expansion of date or time macro is not reproducible">, + ShowInSystemHeader, DefaultIgnore, InGroup<DiagGroup<"date-time">>; + // Module map parsing def err_mmap_unknown_token : Error<"skipping stray token">; def err_mmap_expected_module : Error<"expected module declaration">; @@ -551,8 +562,6 @@ def err_mmap_expected_mmap_file : Error<"expected a module map file name">; def err_mmap_module_redefinition : Error< "redefinition of module '%0'">; def note_mmap_prev_definition : Note<"previously defined here">; -def err_mmap_header_not_found : Error< - "%select{|umbrella }0header '%1' not found">; def err_mmap_umbrella_dir_not_found : Error< "umbrella directory '%0' not found">; def err_mmap_umbrella_clash : Error< @@ -605,7 +614,7 @@ def warn_auto_module_import : Warning< "import of module '%1'">, InGroup<AutoImport>, DefaultIgnore; def warn_uncovered_module_header : Warning< "umbrella header for module '%0' does not include header '%1'">, - InGroup<IncompleteUmbrella>, DefaultIgnore; + InGroup<IncompleteUmbrella>; def warn_forgotten_module_header : Warning< "header '%0' is included in module '%1' but not listed in module map">, InGroup<IncompleteModule>, DefaultIgnore; @@ -614,7 +623,14 @@ def err_expected_id_building_module : Error< def error_use_of_private_header_outside_module : Error< "use of private header from outside its module: '%0'">; def error_undeclared_use_of_module : Error< - "use of a module not declared used: '%0'">; + "module %0 does not depend on a module exporting '%1'">; +def warn_non_modular_include_in_framework_module : Warning< + "include of non-modular header inside framework module '%0'">, + InGroup<NonModularIncludeInFrameworkModule>, DefaultIgnore; +def warn_non_modular_include_in_module : Warning< + "include of non-modular header inside module '%0'">, + InGroup<NonModularIncludeInModule>, DefaultIgnore; + def warn_header_guard : Warning< "%0 is used as a header guard here, followed by #define of a different macro">, diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h index 2fba384..3e4d0ee 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h @@ -19,7 +19,7 @@ namespace clang { /// \brief Specifies which overload candidates to display when overload /// resolution fails. -enum OverloadsShown { +enum OverloadsShown : unsigned { Ovl_All, ///< Show all overloads. Ovl_Best ///< Show just the "best" overload candidates. }; @@ -58,6 +58,10 @@ public: /// prefixes removed. std::vector<std::string> Warnings; + /// The list of -R... options used to alter the diagnostic mappings, with the + /// prefixes removed. + std::vector<std::string> Remarks; + public: // Define accessors/mutators for diagnostic options of enumeration type. #define DIAGOPT(Name, Bits, Default) diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td index 2feab52..b1305e1 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -59,7 +59,8 @@ def ext_integer_complex : Extension< "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>; def ext_thread_before : Extension<"'__thread' before '%0'">; def ext_keyword_as_ident : ExtWarn< - "keyword '%0' will be treated as an identifier %select{here|for the remainder of the translation unit}1">, + "keyword '%0' will be made available as an identifier " + "%select{here|for the remainder of the translation unit}1">, InGroup<KeywordCompat>; def error_empty_enum : Error<"use of empty enum">; @@ -68,7 +69,7 @@ def err_invalid_short_spec : Error<"'short %0' is invalid">; def err_invalid_long_spec : Error<"'long %0' is invalid">; def err_invalid_longlong_spec : Error<"'long long %0' is invalid">; def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">; -def err_friend_storage_spec : Error<"'%0' is invalid in friend declarations">; +def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">; def ext_ident_list_in_param : Extension< "type-less parameter names in function declaration">; @@ -148,18 +149,6 @@ def err_expected_expression : Error<"expected expression">; def err_expected_type : Error<"expected a type">; def err_expected_external_declaration : Error<"expected external declaration">; def err_extraneous_closing_brace : Error<"extraneous closing brace ('}')">; -def err_expected_ident : Error<"expected identifier">; -def err_expected_ident_lparen : Error<"expected identifier or '('">; -def err_expected_ident_lbrace : Error<"expected identifier or '{'">; -def err_expected_lbrace : Error<"expected '{'">; -def err_expected_lparen : Error<"expected '('">; -def err_expected_lparen_or_lbrace : Error<"expected '(' or '{'">; -def err_expected_rparen : Error<"expected ')'">; -def err_expected_lsquare : Error<"expected '['">; -def err_expected_rsquare : Error<"expected ']'">; -def err_expected_rbrace : Error<"expected '}'">; -def err_expected_greater : Error<"expected '>'">; -def err_expected_ggg : Error<"expected '>>>'">; def err_expected_semi_declaration : Error< "expected ';' at end of declaration">; def err_expected_semi_decl_list : Error< @@ -185,18 +174,16 @@ def err_expected_method_body : Error<"expected method body">; def err_invalid_token_after_toplevel_declarator : Error< "expected ';' after top level declarator">; def err_invalid_token_after_declarator_suggest_equal : Error< - "invalid '%0' at end of declaration; did you mean '='?">; + "invalid %0 at end of declaration; did you mean '='?">; def err_expected_statement : Error<"expected statement">; def err_expected_lparen_after : Error<"expected '(' after '%0'">; -def err_expected_lparen_after_id : Error<"expected '(' after %0">; +def err_expected_rparen_after : Error<"expected ')' after '%0'">; +def err_expected_punc : Error<"expected ')' or ',' after '%0'">; def err_expected_less_after : Error<"expected '<' after '%0'">; -def err_expected_equal_after : Error<"expected '=' after %0">; -def err_expected_comma : Error<"expected ','">; def err_expected_lbrace_in_compound_literal : Error< "expected '{' in compound literal">; def err_expected_while : Error<"expected 'while' in do/while loop">; -def err_expected_semi_after : Error<"expected ';' after %0">; def err_expected_semi_after_stmt : Error<"expected ';' after %0 statement">; def err_expected_semi_after_expr : Error<"expected ';' after expression">; def err_extraneous_token_before_semi : Error<"extraneous '%0' before ';'">; @@ -206,7 +193,7 @@ def err_expected_semi_after_method_proto : Error< def err_expected_semi_after_namespace_name : Error< "expected ';' after namespace name">; def err_unexpected_namespace_attributes_alias : Error< - "attributes can not be specified on namespace alias">; + "attributes cannot be specified on namespace alias">; def err_inline_namespace_alias : Error<"namespace alias cannot be inline">; def err_namespace_nonnamespace_scope : Error< "namespaces can only be defined in global or namespace scope">; @@ -217,7 +204,8 @@ def err_expected_semi_after_attribute_list : Error< def err_expected_semi_after_static_assert : Error< "expected ';' after static_assert">; def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">; -def err_expected_colon_after : Error<"expected ':' after %0">; +def err_single_decl_assign_in_for_range : Error< + "range-based 'for' statement uses ':', not '='">; def warn_missing_selector_name : Warning< "%0 used as the name of the previous parameter rather than as part " "of the selector">, @@ -238,6 +226,8 @@ def err_expected_selector_for_method : Error< def err_expected_property_name : Error<"expected property name">; def err_unexpected_at : Error<"unexpected '@' in program">; +def err_atimport : Error< +"use of '@import' when modules are disabled">; def err_invalid_reference_qualifier_application : Error< "'%0' qualifier may not be applied to a reference">; @@ -287,6 +277,13 @@ def ext_for_range : ExtWarn< def warn_cxx98_compat_for_range : Warning< "range-based for loop is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def ext_for_range_identifier : ExtWarn< + "range-based for loop with implicit deduced type is a C++1z extension">, + InGroup<CXX1z>; +def warn_cxx1y_compat_for_range_identifier : Warning< + "range-based for loop with implicit deduced type is incompatible with " + "C++ standards before C++1z">, + InGroup<CXXPre1zCompat>, DefaultIgnore; def err_for_range_expected_decl : Error< "for range declaration must declare a variable">; def err_argument_required_after_attribute : Error< @@ -343,16 +340,16 @@ def warn_vector_long_decl_spec_combination : Warning< "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>; def err_friend_invalid_in_context : Error< "'friend' used outside of class">; -def err_unknown_typename : Error< - "unknown type name %0">; def err_use_of_tag_name_without_tag : Error< "must use '%1' tag to refer to type %0%select{| in this scope}2">; def err_templated_using_directive : Error< "cannot template a using directive">; def err_templated_using_declaration : Error< "cannot template a using declaration">; -def err_unexected_colon_in_nested_name_spec : Error< +def err_unexpected_colon_in_nested_name_spec : Error< "unexpected ':' in nested name specifier; did you mean '::'?">; +def err_unexpected_token_in_nested_name_spec : Error< + "'%0' cannot be a part of nested name specifier; did you mean ':'?">; def err_bool_redeclaration : Error< "redeclaration of C++ built-in type 'bool'">; def ext_c11_static_assert : Extension< @@ -364,6 +361,8 @@ def err_paren_after_colon_colon : Error< "unexpected parenthesis after '::'">; def err_function_definition_not_allowed : Error< "function definition is not allowed here">; +def err_expected_end_of_enumerator : Error< + "expected '= constant-expression' or end of enumerator definition">; /// Objective-C parser diagnostics def err_expected_minus_or_plus : Error< @@ -424,7 +423,7 @@ def err_objc_concat_string : Error<"unexpected token after Objective-C string">; def err_expected_objc_container : Error< "'@end' must appear in an Objective-C context">; def err_unexpected_protocol_qualifier : Error< - "@implementation declaration can not be protocol qualified">; + "@implementation declaration cannot be protocol qualified">; def err_objc_unexpected_atend : Error< "'@end' appears where closing brace '}' is expected">; def error_property_ivar_decl : Error< @@ -449,6 +448,8 @@ def err_invalid_operator_on_type : Error< "cannot use %select{dot|arrow}0 operator on a type">; def err_expected_unqualified_id : Error< "expected %select{identifier|unqualified-id}0">; +def err_brackets_go_after_unqualified_id : Error< + "brackets go after the %select{identifier|unqualified-id}0">; def err_unexpected_unqualified_id : Error<"type-id cannot have a name">; def err_func_def_no_params : Error< "function definition does not declare parameters">; @@ -480,9 +481,6 @@ def warn_cxx98_compat_noexcept_decl : Warning< "noexcept specifications are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_expected_catch : Error<"expected catch">; -def err_expected_lbrace_or_comma : Error<"expected '{' or ','">; -def err_expected_rbrace_or_comma : Error<"expected '}' or ','">; -def err_expected_rsquare_or_comma : Error<"expected ']' or ','">; def err_using_namespace_in_class : Error< "'using namespace' is not allowed in classes">; def err_constructor_bad_name : Error< @@ -504,8 +502,7 @@ def ext_abstract_pack_declarator_parens : ExtWarn< "ISO C++11 requires a parenthesized pack declaration to have a name">, InGroup<DiagGroup<"anonymous-pack-parens">>; def err_function_is_not_record : Error< - "unexpected '%select{.|->}0' in function call; perhaps remove the " - "'%select{.|->}0'?">; + "unexpected %0 in function call; perhaps remove the %0?">; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; @@ -535,10 +532,12 @@ def warn_cxx98_compat_nullptr : Warning< def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def warn_cxx98_compat_attribute : Warning< - "attributes are incompatible with C++98">, + "C++11 attribute syntax is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_cxx11_attribute_forbids_arguments : Error< - "attribute '%0' cannot have an argument list">; + "attribute %0 cannot have an argument list">; +def err_attribute_requires_arguments : Error< + "parentheses must be omitted if %0 attribute's argument list is empty">; def err_cxx11_attribute_forbids_ellipsis : Error< "attribute '%0' cannot be used as an attribute pack">; def err_cxx11_attribute_repeated : Error< @@ -549,8 +548,6 @@ def err_l_square_l_square_not_attribute : Error< "introducing an attribute">; 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>; def err_ms_property_no_getter_or_putter : Error< "property does not specify a getter or a putter">; def err_ms_property_unknown_accessor : Error< @@ -576,10 +573,17 @@ def err_expected_comma_greater : Error< "expected ',' or '>' in template-parameter-list">; def err_class_on_template_template_param : Error< "template template parameter requires 'class' after the parameter list">; +def ext_template_template_param_typename : ExtWarn< + "template template parameter using 'typename' is a C++1z extension">, + InGroup<CXX1z>; +def warn_cxx1y_compat_template_template_param_typename : Warning< + "template template parameter using 'typename' is " + "incompatible with C++ standards before C++1z">, + InGroup<CXXPre1zCompat>, DefaultIgnore; def err_template_spec_syntax_non_template : Error< "identifier followed by '<' indicates a class template specialization but " - "%0 %select{does not refer to a template|refers to a function " - "template|<unused>|refers to a template template parameter}1">; + "%0 %select{does not refer to a template|refers to a function template|" + "<unused>|refers to a variable template|<unused>}1">; 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< @@ -639,16 +643,13 @@ def err_expected_qualified_after_typename : Error< "expected a qualified name after 'typename'">; def warn_expected_qualified_after_typename : ExtWarn< "expected a qualified name after 'typename'">; -def err_expected_semi_after_tagdecl : Error< - "expected ';' after %0">; def err_typename_refers_to_non_type_template : Error< - "typename specifier refers to a non-template">; + "typename specifier refers to a non-type template">; def err_expected_type_name_after_typename : Error< "expected an identifier or template-id after '::'">; def err_explicit_spec_non_template : Error< - "explicit %select{specialization|instantiation}0 of non-template " - "%select{class|struct|union|interface}1 %2">; + "explicit %select{specialization|instantiation}0 of non-template %1 %2">; def err_default_template_template_parameter_not_template : Error< "default template argument for a template template parameter must be a class " @@ -744,7 +745,8 @@ def warn_cxx98_compat_lambda : Warning< "lambda expressions are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_lambda_missing_parens : Error< - "lambda requires '()' before %select{'mutable'|return type}0">; + "lambda requires '()' before %select{'mutable'|return type|" + "attribute specifier}0">; // Availability attribute def err_expected_version : Error< @@ -753,6 +755,13 @@ def err_zero_version : Error< "version number must have non-zero major, minor, or sub-minor version">; def err_availability_expected_platform : Error< "expected a platform name, e.g., 'macosx'">; + +// objc_bridge_related attribute +def err_objcbridge_related_expected_related_class : Error< + "expected a related ObjectiveC class name, e.g., 'NSColor'">; +def err_objcbridge_related_selector_name : Error< + "expected a class method selector with single argument, e.g., 'colorWithCGColor:'">; + def err_availability_expected_change : Error< "expected 'introduced', 'deprecated', or 'obsoleted'">; def err_availability_unknown_change : Error< @@ -769,35 +778,82 @@ def warn_availability_and_unavailable : Warning< def err_type_safety_unknown_flag : Error< "invalid comparison flag %0; use 'layout_compatible' or 'must_be_null'">; +// Type traits +def err_type_trait_arity : Error< + "type trait requires %0%select{| or more}1 argument%select{|s}2; have " + "%3 argument%s3">; + // Language specific pragmas // - Generic warnings def warn_pragma_expected_lparen : Warning< - "missing '(' after '#pragma %0' - ignoring">; + "missing '(' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>; def warn_pragma_expected_rparen : Warning< - "missing ')' after '#pragma %0' - ignoring">; + "missing ')' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>; def warn_pragma_expected_identifier : Warning< - "expected identifier in '#pragma %0' - ignored">; + "expected identifier in '#pragma %0' - ignored">, InGroup<IgnoredPragmas>; +def warn_pragma_expected_section_name : Warning< + "expected a string literal for the section name in '#pragma %0' - ignored">, + InGroup<IgnoredPragmas>; +def warn_pragma_expected_section_push_pop_or_name : Warning< + "expected push, pop or a string literal for the section name in '#pragma %0' - ignored">, + InGroup<IgnoredPragmas>; +def warn_pragma_expected_section_label_or_name : Warning< + "expected a stack label or a string literal for the section name in '#pragma %0' - ignored">, + InGroup<IgnoredPragmas>; +def warn_pragma_expected_init_seg : Warning< + "expected 'compiler', 'lib', 'user', or a string literal for the section name in '#pragma %0' - ignored">, + InGroup<IgnoredPragmas>; +def warn_pragma_expected_integer : Warning< + "expected integer between %0 and %1 inclusive in '#pragma %2' - ignored">, + InGroup<IgnoredPragmas>; def warn_pragma_ms_struct : Warning< - "incorrect use of '#pragma ms_struct on|off' - ignored">; + "incorrect use of '#pragma ms_struct on|off' - ignored">, + InGroup<IgnoredPragmas>; def warn_pragma_extra_tokens_at_eol : Warning< - "extra tokens at end of '#pragma %0' - ignored">; + "extra tokens at end of '#pragma %0' - ignored">, + InGroup<IgnoredPragmas>; +def warn_pragma_expected_punc : Warning< + "expected ')' or ',' in '#pragma %0'">, InGroup<IgnoredPragmas>; +def warn_pragma_expected_non_wide_string : Warning< + "expected non-wide string literal in '#pragma %0'">, InGroup<IgnoredPragmas>; +// - Generic errors +def err_pragma_missing_argument : Error< + "missing argument to '#pragma %0'; expected %1">; // - #pragma options def warn_pragma_options_expected_align : Warning< - "expected 'align' following '#pragma options' - ignored">; + "expected 'align' following '#pragma options' - ignored">, + InGroup<IgnoredPragmas>; def warn_pragma_align_expected_equal : Warning< - "expected '=' following '#pragma %select{align|options align}0' - ignored">; + "expected '=' following '#pragma %select{align|options align}0' - ignored">, + InGroup<IgnoredPragmas>; def warn_pragma_align_invalid_option : Warning< - "invalid alignment option in '#pragma %select{align|options align}0' - ignored">; + "invalid alignment option in '#pragma %select{align|options align}0' - ignored">, + InGroup<IgnoredPragmas>; // - #pragma pack -def warn_pragma_pack_invalid_action : Warning< - "unknown action for '#pragma pack' - ignored">; +def warn_pragma_unsupported_action : Warning< + "known but unsupported action '%1' for '#pragma %0' - ignored">, + InGroup<IgnoredPragmas>; +def warn_pragma_invalid_specific_action : Warning< + "unknown action '%1' for '#pragma %0' - ignored">, + InGroup<IgnoredPragmas>; +def warn_pragma_expected_action_or_r_paren : Warning< + "expected action or ')' in '#pragma %0' - ignored">, + InGroup<IgnoredPragmas>; +def warn_pragma_invalid_action : Warning< + "unknown action for '#pragma %0' - ignored">, + InGroup<IgnoredPragmas>; def warn_pragma_pack_malformed : Warning< - "expected integer or identifier in '#pragma pack' - ignored">; + "expected integer or identifier in '#pragma pack' - ignored">, + InGroup<IgnoredPragmas>; // - #pragma unused def warn_pragma_unused_expected_var : Warning< - "expected '#pragma unused' argument to be a variable name">; -def warn_pragma_unused_expected_punc : Warning< - "expected ')' or ',' in '#pragma unused'">; + "expected '#pragma unused' argument to be a variable name">, + InGroup<IgnoredPragmas>; +// - #pragma init_seg +def warn_pragma_init_seg_unsupported_target : Warning< + "'#pragma init_seg' is only supported when targeting a " + "Microsoft environment">, + InGroup<IgnoredPragmas>; // - #pragma fp_contract def err_pragma_fp_contract_scope : Error< "'#pragma fp_contract' can only appear at file scope or at the start of a " @@ -810,6 +866,16 @@ def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">; def err_pragma_detect_mismatch_malformed : Error< "pragma detect_mismatch is malformed; it requires two comma-separated " "string literals">; +// - #pragma pointers_to_members +def err_pragma_pointers_to_members_unknown_kind : Error< + "unexpected %0, expected to see one of %select{|'best_case', 'full_generality', }1" + "'single_inheritance', 'multiple_inheritance', or 'virtual_inheritance'">; +// - #pragma clang optimize on/off +def err_pragma_optimize_invalid_argument : Error< + "unexpected argument '%0' to '#pragma clang optimize'; " + "expected 'on' or 'off'">; +def err_pragma_optimize_extra_argument : Error< + "unexpected extra argument '%0' to '#pragma clang optimize'">; // OpenCL Section 6.8.g def err_not_opencl_storage_class_specifier : Error< @@ -817,11 +883,11 @@ def err_not_opencl_storage_class_specifier : Error< // OpenCL EXTENSION pragma (OpenCL 1.1 [9.1]) def warn_pragma_expected_colon : Warning< - "missing ':' after %0 - ignoring">; + "missing ':' after %0 - ignoring">, InGroup<IgnoredPragmas>; def warn_pragma_expected_enable_disable : Warning< - "expected 'enable' or 'disable' - ignoring">; + "expected 'enable' or 'disable' - ignoring">, InGroup<IgnoredPragmas>; def warn_pragma_unknown_extension : Warning< - "unknown OpenCL extension %0 - ignoring">; + "unknown OpenCL extension %0 - ignoring">, InGroup<IgnoredPragmas>; def err_seh_expected_handler : Error< "expected '__except' or '__finally' block">; @@ -836,21 +902,35 @@ def err_seh___finally_block : Error< "%0 only allowed in __finally block">; // OpenMP support. -def warn_pragma_omp_ignored : Warning < +def warn_pragma_omp_ignored : Warning< "unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore; -def warn_omp_extra_tokens_at_eol : Warning < +def warn_omp_extra_tokens_at_eol : Warning< "extra tokens at the end of '#pragma omp %0' are ignored">, InGroup<ExtraTokens>; -def err_omp_unknown_directive : Error < +def err_omp_unknown_directive : Error< "expected an OpenMP directive">; -def err_omp_unexpected_directive : Error < +def err_omp_unexpected_directive : Error< "unexpected OpenMP directive '#pragma omp %0'">; -def err_omp_expected_punc : Error < - "expected ',' or ')' in %select{'#pragma omp %1'|'%1' clause}0">; -def err_omp_unexpected_clause : Error < +def err_omp_expected_punc : Error< + "expected ',' or ')' in '%0' %select{clause|directive}1">; +def err_omp_unexpected_clause : Error< "unexpected OpenMP clause '%0' in directive '#pragma omp %1'">; -def err_omp_more_one_clause : Error < +def err_omp_more_one_clause : Error< "directive '#pragma omp %0' cannot contain more than one '%1' clause">; +def err_omp_immediate_directive : Error< + "'#pragma omp %0' cannot be an immediate substatement">; +def err_omp_expected_identifier_for_critical : Error< + "expected identifier specifying the name of the 'omp critical' directive">; + +// Pragma loop support. +def err_pragma_loop_invalid_option : Error< + "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, " + "vectorize_width, interleave, interleave_count, unroll, or unroll_count">; + +// Pragma unroll support. +def warn_pragma_unroll_cuda_value_in_parens : Warning< + "argument to '#pragma unroll' should not be in parentheses in CUDA C/C++">, + InGroup<CudaCompat>; } // end of Parse Issue category. let CategoryName = "Modules Issue" in { diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6c7cb00..89749ed 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -14,6 +14,11 @@ let Component = "Sema" in { let CategoryName = "Semantic Issue" in { +def note_previous_decl : Note<"%0 declared here">; +def note_entity_declared_at : Note<"%0 declared here">; +def note_callee_decl : Note<"%0 declared here">; +def note_defined_here : Note<"%0 defined here">; + // 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 " @@ -30,6 +35,25 @@ def warn_duplicate_enum_values : Warning< "been assigned">, InGroup<DiagGroup<"duplicate-enum">>, DefaultIgnore; def note_duplicate_element : Note<"element %0 also has value %1">; +// Absolute value functions +def warn_unsigned_abs : Warning< + "taking the absolute value of unsigned type %0 has no effect">, + InGroup<AbsoluteValue>; +def note_remove_abs : Note< + "remove the call to '%0' since unsigned values cannot be negative">; +def warn_abs_too_small : Warning< + "absolute value function %0 given an argument of type %1 but has parameter " + "of type %2 which may cause truncation of value">, InGroup<AbsoluteValue>; +def warn_wrong_absolute_value_type : Warning< + "using %select{integer|floating point|complex}1 absolute value function %0 " + "when argument is of %select{integer|floating point|complex}2 type">, + InGroup<AbsoluteValue>; +def note_replace_abs_function : Note<"use function '%0' instead">; + +def warn_infinite_recursive_function : Warning< + "all paths through this function will call itself">, + InGroup<InfiniteRecursion>, DefaultIgnore; + // Constant expressions def err_expr_not_ice : Error< "expression is not an %select{integer|integral}0 constant expression">; @@ -87,9 +111,9 @@ def err_array_star_in_function_definition : Error< def err_vla_decl_in_file_scope : Error< "variable length array declaration not allowed at file scope">; def err_vla_decl_has_static_storage : Error< - "variable length array declaration can not have 'static' storage duration">; + "variable length array declaration cannot have 'static' storage duration">; def err_vla_decl_has_extern_linkage : Error< - "variable length array declaration can not have 'extern' linkage">; + "variable length array declaration cannot have 'extern' linkage">; def ext_vla_folded_to_constant : Extension< "variable length array folded to constant array as an extension">, InGroup<GNUFoldingConstant>; @@ -142,7 +166,7 @@ def ext_flexible_array_init : Extension< def err_bad_variable_name : Error< "%0 cannot be the name of a variable or data member">; def err_bad_parameter_name : Error< - "'%0' cannot be the name of a parameter">; + "%0 cannot be the name of a parameter">; def err_parameter_name_omitted : Error<"parameter name omitted">; def warn_unused_parameter : Warning<"unused parameter %0">, InGroup<UnusedParameter>, DefaultIgnore; @@ -215,10 +239,13 @@ def ext_implicit_function_decl : ExtWarn< InGroup<ImplicitFunctionDeclare>; def note_function_suggestion : Note<"did you mean %0?">; -def err_ellipsis_first_arg : Error< - "ISO C requires a named argument before '...'">; +def err_ellipsis_first_param : Error< + "ISO C requires a named parameter before '...'">; def err_declarator_need_ident : Error<"declarator requires an identifier">; -def err_bad_language : Error<"unknown linkage language">; +def err_language_linkage_spec_unknown : Error<"unknown linkage language">; +def err_language_linkage_spec_not_ascii : Error< + "string literal in language linkage specifier cannot have an " + "encoding-prefix">; def warn_use_out_of_scope_declaration : Warning< "use of out-of-scope declaration of %0">; def err_inline_non_function : Error< @@ -251,9 +278,9 @@ def err_using_decl_nested_name_specifier_is_current_class : Error< def err_using_decl_nested_name_specifier_is_not_base_class : Error< "using declaration refers into '%0', which is not a base class of %1">; def err_using_decl_constructor_not_in_direct_base : Error< - "%0 is not a direct base of %1, can not inherit constructors">; + "%0 is not a direct base of %1, cannot inherit constructors">; def err_using_decl_constructor_conflict : Error< - "can not inherit constructor, already inherited constructor with " + "cannot inherit constructor, already inherited constructor with " "the same signature">; def note_using_decl_constructor_conflict_current_ctor : Note< "conflicting constructor">; @@ -267,18 +294,21 @@ def warn_using_decl_constructor_ellipsis : Warning< def note_using_decl_constructor_ellipsis : Note< "constructor declared with ellipsis here">; def err_using_decl_can_not_refer_to_class_member : Error< - "using declaration can not refer to class member">; + "using declaration cannot refer to class member">; +def note_using_decl_class_member_workaround : Note< + "use %select{an alias declaration|a typedef declaration|a reference}0 " + "instead">; def err_using_decl_can_not_refer_to_namespace : Error< - "using declaration can not refer to namespace">; + "using declaration cannot refer to namespace">; def err_using_decl_constructor : Error< - "using declaration can not refer to a constructor">; + "using declaration cannot refer to a constructor">; def warn_cxx98_compat_using_decl_constructor : Warning< "inheriting constructors are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_using_decl_destructor : Error< - "using declaration can not refer to a destructor">; + "using declaration cannot refer to a destructor">; def err_using_decl_template_id : Error< - "using declaration can not refer to a template specialization">; + "using declaration cannot refer to a template specialization">; def note_using_decl_target : Note<"target of using declaration">; def note_using_decl_conflict : Note<"conflicting declaration">; def err_using_decl_redeclaration : Error<"redeclaration of using decl">; @@ -319,7 +349,7 @@ def err_invalid_thread : Error< def err_thread_non_global : Error< "'%0' variables must have global storage">; def err_thread_unsupported : Error< - "thread-local storage is unsupported for the current target">; + "thread-local storage is not supported for the current target">; def warn_maybe_falloff_nonvoid_function : Warning< "control may reach end of non-void function">, @@ -337,40 +367,42 @@ def warn_suggest_noreturn_function : Warning< def warn_suggest_noreturn_block : Warning< "block could be declared with attribute 'noreturn'">, InGroup<MissingNoreturn>, DefaultIgnore; -def warn_unreachable : Warning<"will never be executed">, - InGroup<DiagGroup<"unreachable-code">>, DefaultIgnore; + +// Unreachable code. +def warn_unreachable : Warning< + "code will never be executed">, + InGroup<UnreachableCode>, DefaultIgnore; +def warn_unreachable_break : Warning< + "'break' will never be executed">, + InGroup<UnreachableCodeBreak>, DefaultIgnore; +def warn_unreachable_return : Warning< + "'return' will never be executed">, + InGroup<UnreachableCodeReturn>, DefaultIgnore; +def warn_unreachable_loop_increment : Warning< + "loop will run at most once (loop increment never executed)">, + InGroup<UnreachableCodeLoopIncrement>, DefaultIgnore; +def note_unreachable_silence : Note< + "silence by adding parentheses to mark code as explicitly dead">; /// Built-in functions. def ext_implicit_lib_function_decl : ExtWarn< "implicitly declaring library function '%0' with type %1">; -def note_please_include_header : Note< - "please include the header <%0> or explicitly provide a " - "declaration for '%1'">; +def note_include_header_or_declare : Note< + "include the header <%0> or explicitly provide a declaration for '%1'">; def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">; -def warn_implicit_decl_requires_stdio : Warning< - "declaration of built-in function '%0' requires inclusion of the header " - "<stdio.h>">, - InGroup<BuiltinRequiresHeader>; -def warn_implicit_decl_requires_setjmp : Warning< - "declaration of built-in function '%0' requires inclusion of the header " - "<setjmp.h>">, - InGroup<BuiltinRequiresHeader>; -def warn_implicit_decl_requires_ucontext : Warning< - "declaration of built-in function '%0' requires inclusion of the header " - "<ucontext.h>">, +def warn_implicit_decl_requires_sysheader : Warning< + "declaration of built-in function '%1' requires inclusion of the header <%0>">, InGroup<BuiltinRequiresHeader>; def warn_redecl_library_builtin : Warning< "incompatible redeclaration of library function %0">, InGroup<DiagGroup<"incompatible-library-redeclaration">>; def err_builtin_definition : Error<"definition of builtin function %0">; -def err_types_compatible_p_in_cplusplus : Error< - "__builtin_types_compatible_p is not valid in C++">; def warn_builtin_unknown : Warning<"use of unknown builtin %0">, InGroup<ImplicitFunctionDeclare>, DefaultError; def warn_dyn_class_memaccess : Warning< "%select{destination for|source of|first operand of|second operand of}0 this " - "%1 call is a pointer to dynamic class %2; vtable pointer will be " - "%select{overwritten|copied|moved|compared}3">, + "%1 call is a pointer to %select{|class containing a }2dynamic class %3; " + "vtable pointer will be %select{overwritten|copied|moved|compared}4">, InGroup<DiagGroup<"dynamic-class-memaccess">>; def note_bad_memaccess_silence : Note< "explicitly cast the pointer to silence this warning">; @@ -388,11 +420,18 @@ def warn_sizeof_pointer_type_memaccess : Warning< "%select{destination|source}2; expected %3 or an explicit length">, InGroup<SizeofPointerMemaccess>; def warn_strlcpycat_wrong_size : Warning< - "size argument in %0 call appears to be size of the source; expected the size of " - "the destination">, + "size argument in %0 call appears to be size of the source; " + "expected the size of the destination">, InGroup<DiagGroup<"strlcpy-strlcat-size">>; def note_strlcpycat_wrong_size : Note< "change size argument to be the size of the destination">; +def warn_memsize_comparison : Warning< + "size argument in %0 call is a comparison">, + InGroup<DiagGroup<"memsize-comparison">>; +def note_memsize_comparison_paren : Note< + "did you mean to compare the result of %0 instead?">; +def note_memsize_comparison_cast_silence : Note< + "explicitly cast the argument to size_t to silence this warning">; def warn_strncat_large_size : Warning< "the value of the size argument in 'strncat' is too large, might lead to a " @@ -405,6 +444,10 @@ def note_strncat_wrong_size : Note< "change the argument to be the free space in the destination buffer minus " "the terminating null byte">; +def warn_assume_side_effects : Warning< + "the argument to __assume has side effects that will be discarded">, + InGroup<DiagGroup<"assume">>; + /// main() // static main() is not an error in C, just in C++. def warn_static_main : Warning<"'main' should not be declared static">, @@ -416,7 +459,8 @@ def ext_noreturn_main : ExtWarn< def note_main_remove_noreturn : Note<"remove '_Noreturn'">; def err_constexpr_main : Error< "'main' is not allowed to be declared constexpr">; -def err_mainlike_template_decl : Error<"'%0' cannot be a template">; +def err_deleted_main : Error<"'main' is not allowed to be deleted">; +def err_mainlike_template_decl : Error<"%0 cannot be a template">; def err_main_returns_nonint : Error<"'main' must return 'int'">; def ext_main_returns_nonint : ExtWarn<"return type of 'main' is not 'int'">, InGroup<MainReturnType>; @@ -428,6 +472,8 @@ def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">, def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " "parameter of 'main' (%select{argument count|argument array|environment|" "platform-specific data}0) must be of type %1">; +def ext_main_used : Extension< + "ISO C++ does not allow 'main' to be used by a program">, InGroup<Main>; /// parser diagnostics def ext_no_declarators : ExtWarn<"declaration does not declare anything">, @@ -435,6 +481,10 @@ def ext_no_declarators : ExtWarn<"declaration does not declare anything">, def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">, InGroup<MissingDeclarations>; def err_typedef_not_identifier : Error<"typedef name must be an identifier">; +def err_typedef_changes_linkage : Error<"unsupported: typedef changes linkage" + " of anonymous type, but linkage was already computed">; +def note_typedef_changes_linkage : Note<"use a tag name here to establish " + "linkage prior to definition">; def err_statically_allocated_object : Error< "interface type cannot be statically allocated">; def err_object_cannot_be_passed_returned_by_value : Error< @@ -447,28 +497,37 @@ def err_opencl_half_load_store : Error< def err_opencl_cast_to_half : Error<"casting to type %0 is not allowed">; def err_opencl_half_declaration : Error< "declaring variable of type %0 is not allowed">; -def err_opencl_half_argument : Error< - "declaring function argument of type %0 is not allowed; did you forget * ?">; +def err_opencl_half_param : Error< + "declaring function parameter of type %0 is not allowed; did you forget * ?">; def err_opencl_half_return : Error< "declaring function return value of type %0 is not allowed; did you forget * ?">; def warn_enum_value_overflow : Warning<"overflow in enumeration value">; def warn_pragma_options_align_reset_failed : Warning< - "#pragma options align=reset failed: %0">; + "#pragma options align=reset failed: %0">, + InGroup<IgnoredPragmas>; def err_pragma_options_align_mac68k_target_unsupported : Error< "mac68k alignment pragma is not supported on this target">; def warn_pragma_pack_invalid_alignment : Warning< - "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">; + "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">, + InGroup<IgnoredPragmas>; // Follow the MSVC implementation. def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">; def warn_pragma_pack_pop_identifer_and_alignment : Warning< "specifying both a name and alignment to 'pop' is undefined">; -def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">; -def warn_pragma_ms_struct_failed : Warning<"#pramga ms_struct can not be used with dynamic classes or structures">, InGroup<IgnoredAttributes>; +def warn_pragma_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">, + InGroup<IgnoredPragmas>; +def warn_cxx_ms_struct : + Warning<"ms_struct may not produce MSVC-compatible layouts for classes " + "with base classes or virtual functions">, + DefaultError, InGroup<IncompatibleMSStruct>; +def err_section_conflict : Error<"%0 causes a section type conflict with %1">; def warn_pragma_unused_undeclared_var : Warning< - "undeclared variable %0 used as an argument for '#pragma unused'">; + "undeclared variable %0 used as an argument for '#pragma unused'">, + InGroup<IgnoredPragmas>; def warn_pragma_unused_expected_var_arg : Warning< - "only variables can be arguments to '#pragma unused'">; + "only variables can be arguments to '#pragma unused'">, + InGroup<IgnoredPragmas>; def err_pragma_push_visibility_mismatch : Error< "#pragma visibility push with no matching #pragma visibility pop">; def note_surrounding_namespace_ends_here : Note< @@ -477,6 +536,14 @@ def err_pragma_pop_visibility_mismatch : Error< "#pragma visibility pop with no matching #pragma visibility push">; def note_surrounding_namespace_starts_here : Note< "surrounding namespace with visibility attribute starts here">; +def err_pragma_loop_invalid_value : Error< + "invalid argument; expected a positive integer value">; +def err_pragma_loop_invalid_keyword : Error< + "invalid argument; expected 'enable' or 'disable'">; +def err_pragma_loop_compatibility : Error< + "%select{incompatible|duplicate}0 directives '%1' and '%2'">; +def err_pragma_loop_precedes_nonloop : Error< + "expected a for, while, or do-while loop to follow '%0'">; /// Objective-C parser diagnostics def err_duplicate_class_def : Error< @@ -547,12 +614,10 @@ def err_conflicting_ivar_bitwidth : Error< "instance variable %0 has conflicting bit-field width">; def err_conflicting_ivar_name : Error< "conflicting instance variable names: %0 vs %1">; -def err_inconsistant_ivar_count : Error< +def err_inconsistent_ivar_count : Error< "inconsistent number of instance variables specified">; def warn_undef_method_impl : Warning<"method definition for %0 not found">, InGroup<DiagGroup<"incomplete-implementation">>; -def note_required_for_protocol_at : - Note<"required for direct or indirect protocol %0">; def warn_conflicting_overriding_ret_types : Warning< "conflicting return type in " @@ -696,21 +761,21 @@ def note_atomic_property_fixup_suggest : Note<"setter and getter must both be " def err_atomic_property_nontrivial_assign_op : Error< "atomic property of reference type %0 cannot have non-trivial assignment" " operator">; -def warn_owning_getter_rule : Warning< - "property's synthesized getter follows Cocoa naming" +def warn_cocoa_naming_owned_rule : Warning< + "property follows Cocoa naming" " convention for returning 'owned' objects">, InGroup<DiagGroup<"objc-property-matches-cocoa-ownership-rule">>; def warn_auto_synthesizing_protocol_property :Warning< - "auto property synthesis will not synthesize property" - " declared in a protocol">, + "auto property synthesis will not synthesize property %0" + " declared in protocol %1">, InGroup<DiagGroup<"objc-protocol-property-synthesis">>; def warn_no_autosynthesis_shared_ivar_property : Warning < "auto property synthesis will not synthesize property " - "'%0' because it cannot share an ivar with another synthesized property">, + "%0 because it cannot share an ivar with another synthesized property">, InGroup<ObjCNoPropertyAutoSynthesis>; def warn_no_autosynthesis_property : Warning< "auto property synthesis will not synthesize property " - "'%0' because it is 'readwrite' but it will be synthesized 'readonly' " + "%0 because it is 'readwrite' but it will be synthesized 'readonly' " "via another property">, InGroup<ObjCNoPropertyAutoSynthesis>; def warn_autosynthesis_property_ivar_match :Warning< @@ -724,10 +789,10 @@ 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 -" + "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" +def err_cocoa_naming_owned_rule : Error< + "property follows Cocoa naming" " convention for returning 'owned' objects">; def warn_default_atomic_custom_getter_setter : Warning< "atomic by default property %0 has a user defined %select{getter|setter}1 " @@ -778,6 +843,9 @@ def err_arc_perform_selector_retains : Error< def warn_arc_perform_selector_leaks : Warning< "performSelector may cause a leak because its selector is unknown">, InGroup<DiagGroup<"arc-performSelector-leaks">>; +def warn_dealloc_in_category : Warning< +"-dealloc is being overridden in a category">, +InGroup<DeallocInCategory>; 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 < @@ -818,13 +886,10 @@ def error_weak_property : Error< def error_strong_property : Error< "existing instance variable %1 for strong property %0 may not be __weak">; def error_dynamic_property_ivar_decl : Error< - "dynamic property can not have instance variable specification">; + "dynamic property cannot have instance variable specification">; def error_duplicate_ivar_use : Error< "synthesized properties %0 and %1 both claim instance variable %2">; def error_property_implemented : Error<"property %0 is already implemented">; -def warn_objc_property_attr_mutually_exclusive : Warning< - "property attributes '%0' and '%1' are mutually exclusive">, - InGroup<ReadOnlySetterAttrs>, DefaultIgnore; def warn_objc_missing_super_call : Warning< "method possibly missing a [super %0] call">, InGroup<ObjCMissingSuperCalls>; @@ -841,23 +906,30 @@ def warn_implicit_atomic_property : Warning< def note_auto_readonly_iboutlet_fixup_suggest : Note< "property should be changed to be readwrite">; def warn_auto_readonly_iboutlet_property : Warning< - "readonly IBOutlet property '%0' when auto-synthesized may " + "readonly IBOutlet property %0 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; def warn_unimplemented_selector: Warning< - "creating selector for nonexistent method %0">, InGroup<Selector>, DefaultIgnore; -def warning_multiple_selectors: Warning< - "multiple selectors named %0 found">, InGroup<SelectorTypeMismatch>, DefaultIgnore; + "no method with selector %0 is implemented in this translation unit">, + InGroup<Selector>, DefaultIgnore; def warn_unimplemented_protocol_method : Warning< - "method %0 in protocol not implemented">, InGroup<Protocol>; - + "method %0 in protocol %1 not implemented">, InGroup<Protocol>; +def warning_multiple_selectors: Warning< + "several methods with selector %0 of mismatched types are found " + "for the @selector expression">, + InGroup<SelectorTypeMismatch>, DefaultIgnore; // C++ declarations def err_static_assert_expression_is_not_constant : Error< "static_assert expression is not an integral constant expression">; -def err_static_assert_failed : Error<"static_assert failed %0">; +def err_static_assert_failed : Error<"static_assert failed%select{ %1|}0">; +def ext_static_assert_no_message : ExtWarn< + "static_assert with no message is a C++1z extension">, InGroup<CXX1z>; +def warn_cxx1y_compat_static_assert_no_message : Warning< + "static_assert with no message is incompatible with C++ standards before C++1z">, + DefaultIgnore, InGroup<CXXPre1zCompat>; def warn_inline_namespace_reopened_noninline : Warning< "inline namespace cannot be reopened as a non-inline namespace">; @@ -918,7 +990,11 @@ def warn_template_qualified_friend_ignored : Warning< "dependent nested name specifier '%0' for friend template declaration is " "not supported; ignoring this friend declaration">, InGroup<UnsupportedFriend>; - +def ext_friend_tag_redecl_outside_namespace : ExtWarn< + "unqualified friend declaration referring to type outside of the nearest " + "enclosing namespace is a Microsoft extension; add a nested name specifier">, + InGroup<Microsoft>; + def err_invalid_member_in_interface : Error< "%select{data member |non-public member function |static member function |" "user-declared constructor|user-declared destructor|operator |" @@ -937,19 +1013,23 @@ def err_throw_abstract_type : Error< def err_array_of_abstract_type : Error<"array of abstract class type %0">; def err_capture_of_abstract_type : Error< "by-copy capture of value of abstract type %0">; +def err_capture_of_incomplete_type : Error< + "by-copy capture of variable %0 with incomplete type %1">; +def err_capture_default_non_local : Error< + "non-local lambda expression cannot have a capture-default">; def err_multiple_final_overriders : Error< "virtual function %q0 has more than one final overrider in %1">; def note_final_overrider : Note<"final overrider of %q0 in %1">; def err_type_defined_in_type_specifier : Error< - "%0 can not be defined in a type specifier">; + "%0 cannot be defined in a type specifier">; def err_type_defined_in_result_type : Error< - "%0 can not be defined in the result type of a function">; + "%0 cannot be defined in the result type of a function">; def err_type_defined_in_param_type : Error< - "%0 can not be defined in a parameter type">; + "%0 cannot be defined in a parameter type">; def err_type_defined_in_alias_template : Error< - "%0 can not be defined in a type alias template">; + "%0 cannot be defined in a type alias template">; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; @@ -988,12 +1068,13 @@ def err_rref_in_exception_spec : Error< "rvalue reference type %0 is not allowed in exception specification">; def err_mismatched_exception_spec : Error< "exception specification in declaration does not match previous declaration">; -def warn_mismatched_exception_spec : ExtWarn< - "exception specification in declaration does not match previous declaration">; +def ext_mismatched_exception_spec : ExtWarn< + "exception specification in declaration does not match previous declaration">, + InGroup<Microsoft>; def err_override_exception_spec : Error< "exception specification of overriding function is more lax than " "base version">; -def warn_override_exception_spec : ExtWarn< +def ext_override_exception_spec : ExtWarn< "exception specification of overriding function is more lax than " "base version">, InGroup<Microsoft>; def err_incompatible_exception_specs : Error< @@ -1105,7 +1186,10 @@ def err_incomplete_type : Error< def warn_cxx98_compat_enum_nested_name_spec : Warning< "enumeration type in nested name specifier is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; - +def err_nested_name_spec_is_not_class : Error< + "%0 cannot appear before '::' because it is not a class" + "%select{ or namespace|, namespace, or scoped enumeration}1; did you mean ':'?">; + // C++ class members def err_storageclass_invalid_for_member : Error< "storage class specified for a member declaration">; @@ -1119,7 +1203,7 @@ def err_virtual_non_function : Error< def err_virtual_out_of_class : Error< "'virtual' can only be specified inside the class definition">; def err_virtual_member_function_template : Error< - "'virtual' can not be specified on member function templates">; + "'virtual' cannot be specified on member function templates">; def err_static_overrides_virtual : Error< "'static' member function %0 overrides a virtual function in a base class">; def err_explicit_non_function : Error< @@ -1142,7 +1226,7 @@ def err_member_function_initialization : Error< "initializer on function does not look like a pure-specifier">; def err_non_virtual_pure : Error< "%0 is not virtual and cannot be declared pure">; -def warn_pure_function_definition : ExtWarn< +def ext_pure_function_definition : ExtWarn< "function definition with pure-specifier is a Microsoft extension">, InGroup<Microsoft>; def err_implicit_object_parameter_init : Error< @@ -1155,10 +1239,9 @@ def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning< "call to pure virtual member function %0; overrides of %0 in subclasses are " "not available in the %select{constructor|destructor}1 of %2">; -def note_field_decl : Note<"member is declared here">; +def note_member_declared_at : Note<"member is declared here">; def note_ivar_decl : Note<"instance variable is declared here">; def note_bitfield_decl : Note<"bit-field is declared here">; -def note_previous_decl : Note<"%0 declared here">; def note_implicit_param_decl : Note<"%0 is an implicit parameter">; def note_member_synthesized_at : Note< "implicit %select{default constructor|copy constructor|move constructor|copy " @@ -1419,6 +1502,9 @@ def warn_uninit_byref_blockvar_captured_by_block : Warning< InGroup<Uninitialized>, DefaultIgnore; def note_block_var_fixit_add_initialization : Note< "maybe you meant to use __block %0">; +def note_in_omitted_aggregate_initializer : Note< + "in implicit initialization of %select{array element %1|field %1}0 " + "with omitted initializer">; def note_var_fixit_add_initialization : Note< "initialize the variable %0 to silence this warning">; def note_uninit_fixit_remove_cond : Note< @@ -1495,16 +1581,22 @@ def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< "new expression for type %0 requires a constructor argument">; -def err_auto_new_requires_parens : Error< +def err_auto_new_list_init : Error< "new expression for type %0 cannot use list-initialization">; def err_auto_var_init_no_expression : Error< "initializer for variable %0 with type %1 is empty">; def err_auto_var_init_multiple_expressions : Error< "initializer for variable %0 with type %1 contains multiple expressions">; +def err_auto_var_init_paren_braces : Error< + "cannot deduce type for variable %0 with type %1 from " + "parenthesized initializer list">; def err_auto_new_ctor_multiple_expressions : Error< "new expression for type %0 contains multiple constructor arguments">; def err_auto_missing_trailing_return : Error< - "'auto' return without trailing return type">; + "'auto' return without trailing return type; deduced return types are a " + "C++1y extension">; +def err_deduced_return_type : Error< + "deduced return types are a C++1y extension">; def err_trailing_return_without_auto : Error< "function with trailing return type must specify return type 'auto', not %0">; def err_trailing_return_in_parens : Error< @@ -1570,7 +1662,7 @@ def warn_abstract_final_class : Warning< "abstract class is marked '%select{final|sealed}0'">, InGroup<AbstractFinalClass>; // C++11 attributes -def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">; +def err_repeat_attribute : Error<"%0 attribute cannot be repeated">; // C++11 final def err_final_function_overridden : Error< @@ -1597,6 +1689,8 @@ def err_enum_class_reference : Error< "not 'enum class'">; def err_only_enums_have_underlying_types : Error< "only enumeration types have underlying types">; +def err_underlying_type_of_incomplete_enum : Error< + "cannot determine underlying type of incomplete enumeration type %0">; // C++11 delegating constructors def err_delegating_ctor : Error< @@ -1730,6 +1824,8 @@ def err_constexpr_local_var_no_init : Error< def ext_constexpr_function_never_constant_expr : ExtWarn< "constexpr %select{function|constructor}0 never produces a " "constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError; +def err_enable_if_never_constant_expr : Error< + "'enable_if' attribute expression never produces a constant expression">; def err_constexpr_body_no_return : Error< "no return statement in constexpr function">; def warn_cxx11_compat_constexpr_body_no_return : Warning< @@ -1786,21 +1882,16 @@ def warn_auto_var_is_id : Warning< // Attributes def err_nsobject_attribute : Error< - "__attribute ((NSObject)) is for pointer types only">; -def err_attribute_can_be_applied_only_to_symbol_declaration : Error< - "%0 attribute can be applied only to symbol declaration">; + "'NSObject' attribute is for pointer types only">; def err_attributes_are_not_compatible : Error< "%0 and %1 attributes are not compatible">; def err_attribute_wrong_number_arguments : Error< "%0 attribute %plural{0:takes no arguments|1:takes one argument|" ":requires exactly %1 arguments}1">; def err_attribute_too_many_arguments : Error< - "attribute takes no more than %0 argument%s0">; -def err_suppress_autosynthesis : Error< - "objc_requires_property_definitions attribute may only be specified on a class" - "to a class declaration">; + "%0 attribute takes no more than %1 argument%s1">; def err_attribute_too_few_arguments : Error< - "attribute takes at least %0 argument%s0">; + "%0 attribute takes at least %1 argument%s1">; def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; def err_attribute_bad_neon_vector_size : Error< "Neon vector size must be 64 or 128 bits">; @@ -1809,14 +1900,11 @@ def err_attribute_unsupported : Error< def err_aligned_attribute_argument_not_int : Error< "'aligned' attribute requires integer constant">; def err_alignas_attribute_wrong_decl_type : Error< - "'%select{alignas|_Alignas}0' attribute cannot be applied to a %select{" - "function parameter|variable with 'register' storage class|" - "'catch' variable|bit-field}1">; + "%0 attribute cannot be applied to a %select{function parameter|" + "variable with 'register' storage class|'catch' variable|bit-field}1">; def err_alignas_missing_on_definition : Error< - "'%select{alignas|_Alignas}0' must be specified on definition if it is " - "specified on any declaration">; -def note_alignas_on_declaration : Note< - "declared with '%select{alignas|_Alignas}0' attribute here">; + "%0 must be specified on definition if it is specified on any declaration">; +def note_alignas_on_declaration : Note<"declared with %0 attribute here">; def err_alignas_mismatch : Error< "redeclaration has different alignment requirement (%1 vs %0)">; def err_alignas_underaligned : Error< @@ -1836,17 +1924,20 @@ def err_init_priority_object_attr : Error< def err_attribute_argument_vec_type_hint : Error< "invalid attribute argument %0 - expecting a vector or vectorizable scalar type">; def err_attribute_argument_out_of_bounds : Error< - "'%0' attribute parameter %1 is out of bounds">; + "%0 attribute parameter %1 is out of bounds">; def err_attribute_uuid_malformed_guid : Error< "uuid attribute contains a malformed GUID">; -def warn_nonnull_pointers_only : Warning< - "nonnull attribute only applies to pointer arguments">; -def err_attribute_pointers_only : Error< - "%0 attribute only applies to pointer arguments">; +def warn_attribute_pointers_only : Warning< + "%0 attribute only applies to pointer arguments">, + InGroup<IgnoredAttributes>; +def err_attribute_pointers_only : Error<warn_attribute_pointers_only.Text>; +def warn_attribute_return_pointers_only : Warning< + "%0 attribute only applies to return values that are pointers">, + InGroup<IgnoredAttributes>; def err_attribute_no_member_pointers : Error< "%0 attribute cannot be used with pointers to members">; def err_attribute_invalid_implicit_this_argument : Error< - "'%0' attribute is invalid for the implicit this argument">; + "%0 attribute is invalid for the implicit this argument">; def err_ownership_type : Error< "%0 attribute only applies to %select{pointer|integer}1 arguments">; def err_format_strftime_third_parameter : Error< @@ -1858,8 +1949,6 @@ def err_format_attribute_result_not : Error<"function does not return %0">; def err_format_attribute_implicit_this_format_string : Error< "format attribute cannot specify the implicit this argument as the format " "string">; -def err_common_not_supported_cplusplus : Error< - "common attribute is not supported in C++">; def err_init_method_bad_return_type : Error< "init methods must return an object pointer type, not %0">; def err_attribute_invalid_size : Error< @@ -1868,8 +1957,8 @@ def err_attribute_zero_size : Error<"zero vector size">; def err_attribute_size_too_large : Error<"vector size too large">; def err_typecheck_vector_not_convertable : Error< "can't convert between vector values of different size (%0 and %1)">; -def err_typecheck_ext_vector_not_typedef : Error< - "ext_vector_type only applies to types, not variables">; +def err_typecheck_vector_not_convertable_non_scalar : Error< + "can't convert between vector and non-scalar values (%0 and %1)">; def err_ext_vector_component_exceeds_length : Error< "vector component access exceeds type %0">; def err_ext_vector_component_name_illegal : Error< @@ -1923,8 +2012,8 @@ 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_missing_atsign_prefix : Warning< - "string literal must be prefixed by '@' ">, InGroup<ObjCLiteralMissingAtSign>; +def err_missing_atsign_prefix : Error< + "string literal must be prefixed by '@' ">; def warn_objc_string_literal_comparison : Warning< "direct comparison of a string literal has undefined behavior">, InGroup<ObjCStringComparison>; @@ -1934,6 +2023,11 @@ def warn_concatenated_nsarray_literal : Warning< InGroup<ObjCStringConcatenation>; def note_objc_literal_comparison_isequal : Note< "use 'isEqual:' instead">; +def err_attribute_argument_is_zero : Error< + "%0 attribute must be greater than 0">; +def err_property_function_in_objc_container : Error< + "use of Objective-C property in function nested in Objective-C " + "container not supported, move function outside its container">; let CategoryName = "Cocoa API Issue" in { def warn_objc_redundant_literal_use : Warning< @@ -1948,30 +2042,24 @@ def err_only_annotate_after_access_spec : Error< 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_anonymous_property: Error< "anonymous property is not supported">; -def err_property_is_variably_modified: Error< - "property '%0' has a variably modified type">; -def err_no_getter_for_property : Error< - "no getter defined for property '%0'">; -def err_no_setter_for_property : Error< - "no setter defined for property '%0'">; -def error_cannot_find_suitable_getter : Error< - "cannot find suitable getter for property '%0'">; -def error_cannot_find_suitable_setter : Error< - "cannot find suitable setter for property '%0'">; +def err_property_is_variably_modified : Error< + "property %0 has a variably modified type">; +def err_no_accessor_for_property : Error< + "no %select{getter|setter}0 defined for property %1">; +def error_cannot_find_suitable_accessor : Error< + "cannot find suitable %select{getter|setter}0 for property %1">; 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 err_attribute_aligned_too_great : Error< + "requested alignment must be %0 bytes or smaller">; def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< - "'%0' redeclared without %1 attribute: previous %1 ignored">; + "%q0 redeclared without %1 attribute: previous %1 ignored">; def warn_attribute_ignored : Warning<"%0 attribute ignored">, InGroup<IgnoredAttributes>; def warn_attribute_after_definition_ignored : Warning< @@ -2005,8 +2093,8 @@ def warn_gc_attribute_weak_on_local : Warning< "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>; + "'NSObject' attribute 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 when ARC " "is not enabled">, @@ -2017,19 +2105,54 @@ def err_attribute_weak_static : Error< "weak declaration cannot have internal linkage">; def err_attribute_selectany_non_extern_data : Error< "'selectany' can only be applied to data items with external linkage">; +def err_declspec_thread_on_thread_variable : Error< + "'__declspec(thread)' applied to variable that already has a " + "thread-local storage specifier">; +def err_attribute_dll_not_extern : Error< + "%q0 must have external linkage when declared %q1">; def warn_attribute_invalid_on_definition : Warning< "'%0' attribute cannot be specified on a definition">, InGroup<IgnoredAttributes>; +def err_attribute_dll_redeclaration : Error< + "redeclaration of %q0 cannot add %q1 attribute">; +def err_attribute_dllimport_function_definition : Error< + "dllimport cannot be applied to non-inline function definition">; +def err_attribute_dll_deleted : Error< + "attribute %q0 cannot be applied to a deleted function">; +def err_attribute_dllimport_data_definition : Error< + "definition of dllimport data">; +def err_attribute_dllimport_static_field_definition : Error< + "definition of dllimport static field not allowed">; +def warn_attribute_dllimport_static_field_definition : Warning< + "definition of dllimport static field">, + InGroup<DiagGroup<"dllimport-static-field-def">>; +def warn_invalid_initializer_from_system_header : Warning< + "invalid constructor form class in system header, should not be explicit">, + InGroup<DiagGroup<"invalid-initializer-from-system-header">>; +def note_used_in_initialization_here : Note<"used in initialization here">; +def err_attribute_dll_member_of_dll_class : Error< + "attribute %q0 cannot be applied to member of %q1 class">; +def warn_attribute_dll_instantiated_base_class : Warning< + "propagating dll attribute to %select{already instantiated|explicitly specialized}0 " + "base class template " + "%select{without dll attribute|with different dll attribute}1 is not supported">, + InGroup<DiagGroup<"unsupported-dll-base-class-template">>; def err_attribute_weakref_not_static : Error< "weakref declaration must have internal linkage">; def err_attribute_weakref_not_global_context : Error< - "weakref declaration of '%0' must be in a global context">; + "weakref declaration of %0 must be in a global context">; def err_attribute_weakref_without_alias : Error< - "weakref declaration of '%0' must also have an alias attribute">; + "weakref declaration of %0 must also have an alias attribute">; def err_alias_not_supported_on_darwin : Error < "only weak aliases are supported on darwin">; def err_alias_to_undefined : Error< "alias must point to a defined variable or function">; +def warn_alias_to_weak_alias : Warning< + "alias will always resolve to %0 even if weak definition of alias %1 is overridden">, + InGroup<IgnoredAttributes>; +def warn_alias_with_section : Warning< + "alias will not be in section '%0' but in the same section as the aliasee">, + InGroup<IgnoredAttributes>; def err_duplicate_mangled_name : Error< "definition with same mangled name as another definition">; def err_cyclic_alias : Error< @@ -2042,18 +2165,14 @@ def warn_attribute_wrong_decl_type : Warning< "variables, functions and labels|fields and global variables|structs|" "variables, functions and tag types|thread-local variables|" "variables and fields|variables, data members and tag types|" - "types and namespaces|Objective-C interfaces}1">, + "types and namespaces|Objective-C interfaces|methods and properties|" + "struct or union|struct, union or class|types|" + "Objective-C instance methods|init methods of interface or class extension declarations|" + "variables, functions and classes|Objective-C protocols|" + "functions and global variables|structs or typedefs|" + "interface or protocol declarations}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 classes|" - "functions, methods, and parameters|classes|variables|methods|" - "variables, functions and labels|fields and global variables|structs|" - "variables, functions and tag types|thread-local variables|" - "variables and fields|variables, data members and tag types|" - "types and namespaces|Objective-C interfaces|" - "methods and properties|struct or union|struct, union or class}1">; +def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>; def warn_type_attribute_wrong_type : Warning< "'%0' only applies to %select{function|pointer|" "Objective-C object or block pointer}1 types; type here is %2">, @@ -2093,8 +2212,6 @@ def warn_objc_precise_lifetime_meaningless : Error< "objc_precise_lifetime is not meaningful for " "%select{__unsafe_unretained|__autoreleasing}0 objects">; def err_invalid_pcs : Error<"invalid PCS type">; -def err_attribute_can_be_applied_only_to_value_decl : Error< - "%0 attribute can only be applied to value declarations">; def warn_attribute_not_on_decl : Warning< "%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>; def err_base_specifier_attribute : Error< @@ -2121,29 +2238,23 @@ def note_overridden_method : Note< "overridden method is here">; // Thread Safety Attributes +def warn_invalid_capability_name : Warning< + "invalid capability name '%0'; capability name must be 'mutex' or 'role'">, + InGroup<ThreadSafetyAttributes>, DefaultIgnore; 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'">, + "with 'capability' 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">, + "with 'capability(\"mutex\")' attribute">, InGroup<ThreadSafetyAttributes>, DefaultIgnore; def warn_thread_attribute_decl_not_pointer : Warning< - "'%0' only applies to pointer types; type here is %1">, + "%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|" @@ -2151,41 +2262,43 @@ def err_attribute_argument_out_of_range : Error< ":must be between 1 and %2}2">; // Thread Safety Analysis -def warn_unlock_but_no_lock : Warning< - "unlocking '%0' that was not locked">, +def warn_unlock_but_no_lock : Warning<"releasing %0 '%1' that was not held">, + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; +def warn_unlock_kind_mismatch : Warning< + "releasing %0 '%1' using %select{shared|exclusive}2 access, expected " + "%select{shared|exclusive}3 access">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; -def warn_double_lock : Warning< - "locking '%0' that is already locked">, +def warn_double_lock : Warning<"acquiring %0 '%1' that is already held">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_no_unlock : Warning< - "mutex '%0' is still locked at the end of function">, + "%0 '%1' is still held at the end of function">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_expecting_locked : Warning< - "expecting mutex '%0' to be locked at the end of function">, + "expecting %0 '%1' to be held 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">, + "%0 '%1' is not held on every path through here">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_expecting_lock_held_on_loop : Warning< - "expecting mutex '%0' to be locked at start of each loop">, + "expecting %0 '%1' to be held at start of each loop">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; -def note_locked_here : Note<"mutex acquired here">; +def note_locked_here : Note<"%0 acquired here">; def warn_lock_exclusive_and_shared : Warning< - "mutex '%0' is locked exclusively and shared in the same scope">, + "%0 '%1' is acquired exclusively and shared in the same scope">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def note_lock_exclusive_and_shared : Note< - "the other lock of mutex '%0' is here">; + "the other acquisition of %0 '%1' is here">; def warn_variable_requires_any_lock : Warning< - "%select{reading|writing}1 variable '%0' requires locking " + "%select{reading|writing}1 variable '%0' requires holding " "%select{any mutex|any mutex exclusively}1">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_var_deref_requires_any_lock : Warning< - "%select{reading|writing}1 the value pointed to by '%0' requires locking " + "%select{reading|writing}1 the value pointed to by '%0' requires holding " "%select{any mutex|any mutex exclusively}1">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_fun_excludes_mutex : Warning< - "cannot call function '%0' while mutex '%1' is locked">, + "cannot call function '%1' while %0 '%2' is held">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_cannot_resolve_lock : Warning< "cannot resolve lock expression">, @@ -2193,28 +2306,26 @@ def warn_cannot_resolve_lock : Warning< // Imprecise thread safety warnings def warn_variable_requires_lock : Warning< - "%select{reading|writing}2 variable '%0' requires locking " - "%select{'%1'|'%1' exclusively}2">, + "%select{reading|writing}3 variable '%1' requires holding %0 " + "%select{'%2'|'%2' exclusively}3">, 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">, + "%select{reading|writing}3 the value pointed to by '%1' requires " + "holding %0 %select{'%2'|'%2' exclusively}3">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_fun_requires_lock : Warning< - "calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">, + "calling function '%1' requires holding %0 %select{'%2'|'%2' exclusively}3">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; // Precise thread safety warnings -def warn_variable_requires_lock_precise : Warning< - "%select{reading|writing}2 variable '%0' requires locking " - "%select{'%1'|'%1' exclusively}2">, +def warn_variable_requires_lock_precise : + Warning<warn_variable_requires_lock.Text>, InGroup<ThreadSafetyPrecise>, DefaultIgnore; -def warn_var_deref_requires_lock_precise : Warning< - "%select{reading|writing}2 the value pointed to by '%0' requires locking " - "%select{'%1'|'%1' exclusively}2">, +def warn_var_deref_requires_lock_precise : + Warning<warn_var_deref_requires_lock.Text>, InGroup<ThreadSafetyPrecise>, DefaultIgnore; -def warn_fun_requires_lock_precise : Warning< - "calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">, +def warn_fun_requires_lock_precise : + Warning<warn_fun_requires_lock.Text>, InGroup<ThreadSafetyPrecise>, DefaultIgnore; def note_found_mutex_near_match : Note<"found near match '%0'">; @@ -2259,7 +2370,7 @@ def warn_impcast_float_precision : Warning< InGroup<Conversion>, DefaultIgnore; def warn_impcast_float_integer : Warning< "implicit conversion turns floating-point number into integer: %0 to %1">, - InGroup<Conversion>, DefaultIgnore; + InGroup<FloatConversion>, DefaultIgnore; def warn_impcast_integer_sign : Warning< "implicit conversion changes signedness: %0 to %1">, InGroup<SignConversion>, DefaultIgnore; @@ -2299,17 +2410,48 @@ def warn_impcast_null_pointer_to_integer : Warning< def warn_impcast_floating_point_to_bool : Warning< "implicit conversion turns floating-point number into bool: %0 to %1">, InGroup<ImplicitConversionFloatingPointToBool>; -def warn_impcast_function_to_bool : Warning< - "address of function %q0 will always evaluate to 'true'">, - InGroup<BoolConversion>; -def note_function_to_bool_silence : Note< + +def warn_impcast_pointer_to_bool : Warning< + "address of%select{| function| array}0 '%1' will always evaluate to " + "'true'">, + InGroup<PointerBoolConversion>; +def warn_this_bool_conversion : Warning< + "'this' pointer cannot be null in well-defined C++ code; pointer may be " + "assumed to always convert to true">, InGroup<UndefinedBoolConversion>; +def warn_address_of_reference_bool_conversion : Warning< + "reference cannot be bound to dereferenced null pointer in well-defined C++ " + "code; pointer may be assumed to always convert to true">, + InGroup<UndefinedBoolConversion>; + +def warn_null_pointer_compare : Warning< + "comparison of %select{address of|function|array}0 '%1' %select{not |}2" + "equal to a null pointer is always %select{true|false}2">, + InGroup<TautologicalPointerCompare>; +def warn_this_null_compare : Warning< + "'this' pointer cannot be null in well-defined C++ code; comparison may be " + "assumed to always evaluate to %select{true|false}0">, + InGroup<TautologicalUndefinedCompare>; +def warn_address_of_reference_null_compare : Warning< + "reference cannot be bound to dereferenced null pointer in well-defined C++ " + "code; comparison may be assumed to always evaluate to " + "%select{true|false}0">, + InGroup<TautologicalUndefinedCompare>; +def note_reference_is_return_value : Note<"%0 returns a reference">; + +def note_function_warning_silence : Note< "prefix with the address-of operator to silence this warning">; -def note_function_to_bool_call : Note< +def note_function_to_function_call : Note< "suffix with parentheses to turn this into a function call">; +def warn_impcast_objective_c_literal_to_bool : Warning< + "implicit boolean conversion of Objective-C object literal always " + "evaluates to true">, + InGroup<ObjCLiteralConversion>; def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, InGroup<CastAlign>, DefaultIgnore; +def warn_old_style_cast : Warning< + "use of old-style cast">, InGroup<OldStyleCast>, DefaultIgnore; // Separate between casts to void* and non-void* pointers. // Some APIs use (abuse) void* for something like a user context, @@ -2355,17 +2497,27 @@ def warn_attribute_protected_visibility : 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 note_attribute : Note<"attribute is here">; +def err_mismatched_ms_inheritance : Error< + "inheritance model does not match %select{definition|previous declaration}0">; +def warn_ignored_ms_inheritance : Warning< + "inheritance model ignored on %select{primary template|partial specialization}0">, + InGroup<IgnoredAttributes>; +def note_previous_ms_inheritance : Note< + "previous inheritance model specified here">; +def err_machine_mode : Error<"%select{unknown|unsupported}0 machine mode %1">; def err_mode_not_primitive : Error< "mode attribute only supported for integer and floating-point types">; def err_mode_wrong_type : Error< "type of machine mode does not match type of base type">; def err_attr_wrong_decl : Error< - "'%0' attribute invalid on this declaration, requires typedef or value">; + "%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">, InGroup<IgnoredAttributes>; +def warn_attribute_nonnull_parm_no_args : Warning< + "'nonnull' attribute when used on parameters takes no arguments">, + InGroup<IgnoredAttributes>; def warn_attribute_malloc_pointer_only : Warning< "'malloc' attribute only applies to functions returning a pointer type">, InGroup<IgnoredAttributes>; @@ -2394,15 +2546,14 @@ def err_attribute_regparm_wrong_platform : Error< "'regparm' is not valid on this platform">; def err_attribute_regparm_invalid_number : Error< "'regparm' parameter must be between 0 and %0 inclusive">; +def err_attribute_not_supported_in_lang : Error< + "%0 attribute is not supported in %select{C|C++|Objective-C}1">; // Clang-Specific Attributes def warn_attribute_iboutlet : Warning< "%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">, - InGroup<IgnoredAttributes>; def err_iboutletcollection_type : Error< "invalid type %0 as argument of iboutletcollection attribute">; def err_iboutletcollection_builtintype : Error< @@ -2414,8 +2565,6 @@ def warn_iboutletcollection_property_assign : Warning< "IBOutletCollection properties should be copy/strong and not assign">, InGroup<ObjCInvalidIBOutletProperty>; -def err_attribute_overloadable_not_function : Error< - "'overloadable' attribute can only be applied to a function">; def err_attribute_overloadable_missing : Error< "%select{overloaded function|redeclaration of}0 %1 must have the " "'overloadable' attribute">; @@ -2436,15 +2585,36 @@ def warn_objc_requires_super_protocol : Warning< InGroup<DiagGroup<"requires-super-attribute">>; def note_protocol_decl : Note< "protocol is declared here">; +def note_protocol_decl_undefined : Note< + "protocol %0 has no definition">; + +// objc_designated_initializer attribute diagnostics. +def warn_objc_designated_init_missing_super_call : Warning< + "designated initializer missing a 'super' call to a designated initializer of the super class">, + InGroup<ObjCDesignatedInit>; +def note_objc_designated_init_marked_here : Note< + "method marked as designated initializer of the class here">; +def warn_objc_designated_init_non_super_designated_init_call : Warning< + "designated initializer should only invoke a designated initializer on 'super'">, + InGroup<ObjCDesignatedInit>; +def warn_objc_designated_init_non_designated_init_call : Warning< + "designated initializer invoked a non-designated initializer">, + InGroup<ObjCDesignatedInit>; +def warn_objc_secondary_init_super_init_call : Warning< + "convenience initializer should not invoke an initializer on 'super'">, + InGroup<ObjCDesignatedInit>; +def warn_objc_secondary_init_missing_init_call : Warning< + "convenience initializer missing a 'self' call to another initializer">, + InGroup<ObjCDesignatedInit>; +def warn_objc_implementation_missing_designated_init_override : Warning< + "method override for the designated initializer of the superclass %objcinstance0 not found">, + InGroup<ObjCDesignatedInit>; -def err_ns_bridged_not_interface : Error< - "parameter of 'ns_bridged' attribute does not name an Objective-C class">; - // objc_bridge attribute diagnostics. -def err_objc_bridge_not_id : Error< - "parameter of 'objc_bridge' attribute must be a single name of an Objective-C class">; +def err_objc_attr_not_id : Error< + "parameter of %0 attribute must be a single name of an Objective-C %select{class|protocol}1">; def err_objc_cf_bridged_not_interface : Error< - "CF object of type %0 is bridged to '%1', which is not an Objective-C class">; + "CF object of type %0 is bridged to %1, which is not an Objective-C class">; def err_objc_ns_bridged_invalid_cfobject : Error< "ObjectiveC object of type %0 is bridged to %1, which is not valid CF object">; def warn_objc_invalid_bridge : Warning< @@ -2452,6 +2622,18 @@ def warn_objc_invalid_bridge : Warning< def warn_objc_invalid_bridge_to_cf : Warning< "%0 cannot bridge to %1">, InGroup<ObjCBridge>; +// objc_bridge_related attribute diagnostics. +def err_objc_bridged_related_invalid_class : Error< + "could not find Objective-C class %0 to convert %1 to %2">; +def err_objc_bridged_related_invalid_class_name : Error< + "%0 must be name of an Objective-C class to be able to convert %1 to %2">; +def err_objc_bridged_related_known_method : Error< + "%0 must be explicitly converted to %1; use %select{%objcclass2|%objcinstance2}3 " + "method for this conversion">; + +def err_objc_attr_protocol_requires_definition : Error< + "attribute %0 can only be applied to @protocol definitions, not forward declarations">; + // Function Parameter Semantic Analysis. def err_param_with_void_type : Error<"argument may not have 'void' type">; def err_void_only_param : Error< @@ -2462,14 +2644,12 @@ def err_ident_list_in_fn_declaration : Error< "a parameter list without types is only allowed in a function definition">; def ext_param_not_declared : Extension< "parameter %0 was not declared, defaulting to type 'int'">; -def err_param_typedef_of_void : Error< - "empty parameter list defined with a %select{typedef|type alias}0 of 'void' not allowed%select{ in C++|}0">; def err_param_default_argument : Error< "C does not support default arguments">; def err_param_default_argument_redefinition : Error< "redefinition of default argument">; -def warn_param_default_argument_redefinition : ExtWarn< - "redefinition of default argument">; +def ext_param_default_argument_redefinition : ExtWarn< + "redefinition of default argument">, InGroup<Microsoft>; def err_param_default_argument_missing : Error< "missing default argument on parameter">; def err_param_default_argument_missing_name : Error< @@ -2579,6 +2759,8 @@ def note_ovl_candidate_substitution_failure : Note< "candidate template ignored: substitution failure%0%1">; def note_ovl_candidate_disabled_by_enable_if : Note< "candidate template ignored: disabled by %0%1">; +def note_ovl_candidate_disabled_by_enable_if_attr : Note< + "candidate disabled: %0">; def note_ovl_candidate_failed_overload_resolution : Note< "candidate template ignored: couldn't resolve reference to overloaded " "function %0">; @@ -2941,11 +3123,14 @@ def err_template_arg_list_different_arity : Error< "%select{class template|function template|template template parameter" "|template}1 %2">; 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 ext_ms_template_type_arg_missing_typename : ExtWarn< + "template argument for template type parameter must be a type; " + "omitted 'typename' is a Microsoft extension">, + InGroup<Microsoft>; 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< @@ -3059,6 +3244,9 @@ def err_pointer_to_member_oper_value_classify: Error< def ext_ms_deref_template_argument: ExtWarn< "non-type template argument containing a dereference operation is a " "Microsoft extension">, InGroup<Microsoft>; +def ext_ms_delayed_template_argument: ExtWarn< + "using the undeclared type %0 as a default template argument is a " + "Microsoft extension">, InGroup<Microsoft>; // C++ template specialization def err_template_spec_unknown_kind : Error< @@ -3155,8 +3343,8 @@ def err_template_qualified_declarator_no_match : Error< "nested name specifier '%0' for declaration does not refer into a class, " "class template or class template partial specialization">; def err_specialize_member_of_template : Error< - "cannot specialize (with 'template<>') a member of an unspecialized " - "template">; + "cannot specialize %select{|(with 'template<>') }0a member of an " + "unspecialized template">; // C++ Class Template Partial Specialization def err_default_arg_in_partial_spec : Error< @@ -3164,6 +3352,8 @@ def err_default_arg_in_partial_spec : Error< def err_dependent_non_type_arg_in_partial_spec : Error< "non-type template argument depends on a template parameter of the " "partial specialization">; +def note_dependent_non_type_default_arg_in_partial_spec : Note< + "template parameter is used in default argument declared here">; def err_dependent_typed_non_type_arg_in_partial_spec : Error< "non-type template argument specializes a template parameter with " "dependent type %0">; @@ -3173,7 +3363,7 @@ def err_partial_spec_args_match_primary_template : Error< "primary template, remove the template argument list">; def warn_partial_specs_not_deducible : Warning< "%select{class|variable}0 template partial specialization contains " - "%select{a template parameter|template parameters}1 that can not be " + "%select{a template parameter|template parameters}1 that cannot be " "deduced; this partial specialization will never be used">; def note_partial_spec_unused_parameter : Note< "non-deducible template parameter %0">; @@ -3194,6 +3384,9 @@ def note_var_prev_partial_spec_here : Note< "previous declaration of variable template partial specialization is here">; def err_var_spec_no_template : Error< "no variable template matches%select{| partial}0 specialization">; +def err_var_spec_no_template_but_method : Error< + "no variable template matches specialization; " + "did you mean to use %0 as function template instead?">; // C++ Function template specializations def err_function_template_spec_no_match : Error< @@ -3221,6 +3414,10 @@ def err_template_instantiate_undefined : Error< "%select{implicit|explicit}0 instantiation of undefined template %1">; def err_implicit_instantiate_member_undefined : Error< "implicit instantiation of undefined member %0">; +def note_template_class_instantiation_was_here : Note< + "class template %0 was instantiated here">; +def note_template_class_explicit_specialization_was_here : Note< + "class template %0 was explicitly specialized here">; def note_template_class_instantiation_here : Note< "in instantiation of template class %0 requested here">; def note_template_member_class_here : Note< @@ -3273,6 +3470,9 @@ def err_nested_name_spec_non_tag : Error< // C++ Explicit Instantiation def err_explicit_instantiation_duplicate : Error< "duplicate explicit instantiation of %0">; +def ext_explicit_instantiation_duplicate : ExtWarn< + "duplicate explicit instantiation of %0 ignored as a Microsoft extension">, + InGroup<Microsoft>; def note_previous_explicit_instantiation : Note< "previous explicit instantiation is here">; def ext_explicit_instantiation_after_specialization : Extension< @@ -3368,7 +3568,7 @@ def note_typename_refers_here : Note< "referenced member %0 is declared here">; def err_typename_missing : Error< "missing 'typename' prior to dependent type name '%0%1'">; -def warn_typename_missing : ExtWarn< +def ext_typename_missing : ExtWarn< "missing 'typename' prior to dependent type name '%0%1'">, InGroup<DiagGroup<"typename-missing">>; def ext_typename_outside_of_template : ExtWarn< @@ -3383,11 +3583,11 @@ def note_using_value_decl_missing_typename : Note< "add 'typename' to treat this using declaration as a type">; def err_template_kw_refers_to_non_template : Error< - "%0 following the 'template' keyword does not refer to a template">; + "%0 following the 'template' keyword does not refer to a template">; def err_template_kw_refers_to_class_template : Error< - "'%0%1' instantiated to a class template, not a function template">; + "'%0%1' instantiated to a class template, not a function template">; def note_referenced_class_template : Error< - "class template declared here">; + "class template declared here">; def err_template_kw_missing : Error< "missing 'template' keyword prior to dependent template name '%0%1'">; def ext_template_outside_of_template : ExtWarn< @@ -3397,13 +3597,16 @@ def warn_cxx98_compat_template_outside_of_template : Warning< InGroup<CXX98Compat>, DefaultIgnore; def err_non_type_template_in_nested_name_specifier : Error< - "qualified name refers into a specialization of function template %0">; + "qualified name refers into a specialization of %select{function|variable}0 " + "template %1">; def err_template_id_not_a_type : Error< "template name refers to non-type template %0">; def note_template_declared_here : Note< "%select{function template|class template|variable template" "|type alias template|template template parameter}0 " "%1 declared here">; +def err_alias_template_expansion_into_fixed_list : Error< + "pack expansion used as argument for non-pack parameter of alias template">; def note_parameter_type : Note< "parameter of type %0 is declared here">; @@ -3479,9 +3682,13 @@ def err_unexpected_typedef : Error< def err_unexpected_namespace : Error< "unexpected namespace name %0: expected expression">; def err_undeclared_var_use : Error<"use of undeclared identifier %0">; -def warn_found_via_dependent_bases_lookup : ExtWarn<"use of identifier %0 " - "found via unqualified lookup into dependent bases of class templates is a " - "Microsoft extension">, InGroup<Microsoft>; +def ext_undeclared_unqual_id_with_dependent_base : ExtWarn< + "use of undeclared identifier %0; " + "unqualified lookup into dependent bases of class template %1 is a Microsoft extension">, + InGroup<Microsoft>; +def ext_found_via_dependent_bases_lookup : ExtWarn<"use of identifier %0 " + "found via unqualified lookup into dependent bases of class templates is a " + "Microsoft extension">, InGroup<Microsoft>; def note_dependent_var_use : Note<"must qualify identifier to find this " "declaration in dependent base class">; def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neither " @@ -3491,20 +3698,26 @@ def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to th def err_undeclared_use : Error<"use of undeclared %0">; def warn_deprecated : Warning<"%0 is deprecated">, InGroup<DeprecatedDeclarations>; +def warn_property_method_deprecated : + Warning<"property access is using %0 method which is deprecated">, + InGroup<DeprecatedDeclarations>; def warn_deprecated_message : Warning<"%0 is deprecated: %1">, InGroup<DeprecatedDeclarations>; def warn_deprecated_fwdclass_message : Warning< - "%0 maybe deprecated because receiver type is unknown">, + "%0 may be deprecated because the receiver type is unknown">, InGroup<DeprecatedDeclarations>; def warn_deprecated_def : Warning< "Implementing deprecated %select{method|class|category}0">, InGroup<DeprecatedImplementations>, DefaultIgnore; def err_unavailable : Error<"%0 is unavailable">; +def err_property_method_unavailable : + Error<"property access is using %0 method which is unavailable">; def err_unavailable_message : Error<"%0 is unavailable: %1">; def warn_unavailable_fwdclass_message : Warning< - "%0 maybe unavailable because receiver type is unknown">; -def note_unavailable_here : Note< - "%select{declaration|function}0 has been explicitly marked " + "%0 may be unavailable because the receiver type is unknown">, + InGroup<UnavailableDeclarations>; +def note_availability_specified_here : Note< + "%0 has been explicitly marked " "%select{unavailable|deleted|deprecated}1 here">; def note_implicitly_deleted : Note< "explicitly defaulted function was implicitly deleted here">; @@ -3528,6 +3741,8 @@ def note_declaration_not_a_prototype : Note< def warn_missing_variable_declarations : Warning< "no previous extern declaration for non-static variable %0">, InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore; +def err_static_data_member_reinitialization : + Error<"static data member %0 already has an initializer">; def err_redefinition : Error<"redefinition of %0">; def err_alias_after_tentative : Error<"alias definition of %0 after tentative definition">; @@ -3544,9 +3759,6 @@ def err_definition_of_explicitly_defaulted_member : Error< def err_redefinition_extern_inline : Error< "redefinition of a 'extern inline' function %0 is not supported in " "%select{C99 mode|C++}1">; -def warn_cxx98_compat_friend_redefinition : Warning< - "friend function %0 would be implicitly redefined in C++98">, - InGroup<CXX98Compat>, DefaultIgnore; def note_deleted_dtor_no_operator_delete : Note< "virtual destructor requires an unambiguous, accessible 'operator delete'">; @@ -3584,10 +3796,10 @@ def warn_undefined_inline : Warning<"inline function %q0 is not defined">, InGroup<DiagGroup<"undefined-inline">>; def note_used_here : Note<"used here">; -def warn_internal_in_extern_inline : ExtWarn< +def ext_internal_in_extern_inline : ExtWarn< "static %select{function|variable}0 %1 is used in an inline function with " "external linkage">, InGroup<StaticInInline>; -def ext_internal_in_extern_inline : Extension< +def ext_internal_in_extern_inline_quiet : Extension< "static %select{function|variable}0 %1 is used in an inline function with " "external linkage">, InGroup<StaticInInline>; def warn_static_local_in_extern_inline : Warning< @@ -3595,15 +3807,15 @@ def warn_static_local_in_extern_inline : Warning< "in different files">, InGroup<StaticLocalInInline>; 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< +def ext_redefinition_of_typedef : ExtWarn< "redefinition of typedef %0 is a C11 feature">, InGroup<DiagGroup<"typedef-redefinition"> >; def err_redefinition_variably_modified_typedef : Error< "redefinition of %select{typedef|type alias}0 for variably-modified type %1">; +def err_inline_decl_follows_def : Error< + "inline declaration of %0 follows non-inline definition">; def err_inline_declaration_block_scope : Error< "inline declaration of %0 not allowed in block scope">; def err_static_non_static : Error< @@ -3620,8 +3832,8 @@ def note_extern_c_global_conflict : Note< "declared %select{in global scope|with C language linkage}0 here">; def warn_weak_import : Warning < "an already-declared variable is made a weak_import declaration %0">; -def warn_static_non_static : ExtWarn< - "static declaration of %0 follows non-static declaration">; +def ext_static_non_static : Extension< + "redeclaring non-static %0 as static is a Microsoft extension">, InGroup<Microsoft>; def err_non_static_static : Error< "non-static declaration of %0 follows static declaration">; def err_extern_non_extern : Error< @@ -3689,17 +3901,18 @@ def warn_ivars_in_interface : Warning< def ext_enum_value_not_int : Extension< "ISO C restricts enumerator values to range of 'int' (%0 is too " "%select{small|large}1)">; -def warn_enum_too_large : Warning< - "enumeration values exceed range of largest integer">; -def warn_enumerator_too_large : Warning< - "enumerator value %0 is not representable in the largest integer type">; +def ext_enum_too_large : ExtWarn< + "enumeration values exceed range of largest integer">, InGroup<EnumTooLarge>; +def ext_enumerator_increment_too_large : ExtWarn< + "incremented enumerator value %0 is not representable in the " + "largest integer type">, InGroup<EnumTooLarge>; def warn_illegal_constant_array_size : Extension< "size of static array must be an integer constant expression">; def err_vm_decl_in_file_scope : Error< "variably modified type declaration not allowed at file scope">; def err_vm_decl_has_extern_linkage : Error< - "variably modified type declaration can not have 'extern' linkage">; + "variably modified type declaration cannot have 'extern' linkage">; def err_typecheck_field_variable_size : Error< "fields must have a constant size: 'variable length array in structure' " "extension will never be supported">; @@ -3732,6 +3945,9 @@ def warn_typecheck_negative_array_new_size : Warning<"array size is negative">, InGroup<BadArrayNewLength>; def warn_typecheck_function_qualifiers : Warning< "qualifier on function type %0 has unspecified behavior">; +def warn_typecheck_reference_qualifiers : Warning< + "'%0' qualifier on reference type %1 has no effect">, + InGroup<IgnoredQualifiers>; def err_typecheck_invalid_restrict_not_pointer : Error< "restrict requires a pointer or reference (%0 is invalid)">; def err_typecheck_invalid_restrict_not_pointer_noarg : Error< @@ -3760,22 +3976,22 @@ def err_variable_object_no_init : Error< "variable-sized object may not be initialized">; def err_excess_initializers : Error< "excess elements in %select{array|vector|scalar|union|struct}0 initializer">; -def warn_excess_initializers : ExtWarn< +def ext_excess_initializers : ExtWarn< "excess elements in %select{array|vector|scalar|union|struct}0 initializer">; def err_excess_initializers_in_char_array_initializer : Error< "excess elements in char array initializer">; -def warn_excess_initializers_in_char_array_initializer : ExtWarn< +def ext_excess_initializers_in_char_array_initializer : ExtWarn< "excess elements in char array initializer">; def err_initializer_string_for_char_array_too_long : Error< "initializer-string for char array is too long">; -def warn_initializer_string_for_char_array_too_long : ExtWarn< +def ext_initializer_string_for_char_array_too_long : ExtWarn< "initializer-string for char array is too long">; def warn_missing_field_initializers : Warning< - "missing field '%0' initializer">, + "missing field %0 initializer">, InGroup<MissingFieldInitializers>, DefaultIgnore; def warn_braces_around_scalar_init : Warning< "braces around scalar initializer">; -def warn_many_braces_around_scalar_init : ExtWarn< +def ext_many_braces_around_scalar_init : ExtWarn< "too many braces around scalar initializer">; def ext_complex_component_init : Extension< "complex initialization specifying real and imaginary components " @@ -3816,8 +4032,8 @@ def warn_init_list_constant_narrowing : Warning< "constant expression evaluates to %0 which cannot be narrowed to type %1 in " "C++11">, InGroup<CXX11Narrowing>, DefaultIgnore; -def note_init_list_narrowing_override : Note< - "override this message by inserting an explicit cast">; +def note_init_list_narrowing_silence : Note< + "insert an explicit cast to silence this issue">; def err_init_objc_class : Error< "cannot initialize Objective-C class type %0">; def err_implicit_empty_initializer : Error< @@ -3852,7 +4068,7 @@ def warn_unused_label : Warning<"unused label %0">, InGroup<UnusedLabel>, DefaultIgnore; def err_goto_into_protected_scope : Error<"goto into protected scope">; -def warn_goto_into_protected_scope : ExtWarn<"goto into protected scope">, +def ext_goto_into_protected_scope : ExtWarn<"goto into protected scope">, InGroup<Microsoft>; def warn_cxx98_compat_goto_into_protected_scope : Warning< "goto would jump into protected scope in C++98">, @@ -3913,6 +4129,9 @@ def note_exits_cleanup : Note< "jump exits scope of variable with __attribute__((cleanup))">; def note_exits_dtor : Note< "jump exits scope of variable with non-trivial destructor">; +def note_exits_temporary_dtor : Note< + "jump exits scope of lifetime-extended temporary with non-trivial " + "destructor">; def note_exits___block : Note< "jump exits scope of __block variable">; def note_exits_objc_try : Note< @@ -3954,8 +4173,8 @@ def err_flexible_array_virtual_base : Error< def err_flexible_array_empty_aggregate : Error< "flexible array member %0 not allowed in otherwise empty " "%select{struct|interface|union|class|enum}1">; -def err_flexible_array_has_nonpod_type : Error< - "flexible array member %0 of non-POD element type %1">; +def err_flexible_array_has_nontrivial_dtor : Error< + "flexible array member %0 of type %1 with non-trivial destruction">; def ext_flexible_array_in_struct : Extension< "%0 may not be nested in a struct due to flexible array member">, InGroup<FlexibleArrayExtensions>; @@ -4224,6 +4443,8 @@ def ext_sizeof_alignof_function_type : Extension< def ext_sizeof_alignof_void_type : Extension< "invalid application of '%select{sizeof|alignof|vec_step}0' to a void " "type">, InGroup<PointerArith>; +def err_opencl_sizeof_alignof_type : Error< + "invalid application of '%select{sizeof|alignof|vec_step}0' to a void type">; def err_sizeof_alignof_incomplete_type : Error< "invalid application of '%select{sizeof|alignof|vec_step}0' to an " "incomplete type %1">; @@ -4244,9 +4465,9 @@ def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">; def ext_offsetof_extended_field_designator : Extension< "using extended field designator is an extension">, InGroup<DiagGroup<"extended-offsetof">>; -def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">, +def ext_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">, InGroup<InvalidOffsetof>; -def warn_offsetof_non_standardlayout_type : ExtWarn< +def ext_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 err_offsetof_field_of_virtual_base : Error< @@ -4315,7 +4536,7 @@ def warn_addition_in_bitshift : Warning< "'%1' will be evaluated first">, InGroup<ShiftOpParentheses>; def warn_self_assignment : Warning< - "explicitly assigning a variable of type %0 to itself">, + "explicitly assigning value of variable of type %0 to itself">, InGroup<SelfAssignment>, DefaultIgnore; def warn_string_plus_int : Warning< @@ -4439,6 +4660,9 @@ def warn_member_extra_qualification : Warning< "extra qualification on member %0">, InGroup<Microsoft>; def err_member_extra_qualification : Error< "extra qualification on member %0">; +def warn_namespace_member_extra_qualification : Warning< + "extra qualification on member %0">, + InGroup<DiagGroup<"extra-qualification">>; def err_member_qualification : Error< "non-friend class member %0 cannot have a qualified name">; def note_member_def_close_match : Note<"member declaration nearly matches">; @@ -4505,13 +4729,12 @@ def ext_array_init_parens : ExtWarn< def warn_deprecated_string_literal_conversion : Warning< "conversion from string literal to %0 is deprecated">, InGroup<CXX11CompatDeprecatedWritableStr>; -def warn_deprecated_string_literal_conversion_c : Warning< - "dummy warning to enable -fconst-strings">, InGroup<DeprecatedWritableStr>, DefaultIgnore; +def ext_deprecated_string_literal_conversion : ExtWarn< + "ISO C++11 does not allow conversion from string literal to %0">, + InGroup<WritableStrings>, SFINAEFailure; def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; def err_typecheck_sclass_fscope : Error< "illegal storage class on file-scoped variable">; -def err_unsupported_global_register : Error< - "global register variables are not supported">; def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">, InGroup<MissingDeclarations>; def ext_standalone_specifier : ExtWarn<"'%0' is not permitted on a declaration " @@ -4547,6 +4770,9 @@ def err_typecheck_unary_expr : Error< "invalid argument type %0 to unary expression">; def err_typecheck_indirection_requires_pointer : Error< "indirection requires pointer operand (%0 invalid)">; +def ext_typecheck_indirection_through_void_pointer : Extension< + "ISO C++ does not allow indirection on operand of type %0">, + InGroup<DiagGroup<"void-ptr-dereference">>; def warn_indirection_through_null : Warning< "indirection of non-volatile null pointer will be deleted, not trap">, InGroup<NullDereference>; def note_indirection_through_null : Note< @@ -4600,8 +4826,9 @@ def warn_lunsigned_always_true_comparison : Warning< "comparison of unsigned%select{| enum}2 expression %0 is always %1">, InGroup<TautologicalCompare>; def warn_out_of_range_compare : Warning< - "comparison of constant %0 with expression of type %1 is always " - "%select{false|true}2">, InGroup<TautologicalOutOfRangeCompare>; + "comparison of %select{constant %0|true|false}1 with " + "%select{expression of type %2|boolean expression}3 is always " + "%select{false|true}4">, InGroup<TautologicalOutOfRangeCompare>; def warn_runsigned_always_true_comparison : Warning< "comparison of %0 unsigned%select{| enum}2 expression is always %1">, InGroup<TautologicalCompare>; @@ -4812,7 +5039,7 @@ def warn_register_objc_catch_parm : Warning< def err_qualified_objc_catch_parm : Error< "@catch parameter declarator cannot be qualified">; def warn_objc_pointer_cxx_catch_fragile : Warning< - "can not catch an exception thrown with @throw in C++ in the non-unified " + "cannot 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">; @@ -4925,6 +5152,8 @@ def err_need_header_before_typeid : Error< "you need to include <typeinfo> before using the 'typeid' operator">; def err_need_header_before_ms_uuidof : Error< "you need to include <guiddef.h> before using the '__uuidof' operator">; +def err_ms___leave_not_in___try : Error< + "'__leave' statement not in __try block">; def err_uuidof_without_guid : Error< "cannot call operator __uuidof on a type with no GUID">; def err_uuidof_with_multiple_guids : Error< @@ -5013,7 +5242,7 @@ def err_qualified_catch_declarator : Error< "exception declarator cannot be qualified">; def err_early_catch_all : Error<"catch-all handler must come last">; def err_bad_memptr_rhs : Error< - "right hand operand to %0 has non pointer-to-member type %1">; + "right hand operand to %0 has non-pointer-to-member type %1">; def err_bad_memptr_lhs : Error< "left hand operand to %0 must be a %select{|pointer to }1class " "compatible with the right hand operand, but is %2">; @@ -5139,6 +5368,9 @@ let CategoryName = "Lambda Issue" in { "initializer missing for lambda capture %0">; def err_init_capture_multiple_expressions : Error< "initializer for lambda capture %0 contains multiple expressions">; + def err_init_capture_paren_braces : Error< + "cannot deduce type for lambda capture %0 from " + "parenthesized initializer list">; def err_init_capture_deduction_failure : Error< "cannot deduce type for lambda capture %0 from initializer of type %2">; def err_init_capture_deduction_failure_from_init_list : Error< @@ -5199,9 +5431,8 @@ def err_typecheck_deleted_function : Error< "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|, " - "namespace, or scoped enumeration}1">; +def err_expected_class_or_namespace : Error<"%0 is not a class" + "%select{ or namespace|, namespace, or scoped enumeration}1">; def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here " "because namespace %1 does not enclose namespace %2">; def err_invalid_declarator_global_scope : Error< @@ -5280,6 +5511,8 @@ def err_typecheck_missing_return_type_incompatible : Error< "return type must match previous return type}0,1 when %select{block " "literal|lambda expression}2 has unspecified explicit return type">; +def not_incomplete_class_and_qualified_id : Note< + "conformance of forward class %0 to protocol %1 can not be confirmed">; def warn_incompatible_qualified_id : Warning< "%select{%diff{assigning to $ from incompatible type $|" "assigning to type from incompatible type}0,1" @@ -5496,8 +5729,6 @@ def err_call_incomplete_return : Error< "calling function with incomplete return type %0">; def err_call_function_incomplete_return : Error< "calling %0 with incomplete return type %1">; -def note_function_with_incomplete_return_type_declared_here : Note< - "%0 declared here">; def err_call_incomplete_argument : Error< "argument type %0 is incomplete">; def err_typecheck_call_too_few_args : Error< @@ -5553,10 +5784,6 @@ def err_arc_typecheck_convert_incompatible_pointer : Error< "incompatible pointer types passing retainable parameter of type %0" "to a CF function expecting %1 type">; -def note_callee_decl : Note< - "%0 declared here">; -def note_defined_here : Note<"%0 defined here">; - def err_builtin_fn_use : Error<"builtin functions must be directly called">; def warn_call_wrong_number_of_arguments : Warning< @@ -5590,7 +5817,10 @@ def err_atomic_op_needs_atomic_int_or_ptr : Error< def err_atomic_op_bitwise_needs_atomic_int : Error< "address argument to bitwise atomic operation must be a pointer to " "%select{|atomic }0integer (%1 invalid)">; - +def warn_atomic_op_has_invalid_memory_order : Warning< + "memory order argument to atomic operation is invalid">, + InGroup<DiagGroup<"atomic-memory-ordering">>; + def err_atomic_load_store_uses_lib : Error< "atomic %select{load|store}0 requires runtime support that is not " "available for this target">; @@ -5630,6 +5860,11 @@ def warn_cxx98_compat_pass_non_pod_arg_to_vararg : Warning< "passing object of trivial but non-POD type %0 through variadic" " %select{function|block|method|constructor}1 is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_pass_class_arg_to_vararg : Warning< + "passing object of class type %0 through variadic " + "%select{function|block|method|constructor}1" + "%select{|; did you mean to call '%3'?}2">, + InGroup<ClassVarargs>, DefaultIgnore; def err_cannot_pass_to_vararg : Error< "cannot pass %select{expression of type %1|initializer list}0 to variadic " "%select{function|block|method|constructor}2">; @@ -5664,6 +5899,10 @@ def err_cast_pointer_from_non_pointer_int : Error< def warn_cast_pointer_from_sel : Warning< "cast of type %0 to %1 is deprecated; use sel_getName instead">, InGroup<SelTypeCast>; +def warn_function_def_in_objc_container : Warning< + "function definition inside an Objective-C container is deprecated">, + InGroup<FunctionDefInObjCContainer>; + def warn_bad_function_cast : Warning< "cast from function call of type %0 to non-matching type %1">, InGroup<BadFunctionCast>, DefaultIgnore; @@ -5678,10 +5917,10 @@ def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn< "pointer type %2">; def err_cast_selector_expr : Error< "cannot type cast @selector expression">; -def warn_typecheck_cond_incompatible_pointers : ExtWarn< +def ext_typecheck_cond_incompatible_pointers : ExtWarn< "pointer type mismatch%diff{ ($ and $)|}0,1">, InGroup<DiagGroup<"pointer-type-mismatch">>; -def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn< +def ext_typecheck_cond_pointer_integer_mismatch : ExtWarn< "pointer/integer type mismatch in conditional expression" "%diff{ ($ and $)|}0,1">, InGroup<DiagGroup<"conditional-type-mismatch">>; @@ -5709,20 +5948,16 @@ def warn_unused_volatile : Warning< InGroup<DiagGroup<"unused-volatile-lvalue">>; def warn_unused_comparison : Warning< - "%select{equality|inequality}0 comparison result unused">, + "%select{%select{|in}1equality|relational}0 comparison result unused">, InGroup<UnusedComparison>; def note_inequality_comparison_to_or_assign : Note< "use '|=' to turn this inequality comparison into an or-assignment">; def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">; -def err_type_trait_arity : Error< - "type trait requires %0%select{| or more}1 argument%select{|s}2; have " - "%3 argument%s3">; def err_dimension_expr_not_constant_integer : Error< "dimension expression does not evaluate to a constant unsigned int">; -def err_expected_ident_or_lparen : Error<"expected identifier or '('">; def err_typecheck_cond_incompatible_operands_null : Error< "non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">; @@ -5755,6 +5990,7 @@ let CategoryName = "Inline Assembly Issue" in { "%diff{$ matching output with type $|}0,1">; def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">; def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; + def err_asm_bad_register_type : Error<"bad type for named register variable">; def err_asm_invalid_input_size : Error< "invalid input size for constraint '%0'">; def err_invalid_asm_cast_lvalue : Error< @@ -5782,6 +6018,12 @@ def err_invalid_conversion_between_vector_and_integer : Error< "invalid conversion between vector type %0 and integer type %1 " "of different size">; +def err_opencl_function_pointer_variable : Error< + "pointers to functions are not allowed">; + +def err_opencl_taking_function_address : Error< + "taking address of function is not allowed">; + def err_invalid_conversion_between_vector_and_scalar : Error< "invalid conversion between vector type %0 and scalar type %1">; @@ -5898,8 +6140,6 @@ def err_reference_to_local_var_in_enclosing_lambda : Error< def err_reference_to_local_var_in_enclosing_context : Error< "reference to local variable %0 declared in enclosing context">; -def note_local_variable_declared_here : Note< - "%0 declared here">; def err_static_data_member_not_allowed_in_local_class : Error< "static data member %0 not allowed in local class %1">; @@ -5974,6 +6214,9 @@ def err_operator_new_delete_too_few_parameters : Error< "%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">; +def warn_operator_new_returns_null : Warning< + "%0 should not return a null pointer unless it is declared 'throw()'" + "%select{| or 'noexcept'}1">, InGroup<OperatorNewReturnsNull>; def err_operator_new_dependent_param_type : Error< "%0 cannot take a dependent type as first parameter; " @@ -5990,6 +6233,8 @@ def err_operator_delete_param_type : Error< // C++ literal operators def err_literal_operator_outside_namespace : Error< "literal operator %0 must be in a namespace or global scope">; +def err_literal_operator_id_outside_namespace : Error< + "non-namespace scope '%0' cannot have a literal operator member">; def err_literal_operator_default_argument : Error< "literal operator cannot have a default argument">; // FIXME: This diagnostic sucks @@ -6120,12 +6365,13 @@ def warn_missing_format_string : Warning< def warn_scanf_nonzero_width : Warning< "zero field width in scanf format string is unused">, InGroup<Format>; -def warn_printf_conversion_argument_type_mismatch : Warning< - "format specifies type %0 but the argument has type %1">, +def warn_format_conversion_argument_type_mismatch : Warning< + "format specifies type %0 but the argument has " + "%select{type|underlying type}2 %1">, InGroup<Format>; def warn_format_argument_needs_cast : Warning< - "values of type '%0' should not be used as format arguments; add an explicit " - "cast to %1 instead">, + "%select{values of type|enum values with underlying type}2 '%0' should not " + "be used as format arguments; add an explicit cast to %1 instead">, InGroup<Format>; def warn_printf_positional_arg_exceeds_data_args : Warning < "data argument position '%0' exceeds the number of data arguments (%1)">, @@ -6150,6 +6396,8 @@ def warn_format_string_is_wide_literal : Warning< "format string should not be a wide string">, InGroup<Format>; def warn_printf_format_string_contains_null_char : Warning< "format string contains '\\0' within the string body">, InGroup<Format>; +def warn_printf_format_string_not_null_terminated : Warning< + "format string is not null-terminated">, InGroup<Format>; def warn_printf_asterisk_missing_arg : Warning< "'%select{*|.*}0' specified field %select{width|precision}0 is missing a matching 'int' argument">, InGroup<Format>; @@ -6165,12 +6413,12 @@ def warn_printf_nonsensical_flag: Warning< def warn_format_nonsensical_length: Warning< "length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">, InGroup<Format>; -def warn_format_non_standard_positional_arg: ExtWarn< +def warn_format_non_standard_positional_arg: Warning< "positional arguments are not supported by ISO C">, InGroup<FormatNonStandard>, DefaultIgnore; -def warn_format_non_standard: ExtWarn< +def warn_format_non_standard: Warning< "'%0' %select{length modifier|conversion specifier}1 is not supported by ISO C">, InGroup<FormatNonStandard>, DefaultIgnore; -def warn_format_non_standard_conversion_spec: ExtWarn< +def warn_format_non_standard_conversion_spec: Warning< "using length modifier '%0' with conversion specifier '%1' is not supported by ISO C">, InGroup<FormatNonStandard>, DefaultIgnore; def warn_printf_ignored_flag: Warning< @@ -6186,6 +6434,9 @@ 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>; +def warn_null_ret : Warning< + "null returned from %select{function|method}0 that requires a non-null return value">, + InGroup<NonNull>; // CHECK: returning address/reference of stack memory def warn_ret_stack_addr : Warning< @@ -6230,11 +6481,17 @@ def note_ref_subobject_of_member_declared_here : Note< def warn_comparison_always : Warning< "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">, InGroup<TautologicalCompare>; +def warn_comparison_bitwise_always : Warning< + "bitwise comparison always evaluates to %select{false|true}0">, + InGroup<TautologicalCompare>; +def warn_tautological_overlap_comparison : Warning< + "overlapping comparisons always evaluate to %select{false|true}0">, + InGroup<TautologicalOverlapCompare>, DefaultIgnore; def warn_stringcompare : Warning< "result of comparison against %select{a string literal|@encode}0 is " "unspecified (use strncmp instead)">, - InGroup<DiagGroup<"string-compare">>; + InGroup<StringCompare>; def warn_identity_field_assign : Warning< "assigning %select{field|instance variable}0 to itself">, @@ -6252,7 +6509,7 @@ def warn_type_tag_for_datatype_wrong_kind : Warning< "this type tag was not designed to be used with this function">, InGroup<TypeSafety>; def warn_type_safety_type_mismatch : Warning< - "argument type %0 doesn't match specified '%1' type tag " + "argument type %0 doesn't match specified %1 type tag " "%select{that requires %3|}2">, InGroup<TypeSafety>; def warn_type_safety_null_pointer_required : Warning< "specified %0 type tag requires a null pointer">, InGroup<TypeSafety>; @@ -6299,11 +6556,17 @@ def err_continue_not_in_loop : Error< "'continue' statement not in loop statement">; def err_break_not_in_loop_or_switch : Error< "'break' statement not in loop or switch statement">; +def warn_loop_ctrl_binds_to_inner : Warning< + "'%0' is bound to current loop, GCC binds it to the enclosing loop">, + InGroup<GccCompat>; +def warn_break_binds_to_switch : Warning< + "'break' is bound to loop, GCC binds it to switch">, + InGroup<GccCompat>; def err_default_not_in_switch : Error< "'default' statement not in switch statement">; def err_case_not_in_switch : Error<"'case' statement not in switch statement">; def warn_bool_switch_condition : Warning< - "switch condition has boolean value">; + "switch condition has boolean value">, InGroup<SwitchBool>; def warn_case_value_overflow : Warning< "overflow converting case value to switch condition type (%0 to %1)">, InGroup<Switch>; @@ -6434,6 +6697,8 @@ def ext_return_has_void_expr : Extension< def err_return_init_list : Error< "%select{void function|void method|constructor|destructor}1 %0 " "must not return a value">; +def err_ctor_dtor_returns_void : Error< + "%select{constructor|destructor}1 %0 must not return void expression">; def warn_noreturn_function_has_return_expr : Warning< "function %0 declared 'noreturn' should not return">, InGroup<InvalidNoreturn>; @@ -6484,9 +6749,20 @@ def err_invalid_neon_type_code : Error< "incompatible constant for this __builtin_neon function">; def err_argument_invalid_range : Error< "argument should be a value from %0 to %1">; +def warn_neon_vector_initializer_non_portable : Warning< + "vector initializers are not compatible with NEON intrinsics in big endian " + "mode">, InGroup<DiagGroup<"nonportable-vector-initialization">>; +def note_neon_vector_initializer_non_portable : Note< + "consider using vld1_%0%1() to initialize a vector from memory, or " + "vcreate_%0%1() to initialize from an integer constant">; +def note_neon_vector_initializer_non_portable_q : Note< + "consider using vld1q_%0%1() to initialize a vector from memory, or " + "vcombine_%0%1(vcreate_%0%1(), vcreate_%0%1()) to initialize from integer " + "constants">; def err_builtin_longjmp_invalid_val : Error< "argument to __builtin_longjmp must be a constant 1">; +def err_builtin_requires_language : Error<"'%0' is only available in %1">; def err_constant_integer_arg_type : Error< "argument to %0 must be a constant integer">; @@ -6572,9 +6848,6 @@ def error_private_ivar_access : Error<"instance variable %0 is private">, def error_protected_ivar_access : Error<"instance variable %0 is protected">, AccessControl; def warn_maynot_respond : Warning<"%0 may not respond to %1">; -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 " "%diff{$ does not match super class method parameter type $|" @@ -6587,6 +6860,8 @@ 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_typename : Error< + "unknown type name %0">; def err_unknown_type_or_class_name_suggest : Error< "unknown %select{type|class}1 name %0; did you mean %2?">; def err_unknown_typename_suggest : Error< @@ -6644,7 +6919,7 @@ def err_uncasted_send_to_unknown_any_method : Error< "no known method %select{%objcinstance1|%objcclass1}0; cast the " "message send to the method's return type">; def err_unsupported_unknown_any_decl : Error< - "%0 has unknown type, which is unsupported for this kind of declaration">; + "%0 has unknown type, which is not supported for this kind of declaration">; def err_unsupported_unknown_any_expr : Error< "unsupported expression with unknown type">; def err_unsupported_unknown_any_call : Error< @@ -6667,6 +6942,8 @@ def err_static_kernel : Error< "kernel functions cannot be declared static">; def err_opencl_ptrptr_kernel_param : Error< "kernel parameter cannot be declared as a pointer to a pointer">; +def err_opencl_private_ptr_kernel_param : Error< + "kernel parameter cannot be declared as a pointer to the __private address space">; def err_static_function_scope : Error< "variables in function scope cannot be declared static">; def err_opencl_bitfields : Error< @@ -6696,6 +6973,12 @@ def err_wrong_sampler_addressspace: Error< def err_opencl_global_invalid_addr_space : Error< "global variables must have a constant address space qualifier">; def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">; +def err_opencl_kernel_attr : + Error<"attribute %0 can only be applied to a kernel function">; +def err_opencl_return_value_with_address_space : Error< + "return value cannot be qualified with address space">; +def err_opencl_constant_no_init : Error< + "variable in constant address space must be initialized">; } // end of sema category let CategoryName = "OpenMP Issue" in { @@ -6719,24 +7002,147 @@ def err_omp_private_incomplete_type : Error< "a private variable with incomplete type %0">; def err_omp_firstprivate_incomplete_type : Error< "a firstprivate variable with incomplete type %0">; -def err_omp_unexpected_clause_value : Error < +def err_omp_lastprivate_incomplete_type : Error< + "a lastprivate variable with incomplete type %0">; +def err_omp_reduction_incomplete_type : Error< + "a reduction variable with incomplete type %0">; +def err_omp_unexpected_clause_value : Error< "expected %0 in OpenMP clause '%1'">; -def err_omp_expected_var_name : Error < +def err_omp_expected_var_name : Error< "expected variable name">; -def err_omp_required_method : Error < +def err_omp_required_method : Error< "%0 variable must have an accessible, unambiguous %select{default constructor|copy constructor|copy assignment operator|'%2'|destructor}1">; +def err_omp_task_predetermined_firstprivate_required_method : Error< + "predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous %select{copy constructor|destructor}0">; def err_omp_clause_ref_type_arg : Error< "arguments of OpenMP clause '%0' cannot be of reference type %1">; +def err_omp_task_predetermined_firstprivate_ref_type_arg : Error< + "predetermined as a firstprivate in a task construct variable cannot be of reference type %0">; def err_omp_threadprivate_incomplete_type : Error< "threadprivate variable with incomplete type %0">; -def err_omp_no_dsa_for_variable : Error < +def err_omp_no_dsa_for_variable : Error< "variable %0 must have explicitly specified data sharing attributes">; def err_omp_wrong_dsa : Error< "%0 variable cannot be %1">; -def note_omp_explicit_dsa : Note < +def note_omp_explicit_dsa : Note< "defined as %0">; -def note_omp_predetermined_dsa : Note < - "predetermined as %0">; +def note_omp_predetermined_dsa : Note< + "%select{static data member is predetermined as shared|" + "variable with static storage duration is predetermined as shared|" + "loop iteration variable is predetermined as private|" + "loop iteration variable is predetermined as linear|" + "loop iteration variable is predetermined as lastprivate|" + "constant variable is predetermined as shared|" + "global variable is predetermined as shared|" + "non-shared variable in a task construct is predetermined as firstprivate|" + "variable with automatic storage duration is predetermined as private}0" + "%select{|; perhaps you forget to enclose 'omp %2' directive into a parallel or another task region?}1">; +def note_omp_implicit_dsa : Note< + "implicitly determined as %0">; +def err_omp_loop_var_dsa : Error< + "loop iteration variable in the associated loop of 'omp %1' directive may not be %0, predetermined as %2">; +def err_omp_not_for : Error< + "%select{statement after '#pragma omp %1' must be a for loop|" + "expected %2 for loops after '#pragma omp %1'%select{|, but found only %4}3}0">; +def note_omp_collapse_expr : Note< + "as specified in 'collapse' clause">; +def err_omp_negative_expression_in_clause : Error< + "argument to '%0' clause must be a positive integer value">; +def err_omp_not_integral : Error< + "expression must have integral or unscoped enumeration " + "type, not %0">; +def err_omp_incomplete_type : Error< + "expression has incomplete class type %0">; +def err_omp_explicit_conversion : Error< + "expression requires explicit conversion from %0 to %1">; +def note_omp_conversion_here : Note< + "conversion to %select{integral|enumeration}0 type %1 declared here">; +def err_omp_ambiguous_conversion : Error< + "ambiguous conversion from type %0 to an integral or unscoped " + "enumeration type">; +def err_omp_required_access : Error< + "%0 variable must be %1">; +def err_omp_const_variable : Error< + "const-qualified variable cannot be %0">; +def err_omp_linear_incomplete_type : Error< + "a linear variable with incomplete type %0">; +def err_omp_linear_expected_int_or_ptr : Error< + "argument of a linear clause should be of integral or pointer " + "type, not %0">; +def warn_omp_linear_step_zero : Warning< + "zero linear step (%0 %select{|and other variables in clause }1should probably be const)">, + InGroup<OpenMPClauses>; +def err_omp_aligned_expected_array_or_ptr : Error< + "argument of aligned clause should be array" + "%select{ or pointer|, pointer, reference to array or reference to pointer}1" + ", not %0">; +def err_omp_aligned_twice : Error< + "a variable cannot appear in more than one aligned clause">; +def err_omp_local_var_in_threadprivate_init : Error< + "variable with local storage in initial value of threadprivate variable">; +def err_omp_loop_not_canonical_init : Error< + "initialization clause of OpenMP for loop must be of the form " + "'var = init' or 'T var = init'">; +def ext_omp_loop_not_canonical_init : ExtWarn< + "initialization clause of OpenMP for loop is not in canonical form " + "('var = init' or 'T var = init')">, InGroup<OpenMPLoopForm>; +def err_omp_loop_not_canonical_cond : Error< + "condition of OpenMP for loop must be a relational comparison " + "('<', '<=', '>', or '>=') of loop variable %0">; +def err_omp_loop_not_canonical_incr : Error< + "increment clause of OpenMP for loop must perform simple addition " + "or subtraction on loop variable %0">; +def err_omp_loop_variable_type : Error< + "variable must be of integer or %select{pointer|random access iterator}0 type">; +def err_omp_loop_incr_not_compatible : Error< + "increment expression must cause %0 to %select{decrease|increase}1 " + "on each iteration of OpenMP for loop">; +def note_omp_loop_cond_requres_compatible_incr : Note< + "loop step is expected to be %select{negative|positive}0 due to this condition">; +def err_omp_loop_cannot_use_stmt : Error< + "'%0' statement cannot be used in OpenMP for loop">; +def err_omp_simd_region_cannot_use_stmt : Error< + "'%0' statement cannot be used in OpenMP simd region">; +def err_omp_unknown_reduction_identifier : Error< + "incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'">; +def err_omp_reduction_type_array : Error< + "a reduction variable with array type %0">; +def err_omp_reduction_ref_type_arg : Error< + "argument of OpenMP clause 'reduction' must reference the same object in all threads">; +def err_omp_clause_not_arithmetic_type_arg : Error< + "arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of %select{scalar|arithmetic}0 type">; +def err_omp_clause_floating_type_arg : Error< + "arguments of OpenMP clause 'reduction' with bitwise operators cannot be of floating type">; +def err_omp_once_referenced : Error< + "variable can appear only once in OpenMP '%0' clause">; +def note_omp_referenced : Note< + "previously referenced here">; +def err_omp_reduction_in_task : Error< + "reduction variables may not be accessed in an explicit task">; +def err_omp_reduction_id_not_compatible : Error< + "variable of type %0 is not valid for specified reduction operation">; +def err_omp_prohibited_region : Error< + "region cannot be%select{| closely}0 nested inside '%1' region" + "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?}2">; +def err_omp_prohibited_region_simd : Error< + "OpenMP constructs may not be nested inside a simd region">; +def err_omp_prohibited_region_critical_same_name : Error< + "cannot nest 'critical' regions having the same name %0">; +def note_omp_previous_critical_region : Note< + "previous 'critical' region starts here">; +def err_omp_sections_not_compound_stmt : Error< + "the statement for '#pragma omp sections' must be a compound statement">; +def err_omp_parallel_sections_not_compound_stmt : Error< + "the statement for '#pragma omp parallel sections' must be a compound statement">; +def err_omp_orphaned_section_directive : Error< + "%select{orphaned 'omp section' directives are prohibited, it|'omp section' directive}0" + " must be closely nested to a sections region%select{|, not a %1 region}0">; +def err_omp_sections_substmt_not_section : Error< + "statement in 'omp sections' directive must be enclosed into a section region">; +def err_omp_parallel_sections_substmt_not_section : Error< + "statement in 'omp parallel sections' directive must be enclosed into a section region">; +def err_omp_parallel_reduction_in_task_firstprivate : Error< + "argument of a reduction clause of a %0 construct must not appear in a firstprivate clause on a task construct">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { @@ -6778,6 +7184,16 @@ def err_module_private_declaration : Error< "declaration of %0 must be imported from module '%1' before it is required">; def err_module_private_definition : Error< "definition of %0 must be imported from module '%1' before it is required">; +def err_module_import_in_extern_c : Error< + "import of C++ module '%0' appears within extern \"C\" language linkage " + "specification">; +def note_module_import_in_extern_c : Note< + "extern \"C\" language linkage specification begins here">; +def err_module_import_not_at_top_level : Error< + "import of module '%0' appears within %1">; +def note_module_import_not_at_top_level : Note<"%0 begins here">; +def err_module_self_import : Error< + "import of module '%0' appears within same top-level module '%1'">; } let CategoryName = "Documentation Issue" in { @@ -6785,4 +7201,15 @@ def warn_not_a_doxygen_trailing_member_comment : Warning< "not a Doxygen trailing comment">, InGroup<Documentation>, DefaultIgnore; } // end of documentation issue category +let CategoryName = "Instrumentation Issue" in { +def warn_profile_data_out_of_date : Warning< + "profile data may be out of date: of %0 function%s0, %1 %plural{1:has|:have}1" + " no data and %2 %plural{1:has|:have}2 mismatched data that will be ignored">, + InGroup<ProfileInstrOutOfDate>; +def warn_profile_data_unprofiled : Warning< + "no profile data available for file \"%0\"">, + InGroup<ProfileInstrUnprofiled>; + +} // end of instrumentation issue category + } // end of sema component. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td index 81509cc..be9d2bd 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// let Component = "Serialization" in { +let CategoryName = "AST Deserialization Issue" in { def err_fe_unable_to_read_pch_file : Error< "unable to read PCH file %0: '%1'">; @@ -22,6 +23,8 @@ def err_fe_pch_file_modified : Error< DefaultFatal; def err_fe_pch_file_overridden : Error< "file '%0' from the precompiled header has been overridden">; +def note_pch_required_by : Note<"'%0' required by '%1'">; +def note_pch_rebuild_required : Note<"please rebuild precompiled header '%0'">; def note_module_cache_path : Note< "after modifying system headers, please delete the module cache at '%0'">; @@ -36,16 +39,23 @@ def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in " "PCH file but is currently %select{disabled|enabled}2">; def err_pch_langopt_value_mismatch : Error< "%0 differs in PCH file vs. current file">; +def err_pch_diagopt_mismatch : Error<"%0 is currently enabled, but was not in " + "the PCH file">; -def warn_pch_version_too_old : Error< +def err_pch_version_too_old : Error< "PCH file uses an older PCH format that is no longer supported">; -def warn_pch_version_too_new : Error< +def err_pch_version_too_new : Error< "PCH file uses a newer PCH format that cannot be read">; -def warn_pch_different_branch : Error< +def err_pch_different_branch : Error< "PCH file built from a different branch (%0) than the compiler (%1)">; def err_pch_with_compiler_errors : Error< "PCH file contains compiler errors">; - + +def err_imported_module_not_found : Error< + "module '%0' imported by AST file '%1' not found">, DefaultFatal; +def err_imported_module_modmap_changed : Error< + "module '%0' imported by AST file '%1' found in a different module map file" + " (%2) than when the importing AST file was built (%3)">, DefaultFatal; def warn_module_conflict : Warning< "module '%0' conflicts with already-imported module '%1': %2">, InGroup<ModuleConflict>; @@ -75,5 +85,14 @@ def note_module_odr_violation_no_possible_decls : Note< "definition has no member %0">; def note_module_odr_violation_possible_decl : Note< "declaration of %0 does not match">; +def err_module_odr_violation_different_definitions : Error< + "%q0 has different definitions in different modules; " + "%select{definition in module '%2' is here|defined here}1">; +def note_module_odr_violation_different_definitions : Note< + "definition in module '%0' is here">; +def err_module_odr_violation_different_instantiations : Error< + "instantiation of %q0 is different in different modules">; + +} // let CategoryName +} // let Component -} diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h index 255eee3..0ad53c4 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h @@ -17,16 +17,17 @@ #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/VirtualFileSystem.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/FileSystem.h" +#include <memory> // FIXME: Enhance libsystem to support inode and other fields in stat. #include <sys/types.h> +#include <map> #ifdef _MSC_VER typedef unsigned short mode_t; @@ -48,17 +49,17 @@ class DirectoryEntry { const char *Name; // Name of the directory. friend class FileManager; public: - DirectoryEntry() : Name(0) {} + DirectoryEntry() : Name(nullptr) {} const char *getName() const { return Name; } }; /// \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 +/// If the 'File' member is valid, then this FileEntry has an open file /// descriptor for the file. class FileEntry { - const char *Name; // Name of the file. + std::string Name; // Name of the file. off_t Size; // File size in bytes. time_t ModTime; // Modification time of file. const DirectoryEntry *Dir; // Directory file lives in. @@ -66,33 +67,34 @@ class FileEntry { llvm::sys::fs::UniqueID UniqueID; bool IsNamedPipe; bool InPCH; + bool IsValid; // Is this \c FileEntry initialized and valid? - /// FD - The file descriptor for the file entry if it is opened and owned - /// by the FileEntry. If not, this is set to -1. - mutable int FD; + /// \brief The open file, if it is owned by the \p FileEntry. + mutable std::unique_ptr<vfs::File> File; friend class FileManager; -public: - FileEntry(llvm::sys::fs::UniqueID UniqueID, bool IsNamedPipe, bool InPCH) - : Name(0), UniqueID(UniqueID), IsNamedPipe(IsNamedPipe), InPCH(InPCH), - FD(-1) {} - // Add a default constructor for use with llvm::StringMap - FileEntry() - : Name(0), UniqueID(0, 0), IsNamedPipe(false), InPCH(false), FD(-1) {} - - FileEntry(const FileEntry &FE) { - memcpy(this, &FE, sizeof(FE)); - assert(FD == -1 && "Cannot copy a file-owning FileEntry"); + void closeFile() const { + File.reset(); // rely on destructor to close File } - void operator=(const FileEntry &FE) { - memcpy(this, &FE, sizeof(FE)); - assert(FD == -1 && "Cannot assign a file-owning FileEntry"); - } + void operator=(const FileEntry &) LLVM_DELETED_FUNCTION; - ~FileEntry(); +public: + FileEntry() + : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false) + {} + + // FIXME: this is here to allow putting FileEntry in std::map. Once we have + // emplace, we shouldn't need a copy constructor anymore. + /// Intentionally does not copy fields that are not set in an uninitialized + /// \c FileEntry. + FileEntry(const FileEntry &FE) : UniqueID(FE.UniqueID), + IsNamedPipe(FE.IsNamedPipe), InPCH(FE.InPCH), IsValid(FE.IsValid) { + assert(!isValid() && "Cannot copy an initialized FileEntry"); + } - const char *getName() const { return Name; } + const char *getName() const { return Name.c_str(); } + bool isValid() const { return IsValid; } off_t getSize() const { return Size; } unsigned getUID() const { return UID; } const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; } @@ -119,16 +121,14 @@ struct FileData; /// as a single file. /// class FileManager : public RefCountedBase<FileManager> { + IntrusiveRefCntPtr<vfs::FileSystem> FS; FileSystemOptions FileSystemOpts; - class UniqueDirContainer; - class UniqueFileContainer; - /// \brief Cache for existing real directories. - UniqueDirContainer &UniqueRealDirs; + std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs; /// \brief Cache for existing real files. - UniqueFileContainer &UniqueRealFiles; + std::map<llvm::sys::fs::UniqueID, FileEntry> UniqueRealFiles; /// \brief The virtual directories that we have allocated. /// @@ -169,17 +169,18 @@ class FileManager : public RefCountedBase<FileManager> { unsigned NumDirCacheMisses, NumFileCacheMisses; // Caching. - OwningPtr<FileSystemStatCache> StatCache; + std::unique_ptr<FileSystemStatCache> StatCache; bool getStatValue(const char *Path, FileData &Data, bool isFile, - int *FileDescriptor); + std::unique_ptr<vfs::File> *F); /// Add all ancestors of the given path (pointing to either a file /// or a directory) as virtual directories. void addAncestorsAsVirtualDirs(StringRef Path); public: - FileManager(const FileSystemOptions &FileSystemOpts); + FileManager(const FileSystemOptions &FileSystemOpts, + IntrusiveRefCntPtr<vfs::FileSystem> FS = nullptr); ~FileManager(); /// \brief Installs the provided FileSystemStatCache object within @@ -226,6 +227,10 @@ public: /// \brief Returns the current file system options const FileSystemOptions &getFileSystemOptions() { return FileSystemOpts; } + IntrusiveRefCntPtr<vfs::FileSystem> getVirtualFileSystem() const { + return FS; + } + /// \brief Retrieve a file entry for a "virtual" file that acts as /// if there were a file with the given name on disk. /// @@ -236,17 +241,20 @@ public: /// \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, - bool isVolatile = false); + std::string *ErrorStr = nullptr, + bool isVolatile = false, + bool ShouldCloseOpenFile = true); llvm::MemoryBuffer *getBufferForFile(StringRef Filename, - std::string *ErrorStr = 0); + std::string *ErrorStr = nullptr); /// \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. + /// + /// \returns false on success, true on error. bool getNoncachedStatValue(StringRef Path, - llvm::sys::fs::file_status &Result); + vfs::Status &Result); /// \brief Remove the real file \p Entry from the cache. void invalidateCache(const FileEntry *Entry); diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h index 23d8256..9be8b10 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h @@ -16,21 +16,30 @@ #define LLVM_CLANG_FILESYSTEMSTATCACHE_H #include "clang/Basic/LLVM.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/FileSystem.h" -#include <sys/stat.h> -#include <sys/types.h> +#include <memory> namespace clang { +namespace vfs { +class File; +class FileSystem; +} + +// FIXME: should probably replace this with vfs::Status struct FileData { + std::string Name; uint64_t Size; time_t ModTime; llvm::sys::fs::UniqueID UniqueID; bool IsDirectory; bool IsNamedPipe; bool InPCH; + bool IsVFSMapped; // FIXME: remove this when files support multiple names + FileData() + : Size(0), ModTime(0), IsDirectory(false), IsNamedPipe(false), + InPCH(false), IsVFSMapped(false) {} }; /// \brief Abstract interface for introducing a FileManager cache for 'stat' @@ -39,8 +48,8 @@ struct FileData { class FileSystemStatCache { virtual void anchor(); protected: - OwningPtr<FileSystemStatCache> NextStatCache; - + std::unique_ptr<FileSystemStatCache> NextStatCache; + public: virtual ~FileSystemStatCache() {} @@ -57,10 +66,11 @@ public: /// If isFile is true, then this lookup should only return success for files /// (not directories). If it is false this lookup should only return /// success for directories (not files). On a successful file lookup, the - /// implementation can optionally fill in FileDescriptor with a valid - /// descriptor and the client guarantees that it will close it. + /// implementation can optionally fill in \p F with a valid \p File object and + /// the client guarantees that it will close it. static bool get(const char *Path, FileData &Data, bool isFile, - int *FileDescriptor, FileSystemStatCache *Cache); + std::unique_ptr<vfs::File> *F, FileSystemStatCache *Cache, + vfs::FileSystem &FS); /// \brief Sets the next stat call cache in the chain of stat caches. /// Takes ownership of the given stat cache. @@ -74,21 +84,24 @@ public: /// \brief Retrieve the next stat call cache in the chain, transferring /// ownership of this cache (and, transitively, all of the remaining caches) /// to the caller. - FileSystemStatCache *takeNextStatCache() { return NextStatCache.take(); } - + FileSystemStatCache *takeNextStatCache() { return NextStatCache.release(); } + protected: + // FIXME: The pointer here is a non-owning/optional reference to the + // unique_ptr. Optional<unique_ptr<vfs::File>&> might be nicer, but + // Optional needs some work to support references so this isn't possible yet. virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile, - int *FileDescriptor) = 0; + std::unique_ptr<vfs::File> *F, + vfs::FileSystem &FS) = 0; LookupResult statChained(const char *Path, FileData &Data, bool isFile, - int *FileDescriptor) { + std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) { if (FileSystemStatCache *Next = getNextStatCache()) - return Next->getStat(Path, Data, isFile, FileDescriptor); + return Next->getStat(Path, Data, isFile, F, FS); // If we hit the end of the list of stat caches to try, just compute and // return it without a cache. - return get(Path, Data, isFile, FileDescriptor, 0) ? CacheMissing - : CacheExists; + return get(Path, Data, isFile, F, nullptr, FS) ? CacheMissing : CacheExists; } }; @@ -106,8 +119,9 @@ public: iterator begin() const { return StatCalls.begin(); } iterator end() const { return StatCalls.end(); } - virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile, - int *FileDescriptor); + LookupResult getStat(const char *Path, FileData &Data, bool isFile, + std::unique_ptr<vfs::File> *F, + vfs::FileSystem &FS) override; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h index 304ff36..0c278a1 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h @@ -17,12 +17,9 @@ #define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H #include "clang/Basic/LLVM.h" -#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/TokenKinds.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> #include <string> @@ -428,7 +425,7 @@ public: /// \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); + IdentifierInfoLookup* externalLookup = nullptr); /// \brief Set the external identifier lookup mechanism. void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) { @@ -625,7 +622,7 @@ class Selector { IdentifierInfo *getAsIdentifierInfo() const { if (getIdentifierInfoFlag() < MultiArg) return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags); - return 0; + return nullptr; } MultiKeywordSelector *getMultiKeywordSelector() const { return reinterpret_cast<MultiKeywordSelector *>(InfoPtr & ~ArgFlags); @@ -697,9 +694,11 @@ public: /// \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; + /// \brief Prints the full selector name (e.g. "foo:bar:"). + void print(llvm::raw_ostream &OS) const; + /// \brief Derive the conventional family of this method. ObjCMethodFamily getMethodFamily() const { return getMethodFamilyImpl(*this); @@ -812,6 +811,8 @@ struct DenseMapInfo<clang::Selector> { template <> struct isPodLike<clang::Selector> { static const bool value = true; }; +template <typename T> class PointerLikeTypeTraits; + template<> class PointerLikeTypeTraits<clang::Selector> { public: diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h index 306c75e..5a71fa8 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Forward declares and imports various common LLVM datatypes that +/// \brief Forward-declares and imports various common LLVM datatypes that /// clang wants to use unqualified. /// //===----------------------------------------------------------------------===// @@ -29,7 +29,7 @@ namespace llvm { class StringRef; class Twine; template<typename T> class ArrayRef; - template<typename T> class OwningPtr; + template<typename T> class MutableArrayRef; template<unsigned InternalLen> class SmallString; template<typename T, unsigned N> class SmallVector; template<typename T> class SmallVectorImpl; @@ -63,7 +63,7 @@ namespace clang { using llvm::StringRef; using llvm::Twine; using llvm::ArrayRef; - using llvm::OwningPtr; + using llvm::MutableArrayRef; using llvm::SmallString; using llvm::SmallVector; using llvm::SmallVectorImpl; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def index 2729f79..b701ff0 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def @@ -43,13 +43,14 @@ LANGOPT(C99 , 1, 0, "C99") LANGOPT(C11 , 1, 0, "C11") -LANGOPT(MicrosoftExt , 1, 0, "Microsoft extensions") -LANGOPT(MicrosoftMode , 1, 0, "Microsoft compatibility mode") +LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode") +LANGOPT(MicrosoftExt , 1, 0, "Microsoft C++ extensions") LANGOPT(AsmBlocks , 1, 0, "Microsoft inline asm blocks") LANGOPT(Borland , 1, 0, "Borland extensions") LANGOPT(CPlusPlus , 1, 0, "C++") -LANGOPT(CPlusPlus11 , 1, 0, "C++0x") +LANGOPT(CPlusPlus11 , 1, 0, "C++11") LANGOPT(CPlusPlus1y , 1, 0, "C++1y") +LANGOPT(CPlusPlus1z , 1, 0, "C++1z") LANGOPT(ObjC1 , 1, 0, "Objective-C 1") LANGOPT(ObjC2 , 1, 0, "Objective-C 2") BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0, @@ -61,6 +62,7 @@ BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1, LANGOPT(Trigraphs , 1, 0,"trigraphs") LANGOPT(LineComment , 1, 0, "'//' comments") LANGOPT(Bool , 1, 0, "bool, true, and false keywords") +LANGOPT(Half , 1, 0, "half keyword") LANGOPT(WChar , 1, CPlusPlus, "wchar_t keyword") BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers") BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode") @@ -82,6 +84,7 @@ LANGOPT(CXXExceptions , 1, 0, "C++ exceptions") LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation") LANGOPT(RTTI , 1, 1, "run-time type information") +LANGOPT(RTTIData , 1, 1, "emit run-time type information data") LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout") LANGOPT(Freestanding, 1, 0, "freestanding implementation") LANGOPT(FormatExtensions , 1, 0, "FreeBSD format extensions") @@ -96,6 +99,9 @@ LANGOPT(MathErrno , 1, 1, "errno support for math functions") BENIGN_LANGOPT(HeinousExtensions , 1, 0, "Extensions that we really don't like and may be ripped out at any time") LANGOPT(Modules , 1, 0, "modules extension to C") LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses") +LANGOPT(ModulesSearchAll , 1, 1, "search even non-imported modules to find unresolved references") +LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module uses and all headers to be in modules") +LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery") LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro") LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro") LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)") @@ -114,6 +120,7 @@ BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __w BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control") LANGOPT(CharIsSigned , 1, 1, "signed char") LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t") +ENUM_LANGOPT(MSPointerToMemberRepresentationMethod, PragmaMSPointersToMembersKind, 2, PPTMK_BestCase, "member-pointer representation method") LANGOPT(ShortEnums , 1, 0, "short enum types") @@ -174,12 +181,12 @@ BENIGN_LANGOPT(BracketDepth, 32, 256, "maximum bracket nesting depth") BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0, "if non-zero, warn about parameter or return Warn if parameter/return value is larger in bytes than this setting. 0 is no check.") -VALUE_LANGOPT(MSCVersion, 32, 0, - "version of Microsoft Visual C/C++") +VALUE_LANGOPT(MSCompatibilityVersion, 32, 0, "Microsoft Visual C/C++ Version") +VALUE_LANGOPT(VtorDispMode, 2, 1, "How many vtordisps to insert") LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling") -BENIGN_LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST") +LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST") #undef LANGOPT #undef VALUE_LANGOPT diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h index d4e8b4e..9bffc7c 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h @@ -19,7 +19,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Visibility.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include <string> namespace clang { @@ -53,12 +52,12 @@ protected: /// \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 { +class LangOptions : public LangOptionsBase { public: typedef clang::Visibility Visibility; enum GCMode { NonGC, GCOnly, HybridGC }; - enum StackProtectorMode { SSPOff, SSPOn, SSPReq }; + enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq }; enum SignedOverflowBehaviorTy { SOB_Undefined, // Default C standard behavior. @@ -66,6 +65,13 @@ public: SOB_Trapping // -ftrapv }; + enum PragmaMSPointersToMembersKind { + PPTMK_BestCase, + PPTMK_FullGeneralitySingleInheritance, + PPTMK_FullGeneralityMultipleInheritance, + PPTMK_FullGeneralityVirtualInheritance + }; + enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; public: diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h index 6996207..f3b4769 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h @@ -18,7 +18,7 @@ namespace clang { /// \brief Describes the different kinds of linkage /// (C++ [basic.link], C99 6.2.2) that an entity may have. -enum Linkage { +enum Linkage : unsigned char { /// \brief No linkage, which means that the entity is unique and /// can only be referred to from within its scope. NoLinkage = 0, @@ -59,11 +59,10 @@ enum LanguageLinkage { /// This is relevant to CodeGen and AST file reading. enum GVALinkage { GVA_Internal, - GVA_C99Inline, - GVA_CXXInline, + GVA_AvailableExternally, + GVA_DiscardableODR, GVA_StrongExternal, - GVA_TemplateInstantiation, - GVA_ExplicitTemplateInstantiation + GVA_StrongODR }; inline bool isExternallyVisible(Linkage L) { diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Module.h b/contrib/llvm/tools/clang/include/clang/Basic/Module.h index e8d774e..9b66840 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Module.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Module.h @@ -51,10 +51,21 @@ public: /// \brief The location of the module definition. SourceLocation DefinitionLoc; - + /// \brief The parent of this module. This will be NULL for the top-level /// module. Module *Parent; + + /// \brief The module map file that (along with the module name) uniquely + /// identifies this module. + /// + /// The particular module that \c Name refers to may depend on how the module + /// was found in header search. However, the combination of \c Name and + /// \c ModuleMap will be globally unique for top-level modules. In the case of + /// inferred modules, \c ModuleMap will contain the module map that allowed + /// the inference (e.g. contained 'Module *') rather than the virtual + /// inferred module map file. + const FileEntry *ModuleMap; /// \brief The umbrella header or directory. llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella; @@ -88,7 +99,19 @@ public: SmallVector<const FileEntry *, 2> ExcludedHeaders; /// \brief The headers that are private to this module. - llvm::SmallVector<const FileEntry *, 2> PrivateHeaders; + SmallVector<const FileEntry *, 2> PrivateHeaders; + + /// \brief Information about a header directive as found in the module map + /// file. + struct HeaderDirective { + SourceLocation FileNameLoc; + std::string FileName; + bool IsUmbrella; + }; + + /// \brief Headers that are mentioned in the module map file but could not be + /// found on the file system. + SmallVector<HeaderDirective, 1> MissingHeaders; /// \brief An individual requirement: a feature name and a flag indicating /// the required state of that feature. @@ -100,8 +123,13 @@ public: /// will be false to indicate that this (sub)module is not available. SmallVector<Requirement, 2> Requirements; - /// \brief Whether this module is available in the current - /// translation unit. + /// \brief Whether this module is missing a feature from \c Requirements. + unsigned IsMissingRequirement : 1; + + /// \brief Whether this module is available in the current translation unit. + /// + /// If the module is missing headers or does not meet all requirements then + /// this bit will be 0. unsigned IsAvailable : 1; /// \brief Whether this module was loaded from a module file. @@ -116,7 +144,15 @@ public: /// \brief Whether this is a "system" module (which assumes that all /// headers in it are system headers). unsigned IsSystem : 1; - + + /// \brief Whether this is an 'extern "C"' module (which implicitly puts all + /// headers in it within an 'extern "C"' block, and allows the module to be + /// imported within such a block). + unsigned IsExternC : 1; + + /// \brief Whether this is an inferred submodule (module * { ... }). + unsigned IsInferred : 1; + /// \brief Whether we should infer submodules for this module based on /// the headers. /// @@ -148,11 +184,14 @@ public: MacrosVisible, /// \brief All of the names in this module are visible. AllVisible - }; - - ///\ brief The visibility of names within this particular module. + }; + + /// \brief The visibility of names within this particular module. NameVisibilityKind NameVisibility; + /// \brief The location at which macros within this module became visible. + SourceLocation MacroVisibilityLoc; + /// \brief The location of the inferred submodule. SourceLocation InferredSubmoduleLoc; @@ -243,19 +282,11 @@ public: /// \brief The list of conflicts. std::vector<Conflict> Conflicts; - /// \brief Construct a top-level module. - explicit Module(StringRef Name, SourceLocation DefinitionLoc, - bool IsFramework) - : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0),Umbrella(),ASTFile(0), - IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), - IsExplicit(false), IsSystem(false), - InferSubmodules(false), InferExplicitSubmodules(false), - InferExportWildcard(false), ConfigMacrosExhaustive(false), - NameVisibility(Hidden) { } - /// \brief Construct a new module or submodule. - Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, - bool IsFramework, bool IsExplicit); + /// + /// For an explanation of \p ModuleMap, see Module::ModuleMap. + Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, + const FileEntry *ModuleMap, bool IsFramework, bool IsExplicit); ~Module(); @@ -276,14 +307,15 @@ public: /// this module. bool isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, - Requirement &Req) const; + Requirement &Req, + HeaderDirective &MissingHeader) const; /// \brief Determine whether this module is a submodule. - bool isSubModule() const { return Parent != 0; } + bool isSubModule() const { return Parent != nullptr; } /// \brief Determine whether this module is a submodule of the given other /// module. - bool isSubModuleOf(Module *Other) const; + bool isSubModuleOf(const Module *Other) const; /// \brief Determine whether this module is a part of a framework, /// either because it is a framework module or because it is a submodule @@ -330,7 +362,8 @@ public: /// \brief Set the serialized AST file for the top-level module of this module. void setASTFile(const FileEntry *File) { - assert((getASTFile() == 0 || getASTFile() == File) && "file path changed"); + assert((File == nullptr || getASTFile() == nullptr || + getASTFile() == File) && "file path changed"); getTopLevelModule()->ASTFile = File; } @@ -382,6 +415,9 @@ public: const LangOptions &LangOpts, const TargetInfo &Target); + /// \brief Mark this module and all of its submodules as unavailable. + void markUnavailable(bool MissingRequirement = false); + /// \brief Find the submodule with the given name. /// /// \returns The submodule if found, or NULL otherwise. @@ -389,6 +425,10 @@ public: /// \brief Determine whether the specified module would be visible to /// a lookup at the end of this module. + /// + /// FIXME: This may return incorrect results for (submodules of) the + /// module currently being built, if it's queried before we see all + /// of its imports. bool isModuleVisible(const Module *M) const { if (VisibleModulesCache.empty()) buildVisibleModulesCache(); diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h b/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h index 4c64497..fa375f4 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h @@ -99,6 +99,11 @@ public: Arch == llvm::Triple::x86_64) return false; } + else if ((getKind() == MacOSX) && isNonFragile() && + (getVersion() >= VersionTuple(10, 0)) && + (getVersion() < VersionTuple(10, 6))) + return Arch != llvm::Triple::x86_64; + // Except for deployment target of 10.5 or less, // Mac runtimes use legacy dispatch everywhere now. return true; } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h b/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h deleted file mode 100644 index ee30123..0000000 --- a/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h +++ /dev/null @@ -1,485 +0,0 @@ -//===--- OnDiskHashTable.h - On-Disk Hash Table Implementation --*- 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 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 - -#include "clang/Basic/LLVM.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdlib> - -namespace clang { - -namespace io { - -typedef uint32_t Offset; - -inline void Emit8(raw_ostream& Out, uint32_t V) { - Out << (unsigned char)(V); -} - -inline void Emit16(raw_ostream& Out, uint32_t V) { - Out << (unsigned char)(V); - Out << (unsigned char)(V >> 8); - assert((V >> 16) == 0); -} - -inline void Emit24(raw_ostream& Out, uint32_t V) { - Out << (unsigned char)(V); - Out << (unsigned char)(V >> 8); - Out << (unsigned char)(V >> 16); - assert((V >> 24) == 0); -} - -inline void Emit32(raw_ostream& Out, uint32_t V) { - Out << (unsigned char)(V); - Out << (unsigned char)(V >> 8); - Out << (unsigned char)(V >> 16); - Out << (unsigned char)(V >> 24); -} - -inline void Emit64(raw_ostream& Out, uint64_t V) { - Out << (unsigned char)(V); - Out << (unsigned char)(V >> 8); - Out << (unsigned char)(V >> 16); - Out << (unsigned char)(V >> 24); - Out << (unsigned char)(V >> 32); - Out << (unsigned char)(V >> 40); - Out << (unsigned char)(V >> 48); - Out << (unsigned char)(V >> 56); -} - -inline void Pad(raw_ostream& Out, unsigned A) { - Offset off = (Offset) Out.tell(); - for (uint32_t n = llvm::OffsetToAlignment(off, A); n; --n) - Emit8(Out, 0); -} - -inline uint16_t ReadUnalignedLE16(const unsigned char *&Data) { - uint16_t V = ((uint16_t)Data[0]) | - ((uint16_t)Data[1] << 8); - Data += 2; - return V; -} - -inline uint32_t ReadUnalignedLE32(const unsigned char *&Data) { - uint32_t V = ((uint32_t)Data[0]) | - ((uint32_t)Data[1] << 8) | - ((uint32_t)Data[2] << 16) | - ((uint32_t)Data[3] << 24); - Data += 4; - return V; -} - -inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) { - uint64_t V = ((uint64_t)Data[0]) | - ((uint64_t)Data[1] << 8) | - ((uint64_t)Data[2] << 16) | - ((uint64_t)Data[3] << 24) | - ((uint64_t)Data[4] << 32) | - ((uint64_t)Data[5] << 40) | - ((uint64_t)Data[6] << 48) | - ((uint64_t)Data[7] << 56); - Data += 8; - return V; -} - -inline uint32_t ReadLE32(const unsigned char *&Data) { - // Hosts that directly support little-endian 32-bit loads can just - // use them. Big-endian hosts need a bswap. - uint32_t V = *((const uint32_t*)Data); - if (llvm::sys::IsBigEndianHost) - V = llvm::ByteSwap_32(V); - Data += 4; - return V; -} - -} // end namespace io - -template<typename Info> -class OnDiskChainedHashTableGenerator { - unsigned NumBuckets; - unsigned NumEntries; - llvm::BumpPtrAllocator BA; - - class Item { - public: - typename Info::key_type key; - typename Info::data_type data; - Item *next; - const uint32_t hash; - - Item(typename Info::key_type_ref k, typename Info::data_type_ref d, - Info &InfoObj) - : key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {} - }; - - class Bucket { - public: - io::Offset off; - Item* head; - unsigned length; - - Bucket() {} - }; - - Bucket* Buckets; - -private: - void insert(Bucket* b, size_t size, Item* E) { - unsigned idx = E->hash & (size - 1); - Bucket& B = b[idx]; - E->next = B.head; - ++B.length; - B.head = E; - } - - void resize(size_t newsize) { - Bucket* newBuckets = (Bucket*) std::calloc(newsize, sizeof(Bucket)); - // Populate newBuckets with the old entries. - for (unsigned i = 0; i < NumBuckets; ++i) - for (Item* E = Buckets[i].head; E ; ) { - Item* N = E->next; - E->next = 0; - insert(newBuckets, newsize, E); - E = N; - } - - free(Buckets); - NumBuckets = newsize; - Buckets = newBuckets; - } - -public: - - void insert(typename Info::key_type_ref key, - typename Info::data_type_ref data) { - Info InfoObj; - insert(key, data, InfoObj); - } - - void insert(typename Info::key_type_ref key, - typename Info::data_type_ref data, Info &InfoObj) { - - ++NumEntries; - if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2); - insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data, - InfoObj)); - } - - io::Offset Emit(raw_ostream &out) { - Info InfoObj; - return Emit(out, InfoObj); - } - - io::Offset Emit(raw_ostream &out, Info &InfoObj) { - using namespace clang::io; - - // Emit the payload of the table. - for (unsigned i = 0; i < NumBuckets; ++i) { - Bucket& B = Buckets[i]; - if (!B.head) continue; - - // Store the offset for the data of this bucket. - B.off = out.tell(); - assert(B.off && "Cannot write a bucket at offset 0. Please add padding."); - - // Write out the number of items in the bucket. - Emit16(out, B.length); - assert(B.length != 0 && "Bucket has a head but zero length?"); - - // Write out the entries in the bucket. - for (Item *I = B.head; I ; I = I->next) { - Emit32(out, I->hash); - const std::pair<unsigned, unsigned>& Len = - InfoObj.EmitKeyDataLength(out, I->key, I->data); - InfoObj.EmitKey(out, I->key, Len.first); - InfoObj.EmitData(out, I->key, I->data, Len.second); - } - } - - // Emit the hashtable itself. - Pad(out, 4); - io::Offset TableOff = out.tell(); - Emit32(out, NumBuckets); - Emit32(out, NumEntries); - for (unsigned i = 0; i < NumBuckets; ++i) Emit32(out, Buckets[i].off); - - return TableOff; - } - - OnDiskChainedHashTableGenerator() { - NumEntries = 0; - NumBuckets = 64; - // Note that we do not need to run the constructors of the individual - // Bucket objects since 'calloc' returns bytes that are all 0. - Buckets = (Bucket*) std::calloc(NumBuckets, sizeof(Bucket)); - } - - ~OnDiskChainedHashTableGenerator() { - std::free(Buckets); - } -}; - -template<typename Info> -class OnDiskChainedHashTable { - const unsigned NumBuckets; - const unsigned NumEntries; - const unsigned char* const Buckets; - const unsigned char* const Base; - Info InfoObj; - -public: - typedef typename Info::internal_key_type internal_key_type; - typedef typename Info::external_key_type external_key_type; - typedef typename Info::data_type data_type; - - OnDiskChainedHashTable(unsigned numBuckets, unsigned numEntries, - const unsigned char* buckets, - const unsigned char* base, - const Info &InfoObj = Info()) - : NumBuckets(numBuckets), NumEntries(numEntries), - Buckets(buckets), Base(base), InfoObj(InfoObj) { - assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 && - "'buckets' must have a 4-byte alignment"); - } - - unsigned getNumBuckets() const { return NumBuckets; } - unsigned getNumEntries() const { return NumEntries; } - const unsigned char* getBase() const { return Base; } - const unsigned char* getBuckets() const { return Buckets; } - - bool isEmpty() const { return NumEntries == 0; } - - class iterator { - internal_key_type key; - const unsigned char* const data; - const unsigned len; - Info *InfoObj; - public: - iterator() : data(0), len(0) {} - iterator(const internal_key_type k, const unsigned char* d, unsigned l, - Info *InfoObj) - : key(k), data(d), len(l), InfoObj(InfoObj) {} - - data_type operator*() const { return InfoObj->ReadData(key, data, len); } - bool operator==(const iterator& X) const { return X.data == data; } - bool operator!=(const iterator& X) const { return X.data != data; } - }; - - iterator find(const external_key_type& eKey, Info *InfoPtr = 0) { - if (!InfoPtr) - InfoPtr = &InfoObj; - - using namespace io; - const internal_key_type& iKey = InfoObj.GetInternalKey(eKey); - unsigned key_hash = InfoObj.ComputeHash(iKey); - - // Each bucket is just a 32-bit offset into the hash table file. - unsigned idx = key_hash & (NumBuckets - 1); - const unsigned char* Bucket = Buckets + sizeof(uint32_t)*idx; - - unsigned offset = ReadLE32(Bucket); - if (offset == 0) return iterator(); // Empty bucket. - const unsigned char* Items = Base + offset; - - // 'Items' starts with a 16-bit unsigned integer representing the - // number of items in this bucket. - unsigned len = ReadUnalignedLE16(Items); - - for (unsigned i = 0; i < len; ++i) { - // Read the hash. - uint32_t item_hash = ReadUnalignedLE32(Items); - - // Determine the length of the key and the data. - const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Items); - unsigned item_len = L.first + L.second; - - // Compare the hashes. If they are not the same, skip the entry entirely. - if (item_hash != key_hash) { - Items += item_len; - continue; - } - - // Read the key. - const internal_key_type& X = - InfoPtr->ReadKey((const unsigned char* const) Items, L.first); - - // If the key doesn't match just skip reading the value. - if (!InfoPtr->EqualKey(X, iKey)) { - Items += item_len; - continue; - } - - // The key matches! - return iterator(X, Items + L.first, L.second, InfoPtr); - } - - return iterator(); - } - - iterator end() const { return iterator(); } - - /// \brief Iterates over all of the keys in the table. - class key_iterator { - const unsigned char* Ptr; - unsigned NumItemsInBucketLeft; - unsigned NumEntriesLeft; - Info *InfoObj; - public: - typedef external_key_type value_type; - - key_iterator(const unsigned char* const Ptr, unsigned NumEntries, - Info *InfoObj) - : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries), - InfoObj(InfoObj) { } - key_iterator() - : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { } - - friend bool operator==(const key_iterator &X, const key_iterator &Y) { - return X.NumEntriesLeft == Y.NumEntriesLeft; - } - friend bool operator!=(const key_iterator& X, const key_iterator &Y) { - return X.NumEntriesLeft != Y.NumEntriesLeft; - } - - key_iterator& operator++() { // Preincrement - if (!NumItemsInBucketLeft) { - // 'Items' starts with a 16-bit unsigned integer representing the - // number of items in this bucket. - NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr); - } - Ptr += 4; // Skip the hash. - // Determine the length of the key and the data. - const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr); - Ptr += L.first + L.second; - assert(NumItemsInBucketLeft); - --NumItemsInBucketLeft; - assert(NumEntriesLeft); - --NumEntriesLeft; - return *this; - } - key_iterator operator++(int) { // Postincrement - key_iterator tmp = *this; ++*this; return tmp; - } - - value_type operator*() const { - const unsigned char* LocalPtr = Ptr; - if (!NumItemsInBucketLeft) - LocalPtr += 2; // number of items in bucket - LocalPtr += 4; // Skip the hash. - - // Determine the length of the key and the data. - const std::pair<unsigned, unsigned>& L - = Info::ReadKeyDataLength(LocalPtr); - - // Read the key. - const internal_key_type& Key = InfoObj->ReadKey(LocalPtr, L.first); - return InfoObj->GetExternalKey(Key); - } - }; - - key_iterator key_begin() { - return key_iterator(Base + 4, getNumEntries(), &InfoObj); - } - key_iterator key_end() { return key_iterator(); } - - /// \brief Iterates over all the entries in the table, returning the data. - class data_iterator { - const unsigned char* Ptr; - unsigned NumItemsInBucketLeft; - unsigned NumEntriesLeft; - Info *InfoObj; - public: - typedef data_type value_type; - - data_iterator(const unsigned char* const Ptr, unsigned NumEntries, - Info *InfoObj) - : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries), - InfoObj(InfoObj) { } - data_iterator() - : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { } - - bool operator==(const data_iterator& X) const { - return X.NumEntriesLeft == NumEntriesLeft; - } - bool operator!=(const data_iterator& X) const { - return X.NumEntriesLeft != NumEntriesLeft; - } - - data_iterator& operator++() { // Preincrement - if (!NumItemsInBucketLeft) { - // 'Items' starts with a 16-bit unsigned integer representing the - // number of items in this bucket. - NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr); - } - Ptr += 4; // Skip the hash. - // Determine the length of the key and the data. - const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr); - Ptr += L.first + L.second; - assert(NumItemsInBucketLeft); - --NumItemsInBucketLeft; - assert(NumEntriesLeft); - --NumEntriesLeft; - return *this; - } - data_iterator operator++(int) { // Postincrement - data_iterator tmp = *this; ++*this; return tmp; - } - - value_type operator*() const { - const unsigned char* LocalPtr = Ptr; - if (!NumItemsInBucketLeft) - LocalPtr += 2; // number of items in bucket - LocalPtr += 4; // Skip the hash. - - // Determine the length of the key and the data. - const std::pair<unsigned, unsigned>& L =Info::ReadKeyDataLength(LocalPtr); - - // Read the key. - const internal_key_type& Key = - InfoObj->ReadKey(LocalPtr, L.first); - return InfoObj->ReadData(Key, LocalPtr + L.first, L.second); - } - }; - - data_iterator data_begin() { - return data_iterator(Base + 4, getNumEntries(), &InfoObj); - } - data_iterator data_end() { return data_iterator(); } - - Info &getInfoObj() { return InfoObj; } - - static OnDiskChainedHashTable* Create(const unsigned char* buckets, - const unsigned char* const base, - const Info &InfoObj = Info()) { - using namespace io; - assert(buckets > base); - assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 && - "buckets should be 4-byte aligned."); - - unsigned numBuckets = ReadLE32(buckets); - unsigned numEntries = ReadLE32(buckets); - return new OnDiskChainedHashTable<Info>(numBuckets, numEntries, buckets, - base, InfoObj); - } -}; - -} // end namespace clang - -#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenCL.h b/contrib/llvm/tools/clang/include/clang/Basic/OpenCL.h deleted file mode 100644 index 3b3f259..0000000 --- a/contrib/llvm/tools/clang/include/clang/Basic/OpenCL.h +++ /dev/null @@ -1,29 +0,0 @@ -//===--- OpenCL.h - OpenCL enums --------------------------------*- 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 some OpenCL-specific enums. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_BASIC_OPENCL_H -#define LLVM_CLANG_BASIC_OPENCL_H - -namespace clang { - -/// \brief Names for the OpenCL image access qualifiers (OpenCL 1.1 6.6). -enum OpenCLImageAccess { - CLIA_read_only = 1, - CLIA_write_only = 2, - CLIA_read_write = 3 -}; - -} - -#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def index 6d1a7b2..6cfa5ea 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def @@ -15,38 +15,196 @@ #ifndef OPENMP_DIRECTIVE # define OPENMP_DIRECTIVE(Name) #endif +#ifndef OPENMP_DIRECTIVE_EXT +#define OPENMP_DIRECTIVE_EXT(Name, Str) +#endif #ifndef OPENMP_CLAUSE # define OPENMP_CLAUSE(Name, Class) #endif #ifndef OPENMP_PARALLEL_CLAUSE # define OPENMP_PARALLEL_CLAUSE(Name) #endif +#ifndef OPENMP_SIMD_CLAUSE +# define OPENMP_SIMD_CLAUSE(Name) +#endif +#ifndef OPENMP_FOR_CLAUSE +# define OPENMP_FOR_CLAUSE(Name) +#endif +#ifndef OPENMP_SECTIONS_CLAUSE +# define OPENMP_SECTIONS_CLAUSE(Name) +#endif +#ifndef OPENMP_SINGLE_CLAUSE +# define OPENMP_SINGLE_CLAUSE(Name) +#endif +#ifndef OPENMP_PARALLEL_FOR_CLAUSE +# define OPENMP_PARALLEL_FOR_CLAUSE(Name) +#endif +#ifndef OPENMP_PARALLEL_SECTIONS_CLAUSE +# define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name) +#endif +#ifndef OPENMP_TASK_CLAUSE +# define OPENMP_TASK_CLAUSE(Name) +#endif #ifndef OPENMP_DEFAULT_KIND # define OPENMP_DEFAULT_KIND(Name) #endif +#ifndef OPENMP_PROC_BIND_KIND +# define OPENMP_PROC_BIND_KIND(Name) +#endif +#ifndef OPENMP_SCHEDULE_KIND +#define OPENMP_SCHEDULE_KIND(Name) +#endif // OpenMP directives. OPENMP_DIRECTIVE(threadprivate) OPENMP_DIRECTIVE(parallel) OPENMP_DIRECTIVE(task) +OPENMP_DIRECTIVE(simd) +OPENMP_DIRECTIVE(for) +OPENMP_DIRECTIVE(sections) +OPENMP_DIRECTIVE(section) +OPENMP_DIRECTIVE(single) +OPENMP_DIRECTIVE(master) +OPENMP_DIRECTIVE(critical) +OPENMP_DIRECTIVE(taskyield) +OPENMP_DIRECTIVE(barrier) +OPENMP_DIRECTIVE(taskwait) +OPENMP_DIRECTIVE(flush) +OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for") +OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections") // OpenMP clauses. +OPENMP_CLAUSE(if, OMPIfClause) +OPENMP_CLAUSE(final, OMPFinalClause) +OPENMP_CLAUSE(num_threads, OMPNumThreadsClause) +OPENMP_CLAUSE(safelen, OMPSafelenClause) +OPENMP_CLAUSE(collapse, OMPCollapseClause) OPENMP_CLAUSE(default, OMPDefaultClause) OPENMP_CLAUSE(private, OMPPrivateClause) OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause) +OPENMP_CLAUSE(lastprivate, OMPLastprivateClause) OPENMP_CLAUSE(shared, OMPSharedClause) +OPENMP_CLAUSE(reduction, OMPReductionClause) +OPENMP_CLAUSE(linear, OMPLinearClause) +OPENMP_CLAUSE(aligned, OMPAlignedClause) +OPENMP_CLAUSE(copyin, OMPCopyinClause) +OPENMP_CLAUSE(copyprivate, OMPCopyprivateClause) +OPENMP_CLAUSE(proc_bind, OMPProcBindClause) +OPENMP_CLAUSE(schedule, OMPScheduleClause) +OPENMP_CLAUSE(ordered, OMPOrderedClause) +OPENMP_CLAUSE(nowait, OMPNowaitClause) +OPENMP_CLAUSE(untied, OMPUntiedClause) +OPENMP_CLAUSE(mergeable, OMPMergeableClause) +OPENMP_CLAUSE(flush, OMPFlushClause) -// Clauses allowed for OpenMP directives. +// Clauses allowed for OpenMP directive 'parallel'. +OPENMP_PARALLEL_CLAUSE(if) +OPENMP_PARALLEL_CLAUSE(num_threads) OPENMP_PARALLEL_CLAUSE(default) +OPENMP_PARALLEL_CLAUSE(proc_bind) OPENMP_PARALLEL_CLAUSE(private) OPENMP_PARALLEL_CLAUSE(firstprivate) OPENMP_PARALLEL_CLAUSE(shared) +OPENMP_PARALLEL_CLAUSE(reduction) +OPENMP_PARALLEL_CLAUSE(copyin) + +// Clauses allowed for directive 'omp simd'. +OPENMP_SIMD_CLAUSE(private) +OPENMP_SIMD_CLAUSE(lastprivate) +OPENMP_SIMD_CLAUSE(linear) +OPENMP_SIMD_CLAUSE(aligned) +OPENMP_SIMD_CLAUSE(safelen) +OPENMP_SIMD_CLAUSE(collapse) +OPENMP_SIMD_CLAUSE(reduction) + +// Clauses allowed for directive 'omp for'. +OPENMP_FOR_CLAUSE(private) +OPENMP_FOR_CLAUSE(lastprivate) +OPENMP_FOR_CLAUSE(firstprivate) +OPENMP_FOR_CLAUSE(reduction) +OPENMP_FOR_CLAUSE(collapse) +OPENMP_FOR_CLAUSE(schedule) +OPENMP_FOR_CLAUSE(ordered) +OPENMP_FOR_CLAUSE(nowait) + +// Clauses allowed for OpenMP directive 'omp sections'. +OPENMP_SECTIONS_CLAUSE(private) +OPENMP_SECTIONS_CLAUSE(lastprivate) +OPENMP_SECTIONS_CLAUSE(firstprivate) +OPENMP_SECTIONS_CLAUSE(reduction) +OPENMP_SECTIONS_CLAUSE(nowait) + +// Clauses allowed for directive 'omp single'. +OPENMP_SINGLE_CLAUSE(private) +OPENMP_SINGLE_CLAUSE(firstprivate) +OPENMP_SINGLE_CLAUSE(copyprivate) +OPENMP_SINGLE_CLAUSE(nowait) // Static attributes for 'default' clause. OPENMP_DEFAULT_KIND(none) OPENMP_DEFAULT_KIND(shared) +// Static attributes for 'proc_bind' clause. +OPENMP_PROC_BIND_KIND(master) +OPENMP_PROC_BIND_KIND(close) +OPENMP_PROC_BIND_KIND(spread) + +// Static attributes for 'schedule' clause. +OPENMP_SCHEDULE_KIND(static) +OPENMP_SCHEDULE_KIND(dynamic) +OPENMP_SCHEDULE_KIND(guided) +OPENMP_SCHEDULE_KIND(auto) +OPENMP_SCHEDULE_KIND(runtime) + +// Clauses allowed for OpenMP directive 'parallel for'. +OPENMP_PARALLEL_FOR_CLAUSE(if) +OPENMP_PARALLEL_FOR_CLAUSE(num_threads) +OPENMP_PARALLEL_FOR_CLAUSE(default) +OPENMP_PARALLEL_FOR_CLAUSE(proc_bind) +OPENMP_PARALLEL_FOR_CLAUSE(private) +OPENMP_PARALLEL_FOR_CLAUSE(firstprivate) +OPENMP_PARALLEL_FOR_CLAUSE(shared) +OPENMP_PARALLEL_FOR_CLAUSE(reduction) +OPENMP_PARALLEL_FOR_CLAUSE(copyin) +OPENMP_PARALLEL_FOR_CLAUSE(lastprivate) +OPENMP_PARALLEL_FOR_CLAUSE(collapse) +OPENMP_PARALLEL_FOR_CLAUSE(schedule) +OPENMP_PARALLEL_FOR_CLAUSE(ordered) + +// Clauses allowed for OpenMP directive 'parallel sections'. +OPENMP_PARALLEL_SECTIONS_CLAUSE(if) +OPENMP_PARALLEL_SECTIONS_CLAUSE(num_threads) +OPENMP_PARALLEL_SECTIONS_CLAUSE(default) +OPENMP_PARALLEL_SECTIONS_CLAUSE(proc_bind) +OPENMP_PARALLEL_SECTIONS_CLAUSE(private) +OPENMP_PARALLEL_SECTIONS_CLAUSE(firstprivate) +OPENMP_PARALLEL_SECTIONS_CLAUSE(shared) +OPENMP_PARALLEL_SECTIONS_CLAUSE(reduction) +OPENMP_PARALLEL_SECTIONS_CLAUSE(copyin) +OPENMP_PARALLEL_SECTIONS_CLAUSE(lastprivate) + +// Clauses allowed for OpenMP directive 'task'. +OPENMP_TASK_CLAUSE(if) +OPENMP_TASK_CLAUSE(final) +OPENMP_TASK_CLAUSE(default) +OPENMP_TASK_CLAUSE(private) +OPENMP_TASK_CLAUSE(firstprivate) +OPENMP_TASK_CLAUSE(shared) +OPENMP_TASK_CLAUSE(untied) +OPENMP_TASK_CLAUSE(mergeable) + +#undef OPENMP_SCHEDULE_KIND +#undef OPENMP_PROC_BIND_KIND #undef OPENMP_DEFAULT_KIND #undef OPENMP_DIRECTIVE +#undef OPENMP_DIRECTIVE_EXT #undef OPENMP_CLAUSE +#undef OPENMP_SINGLE_CLAUSE +#undef OPENMP_SECTIONS_CLAUSE #undef OPENMP_PARALLEL_CLAUSE +#undef OPENMP_PARALLEL_FOR_CLAUSE +#undef OPENMP_PARALLEL_SECTIONS_CLAUSE +#undef OPENMP_TASK_CLAUSE +#undef OPENMP_SIMD_CLAUSE +#undef OPENMP_FOR_CLAUSE + diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h index 5b45731..526cbb2 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h @@ -21,30 +21,45 @@ namespace clang { /// \brief OpenMP directives. enum OpenMPDirectiveKind { - OMPD_unknown = 0, #define OPENMP_DIRECTIVE(Name) \ OMPD_##Name, +#define OPENMP_DIRECTIVE_EXT(Name, Str) \ + OMPD_##Name, #include "clang/Basic/OpenMPKinds.def" - NUM_OPENMP_DIRECTIVES + OMPD_unknown }; /// \brief OpenMP clauses. enum OpenMPClauseKind { - OMPC_unknown = 0, #define OPENMP_CLAUSE(Name, Class) \ OMPC_##Name, #include "clang/Basic/OpenMPKinds.def" OMPC_threadprivate, - NUM_OPENMP_CLAUSES + OMPC_unknown }; /// \brief OpenMP attributes for 'default' clause. enum OpenMPDefaultClauseKind { - OMPC_DEFAULT_unknown = 0, #define OPENMP_DEFAULT_KIND(Name) \ OMPC_DEFAULT_##Name, #include "clang/Basic/OpenMPKinds.def" - NUM_OPENMP_DEFAULT_KINDS + OMPC_DEFAULT_unknown +}; + +/// \brief OpenMP attributes for 'proc_bind' clause. +enum OpenMPProcBindClauseKind { +#define OPENMP_PROC_BIND_KIND(Name) \ + OMPC_PROC_BIND_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_PROC_BIND_unknown +}; + +/// \brief OpenMP attributes for 'schedule' clause. +enum OpenMPScheduleClauseKind { +#define OPENMP_SCHEDULE_KIND(Name) \ + OMPC_SCHEDULE_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_SCHEDULE_unknown }; OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str); @@ -59,6 +74,43 @@ const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type); bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind); +/// \brief Checks if the specified directive is a directive with an associated +/// loop construct. +/// \param DKind Specified directive. +/// \return true - the directive is a loop-associated directive like 'omp simd' +/// or 'omp for' directive, otherwise - false. +bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind); + +/// \brief Checks if the specified directive is a worksharing directive. +/// \param DKind Specified directive. +/// \return true - the directive is a worksharing directive like 'omp for', +/// otherwise - false. +bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind); + +/// \brief Checks if the specified directive is a parallel-kind directive. +/// \param DKind Specified directive. +/// \return true - the directive is a parallel-like directive like 'omp +/// parallel', otherwise - false. +bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind); + +/// \brief Checks if the specified directive is a simd directive. +/// \param DKind Specified directive. +/// \return true - the directive is a simd directive like 'omp simd', +/// otherwise - false. +bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind); + +/// \brief Checks if the specified clause is one of private clauses like +/// 'private', 'firstprivate', 'reduction' etc.. +/// \param Kind Clause kind. +/// \return true - the clause is a private clause, otherwise - false. +bool isOpenMPPrivate(OpenMPClauseKind Kind); + +/// \brief Checks if the specified clause is one of threadprivate clauses like +/// 'threadprivate', 'copyin' or 'copyprivate'. +/// \param Kind Clause kind. +/// \return true - the clause is a threadprivate clause, otherwise - false. +bool isOpenMPThreadPrivate(OpenMPClauseKind Kind); + } #endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h index 2ceab9c..d3b70c2 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h @@ -19,7 +19,7 @@ namespace clang { /// \brief Enumeration specifying the different kinds of C++ overloaded /// operators. -enum OverloadedOperatorKind { +enum OverloadedOperatorKind : int { OO_None, ///< Not an overloaded operator #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ OO_##Name, diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h index dd29926..8ae3b22 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h @@ -36,7 +36,7 @@ public: }; struct Storage { - Storage() : NumDiagArgs(0), NumDiagRanges(0) { } + Storage() : NumDiagArgs(0) { } enum { /// \brief The maximum number of arguments we can hold. We @@ -50,9 +50,6 @@ public: /// \brief The number of entries in Arguments. unsigned char NumDiagArgs; - /// \brief This is the number of ranges in the DiagRanges array. - unsigned char NumDiagRanges; - /// \brief Specifies for each argument whether it is in DiagArgumentsStr /// or in DiagArguments. unsigned char DiagArgumentsKind[MaxArguments]; @@ -69,9 +66,7 @@ public: std::string DiagArgumentsStr[MaxArguments]; /// \brief The list of ranges added to this diagnostic. - /// - /// It currently only support 10 ranges, could easily be extended if needed. - CharSourceRange DiagRanges[10]; + SmallVector<CharSourceRange, 8> DiagRanges; /// \brief If valid, provides a hint with some code to insert, remove, or /// modify at a particular position. @@ -97,7 +92,7 @@ public: Storage *Result = FreeList[--NumFreeListEntries]; Result->NumDiagArgs = 0; - Result->NumDiagRanges = 0; + Result->DiagRanges.clear(); Result->FixItHints.clear(); return Result; } @@ -159,17 +154,14 @@ private: Allocator->Deallocate(DiagStorage); else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) delete DiagStorage; - DiagStorage = 0; + DiagStorage = nullptr; } void AddSourceRange(const CharSourceRange &R) const { if (!DiagStorage) DiagStorage = getStorage(); - assert(DiagStorage->NumDiagRanges < - llvm::array_lengthof(DiagStorage->DiagRanges) && - "Too many arguments to diagnostic!"); - DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R; + DiagStorage->DiagRanges.push_back(R); } void AddFixItHint(const FixItHint &Hint) const { @@ -187,13 +179,13 @@ public: /// \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) { } + : DiagID(0), DiagStorage(nullptr), Allocator(nullptr) { } PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator) - : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { } + : DiagID(DiagID), DiagStorage(nullptr), Allocator(&Allocator) { } PartialDiagnostic(const PartialDiagnostic &Other) - : DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator) + : DiagID(Other.DiagID), DiagStorage(nullptr), Allocator(Other.Allocator) { if (Other.DiagStorage) { DiagStorage = getStorage(); @@ -201,13 +193,11 @@ public: } } -#if LLVM_HAS_RVALUE_REFERENCES PartialDiagnostic(PartialDiagnostic &&Other) : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage), Allocator(Other.Allocator) { - Other.DiagStorage = 0; + Other.DiagStorage = nullptr; } -#endif PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage) : DiagID(Other.DiagID), DiagStorage(DiagStorage), @@ -218,7 +208,7 @@ public: } PartialDiagnostic(const Diagnostic &Other, StorageAllocator &Allocator) - : DiagID(Other.getID()), DiagStorage(0), Allocator(&Allocator) + : DiagID(Other.getID()), DiagStorage(nullptr), Allocator(&Allocator) { // Copy arguments. for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) { @@ -251,7 +241,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES PartialDiagnostic &operator=(PartialDiagnostic &&Other) { freeStorage(); @@ -259,10 +248,9 @@ public: DiagStorage = Other.DiagStorage; Allocator = Other.Allocator; - Other.DiagStorage = 0; + Other.DiagStorage = nullptr; return *this; } -#endif ~PartialDiagnostic() { freeStorage(); @@ -312,12 +300,12 @@ public: } // Add all ranges. - for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i) - DB.AddSourceRange(DiagStorage->DiagRanges[i]); + for (const CharSourceRange &Range : DiagStorage->DiagRanges) + DB.AddSourceRange(Range); // Add all fix-its. - for (unsigned i = 0, e = DiagStorage->FixItHints.size(); i != e; ++i) - DB.AddFixItHint(DiagStorage->FixItHints[i]); + for (const FixItHint &Fix : DiagStorage->FixItHints) + DB.AddFixItHint(Fix); } void EmitToString(DiagnosticsEngine &Diags, @@ -339,7 +327,7 @@ public: freeStorage(); } - bool hasStorage() const { return DiagStorage != 0; } + bool hasStorage() const { return DiagStorage != nullptr; } friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, unsigned I) { @@ -380,8 +368,8 @@ public: // match. template<typename T> friend inline - typename llvm::enable_if<llvm::is_same<T, DeclContext>, - const PartialDiagnostic &>::type + typename std::enable_if<std::is_same<T, DeclContext>::value, + const PartialDiagnostic &>::type operator<<(const PartialDiagnostic &PD, T *DC) { PD.AddTaggedVal(reinterpret_cast<intptr_t>(DC), DiagnosticsEngine::ak_declcontext); diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h b/contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h new file mode 100644 index 0000000..b7a9382 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h @@ -0,0 +1,122 @@ +//===---------- PlistSupport.h - Plist Output Utilities ---------*- 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_PLISTSUPPORT_H +#define LLVM_CLANG_PLISTSUPPORT_H + +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { +namespace markup { +typedef llvm::DenseMap<FileID, unsigned> FIDMap; + +inline void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V, + const SourceManager &SM, SourceLocation L) { + FileID FID = SM.getFileID(SM.getExpansionLoc(L)); + FIDMap::iterator I = FIDs.find(FID); + if (I != FIDs.end()) + return; + FIDs[FID] = V.size(); + V.push_back(FID); +} + +inline unsigned GetFID(const FIDMap &FIDs, const SourceManager &SM, + SourceLocation L) { + FileID FID = SM.getFileID(SM.getExpansionLoc(L)); + FIDMap::const_iterator I = FIDs.find(FID); + assert(I != FIDs.end()); + return I->second; +} + +inline raw_ostream &Indent(raw_ostream &o, const unsigned indent) { + for (unsigned i = 0; i < indent; ++i) + o << ' '; + return o; +} + +inline raw_ostream &EmitPlistHeader(raw_ostream &o) { + static const char *PlistHeader = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" " + "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" + "<plist version=\"1.0\">\n"; + return o << PlistHeader; +} + +inline raw_ostream &EmitInteger(raw_ostream &o, int64_t value) { + o << "<integer>"; + o << value; + o << "</integer>"; + return o; +} + +inline raw_ostream &EmitString(raw_ostream &o, StringRef s) { + o << "<string>"; + for (StringRef::const_iterator I = s.begin(), E = s.end(); I != E; ++I) { + char c = *I; + switch (c) { + default: + o << c; + break; + case '&': + o << "&"; + break; + case '<': + o << "<"; + break; + case '>': + o << ">"; + break; + case '\'': + o << "'"; + break; + case '\"': + o << """; + break; + } + } + o << "</string>"; + return o; +} + +inline void EmitLocation(raw_ostream &o, const SourceManager &SM, + const LangOptions &LangOpts, SourceLocation L, + const FIDMap &FM, unsigned indent, + bool extend = false) { + FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager &>(SM)); + + // Add in the length of the token, so that we cover multi-char tokens. + unsigned offset = + extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0; + + Indent(o, indent) << "<dict>\n"; + Indent(o, indent) << " <key>line</key>"; + EmitInteger(o, Loc.getExpansionLineNumber()) << '\n'; + Indent(o, indent) << " <key>col</key>"; + EmitInteger(o, Loc.getExpansionColumnNumber() + offset) << '\n'; + Indent(o, indent) << " <key>file</key>"; + EmitInteger(o, GetFID(FM, SM, Loc)) << '\n'; + Indent(o, indent) << "</dict>\n"; +} + +inline void EmitRange(raw_ostream &o, const SourceManager &SM, + const LangOptions &LangOpts, CharSourceRange R, + const FIDMap &FM, unsigned indent) { + Indent(o, indent) << "<array>\n"; + EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent + 1); + EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent + 1, R.isTokenRange()); + Indent(o, indent) << "</array>\n"; +} +} +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h b/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h index 967d0d1..0e49295 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h @@ -31,7 +31,7 @@ namespace clang { public: PrettyStackTraceLoc(SourceManager &sm, SourceLocation L, const char *Msg) : SM(sm), Loc(L), Message(Msg) {} - virtual void print(raw_ostream &OS) const; + void print(raw_ostream &OS) const override; }; } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def index c9b31a3..0ef39bc 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def @@ -40,13 +40,6 @@ // AddressSanitizer SANITIZER("address", Address) -// More features of AddressSanitizer that should be turned on explicitly. -SANITIZER("init-order", InitOrder) -SANITIZER("use-after-return", UseAfterReturn) -SANITIZER("use-after-scope", UseAfterScope) - -SANITIZER_GROUP("address-full", AddressFull, - Address | InitOrder | UseAfterReturn | UseAfterScope) // MemorySanitizer SANITIZER("memory", Memory) @@ -89,7 +82,7 @@ SANITIZER_GROUP("undefined", Undefined, ObjectSize | Return | Shift | SignedIntegerOverflow | Unreachable | VLABound | Vptr) -// -fsanitize=undefined-trap (and its alias -fcatch-undefined-behavior) includes +// -fsanitize=undefined-trap includes // all sanitizers included by -fsanitize=undefined, except those that require // runtime support. This group is generally used in conjunction with the // -fsanitize-undefined-trap-on-error flag. @@ -103,7 +96,6 @@ SANITIZER_GROUP("integer", Integer, SignedIntegerOverflow | UnsignedIntegerOverflow | Shift | IntegerDivideByZero) -// -fbounds-checking SANITIZER("local-bounds", LocalBounds) SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds) diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h index 10ae07b..7b637d7 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h @@ -89,7 +89,7 @@ class SourceLocation { friend class SourceManager; friend class ASTReader; friend class ASTWriter; - enum LLVM_ENUM_INT_TYPE(unsigned) { + enum : unsigned { MacroIDBit = 1U << 31 }; public: @@ -172,7 +172,7 @@ public: } void print(raw_ostream &OS, const SourceManager &SM) const; - LLVM_ATTRIBUTE_USED std::string printToString(const SourceManager &SM) const; + std::string printToString(const SourceManager &SM) const; void dump(const SourceManager &SM) const; }; @@ -188,7 +188,7 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { return LHS.getRawEncoding() < RHS.getRawEncoding(); } -/// \brief A trival tuple used to represent a source range. +/// \brief A trivial tuple used to represent a source range. class SourceRange { SourceLocation B; SourceLocation E; @@ -268,7 +268,7 @@ class FullSourceLoc : public SourceLocation { const SourceManager *SrcMgr; public: /// \brief Creates a FullSourceLoc where isValid() returns \c false. - explicit FullSourceLoc() : SrcMgr(0) {} + explicit FullSourceLoc() : SrcMgr(nullptr) {} explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) : SourceLocation(Loc), SrcMgr(&SM) {} @@ -284,19 +284,19 @@ public: FullSourceLoc getExpansionLoc() const; FullSourceLoc getSpellingLoc() const; - unsigned getExpansionLineNumber(bool *Invalid = 0) const; - unsigned getExpansionColumnNumber(bool *Invalid = 0) const; + unsigned getExpansionLineNumber(bool *Invalid = nullptr) const; + unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const; - unsigned getSpellingLineNumber(bool *Invalid = 0) const; - unsigned getSpellingColumnNumber(bool *Invalid = 0) const; + unsigned getSpellingLineNumber(bool *Invalid = nullptr) const; + unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const; - const char *getCharacterData(bool *Invalid = 0) const; + const char *getCharacterData(bool *Invalid = nullptr) const; - const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const; + const llvm::MemoryBuffer* getBuffer(bool *Invalid = nullptr) const; /// \brief Return a StringRef to the source buffer data for the /// specified FileID. - StringRef getBufferData(bool *Invalid = 0) const; + StringRef getBufferData(bool *Invalid = nullptr) const; /// \brief Decompose the specified location into a raw FileID + Offset pair. /// @@ -331,7 +331,7 @@ public: /// \brief Prints information about this FullSourceLoc to stderr. /// /// This is useful for debugging. - LLVM_ATTRIBUTE_USED void dump() const; + void dump() const; friend inline bool operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { @@ -358,7 +358,7 @@ class PresumedLoc { unsigned Line, Col; SourceLocation IncludeLoc; public: - PresumedLoc() : Filename(0) {} + PresumedLoc() : Filename(nullptr) {} PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) { } @@ -367,8 +367,8 @@ public: /// /// 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; } + bool isInvalid() const { return Filename == nullptr; } + bool isValid() const { return Filename != nullptr; } /// \brief Return the presumed filename of this location. /// diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h index 6aab998..e567a7a 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h @@ -42,14 +42,15 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MemoryBuffer.h" #include <cassert> #include <map> +#include <memory> #include <vector> namespace clang { @@ -89,12 +90,21 @@ namespace SrcMgr { DoNotFreeFlag = 0x02 }; + // Note that the first member of this class is an aligned character buffer + // to ensure that this class has an alignment of 8 bytes. This wastes + // 8 bytes for every ContentCache object, but each of these corresponds to + // a file loaded into memory, so the 8 bytes doesn't seem terribly + // important. It is quite awkward to fit this aligner into any other part + // of the class due to the lack of portable ways to combine it with other + // members. + llvm::AlignedCharArray<8, 1> NonceAligner; + /// \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; + mutable llvm::PointerIntPair<llvm::MemoryBuffer *, 2> Buffer; public: /// \brief Reference to the file entry representing this ContentCache. @@ -133,14 +143,16 @@ namespace SrcMgr { /// 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), - IsSystemFile(false) {} + ContentCache(const FileEntry *Ent = nullptr) + : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(Ent), + SourceLineCache(nullptr), NumLines(0), BufferOverridden(false), + IsSystemFile(false) { + (void)NonceAligner; // Silence warnings about unused member. + } ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) - : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt), - SourceLineCache(0), NumLines(0), BufferOverridden(false), + : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt), + SourceLineCache(nullptr), NumLines(0), BufferOverridden(false), IsSystemFile(false) {} ~ContentCache(); @@ -149,15 +161,15 @@ namespace SrcMgr { /// 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), - IsSystemFile(false) - { + : Buffer(nullptr, false), SourceLineCache(nullptr), + BufferOverridden(false), IsSystemFile(false) { OrigEntry = RHS.OrigEntry; ContentsEntry = RHS.ContentsEntry; - - assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 && - "Passed ContentCache object cannot own a buffer."); - + + assert(RHS.Buffer.getPointer() == nullptr && + RHS.SourceLineCache == nullptr && + "Passed ContentCache object cannot own a buffer."); + NumLines = RHS.NumLines; } @@ -170,10 +182,10 @@ namespace SrcMgr { /// will be emitted at. /// /// \param Invalid If non-NULL, will be set \c true if an error occurred. - const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag, - const SourceManager &SM, - SourceLocation Loc = SourceLocation(), - bool *Invalid = 0) const; + llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag, + const SourceManager &SM, + SourceLocation Loc = SourceLocation(), + bool *Invalid = nullptr) const; /// \brief Returns the size of the content encapsulated by this /// ContentCache. @@ -193,7 +205,7 @@ namespace SrcMgr { /// this content cache. This is used for performance analysis. llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const; - void setBuffer(const llvm::MemoryBuffer *B) { + void setBuffer(llvm::MemoryBuffer *B) { assert(!Buffer.getPointer() && "MemoryBuffer already set."); Buffer.setPointer(B); Buffer.setInt(false); @@ -201,13 +213,11 @@ namespace SrcMgr { /// \brief Get the underlying buffer, returning NULL if the buffer is not /// yet available. - const llvm::MemoryBuffer *getRawBuffer() const { - return Buffer.getPointer(); - } + llvm::MemoryBuffer *getRawBuffer() const { return Buffer.getPointer(); } /// \brief Replace the existing buffer (which will be deleted) /// with the given buffer. - void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false); + void replaceBuffer(llvm::MemoryBuffer *B, bool DoNotFree = false); /// \brief Determine whether the buffer itself is invalid. bool isBufferInvalid() const { @@ -224,6 +234,11 @@ namespace SrcMgr { ContentCache &operator=(const ContentCache& RHS) LLVM_DELETED_FUNCTION; }; + // Assert that the \c ContentCache objects will always be 8-byte aligned so + // that we can pack 3 bits of integer into pointers to such objects. + static_assert(llvm::AlignOf<ContentCache>::Alignment >= 8, + "ContentCache must be 8-byte aligned."); + /// \brief Information about a FileID, basically just the logical file /// that it represents and include stack information. /// @@ -551,7 +566,7 @@ class SourceManager : public RefCountedBase<SourceManager> { /// non-null, FileEntry pointers. llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos; - /// \brief True if the ContentCache for files that are overriden by other + /// \brief True if the ContentCache for files that are overridden by other /// files, should report the original file name. Defaults to true. bool OverridenFilesKeepOriginalName; @@ -560,7 +575,7 @@ class SourceManager : public RefCountedBase<SourceManager> { bool UserFilesAreVolatile; struct OverriddenFilesInfoTy { - /// \brief Files that have been overriden with the contents from another + /// \brief Files that have been overridden with the contents from another /// file. llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles; /// \brief Files that were overridden with a memory buffer. @@ -569,7 +584,7 @@ class SourceManager : public RefCountedBase<SourceManager> { /// \brief Lazily create the object keeping overridden files info, since /// it is uncommonly used. - OwningPtr<OverriddenFilesInfoTy> OverriddenFilesInfo; + std::unique_ptr<OverriddenFilesInfoTy> OverriddenFilesInfo; OverriddenFilesInfoTy &getOverriddenFilesInfo() { if (!OverriddenFilesInfo) @@ -704,7 +719,8 @@ public: FileManager &getFileManager() const { return FileMgr; } /// \brief Set true if the SourceManager should report the original file name - /// for contents of files that were overriden by other files.Defaults to true. + /// for contents of files that were overridden by other files. Defaults to + /// true. void setOverridenFilesKeepOriginalName(bool value) { OverridenFilesKeepOriginalName = value; } @@ -729,18 +745,6 @@ public: StoredModuleBuildStack.push_back(std::make_pair(moduleName.str(),importLoc)); } - /// \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, - SrcMgr::CharacteristicKind Kind = SrcMgr::C_User) { - assert(MainFileID.isInvalid() && "MainFileID already set!"); - MainFileID = createFileIDForMemBuffer(Buffer, Kind); - return MainFileID; - } - //===--------------------------------------------------------------------===// // MainFileID creation and querying methods. //===--------------------------------------------------------------------===// @@ -748,14 +752,6 @@ public: /// \brief Returns the FileID of the main source file. FileID getMainFileID() const { return MainFileID; } - /// \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!"); - MainFileID = createFileID(SourceFile, SourceLocation(), Kind); - return MainFileID; - } - /// \brief Set the file ID for the main source file. void setMainFileID(FileID FID) { assert(MainFileID.isInvalid() && "MainFileID already set!"); @@ -793,10 +789,10 @@ public: /// /// 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, + FileID createFileID(llvm::MemoryBuffer *Buffer, SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User, - int LoadedID = 0, unsigned LoadedOffset = 0, - SourceLocation IncludeLoc = SourceLocation()) { + int LoadedID = 0, unsigned LoadedOffset = 0, + SourceLocation IncludeLoc = SourceLocation()) { return createFileID(createMemBufferContentCache(Buffer), IncludeLoc, FileCharacter, LoadedID, LoadedOffset); } @@ -823,13 +819,13 @@ public: /// /// \param Invalid If non-NULL, will be set \c true if an error /// occurs while retrieving the memory buffer. - const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File, - bool *Invalid = 0); + llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File, + bool *Invalid = nullptr); /// \brief Override the contents of the given source file by providing an /// already-allocated buffer. /// - /// \param SourceFile the source file whose contents will be overriden. + /// \param SourceFile the source file whose contents will be overridden. /// /// \param Buffer the memory buffer whose contents will be used as the /// data in the given source file. @@ -837,12 +833,11 @@ public: /// \param DoNotFree If true, then the buffer will not be freed when the /// source manager is destroyed. void overrideFileContents(const FileEntry *SourceFile, - const llvm::MemoryBuffer *Buffer, - bool DoNotFree = false); + llvm::MemoryBuffer *Buffer, bool DoNotFree = false); /// \brief Override the given source file with another one. /// - /// \param SourceFile the source file which will be overriden. + /// \param SourceFile the source file which will be overridden. /// /// \param NewFile the file whose contents will be used as the /// data instead of the contents of the given source file. @@ -875,8 +870,8 @@ public: /// /// 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 { + llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc, + bool *Invalid = nullptr) const { bool MyInvalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); if (MyInvalid || !Entry.isFile()) { @@ -890,7 +885,7 @@ public: Invalid); } - const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const { + llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = nullptr) const { bool MyInvalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); if (MyInvalid || !Entry.isFile()) { @@ -910,11 +905,11 @@ public: bool MyInvalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); if (MyInvalid || !Entry.isFile()) - return 0; + return nullptr; const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache(); if (!Content) - return 0; + return nullptr; return Content->OrigEntry; } @@ -923,7 +918,7 @@ public: { const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache(); if (!Content) - return 0; + return nullptr; return Content->OrigEntry; } @@ -932,7 +927,7 @@ public: /// /// \param FID The file ID whose contents will be returned. /// \param Invalid If non-NULL, will be set true if an error occurred. - StringRef getBufferData(FileID FID, bool *Invalid = 0) const; + StringRef getBufferData(FileID FID, bool *Invalid = nullptr) const; /// \brief Get the number of FileIDs (files and macros) that were created /// during preprocessing of \p FID, including it. @@ -1167,15 +1162,16 @@ public: /// \param MacroBegin If non-null and function returns true, it is set to the /// begin location of the immediate macro expansion. bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, - SourceLocation *MacroBegin = 0) const; + SourceLocation *MacroBegin = nullptr) const; /// \brief Returns true if the given MacroID location points at the character /// end of the immediate macro expansion. /// /// \param MacroEnd If non-null and function returns true, it is set to the /// character end location of the immediate macro expansion. - bool isAtEndOfImmediateMacroExpansion(SourceLocation Loc, - SourceLocation *MacroEnd = 0) const; + bool + isAtEndOfImmediateMacroExpansion(SourceLocation Loc, + SourceLocation *MacroEnd = nullptr) const; /// \brief Returns true if \p Loc is inside the [\p Start, +\p Length) /// chunk of the source location address space. @@ -1184,7 +1180,7 @@ public: /// relative offset of \p Loc inside the chunk. bool isInSLocAddrSpace(SourceLocation Loc, SourceLocation Start, unsigned Length, - unsigned *RelativeOffset = 0) const { + unsigned *RelativeOffset = nullptr) const { assert(((Start.getOffset() < NextLocalOffset && Start.getOffset()+Length <= NextLocalOffset) || (Start.getOffset() >= CurrentLoadedOffset && @@ -1230,7 +1226,8 @@ public: /// 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; + const char *getCharacterData(SourceLocation SL, + bool *Invalid = nullptr) const; /// \brief Return the column # for the specified file position. /// @@ -1239,12 +1236,13 @@ public: /// on a file sloc, so you must choose a spelling or expansion location /// before calling this method. unsigned getColumnNumber(FileID FID, unsigned FilePos, - bool *Invalid = 0) const; - unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid = 0) const; + bool *Invalid = nullptr) const; + unsigned getSpellingColumnNumber(SourceLocation Loc, + bool *Invalid = nullptr) const; unsigned getExpansionColumnNumber(SourceLocation Loc, - bool *Invalid = 0) const; - unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = 0) const; - + bool *Invalid = nullptr) const; + unsigned getPresumedColumnNumber(SourceLocation Loc, + bool *Invalid = nullptr) const; /// \brief Given a SourceLocation, return the spelling line number /// for the position indicated. @@ -1252,17 +1250,17 @@ public: /// 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; + unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = nullptr) const; + unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; + unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; + unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; /// \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; + const char *getBufferName(SourceLocation Loc, bool *Invalid = nullptr) const; /// \brief Return the file characteristic of the specified source /// location, indicating whether this is a normal file, a system @@ -1286,7 +1284,7 @@ public: /// an expansion location, not at the spelling location. /// /// \returns The presumed location of the specified SourceLocation. If the - /// presumed location cannot be calculate (e.g., because \p Loc is invalid + /// presumed location cannot be calculated (e.g., because \p Loc is invalid /// or the file containing \p Loc has changed on disk), returns an invalid /// presumed location. PresumedLoc getPresumedLoc(SourceLocation Loc, @@ -1332,14 +1330,14 @@ public: return loc.isMacroID() && isInSystemHeader(getSpellingLoc(loc)); } - /// \brief The size of the SLocEnty that \p FID represents. + /// \brief The size of the SLocEntry that \p FID represents. unsigned getFileIDSize(FileID FID) const; /// \brief Given a specific FileID, returns true if \p Loc is inside that /// FileID chunk and sets relative offset (offset of \p Loc from beginning /// of FileID) to \p relativeOffset. bool isInFileID(SourceLocation Loc, FileID FID, - unsigned *RelativeOffset = 0) const { + unsigned *RelativeOffset = nullptr) const { unsigned Offs = Loc.getOffset(); if (isOffsetInFileID(FID, Offs)) { if (RelativeOffset) @@ -1368,7 +1366,7 @@ public: bool IsSystemHeader, bool IsExternCHeader); /// \brief Determine if the source manager has a line table. - bool hasLineTable() const { return LineTable != 0; } + bool hasLineTable() const { return LineTable != nullptr; } /// \brief Retrieve the stored line table. LineTableInfo &getLineTable(); @@ -1475,7 +1473,7 @@ public: /// \brief Get a local SLocEntry. This is exposed for indexing. const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index, - bool *Invalid = 0) const { + bool *Invalid = nullptr) const { assert(Index < LocalSLocEntryTable.size() && "Invalid index"); return LocalSLocEntryTable[Index]; } @@ -1485,14 +1483,15 @@ public: /// \brief Get a loaded SLocEntry. This is exposed for indexing. const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, - bool *Invalid = 0) const { + bool *Invalid = nullptr) const { assert(Index < LoadedSLocEntryTable.size() && "Invalid index"); if (SLocEntryLoaded[Index]) return LoadedSLocEntryTable[Index]; return loadSLocEntry(Index, Invalid); } - const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const { + const SrcMgr::SLocEntry &getSLocEntry(FileID FID, + bool *Invalid = nullptr) const { if (FID.ID == 0 || FID.ID == -1) { if (Invalid) *Invalid = true; return LocalSLocEntryTable[0]; @@ -1555,21 +1554,22 @@ public: } private: - const llvm::MemoryBuffer *getFakeBufferForRecovery() const; + llvm::MemoryBuffer *getFakeBufferForRecovery() const; const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const; const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const; /// \brief Get the entry with the given unwrapped FileID. - const SrcMgr::SLocEntry &getSLocEntryByID(int ID, bool *Invalid = 0) const { + const SrcMgr::SLocEntry &getSLocEntryByID(int ID, + bool *Invalid = nullptr) const { assert(ID != -1 && "Using FileID sentinel value"); if (ID < 0) return getLoadedSLocEntryByID(ID, Invalid); return getLocalSLocEntry(static_cast<unsigned>(ID), Invalid); } - const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID, - bool *Invalid = 0) const { + const SrcMgr::SLocEntry & + getLoadedSLocEntryByID(int ID, bool *Invalid = nullptr) const { return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid); } @@ -1623,8 +1623,8 @@ private: bool isSystemFile = false); /// \brief Create a new ContentCache for the specified memory buffer. - const SrcMgr::ContentCache* - createMemBufferContentCache(const llvm::MemoryBuffer *Buf); + const SrcMgr::ContentCache * + createMemBufferContentCache(llvm::MemoryBuffer *Buf); FileID getFileIDSlow(unsigned SLocOffset) const; FileID getFileIDLocal(unsigned SLocOffset) const; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h index 0b80939..f895673 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h @@ -63,21 +63,13 @@ namespace clang { TST_decltype_auto, // C++1y decltype(auto) TST_unknown_anytype, // __unknown_anytype extension TST_atomic, // C11 _Atomic - TST_image1d_t, // OpenCL image1d_t - TST_image1d_array_t, // OpenCL image1d_array_t - TST_image1d_buffer_t, // OpenCL image1d_buffer_t - TST_image2d_t, // OpenCL image2d_t - TST_image2d_array_t, // OpenCL image2d_array_t - TST_image3d_t, // OpenCL image3d_t - TST_sampler_t, // OpenCL sampler_t - TST_event_t, // OpenCL event_t TST_error // erroneous type }; /// \brief Structure that packs information about the type specifiers that /// were written in a particular type specifier sequence. struct WrittenBuiltinSpecs { - /*DeclSpec::TST*/ unsigned Type : 6; + /*DeclSpec::TST*/ unsigned Type : 5; /*DeclSpec::TSS*/ unsigned Sign : 2; /*DeclSpec::TSW*/ unsigned Width : 2; bool ModeAttr : 1; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td index 69851a9..d980648 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td @@ -115,8 +115,6 @@ def CXXNewExpr : DStmt<Expr>; def CXXDeleteExpr : DStmt<Expr>; def CXXPseudoDestructorExpr : DStmt<Expr>; def TypeTraitExpr : DStmt<Expr>; -def UnaryTypeTraitExpr : DStmt<Expr>; -def BinaryTypeTraitExpr : DStmt<Expr>; def ArrayTypeTraitExpr : DStmt<Expr>; def ExpressionTraitExpr : DStmt<Expr>; def DependentScopeDeclRefExpr : DStmt<Expr>; @@ -172,6 +170,7 @@ def CXXUuidofExpr : DStmt<Expr>; def SEHTryStmt : Stmt; def SEHExceptStmt : Stmt; def SEHFinallyStmt : Stmt; +def SEHLeaveStmt : Stmt; def MSDependentExistsStmt : Stmt; // OpenCL Extensions. @@ -180,3 +179,17 @@ def AsTypeExpr : DStmt<Expr>; // OpenMP Directives. def OMPExecutableDirective : Stmt<1>; def OMPParallelDirective : DStmt<OMPExecutableDirective>; +def OMPSimdDirective : DStmt<OMPExecutableDirective>; +def OMPForDirective : DStmt<OMPExecutableDirective>; +def OMPSectionsDirective : DStmt<OMPExecutableDirective>; +def OMPSectionDirective : DStmt<OMPExecutableDirective>; +def OMPSingleDirective : DStmt<OMPExecutableDirective>; +def OMPMasterDirective : DStmt<OMPExecutableDirective>; +def OMPCriticalDirective : DStmt<OMPExecutableDirective>; +def OMPParallelForDirective : DStmt<OMPExecutableDirective>; +def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>; +def OMPTaskDirective : DStmt<OMPExecutableDirective>; +def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>; +def OMPBarrierDirective : DStmt<OMPExecutableDirective>; +def OMPTaskwaitDirective : DStmt<OMPExecutableDirective>; +def OMPFlushDirective : DStmt<OMPExecutableDirective>; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h index ed3cc49..b1652be 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h @@ -1,4 +1,4 @@ -//===--- TargetBuiltins.h - Target specific builtin IDs -------------------===// +//===--- TargetBuiltins.h - Target specific builtin IDs ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,25 +21,37 @@ namespace clang { - /// \brief AArch64 builtins - namespace AArch64 { - enum { - LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, + namespace NEON { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, #define BUILTIN(ID, TYPE, ATTRS) BI##ID, -#include "clang/Basic/BuiltinsAArch64.def" - LastTSBuiltin - }; +#include "clang/Basic/BuiltinsNEON.def" + FirstTSBuiltin + }; } + /// \brief ARM builtins namespace ARM { enum { - LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, + LastNEONBuiltin = NEON::FirstTSBuiltin - 1, #define BUILTIN(ID, TYPE, ATTRS) BI##ID, #include "clang/Basic/BuiltinsARM.def" - LastTSBuiltin + LastTSBuiltin }; } + /// \brief AArch64 builtins + namespace AArch64 { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, + LastNEONBuiltin = NEON::FirstTSBuiltin - 1, + #define BUILTIN(ID, TYPE, ATTRS) BI##ID, + #include "clang/Basic/BuiltinsAArch64.def" + LastTSBuiltin + }; + } + /// \brief PPC builtins namespace PPC { enum { @@ -60,6 +72,15 @@ namespace clang { }; } + /// \brief R600 builtins + namespace R600 { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, + #define BUILTIN(ID, TYPE, ATTRS) BI##ID, + #include "clang/Basic/BuiltinsR600.def" + LastTSBuiltin + }; + } /// \brief X86 builtins namespace X86 { @@ -91,6 +112,7 @@ namespace clang { Poly8, Poly16, Poly64, + Poly128, Float16, Float32, Float64 diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h index 1590cca..f9e37c3 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h @@ -63,6 +63,14 @@ public: /// - constructor/destructor signatures. iOS, + /// The iOS 64-bit ABI is follows ARM's published 64-bit ABI more + /// closely, but we don't guarantee to follow it perfectly. + /// + /// It is documented here: + /// http://infocenter.arm.com + /// /help/topic/com.arm.doc.ihi0059a/IHI0059A_cppabi64.pdf + iOS64, + /// The generic AArch64 ABI is also a modified version of the Itanium ABI, /// but it has fewer divergences than the 32-bit ARM ABI. /// @@ -105,6 +113,7 @@ public: case GenericItanium: case GenericARM: case iOS: + case iOS64: return true; case Microsoft: @@ -120,6 +129,7 @@ public: case GenericItanium: case GenericARM: case iOS: + case iOS64: return false; case Microsoft: @@ -135,14 +145,14 @@ public: return !isMicrosoft(); } - /// Are temporary objects passed by value to a call destroyed by the callee? + /// Are arguments to a call destroyed left to right in the callee? /// This is a fundamental language change, since it implies that objects /// passed by value do *not* live to the end of the full expression. /// Temporaries passed to a function taking a const reference live to the end /// of the full expression as usual. Both the caller and the callee must /// have access to the destructor, while only the caller needs the /// destructor if this is false. - bool isArgumentDestroyedByCallee() const { + bool areArgsDestroyedLeftToRightInCallee() const { return isMicrosoft(); } @@ -195,6 +205,7 @@ public: bool canKeyFunctionBeInline() const { switch (getKind()) { case GenericARM: + case iOS64: return false; case GenericAArch64: @@ -230,7 +241,7 @@ public: /// Only allocate objects in the tail padding of a base class if /// the base class is not POD according to the rules of C++ TR1. - /// This is non strictly conforming in C++11 mode. + /// This is non-strictly conforming in C++11 mode. UseTailPaddingUnlessPOD03, /// Only allocate objects in the tail padding of a base class if @@ -248,6 +259,11 @@ public: case iOS: return UseTailPaddingUnlessPOD03; + // iOS on ARM64 uses the C++11 POD rules. It does not honor the + // Itanium exception about classes with over-large bitfields. + case iOS64: + return UseTailPaddingUnlessPOD11; + // MSVC always allocates fields in the tail-padding of a base class // subobject, even if they're POD. case Microsoft: diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h index 047872d..edef7c0 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h @@ -16,9 +16,9 @@ #define LLVM_CLANG_BASIC_TARGETINFO_H #include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/VersionTuple.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -47,7 +47,7 @@ namespace Builtin { struct Info; } /// \brief Exposes information about the current target. /// class TargetInfo : public RefCountedBase<TargetInfo> { - IntrusiveRefCntPtr<TargetOptions> TargetOpts; + std::shared_ptr<TargetOptions> TargetOpts; llvm::Triple Triple; protected: // Target values set by the ctor of the actual target implementation. Default @@ -94,8 +94,9 @@ public: /// \param Opts - The options to use to initialize the target. The target may /// modify the options to canonicalize the target feature information to match /// what the backend expects. - static TargetInfo* CreateTargetInfo(DiagnosticsEngine &Diags, - TargetOptions *Opts); + static TargetInfo * + CreateTargetInfo(DiagnosticsEngine &Diags, + const std::shared_ptr<TargetOptions> &Opts); virtual ~TargetInfo(); @@ -105,10 +106,6 @@ public: return *TargetOpts; } - void setTargetOpts(TargetOptions *TargetOpts) { - this->TargetOpts = TargetOpts; - } - ///===---- Target Data Type Query Methods -------------------------------===// enum IntType { NoInt = 0, @@ -173,7 +170,7 @@ public: }; protected: - IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, + IntType SizeType, IntMaxType, PtrDiffType, IntPtrType, WCharType, WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType, ProcessIDType; @@ -209,19 +206,44 @@ protected: public: IntType getSizeType() const { return SizeType; } IntType getIntMaxType() const { return IntMaxType; } - IntType getUIntMaxType() const { return UIntMaxType; } + IntType getUIntMaxType() const { + return getCorrespondingUnsignedType(IntMaxType); + } IntType getPtrDiffType(unsigned AddrSpace) const { return AddrSpace == 0 ? PtrDiffType : getPtrDiffTypeV(AddrSpace); } IntType getIntPtrType() const { return IntPtrType; } + IntType getUIntPtrType() const { + return getCorrespondingUnsignedType(IntPtrType); + } IntType getWCharType() const { return WCharType; } IntType getWIntType() const { return WIntType; } IntType getChar16Type() const { return Char16Type; } IntType getChar32Type() const { return Char32Type; } IntType getInt64Type() const { return Int64Type; } + IntType getUInt64Type() const { + return getCorrespondingUnsignedType(Int64Type); + } IntType getSigAtomicType() const { return SigAtomicType; } IntType getProcessIDType() const { return ProcessIDType; } + static IntType getCorrespondingUnsignedType(IntType T) { + switch (T) { + case SignedChar: + return UnsignedChar; + case SignedShort: + return UnsignedShort; + case SignedInt: + return UnsignedInt; + case SignedLong: + return UnsignedLong; + case SignedLongLong: + return UnsignedLongLong; + default: + llvm_unreachable("Unexpected signed integer type"); + } + } + /// \brief Return the width (in bits) of the specified integer type enum. /// /// For example, SignedInt -> getIntWidth(). @@ -230,6 +252,9 @@ public: /// \brief Return integer type with specified width. IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const; + /// \brief Return the smallest integer type with at least the specified width. + IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const; + /// \brief Return floating point type with specified width. RealType getRealTypeByWidth(unsigned BitWidth) const; @@ -283,7 +308,7 @@ public: unsigned getLongLongAlign() const { return LongLongAlign; } /// \brief Determine whether the __int128 type is supported on this target. - bool hasInt128Type() const { return getPointerWidth(0) >= 64; } // FIXME + virtual bool hasInt128Type() const { return getPointerWidth(0) >= 64; } // FIXME /// \brief Return the alignment that is suitable for storing any /// object with a fundamental alignment requirement. @@ -421,7 +446,13 @@ public: /// \brief Return the constant suffix for the specified integer type enum. /// /// For example, SignedLong -> "L". - static const char *getTypeConstantSuffix(IntType T); + const char *getTypeConstantSuffix(IntType T) const; + + /// \brief Return the printf format modifier for the specified + /// integer type enum. + /// + /// For example, SignedLong -> "l". + static const char *getTypeFormatModifier(IntType T); /// \brief Check whether the given real type should use the "fpret" flavor of /// Objective-C message passing on this target. @@ -579,6 +610,7 @@ public: } const char *getTargetDescription() const { + assert(DescriptionString); return DescriptionString; } @@ -604,24 +636,6 @@ public: /// either; the entire thing is pretty badly mangled. virtual bool hasProtectedVisibility() const { return true; } - /// \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"; - } - - /// \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"; - } - - /// \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"; - } - /// \brief An optional hook that targets can implement to perform semantic /// checking on attribute((section("foo"))) specifiers. /// @@ -641,7 +655,7 @@ public: /// /// Apply changes to the target information with respect to certain /// language options which change the target configuration. - virtual void setForcedLangOptions(LangOptions &Opts); + virtual void adjust(const LangOptions &Opts); /// \brief Get the default set of target features for the CPU; /// this should include all legal feature strings on the target. @@ -649,9 +663,7 @@ public: } /// \brief Get the ABI currently in use. - virtual const char *getABI() const { - return ""; - } + virtual StringRef getABI() const { return StringRef(); } /// \brief Get the C++ ABI currently in use. TargetCXXABI getCXXABI() const { @@ -752,7 +764,7 @@ public: /// \brief Return the section to use for C++ static initialization functions. virtual const char *getStaticInitSectionSpecifier() const { - return 0; + return nullptr; } const LangAS::Map &getAddressSpaceMap() const { @@ -818,7 +830,7 @@ protected: unsigned &NumAliases) const = 0; virtual void getGCCAddlRegNames(const AddlRegName *&Addl, unsigned &NumAddl) const { - Addl = 0; + Addl = nullptr; NumAddl = 0; } virtual bool validateAsmConstraint(const char *&Name, diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h index 9909182..2c86c31 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h @@ -15,15 +15,13 @@ #ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H #define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include <string> #include <vector> namespace clang { /// \brief Options for controlling the target. -class TargetOptions : public RefCountedBase<TargetOptions> { +class TargetOptions { public: /// If given, the name of the target triple to compile for. If not given the /// target will be selected to match the host. @@ -38,10 +36,6 @@ public: /// If given, the name of the target ABI to use. std::string ABI; - /// If given, the name of the target C++ ABI to use. If not given, defaults - /// to "itanium". - std::string CXXABI; - /// If given, the version string of the linker in use. std::string LinkerVersion; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h index c521893..b730143 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h @@ -17,6 +17,7 @@ namespace clang { /// \brief Specifies the kind of template name that an identifier refers to. +/// Be careful when changing this: this enumeration is used in diagnostics. enum TemplateNameKind { /// The name does not refer to a template. TNK_Non_template = 0, diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def index 6812cce..5d08833 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def @@ -23,6 +23,18 @@ #ifndef KEYWORD #define KEYWORD(X,Y) TOK(kw_ ## X) #endif +#ifndef TYPE_TRAIT +#define TYPE_TRAIT(N,I,K) KEYWORD(I,K) +#endif +#ifndef TYPE_TRAIT_1 +#define TYPE_TRAIT_1(I,E,K) TYPE_TRAIT(1,I,K) +#endif +#ifndef TYPE_TRAIT_2 +#define TYPE_TRAIT_2(I,E,K) TYPE_TRAIT(2,I,K) +#endif +#ifndef TYPE_TRAIT_N +#define TYPE_TRAIT_N(I,E,K) TYPE_TRAIT(0,I,K) +#endif #ifndef ALIAS #define ALIAS(X,Y,Z) #endif @@ -217,6 +229,7 @@ PUNCTUATOR(greatergreatergreater, ">>>") // KEYALTIVEC - This is a keyword in AltiVec // KEYBORLAND - This is a keyword if Borland extensions are enabled // BOOLSUPPORT - This is a keyword if 'bool' is a built-in type +// HALFSUPPORT - This is a keyword if 'half' is a built-in type // WCHARSUPPORT - This is a keyword if 'wchar_t' is a built-in type // KEYWORD(auto , KEYALL) @@ -255,7 +268,7 @@ KEYWORD(volatile , KEYALL) KEYWORD(while , KEYALL) KEYWORD(_Alignas , KEYALL) KEYWORD(_Alignof , KEYALL) -KEYWORD(_Atomic , KEYALL) +KEYWORD(_Atomic , KEYALL|KEYNOMS) KEYWORD(_Bool , KEYNOCXX) KEYWORD(_Complex , KEYALL) KEYWORD(_Generic , KEYALL) @@ -284,7 +297,7 @@ KEYWORD(mutable , KEYCXX) KEYWORD(namespace , KEYCXX) KEYWORD(new , KEYCXX) KEYWORD(operator , KEYCXX) -KEYWORD(private , KEYCXX|KEYOPENCL) +KEYWORD(private , KEYCXX) KEYWORD(protected , KEYCXX) KEYWORD(public , KEYCXX) KEYWORD(reinterpret_cast , KEYCXX) @@ -334,7 +347,9 @@ KEYWORD(__alignof , KEYALL) KEYWORD(__attribute , KEYALL) KEYWORD(__builtin_choose_expr , KEYALL) KEYWORD(__builtin_offsetof , KEYALL) -KEYWORD(__builtin_types_compatible_p, KEYALL) +// __builtin_types_compatible_p is a GNU C extension that we handle like a C++ +// type trait. +TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX) KEYWORD(__builtin_va_arg , KEYALL) KEYWORD(__extension__ , KEYALL) KEYWORD(__imag , KEYALL) @@ -350,43 +365,51 @@ KEYWORD(typeof , KEYGNU) // MS Extensions KEYWORD(__FUNCDNAME__ , KEYMS) +KEYWORD(__FUNCSIG__ , KEYMS) KEYWORD(L__FUNCTION__ , KEYMS) -KEYWORD(__is_interface_class , KEYMS) -KEYWORD(__is_sealed , KEYMS) +TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS) +TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS) + +// MSVC12.0 / VS2013 Type Traits +TYPE_TRAIT_1(__is_destructible, IsDestructible, KEYMS) +TYPE_TRAIT_1(__is_nothrow_destructible, IsNothrowDestructible, KEYMS) +TYPE_TRAIT_2(__is_nothrow_assignable, IsNothrowAssignable, KEYCXX) +TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYCXX) +TYPE_TRAIT_N(__is_nothrow_constructible, IsNothrowConstructible, KEYCXX) // GNU and MS Type Traits -KEYWORD(__has_nothrow_assign , KEYCXX) -KEYWORD(__has_nothrow_move_assign , KEYCXX) -KEYWORD(__has_nothrow_copy , KEYCXX) -KEYWORD(__has_nothrow_constructor , KEYCXX) -KEYWORD(__has_trivial_assign , KEYCXX) -KEYWORD(__has_trivial_move_assign , KEYCXX) -KEYWORD(__has_trivial_copy , KEYCXX) -KEYWORD(__has_trivial_constructor , KEYCXX) -KEYWORD(__has_trivial_move_constructor, KEYCXX) -KEYWORD(__has_trivial_destructor , KEYCXX) -KEYWORD(__has_virtual_destructor , KEYCXX) -KEYWORD(__is_abstract , KEYCXX) -KEYWORD(__is_base_of , KEYCXX) -KEYWORD(__is_class , KEYCXX) -KEYWORD(__is_convertible_to , KEYCXX) -KEYWORD(__is_empty , KEYCXX) -KEYWORD(__is_enum , KEYCXX) -KEYWORD(__is_final , KEYCXX) +TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX) +TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX) +TYPE_TRAIT_1(__has_nothrow_copy, HasNothrowCopy, KEYCXX) +TYPE_TRAIT_1(__has_nothrow_constructor, HasNothrowConstructor, KEYCXX) +TYPE_TRAIT_1(__has_trivial_assign, HasTrivialAssign, KEYCXX) +TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX) +TYPE_TRAIT_1(__has_trivial_copy, HasTrivialCopy, KEYCXX) +TYPE_TRAIT_1(__has_trivial_constructor, HasTrivialDefaultConstructor, KEYCXX) +TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX) +TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX) +TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX) +TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX) +TYPE_TRAIT_2(__is_base_of, IsBaseOf, KEYCXX) +TYPE_TRAIT_1(__is_class, IsClass, KEYCXX) +TYPE_TRAIT_2(__is_convertible_to, IsConvertibleTo, KEYCXX) +TYPE_TRAIT_1(__is_empty, IsEmpty, KEYCXX) +TYPE_TRAIT_1(__is_enum, IsEnum, KEYCXX) +TYPE_TRAIT_1(__is_final, IsFinal, KEYCXX) // Tentative name - there's no implementation of std::is_literal_type yet. -KEYWORD(__is_literal , KEYCXX) +TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX) // Name for GCC 4.6 compatibility - people have already written libraries using // this name unfortunately. -KEYWORD(__is_literal_type , KEYCXX) -KEYWORD(__is_pod , KEYCXX) -KEYWORD(__is_polymorphic , KEYCXX) -KEYWORD(__is_trivial , KEYCXX) -KEYWORD(__is_union , KEYCXX) +ALIAS("__is_literal_type", __is_literal, KEYCXX) +TYPE_TRAIT_1(__is_pod, IsPOD, KEYCXX) +TYPE_TRAIT_1(__is_polymorphic, IsPolymorphic, KEYCXX) +TYPE_TRAIT_1(__is_trivial, IsTrivial, KEYCXX) +TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX) // Clang-only C++ Type Traits -KEYWORD(__is_trivially_constructible, KEYCXX) -KEYWORD(__is_trivially_copyable , KEYCXX) -KEYWORD(__is_trivially_assignable , KEYCXX) +TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX) +TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX) +TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX) KEYWORD(__underlying_type , KEYCXX) // Embarcadero Expression Traits @@ -394,33 +417,33 @@ KEYWORD(__is_lvalue_expr , KEYCXX) KEYWORD(__is_rvalue_expr , KEYCXX) // Embarcadero Unary Type Traits -KEYWORD(__is_arithmetic , KEYCXX) -KEYWORD(__is_floating_point , KEYCXX) -KEYWORD(__is_integral , KEYCXX) -KEYWORD(__is_complete_type , KEYCXX) -KEYWORD(__is_void , KEYCXX) -KEYWORD(__is_array , KEYCXX) -KEYWORD(__is_function , KEYCXX) -KEYWORD(__is_reference , KEYCXX) -KEYWORD(__is_lvalue_reference , KEYCXX) -KEYWORD(__is_rvalue_reference , KEYCXX) -KEYWORD(__is_fundamental , KEYCXX) -KEYWORD(__is_object , KEYCXX) -KEYWORD(__is_scalar , KEYCXX) -KEYWORD(__is_compound , KEYCXX) -KEYWORD(__is_pointer , KEYCXX) -KEYWORD(__is_member_object_pointer , KEYCXX) -KEYWORD(__is_member_function_pointer, KEYCXX) -KEYWORD(__is_member_pointer , KEYCXX) -KEYWORD(__is_const , KEYCXX) -KEYWORD(__is_volatile , KEYCXX) -KEYWORD(__is_standard_layout , KEYCXX) -KEYWORD(__is_signed , KEYCXX) -KEYWORD(__is_unsigned , KEYCXX) +TYPE_TRAIT_1(__is_arithmetic, IsArithmetic, KEYCXX) +TYPE_TRAIT_1(__is_floating_point, IsFloatingPoint, KEYCXX) +TYPE_TRAIT_1(__is_integral, IsIntegral, KEYCXX) +TYPE_TRAIT_1(__is_complete_type, IsCompleteType, KEYCXX) +TYPE_TRAIT_1(__is_void, IsVoid, KEYCXX) +TYPE_TRAIT_1(__is_array, IsArray, KEYCXX) +TYPE_TRAIT_1(__is_function, IsFunction, KEYCXX) +TYPE_TRAIT_1(__is_reference, IsReference, KEYCXX) +TYPE_TRAIT_1(__is_lvalue_reference, IsLvalueReference, KEYCXX) +TYPE_TRAIT_1(__is_rvalue_reference, IsRvalueReference, KEYCXX) +TYPE_TRAIT_1(__is_fundamental, IsFundamental, KEYCXX) +TYPE_TRAIT_1(__is_object, IsObject, KEYCXX) +TYPE_TRAIT_1(__is_scalar, IsScalar, KEYCXX) +TYPE_TRAIT_1(__is_compound, IsCompound, KEYCXX) +TYPE_TRAIT_1(__is_pointer, IsPointer, KEYCXX) +TYPE_TRAIT_1(__is_member_object_pointer, IsMemberObjectPointer, KEYCXX) +TYPE_TRAIT_1(__is_member_function_pointer, IsMemberFunctionPointer, KEYCXX) +TYPE_TRAIT_1(__is_member_pointer, IsMemberPointer, KEYCXX) +TYPE_TRAIT_1(__is_const, IsConst, KEYCXX) +TYPE_TRAIT_1(__is_volatile, IsVolatile, KEYCXX) +TYPE_TRAIT_1(__is_standard_layout, IsStandardLayout, KEYCXX) +TYPE_TRAIT_1(__is_signed, IsSigned, KEYCXX) +TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX) // Embarcadero Binary Type Traits -KEYWORD(__is_same , KEYCXX) -KEYWORD(__is_convertible , KEYCXX) +TYPE_TRAIT_2(__is_same, IsSame, KEYCXX) +TYPE_TRAIT_2(__is_convertible, IsConvertible, KEYCXX) KEYWORD(__array_rank , KEYCXX) KEYWORD(__array_extent , KEYCXX) @@ -434,35 +457,31 @@ KEYWORD(__cdecl , KEYALL) KEYWORD(__stdcall , KEYALL) KEYWORD(__fastcall , KEYALL) KEYWORD(__thiscall , KEYALL) -KEYWORD(__forceinline , KEYALL) +KEYWORD(__forceinline , KEYMS) KEYWORD(__unaligned , KEYMS) -// OpenCL-specific keywords -KEYWORD(__kernel , KEYOPENCL) -ALIAS("kernel", __kernel , KEYOPENCL) -KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC) -KEYWORD(__private , KEYOPENCL) +// OpenCL address space qualifiers KEYWORD(__global , KEYOPENCL) KEYWORD(__local , KEYOPENCL) KEYWORD(__constant , KEYOPENCL) +KEYWORD(__private , KEYOPENCL) ALIAS("global", __global , KEYOPENCL) ALIAS("local", __local , KEYOPENCL) ALIAS("constant", __constant , KEYOPENCL) +ALIAS("private", __private , KEYOPENCL) +// OpenCL function qualifiers +KEYWORD(__kernel , KEYOPENCL) +ALIAS("kernel", __kernel , KEYOPENCL) +// OpenCL access qualifiers KEYWORD(__read_only , KEYOPENCL) KEYWORD(__write_only , KEYOPENCL) KEYWORD(__read_write , KEYOPENCL) ALIAS("read_only", __read_only , KEYOPENCL) ALIAS("write_only", __write_only , KEYOPENCL) ALIAS("read_write", __read_write , KEYOPENCL) +// OpenCL builtins KEYWORD(__builtin_astype , KEYOPENCL) -KEYWORD(image1d_t , KEYOPENCL) -KEYWORD(image1d_array_t , KEYOPENCL) -KEYWORD(image1d_buffer_t , KEYOPENCL) -KEYWORD(image2d_t , KEYOPENCL) -KEYWORD(image2d_array_t , KEYOPENCL) -KEYWORD(image3d_t , KEYOPENCL) -KEYWORD(sampler_t , KEYOPENCL) -KEYWORD(event_t , KEYOPENCL) +KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC) // Borland Extensions. KEYWORD(__pascal , KEYALL) @@ -475,7 +494,7 @@ KEYWORD(__pixel , KEYALTIVEC) ALIAS("__fp16", half , KEYALL) // OpenCL Extension. -KEYWORD(half , KEYOPENCL) +KEYWORD(half , HALFSUPPORT) // Objective-C ARC keywords. KEYWORD(__bridge , KEYARC) @@ -656,6 +675,21 @@ ANNOTATION(pragma_redefine_extname) // handles them. ANNOTATION(pragma_fp_contract) +// Annotation for #pragma pointers_to_members... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_ms_pointers_to_members) + +// Annotation for #pragma vtordisp... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_ms_vtordisp) + +// Annotation for all microsoft #pragmas... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_ms_pragma) + // Annotation for #pragma OPENCL EXTENSION... // The lexer produces these so that they only take effect when the parser // handles them. @@ -667,8 +701,15 @@ ANNOTATION(pragma_opencl_extension) ANNOTATION(pragma_openmp) ANNOTATION(pragma_openmp_end) -// Annotation for module import translated from #include etc. +// Annotations for loop pragma directives #pragma clang loop ... +// The lexer produces these so that they only take effect when the parser +// handles #pragma loop ... directives. +ANNOTATION(pragma_loop_hint) + +// Annotations for module import translated from #include etc. ANNOTATION(module_include) +ANNOTATION(module_begin) +ANNOTATION(module_end) #undef ANNOTATION #undef TESTING_KEYWORD @@ -677,6 +718,10 @@ ANNOTATION(module_include) #undef CXX_KEYWORD_OPERATOR #undef PPKEYWORD #undef ALIAS +#undef TYPE_TRAIT_N +#undef TYPE_TRAIT_2 +#undef TYPE_TRAIT_1 +#undef TYPE_TRAIT #undef KEYWORD #undef PUNCTUATOR #undef TOK diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h index dcbe1da..794625c 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h @@ -15,12 +15,14 @@ #ifndef LLVM_CLANG_TOKENKINDS_H #define LLVM_CLANG_TOKENKINDS_H +#include "llvm/Support/Compiler.h" + namespace clang { namespace tok { /// \brief Provides a simple uniform namespace for tokens from all C languages. -enum TokenKind { +enum TokenKind : unsigned short { #define TOK(X) X, #include "clang/Basic/TokenKinds.def" NUM_TOKENS @@ -52,7 +54,7 @@ enum OnOffSwitch { /// /// The name of a token will be an internal name (such as "l_square") /// and should not be used as part of diagnostic messages. -const char *getTokenName(enum TokenKind Kind); +const char *getTokenName(TokenKind Kind) LLVM_READNONE; /// \brief Determines the spelling of simple punctuation tokens like /// '!' or '%', and returns NULL for literal and annotation tokens. @@ -61,7 +63,11 @@ const char *getTokenName(enum TokenKind Kind); /// and will not produce any alternative spellings (e.g., a /// digraph). For the actual spelling of a given Token, use /// Preprocessor::getSpelling(). -const char *getTokenSimpleSpelling(enum TokenKind Kind); +const char *getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE; + +/// \brief Determines the spelling of simple keyword and contextual keyword +/// tokens like 'int' and 'dynamic_cast'. Returns NULL for other token kinds. +const char *getKeywordSpelling(TokenKind Kind) LLVM_READNONE; /// \brief Return true if this is a raw identifier or an identifier kind. inline bool isAnyIdentifier(TokenKind K) { diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h index fc53527..d7d2b18 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h @@ -17,8 +17,8 @@ namespace clang { - /// \brief Names for the unary type traits. - enum UnaryTypeTrait { + /// \brief Names for traits that operate specifically on types. + enum TypeTrait { UTT_HasNothrowAssign, UTT_HasNothrowMoveAssign, UTT_HasNothrowCopy, @@ -37,6 +37,7 @@ namespace clang { UTT_IsCompleteType, UTT_IsCompound, UTT_IsConst, + UTT_IsDestructible, UTT_IsEmpty, UTT_IsEnum, UTT_IsFinal, @@ -50,6 +51,7 @@ namespace clang { UTT_IsMemberFunctionPointer, UTT_IsMemberObjectPointer, UTT_IsMemberPointer, + UTT_IsNothrowDestructible, UTT_IsObject, UTT_IsPOD, UTT_IsPointer, @@ -65,17 +67,19 @@ namespace clang { UTT_IsUnion, UTT_IsUnsigned, UTT_IsVoid, - UTT_IsVolatile - }; - - /// \brief Names for the binary type traits. - enum BinaryTypeTrait { + UTT_IsVolatile, + UTT_Last = UTT_IsVolatile, BTT_IsBaseOf, BTT_IsConvertible, BTT_IsConvertibleTo, BTT_IsSame, BTT_TypeCompatible, - BTT_IsTriviallyAssignable + BTT_IsNothrowAssignable, + BTT_IsTriviallyAssignable, + BTT_Last = BTT_IsTriviallyAssignable, + TT_IsConstructible, + TT_IsNothrowConstructible, + TT_IsTriviallyConstructible }; /// \brief Names for the array type traits. @@ -90,12 +94,6 @@ namespace clang { UETT_AlignOf, UETT_VecStep }; - - /// \brief Names for type traits that operate specifically on types. - enum TypeTrait { - TT_IsTriviallyConstructible - }; - } #endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Version.h b/contrib/llvm/tools/clang/include/clang/Basic/Version.h index 7db8a2e..02da432 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Version.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Version.h @@ -70,6 +70,9 @@ namespace clang { /// and the vendor tag. std::string getClangFullVersion(); + /// \brief Like getClangFullVersion(), but with a custom tool name. + std::string getClangToolFullVersion(llvm::StringRef ToolName); + /// \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. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h b/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h index ff06a5c..54d06e0 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h @@ -18,6 +18,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/Optional.h" #include <string> +#include <tuple> namespace clang { @@ -87,13 +88,8 @@ public: /// 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; - - if (X.Minor != Y.Minor) - return X.Minor < Y.Minor; - - return X.Subminor < Y.Subminor; + return std::tie(X.Major, X.Minor, X.Subminor) < + std::tie(Y.Major, Y.Minor, Y.Subminor); } /// \brief Determine whether one version number follows another. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h new file mode 100644 index 0000000..36f78fd --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h @@ -0,0 +1,283 @@ +//===- VirtualFileSystem.h - Virtual File System Layer ----------*- 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 the virtual file system interface vfs::FileSystem. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H +#define LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" + +namespace llvm { +class MemoryBuffer; +} + +namespace clang { +namespace vfs { + +/// \brief The result of a \p status operation. +class Status { + std::string Name; + llvm::sys::fs::UniqueID UID; + llvm::sys::TimeValue MTime; + uint32_t User; + uint32_t Group; + uint64_t Size; + llvm::sys::fs::file_type Type; + llvm::sys::fs::perms Perms; + +public: + bool IsVFSMapped; // FIXME: remove when files support multiple names + +public: + Status() : Type(llvm::sys::fs::file_type::status_error) {} + Status(const llvm::sys::fs::file_status &Status); + Status(StringRef Name, StringRef RealName, llvm::sys::fs::UniqueID UID, + llvm::sys::TimeValue MTime, uint32_t User, uint32_t Group, + uint64_t Size, llvm::sys::fs::file_type Type, + llvm::sys::fs::perms Perms); + + /// \brief Returns the name that should be used for this file or directory. + StringRef getName() const { return Name; } + void setName(StringRef N) { Name = N; } + + /// @name Status interface from llvm::sys::fs + /// @{ + llvm::sys::fs::file_type getType() const { return Type; } + llvm::sys::fs::perms getPermissions() const { return Perms; } + llvm::sys::TimeValue getLastModificationTime() const { return MTime; } + llvm::sys::fs::UniqueID getUniqueID() const { return UID; } + uint32_t getUser() const { return User; } + uint32_t getGroup() const { return Group; } + uint64_t getSize() const { return Size; } + void setType(llvm::sys::fs::file_type v) { Type = v; } + void setPermissions(llvm::sys::fs::perms p) { Perms = p; } + /// @} + /// @name Status queries + /// These are static queries in llvm::sys::fs. + /// @{ + bool equivalent(const Status &Other) const; + bool isDirectory() const; + bool isRegularFile() const; + bool isOther() const; + bool isSymlink() const; + bool isStatusKnown() const; + bool exists() const; + /// @} +}; + +/// \brief Represents an open file. +class File { +public: + /// \brief Destroy the file after closing it (if open). + /// Sub-classes should generally call close() inside their destructors. We + /// cannot do that from the base class, since close is virtual. + virtual ~File(); + /// \brief Get the status of the file. + virtual llvm::ErrorOr<Status> status() = 0; + /// \brief Get the contents of the file as a \p MemoryBuffer. + virtual std::error_code getBuffer(const Twine &Name, + std::unique_ptr<llvm::MemoryBuffer> &Result, + int64_t FileSize = -1, + bool RequiresNullTerminator = true, + bool IsVolatile = false) = 0; + /// \brief Closes the file. + virtual std::error_code close() = 0; + /// \brief Sets the name to use for this file. + virtual void setName(StringRef Name) = 0; +}; + +namespace detail { +/// \brief An interface for virtual file systems to provide an iterator over the +/// (non-recursive) contents of a directory. +struct DirIterImpl { + virtual ~DirIterImpl(); + /// \brief Sets \c CurrentEntry to the next entry in the directory on success, + /// or returns a system-defined \c error_code. + virtual std::error_code increment() = 0; + Status CurrentEntry; +}; +} // end namespace detail + +/// \brief An input iterator over the entries in a virtual path, similar to +/// llvm::sys::fs::directory_iterator. +class directory_iterator { + std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy + +public: + directory_iterator(std::shared_ptr<detail::DirIterImpl> I) : Impl(I) { + assert(Impl.get() != nullptr && "requires non-null implementation"); + if (!Impl->CurrentEntry.isStatusKnown()) + Impl.reset(); // Normalize the end iterator to Impl == nullptr. + } + + /// \brief Construct an 'end' iterator. + directory_iterator() { } + + /// \brief Equivalent to operator++, with an error code. + directory_iterator &increment(std::error_code &EC) { + assert(Impl && "attempting to increment past end"); + EC = Impl->increment(); + if (EC || !Impl->CurrentEntry.isStatusKnown()) + Impl.reset(); // Normalize the end iterator to Impl == nullptr. + return *this; + } + + const Status &operator*() const { return Impl->CurrentEntry; } + const Status *operator->() const { return &Impl->CurrentEntry; } + + bool operator==(const directory_iterator &RHS) const { + if (Impl && RHS.Impl) + return Impl->CurrentEntry.equivalent(RHS.Impl->CurrentEntry); + return !Impl && !RHS.Impl; + } + bool operator!=(const directory_iterator &RHS) const { + return !(*this == RHS); + } +}; + +class FileSystem; + +/// \brief An input iterator over the recursive contents of a virtual path, +/// similar to llvm::sys::fs::recursive_directory_iterator. +class recursive_directory_iterator { + typedef std::stack<directory_iterator, std::vector<directory_iterator>> + IterState; + + FileSystem *FS; + std::shared_ptr<IterState> State; // Input iterator semantics on copy. + +public: + recursive_directory_iterator(FileSystem &FS, const Twine &Path, + std::error_code &EC); + /// \brief Construct an 'end' iterator. + recursive_directory_iterator() { } + + /// \brief Equivalent to operator++, with an error code. + recursive_directory_iterator &increment(std::error_code &EC); + + const Status &operator*() const { return *State->top(); } + const Status *operator->() const { return &*State->top(); } + + bool operator==(const recursive_directory_iterator &Other) const { + return State == Other.State; // identity + } + bool operator!=(const recursive_directory_iterator &RHS) const { + return !(*this == RHS); + } +}; + +/// \brief The virtual file system interface. +class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> { +public: + virtual ~FileSystem(); + + /// \brief Get the status of the entry at \p Path, if one exists. + virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0; + /// \brief Get a \p File object for the file at \p Path, if one exists. + virtual std::error_code openFileForRead(const Twine &Path, + std::unique_ptr<File> &Result) = 0; + + /// This is a convenience method that opens a file, gets its content and then + /// closes the file. + std::error_code getBufferForFile(const Twine &Name, + std::unique_ptr<llvm::MemoryBuffer> &Result, + int64_t FileSize = -1, + bool RequiresNullTerminator = true, + bool IsVolatile = false); + + /// \brief Get a directory_iterator for \p Dir. + /// \note The 'end' iterator is directory_iterator(). + virtual directory_iterator dir_begin(const Twine &Dir, + std::error_code &EC) = 0; +}; + +/// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by +/// the operating system. +IntrusiveRefCntPtr<FileSystem> getRealFileSystem(); + +/// \brief A file system that allows overlaying one \p AbstractFileSystem on top +/// of another. +/// +/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being +/// one merged file system. When there is a directory that exists in more than +/// one file system, the \p OverlayFileSystem contains a directory containing +/// the union of their contents. The attributes (permissions, etc.) of the +/// top-most (most recently added) directory are used. When there is a file +/// that exists in more than one file system, the file in the top-most file +/// system overrides the other(s). +class OverlayFileSystem : public FileSystem { + typedef SmallVector<IntrusiveRefCntPtr<FileSystem>, 1> FileSystemList; + /// \brief The stack of file systems, implemented as a list in order of + /// their addition. + FileSystemList FSList; + +public: + OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> Base); + /// \brief Pushes a file system on top of the stack. + void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS); + + llvm::ErrorOr<Status> status(const Twine &Path) override; + std::error_code openFileForRead(const Twine &Path, + std::unique_ptr<File> &Result) override; + directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; + + typedef FileSystemList::reverse_iterator iterator; + + /// \brief Get an iterator pointing to the most recently added file system. + iterator overlays_begin() { return FSList.rbegin(); } + + /// \brief Get an iterator pointing one-past the least recently added file + /// system. + iterator overlays_end() { return FSList.rend(); } +}; + +/// \brief Get a globally unique ID for a virtual file or directory. +llvm::sys::fs::UniqueID getNextVirtualUniqueID(); + +/// \brief Gets a \p FileSystem for a virtual file system described in YAML +/// format. +/// +/// Takes ownership of \p Buffer. +IntrusiveRefCntPtr<FileSystem> +getVFSFromYAML(llvm::MemoryBuffer *Buffer, + llvm::SourceMgr::DiagHandlerTy DiagHandler, + void *DiagContext = nullptr, + IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem()); + +struct YAMLVFSEntry { + template <typename T1, typename T2> YAMLVFSEntry(T1 &&VPath, T2 &&RPath) + : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {} + std::string VPath; + std::string RPath; +}; + +class YAMLVFSWriter { + std::vector<YAMLVFSEntry> Mappings; + Optional<bool> IsCaseSensitive; + +public: + YAMLVFSWriter() {} + void addFileMapping(StringRef VirtualPath, StringRef RealPath); + void setCaseSensitivity(bool CaseSensitive) { + IsCaseSensitive = CaseSensitive; + } + void write(llvm::raw_ostream &OS); +}; + +} // end namespace vfs +} // end namespace clang +#endif // LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H diff --git a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td index b918459..0247bb5 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td @@ -11,142 +11,265 @@ // file will be generated. See ARM document DUI0348B. // //===----------------------------------------------------------------------===// +// +// Each intrinsic is a subclass of the Inst class. An intrinsic can either +// generate a __builtin_* call or it can expand to a set of generic operations. +// +// The operations are subclasses of Operation providing a list of DAGs, the +// last of which is the return value. The available DAG nodes are documented +// below. +// +//===----------------------------------------------------------------------===// + +// The base Operation class. All operations must subclass this. +class Operation<list<dag> ops=[]> { + list<dag> Ops = ops; + bit Unavailable = 0; +} +// An operation that only contains a single DAG. +class Op<dag op> : Operation<[op]>; +// A shorter version of Operation - takes a list of DAGs. The last of these will +// be the return value. +class LOp<list<dag> ops> : Operation<ops>; + +// These defs and classes are used internally to implement the SetTheory +// expansion and should be ignored. +foreach Index = 0-63 in + def sv##Index; +class MaskExpand; + +//===----------------------------------------------------------------------===// +// Available operations +//===----------------------------------------------------------------------===// + +// DAG arguments can either be operations (documented below) or variables. +// Variables are prefixed with '$'. There are variables for each input argument, +// with the name $pN, where N starts at zero. So the zero'th argument will be +// $p0, the first $p1 etc. + +// op - Binary or unary operator, depending on the number of arguments. The +// operator itself is just treated as a raw string and is not checked. +// example: (op "+", $p0, $p1) -> "__p0 + __p1". +// (op "-", $p0) -> "-__p0" +def op; +// call - Invoke another intrinsic. The input types are type checked and +// disambiguated. If there is no intrinsic defined that takes +// the given types (or if there is a type ambiguity) an error is +// generated at tblgen time. The name of the intrinsic is the raw +// name as given to the Inst class (not mangled). +// example: (call "vget_high", $p0) -> "vgetq_high_s16(__p0)" +// (assuming $p0 has type int16x8_t). +def call; +// cast - Perform a cast to a different type. This gets emitted as a static +// C-style cast. For a pure reinterpret cast (T x = *(T*)&y), use +// "bitcast". +// +// The syntax is (cast MOD* VAL). The last argument is the value to +// cast, preceded by a sequence of type modifiers. The target type +// starts off as the type of VAL, and is modified by MOD in sequence. +// The available modifiers are: +// - $X - Take the type of parameter/variable X. For example: +// (cast $p0, $p1) would cast $p1 to the type of $p0. +// - "R" - The type of the return type. +// - A typedef string - A NEON or stdint.h type that is then parsed. +// for example: (cast "uint32x4_t", $p0). +// - "U" - Make the type unsigned. +// - "S" - Make the type signed. +// - "H" - Halve the number of lanes in the type. +// - "D" - Double the number of lanes in the type. +// - "8" - Convert type to an equivalent vector of 8-bit signed +// integers. +// example: (cast "R", "U", $p0) -> "(uint32x4_t)__p0" (assuming the return +// value is of type "int32x4_t". +// (cast $p0, "D", "8", $p1) -> "(int8x16_t)__p1" (assuming __p0 +// has type float64x1_t or any other vector type of 64 bits). +// (cast "int32_t", $p2) -> "(int32_t)__p2" +def cast; +// bitcast - Same as "cast", except a reinterpret-cast is produced: +// (bitcast "T", $p0) -> "*(T*)&__p0". +// The VAL argument is saved to a temporary so it can be used +// as an l-value. +def bitcast; +// dup - Take a scalar argument and create a vector by duplicating it into +// all lanes. The type of the vector is the base type of the intrinsic. +// example: (dup $p1) -> "(uint32x2_t) {__p1, __p1}" (assuming the base type +// is uint32x2_t). +def dup; +// splat - Take a vector and a lane index, and return a vector of the same type +// containing repeated instances of the source vector at the lane index. +// example: (splat $p0, $p1) -> +// "__builtin_shufflevector(__p0, __p0, __p1, __p1, __p1, __p1)" +// (assuming __p0 has four elements). +def splat; +// save_temp - Create a temporary (local) variable. The variable takes a name +// based on the zero'th parameter and can be referenced using +// using that name in subsequent DAGs in the same +// operation. The scope of a temp is the operation. If a variable +// with the given name already exists, an error will be given at +// tblgen time. +// example: [(save_temp $var, (call "foo", $p0)), +// (op "+", $var, $p1)] -> +// "int32x2_t __var = foo(__p0); return __var + __p1;" +def save_temp; +// name_replace - Return the name of the current intrinsic with the first +// argument replaced by the second argument. Raises an error if +// the first argument does not exist in the intrinsic name. +// example: (call (name_replace "_high_", "_"), $p0) (to call the non-high +// version of this intrinsic). +def name_replace; +// literal - Create a literal piece of code. The code is treated as a raw +// string, and must be given a type. The type is a stdint.h or +// NEON intrinsic type as given to (cast). +// example: (literal "int32_t", "0") +def literal; +// shuffle - Create a vector shuffle. The syntax is (shuffle ARG0, ARG1, MASK). +// The MASK argument is a set of elements. The elements are generated +// from the two special defs "mask0" and "mask1". "mask0" expands to +// the lane indices in sequence for ARG0, and "mask1" expands to +// the lane indices in sequence for ARG1. They can be used as-is, e.g. +// +// (shuffle $p0, $p1, mask0) -> $p0 +// (shuffle $p0, $p1, mask1) -> $p1 +// +// or, more usefully, they can be manipulated using the SetTheory +// operators plus some extra operators defined in the NEON emitter. +// The operators are described below. +// example: (shuffle $p0, $p1, (add (highhalf mask0), (highhalf mask1))) -> +// A concatenation of the high halves of the input vectors. +def shuffle; + +// add, interleave, decimate: These set operators are vanilla SetTheory +// operators and take their normal definition. +def add; +def interleave; +def decimate; +// rotl - Rotate set left by a number of elements. +// example: (rotl mask0, 3) -> [3, 4, 5, 6, 0, 1, 2] +def rotl; +// rotl - Rotate set right by a number of elements. +// example: (rotr mask0, 3) -> [4, 5, 6, 0, 1, 2, 3] +def rotr; +// highhalf - Take only the high half of the input. +// example: (highhalf mask0) -> [4, 5, 6, 7] (assuming mask0 had 8 elements) +def highhalf; +// highhalf - Take only the low half of the input. +// example: (lowhalf mask0) -> [0, 1, 2, 3] (assuming mask0 had 8 elements) +def lowhalf; +// rev - Perform a variable-width reversal of the elements. The zero'th argument +// is a width in bits to reverse. The lanes this maps to is determined +// based on the element width of the underlying type. +// example: (rev 32, mask0) -> [3, 2, 1, 0, 7, 6, 5, 4] (if 8-bit elements) +// example: (rev 32, mask0) -> [1, 0, 3, 2] (if 16-bit elements) +def rev; +// mask0 - The initial sequence of lanes for shuffle ARG0 +def mask0 : MaskExpand; +// mask0 - The initial sequence of lanes for shuffle ARG1 +def mask1 : MaskExpand; + +def OP_NONE : Operation; +def OP_UNAVAILABLE : Operation { + let Unavailable = 1; +} + +//===----------------------------------------------------------------------===// +// Instruction definitions +//===----------------------------------------------------------------------===// -class Op; - -def OP_NONE : Op; -def OP_UNAVAILABLE : Op; -def OP_ADD : Op; -def OP_ADDL : Op; -def OP_ADDLHi : Op; -def OP_ADDW : Op; -def OP_ADDWHi : Op; -def OP_SUB : Op; -def OP_SUBL : Op; -def OP_SUBLHi : Op; -def OP_SUBW : Op; -def OP_SUBWHi : Op; -def OP_MUL : Op; -def OP_MLA : Op; -def OP_MLAL : Op; -def OP_MULLHi : Op; -def OP_MULLHi_N : Op; -def OP_MLALHi : Op; -def OP_MLALHi_N : Op; -def OP_MLS : Op; -def OP_MLSL : Op; -def OP_MLSLHi : Op; -def OP_MLSLHi_N : Op; -def OP_MUL_N : Op; -def OP_MLA_N : Op; -def OP_MLS_N : Op; -def OP_FMLA_N : Op; -def OP_FMLS_N : Op; -def OP_MLAL_N : Op; -def OP_MLSL_N : Op; -def OP_MUL_LN: Op; -def OP_MULX_LN: Op; -def OP_MULL_LN : Op; -def OP_MULLHi_LN : Op; -def OP_MLA_LN: Op; -def OP_MLS_LN: Op; -def OP_MLAL_LN : Op; -def OP_MLALHi_LN : Op; -def OP_MLSL_LN : Op; -def OP_MLSLHi_LN : Op; -def OP_QDMULL_LN : Op; -def OP_QDMULLHi_LN : Op; -def OP_QDMLAL_LN : Op; -def OP_QDMLALHi_LN : Op; -def OP_QDMLSL_LN : Op; -def OP_QDMLSLHi_LN : Op; -def OP_QDMULH_LN : Op; -def OP_QRDMULH_LN : Op; -def OP_FMS_LN : Op; -def OP_FMS_LNQ : Op; -def OP_TRN1 : Op; -def OP_ZIP1 : Op; -def OP_UZP1 : Op; -def OP_TRN2 : Op; -def OP_ZIP2 : Op; -def OP_UZP2 : Op; -def OP_EQ : Op; -def OP_GE : Op; -def OP_LE : Op; -def OP_GT : Op; -def OP_LT : Op; -def OP_NEG : Op; -def OP_NOT : Op; -def OP_AND : Op; -def OP_OR : Op; -def OP_XOR : Op; -def OP_ANDN : Op; -def OP_ORN : Op; -def OP_CAST : Op; -def OP_HI : Op; -def OP_LO : Op; -def OP_CONC : Op; -def OP_DUP : Op; -def OP_DUP_LN: Op; -def OP_SEL : Op; -def OP_REV64 : Op; -def OP_REV32 : Op; -def OP_REV16 : Op; -def OP_XTN : Op; -def OP_SQXTUN : Op; -def OP_QXTN : Op; -def OP_VCVT_NA_HI : Op; -def OP_VCVT_EX_HI : Op; -def OP_VCVTX_HI : Op; -def OP_REINT : Op; -def OP_ADDHNHi : Op; -def OP_RADDHNHi : Op; -def OP_SUBHNHi : Op; -def OP_RSUBHNHi : Op; -def OP_ABDL : Op; -def OP_ABDLHi : Op; -def OP_ABA : Op; -def OP_ABAL : Op; -def OP_ABALHi : Op; -def OP_QDMULLHi : Op; -def OP_QDMULLHi_N : Op; -def OP_QDMLALHi : Op; -def OP_QDMLALHi_N : Op; -def OP_QDMLSLHi : Op; -def OP_QDMLSLHi_N : Op; -def OP_DIV : Op; -def OP_LONG_HI : Op; -def OP_NARROW_HI : Op; -def OP_MOVL_HI : Op; -def OP_COPY_LN : Op; -def OP_COPYQ_LN : Op; -def OP_COPY_LNQ : Op; -def OP_SCALAR_MUL_LN : Op; -def OP_SCALAR_MUL_LNQ : Op; -def OP_SCALAR_MULX_LN : Op; -def OP_SCALAR_MULX_LNQ : Op; -def OP_SCALAR_VMULX_LN : Op; -def OP_SCALAR_VMULX_LNQ : Op; -def OP_SCALAR_QDMULL_LN : Op; -def OP_SCALAR_QDMULL_LNQ : Op; -def OP_SCALAR_QDMULH_LN : Op; -def OP_SCALAR_QDMULH_LNQ : Op; -def OP_SCALAR_QRDMULH_LN : Op; -def OP_SCALAR_QRDMULH_LNQ : Op; -def OP_SCALAR_GET_LN : Op; -def OP_SCALAR_SET_LN : Op; - -class Inst <string n, string p, string t, Op o> { +// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and +// a sequence of typespecs. +// +// The name is the base name of the intrinsic, for example "vget_lane". This is +// then mangled by the tblgen backend to add type information ("vget_lane_s16"). +// +// A typespec is a sequence of uppercase characters (modifiers) followed by one +// lowercase character. A typespec encodes a particular "base type" of the +// intrinsic. +// +// An example typespec is "Qs" - quad-size short - uint16x8_t. The available +// typespec codes are given below. +// +// The string given to an Inst class is a sequence of typespecs. The intrinsic +// is instantiated for every typespec in the sequence. For example "sdQsQd". +// +// The prototype is a string that defines the return type of the intrinsic +// and the type of each argument. The return type and every argument gets a +// "modifier" that can change in some way the "base type" of the intrinsic. +// +// The modifier 'd' means "default" and does not modify the base type in any +// way. The available modifiers are given below. +// +// Typespecs +// --------- +// c: char +// s: short +// i: int +// l: long +// k: 128-bit long +// f: float +// h: half-float +// d: double +// +// Typespec modifiers +// ------------------ +// S: scalar, only used for function mangling. +// U: unsigned +// Q: 128b +// H: 128b without mangling 'q' +// P: polynomial +// +// Prototype modifiers +// ------------------- +// prototype: return (arg, arg, ...) +// +// v: void +// t: best-fit integer (int/poly args) +// x: signed integer (int/float args) +// u: unsigned integer (int/float args) +// f: float (int args) +// F: double (int args) +// d: default +// g: default, ignore 'Q' size modifier. +// j: default, force 'Q' size modifier. +// w: double width elements, same num elts +// n: double width elements, half num elts +// h: half width elements, double num elts +// q: half width elements, quad num elts +// e: half width elements, double num elts, unsigned +// m: half width elements, same num elts +// i: constant int +// l: constant uint64 +// s: scalar of element type +// z: scalar of half width element type, signed +// r: scalar of double width element type, signed +// a: scalar of element type (splat to vector type) +// b: scalar of unsigned integer/long type (int/float args) +// $: scalar of signed integer/long type (int/float args) +// y: scalar of float +// o: scalar of double +// k: default elt width, double num elts +// 2,3,4: array of default vectors +// B,C,D: array of default elts, force 'Q' size modifier. +// p: pointer type +// c: const pointer type + +// Every intrinsic subclasses Inst. +class Inst <string n, string p, string t, Operation o> { string Name = n; string Prototype = p; string Types = t; - Op Operand = o; + string ArchGuard = ""; + + Operation Operation = o; + bit CartesianProductOfTypes = 0; + bit BigEndianSafe = 0; bit isShift = 0; bit isScalarShift = 0; bit isScalarNarrowShift = 0; bit isVCVT_N = 0; - bit isA64 = 0; - bit isCrypto = 0; + // For immediate checks: the immediate will be assumed to specify the lane of + // a Q register. Only used for intrinsics which end up calling polymorphic + // builtins. + bit isLaneQ = 0; // Certain intrinsics have different names than their representative // instructions. This field allows us to handle this correctly when we @@ -181,59 +304,193 @@ class WInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {} // WOpInst: Instruction with bit size only suffix (e.g., "8"). // LOpInst: Logical instruction with no bit size suffix. // NoTestOpInst: Intrinsic that has no corresponding instruction. -class SOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {} -class IOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {} -class WOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {} -class LOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {} -class NoTestOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {} +class SOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} +class IOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} +class WOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} +class LOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} +class NoTestOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} -// prototype: return (arg, arg, ...) -// v: void -// t: best-fit integer (int/poly args) -// x: signed integer (int/float args) -// u: unsigned integer (int/float args) -// f: float (int args) -// F: double (int args) -// d: default -// g: default, ignore 'Q' size modifier. -// j: default, force 'Q' size modifier. -// w: double width elements, same num elts -// n: double width elements, half num elts -// h: half width elements, double num elts -// q: half width elements, quad num elts -// e: half width elements, double num elts, unsigned -// m: half width elements, same num elts -// i: constant int -// l: constant uint64 -// s: scalar of element type -// z: scalar of half width element type, signed -// r: scalar of double width element type, signed -// a: scalar of element type (splat to vector type) -// b: scalar of unsigned integer/long type (int/float args) -// $: scalar of signed integer/long type (int/float args) -// y: scalar of float -// o: scalar of double -// k: default elt width, double num elts -// 2,3,4: array of default vectors -// B,C,D: array of default elts, force 'Q' size modifier. -// p: pointer type -// c: const pointer type +//===----------------------------------------------------------------------===// +// Operations +//===----------------------------------------------------------------------===// -// sizes: -// c: char -// s: short -// i: int -// l: long -// f: float -// h: half-float -// d: double +def OP_ADD : Op<(op "+", $p0, $p1)>; +def OP_ADDL : Op<(op "+", (call "vmovl", $p0), (call "vmovl", $p1))>; +def OP_ADDLHi : Op<(op "+", (call "vmovl_high", $p0), + (call "vmovl_high", $p1))>; +def OP_ADDW : Op<(op "+", $p0, (call "vmovl", $p1))>; +def OP_ADDWHi : Op<(op "+", $p0, (call "vmovl_high", $p1))>; +def OP_SUB : Op<(op "-", $p0, $p1)>; +def OP_SUBL : Op<(op "-", (call "vmovl", $p0), (call "vmovl", $p1))>; +def OP_SUBLHi : Op<(op "-", (call "vmovl_high", $p0), + (call "vmovl_high", $p1))>; +def OP_SUBW : Op<(op "-", $p0, (call "vmovl", $p1))>; +def OP_SUBWHi : Op<(op "-", $p0, (call "vmovl_high", $p1))>; +def OP_MUL : Op<(op "*", $p0, $p1)>; +def OP_MLA : Op<(op "+", $p0, (op "*", $p1, $p2))>; +def OP_MLAL : Op<(op "+", $p0, (call "vmull", $p1, $p2))>; +def OP_MULLHi : Op<(call "vmull", (call "vget_high", $p0), + (call "vget_high", $p1))>; +def OP_MULLHi_P64 : Op<(call "vmull", + (cast "poly64_t", (call "vget_high", $p0)), + (cast "poly64_t", (call "vget_high", $p1)))>; +def OP_MULLHi_N : Op<(call "vmull_n", (call "vget_high", $p0), $p1)>; +def OP_MLALHi : Op<(call "vmlal", $p0, (call "vget_high", $p1), + (call "vget_high", $p2))>; +def OP_MLALHi_N : Op<(call "vmlal_n", $p0, (call "vget_high", $p1), $p2)>; +def OP_MLS : Op<(op "-", $p0, (op "*", $p1, $p2))>; +def OP_MLSL : Op<(op "-", $p0, (call "vmull", $p1, $p2))>; +def OP_MLSLHi : Op<(call "vmlsl", $p0, (call "vget_high", $p1), + (call "vget_high", $p2))>; +def OP_MLSLHi_N : Op<(call "vmlsl_n", $p0, (call "vget_high", $p1), $p2)>; +def OP_MUL_N : Op<(op "*", $p0, (dup $p1))>; +def OP_MLA_N : Op<(op "+", $p0, (op "*", $p1, (dup $p2)))>; +def OP_MLS_N : Op<(op "-", $p0, (op "*", $p1, (dup $p2)))>; +def OP_FMLA_N : Op<(call "vfma", $p0, $p1, (dup $p2))>; +def OP_FMLS_N : Op<(call "vfms", $p0, $p1, (dup $p2))>; +def OP_MLAL_N : Op<(op "+", $p0, (call "vmull", $p1, (dup $p2)))>; +def OP_MLSL_N : Op<(op "-", $p0, (call "vmull", $p1, (dup $p2)))>; +def OP_MUL_LN : Op<(op "*", $p0, (splat $p1, $p2))>; +def OP_MULX_LN : Op<(call "vmulx", $p0, (splat $p1, $p2))>; +def OP_MULL_LN : Op<(call "vmull", $p0, (splat $p1, $p2))>; +def OP_MULLHi_LN: Op<(call "vmull", (call "vget_high", $p0), (splat $p1, $p2))>; +def OP_MLA_LN : Op<(op "+", $p0, (op "*", $p1, (splat $p2, $p3)))>; +def OP_MLS_LN : Op<(op "-", $p0, (op "*", $p1, (splat $p2, $p3)))>; +def OP_MLAL_LN : Op<(op "+", $p0, (call "vmull", $p1, (splat $p2, $p3)))>; +def OP_MLALHi_LN: Op<(op "+", $p0, (call "vmull", (call "vget_high", $p1), + (splat $p2, $p3)))>; +def OP_MLSL_LN : Op<(op "-", $p0, (call "vmull", $p1, (splat $p2, $p3)))>; +def OP_MLSLHi_LN : Op<(op "-", $p0, (call "vmull", (call "vget_high", $p1), + (splat $p2, $p3)))>; +def OP_QDMULL_LN : Op<(call "vqdmull", $p0, (splat $p1, $p2))>; +def OP_QDMULLHi_LN : Op<(call "vqdmull", (call "vget_high", $p0), + (splat $p1, $p2))>; +def OP_QDMLAL_LN : Op<(call "vqdmlal", $p0, $p1, (splat $p2, $p3))>; +def OP_QDMLALHi_LN : Op<(call "vqdmlal", $p0, (call "vget_high", $p1), + (splat $p2, $p3))>; +def OP_QDMLSL_LN : Op<(call "vqdmlsl", $p0, $p1, (splat $p2, $p3))>; +def OP_QDMLSLHi_LN : Op<(call "vqdmlsl", $p0, (call "vget_high", $p1), + (splat $p2, $p3))>; +def OP_QDMULH_LN : Op<(call "vqdmulh", $p0, (splat $p1, $p2))>; +def OP_QRDMULH_LN : Op<(call "vqrdmulh", $p0, (splat $p1, $p2))>; +def OP_FMS_LN : Op<(call "vfma_lane", $p0, $p1, (op "-", $p2), $p3)>; +def OP_FMS_LNQ : Op<(call "vfma_laneq", $p0, $p1, (op "-", $p2), $p3)>; +def OP_TRN1 : Op<(shuffle $p0, $p1, (interleave (decimate mask0, 2), + (decimate mask1, 2)))>; +def OP_ZIP1 : Op<(shuffle $p0, $p1, (lowhalf (interleave mask0, mask1)))>; +def OP_UZP1 : Op<(shuffle $p0, $p1, (add (decimate mask0, 2), + (decimate mask1, 2)))>; +def OP_TRN2 : Op<(shuffle $p0, $p1, (interleave + (decimate (rotl mask0, 1), 2), + (decimate (rotl mask1, 1), 2)))>; +def OP_ZIP2 : Op<(shuffle $p0, $p1, (highhalf (interleave mask0, mask1)))>; +def OP_UZP2 : Op<(shuffle $p0, $p1, (add (decimate (rotl mask0, 1), 2), + (decimate (rotl mask1, 1), 2)))>; +def OP_EQ : Op<(cast "R", (op "==", $p0, $p1))>; +def OP_GE : Op<(cast "R", (op ">=", $p0, $p1))>; +def OP_LE : Op<(cast "R", (op "<=", $p0, $p1))>; +def OP_GT : Op<(cast "R", (op ">", $p0, $p1))>; +def OP_LT : Op<(cast "R", (op "<", $p0, $p1))>; +def OP_NEG : Op<(op "-", $p0)>; +def OP_NOT : Op<(op "~", $p0)>; +def OP_AND : Op<(op "&", $p0, $p1)>; +def OP_OR : Op<(op "|", $p0, $p1)>; +def OP_XOR : Op<(op "^", $p0, $p1)>; +def OP_ANDN : Op<(op "&", $p0, (op "~", $p1))>; +def OP_ORN : Op<(op "|", $p0, (op "~", $p1))>; +def OP_CAST : Op<(cast "R", $p0)>; +def OP_HI : Op<(shuffle $p0, $p0, (highhalf mask0))>; +def OP_LO : Op<(shuffle $p0, $p0, (lowhalf mask0))>; +def OP_CONC : Op<(shuffle $p0, $p1, (add mask0, mask1))>; +def OP_DUP : Op<(dup $p0)>; +def OP_DUP_LN : Op<(splat $p0, $p1)>; +def OP_SEL : Op<(cast "R", (op "|", + (op "&", $p0, (cast $p0, $p1)), + (op "&", (op "~", $p0), (cast $p0, $p2))))>; +def OP_REV16 : Op<(shuffle $p0, $p0, (rev 16, mask0))>; +def OP_REV32 : Op<(shuffle $p0, $p0, (rev 32, mask0))>; +def OP_REV64 : Op<(shuffle $p0, $p0, (rev 64, mask0))>; +def OP_XTN : Op<(call "vcombine", $p0, (call "vmovn", $p1))>; +def OP_SQXTUN : Op<(call "vcombine", (cast $p0, "U", $p0), + (call "vqmovun", $p1))>; +def OP_QXTN : Op<(call "vcombine", $p0, (call "vqmovn", $p1))>; +def OP_VCVT_NA_HI_F16 : Op<(call "vcombine", $p0, (call "vcvt_f16", $p1))>; +def OP_VCVT_NA_HI_F32 : Op<(call "vcombine", $p0, (call "vcvt_f32_f64", $p1))>; +def OP_VCVT_EX_HI_F32 : Op<(call "vcvt_f32_f16", (call "vget_high", $p0))>; +def OP_VCVT_EX_HI_F64 : Op<(call "vcvt_f64_f32", (call "vget_high", $p0))>; +def OP_VCVTX_HI : Op<(call "vcombine", $p0, (call "vcvtx_f32", $p1))>; +def OP_REINT : Op<(cast "R", $p0)>; +def OP_ADDHNHi : Op<(call "vcombine", $p0, (call "vaddhn", $p1, $p2))>; +def OP_RADDHNHi : Op<(call "vcombine", $p0, (call "vraddhn", $p1, $p2))>; +def OP_SUBHNHi : Op<(call "vcombine", $p0, (call "vsubhn", $p1, $p2))>; +def OP_RSUBHNHi : Op<(call "vcombine", $p0, (call "vrsubhn", $p1, $p2))>; +def OP_ABDL : Op<(cast "R", (call "vmovl", (cast $p0, "U", + (call "vabd", $p0, $p1))))>; +def OP_ABDLHi : Op<(call "vabdl", (call "vget_high", $p0), + (call "vget_high", $p1))>; +def OP_ABA : Op<(op "+", $p0, (call "vabd", $p1, $p2))>; +def OP_ABAL : Op<(op "+", $p0, (call "vabdl", $p1, $p2))>; +def OP_ABALHi : Op<(call "vabal", $p0, (call "vget_high", $p1), + (call "vget_high", $p2))>; +def OP_QDMULLHi : Op<(call "vqdmull", (call "vget_high", $p0), + (call "vget_high", $p1))>; +def OP_QDMULLHi_N : Op<(call "vqdmull_n", (call "vget_high", $p0), $p1)>; +def OP_QDMLALHi : Op<(call "vqdmlal", $p0, (call "vget_high", $p1), + (call "vget_high", $p2))>; +def OP_QDMLALHi_N : Op<(call "vqdmlal_n", $p0, (call "vget_high", $p1), $p2)>; +def OP_QDMLSLHi : Op<(call "vqdmlsl", $p0, (call "vget_high", $p1), + (call "vget_high", $p2))>; +def OP_QDMLSLHi_N : Op<(call "vqdmlsl_n", $p0, (call "vget_high", $p1), $p2)>; +def OP_DIV : Op<(op "/", $p0, $p1)>; +def OP_LONG_HI : Op<(cast "R", (call (name_replace "_high_", "_"), + (call "vget_high", $p0), $p1))>; +def OP_NARROW_HI : Op<(cast "R", (call "vcombine", + (cast "R", "H", $p0), + (cast "R", "H", + (call (name_replace "_high_", "_"), + $p1, $p2))))>; +def OP_MOVL_HI : LOp<[(save_temp $a1, (call "vget_high", $p0)), + (cast "R", + (call "vshll_n", $a1, (literal "int32_t", "0")))]>; +def OP_COPY_LN : Op<(call "vset_lane", (call "vget_lane", $p2, $p3), $p0, $p1)>; +def OP_SCALAR_MUL_LN : Op<(op "*", $p0, (call "vget_lane", $p1, $p2))>; +def OP_SCALAR_MULX_LN : Op<(call "vmulx", $p0, (call "vget_lane", $p1, $p2))>; +def OP_SCALAR_VMULX_LN : LOp<[(save_temp $x, (call "vget_lane", $p0, + (literal "int32_t", "0"))), + (save_temp $y, (call "vget_lane", $p1, $p2)), + (save_temp $z, (call "vmulx", $x, $y)), + (call "vset_lane", $z, $p0, $p2)]>; +def OP_SCALAR_VMULX_LNQ : LOp<[(save_temp $x, (call "vget_lane", $p0, + (literal "int32_t", "0"))), + (save_temp $y, (call "vget_lane", $p1, $p2)), + (save_temp $z, (call "vmulx", $x, $y)), + (call "vset_lane", $z, $p0, (literal "int32_t", + "0"))]>; +class ScalarMulOp<string opname> : + Op<(call opname, $p0, (call "vget_lane", $p1, $p2))>; + +def OP_SCALAR_QDMULL_LN : ScalarMulOp<"vqdmull">; +def OP_SCALAR_QDMULH_LN : ScalarMulOp<"vqdmulh">; +def OP_SCALAR_QRDMULH_LN : ScalarMulOp<"vqrdmulh">; + +def OP_SCALAR_HALF_GET_LN : Op<(bitcast "float16_t", + (call "vget_lane", + (bitcast "int16x4_t", $p0), $p1))>; +def OP_SCALAR_HALF_GET_LNQ : Op<(bitcast "float16_t", + (call "vget_lane", + (bitcast "int16x8_t", $p0), $p1))>; +def OP_SCALAR_HALF_SET_LN : Op<(bitcast "float16x4_t", + (call "vset_lane", + (bitcast "int16_t", $p0), + (bitcast "int16x4_t", $p1), $p2))>; +def OP_SCALAR_HALF_SET_LNQ : Op<(bitcast "float16x8_t", + (call "vset_lane", + (bitcast "int16_t", $p0), + (bitcast "int16x8_t", $p1), $p2))>; -// size modifiers: -// S: scalar, only used for function mangling. -// U: unsigned -// Q: 128b -// H: 128b without mangling 'q' -// P: polynomial +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// //////////////////////////////////////////////////////////////////////////////// // E.3.1 Addition @@ -398,15 +655,19 @@ def VSET_LANE : IInst<"vset_lane", "dsdi", //////////////////////////////////////////////////////////////////////////////// // E.3.18 Initialize a vector from bit pattern -def VCREATE : NoTestOpInst<"vcreate", "dl", "csihfUcUsUiUlPcPsl", OP_CAST>; +def VCREATE : NoTestOpInst<"vcreate", "dl", "csihfUcUsUiUlPcPsl", OP_CAST> { + let BigEndianSafe = 1; +} //////////////////////////////////////////////////////////////////////////////// // E.3.19 Set all lanes to same value let InstName = "vmov" in { def VDUP_N : WOpInst<"vdup_n", "ds", - "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; + "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl", + OP_DUP>; def VMOV_N : WOpInst<"vmov_n", "ds", - "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; + "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl", + OP_DUP>; } let InstName = "" in def VDUP_LANE: WOpInst<"vdup_lane", "dgi", @@ -530,7 +791,11 @@ def VUZP : WInst<"vuzp", "2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">; // E.3.31 Vector reinterpret cast operations def VREINTERPRET : NoTestOpInst<"vreinterpret", "dd", - "csilUcUsUiUlhfPcPsQcQsQiQlQUcQUsQUiQUlQhQfQPcQPs", OP_REINT>; + "csilUcUsUiUlhfPcPsQcQsQiQlQUcQUsQUiQUlQhQfQPcQPs", OP_REINT> { + let CartesianProductOfTypes = 1; + let ArchGuard = "!defined(__aarch64__)"; + let BigEndianSafe = 1; +} //////////////////////////////////////////////////////////////////////////////// // Vector fused multiply-add operations @@ -540,87 +805,66 @@ def VFMA : SInst<"vfma", "dddd", "fQf">; //////////////////////////////////////////////////////////////////////////////// // AArch64 Intrinsics -let isA64 = 1 in { +let ArchGuard = "defined(__aarch64__)" in { //////////////////////////////////////////////////////////////////////////////// // Load/Store -// With additional QUl, Ql, d, Qd, Pl, QPl type. -def LD1 : WInst<"vld1", "dc", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">; -def LD2 : WInst<"vld2", "2c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">; -def LD3 : WInst<"vld3", "3c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">; -def LD4 : WInst<"vld4", "4c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">; -def ST1 : WInst<"vst1", "vpd", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">; -def ST2 : WInst<"vst2", "vp2", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">; -def ST3 : WInst<"vst3", "vp3", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">; -def ST4 : WInst<"vst4", "vp4", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">; +def LD1 : WInst<"vld1", "dc", "dQdPlQPl">; +def LD2 : WInst<"vld2", "2c", "QUlQldQdPlQPl">; +def LD3 : WInst<"vld3", "3c", "QUlQldQdPlQPl">; +def LD4 : WInst<"vld4", "4c", "QUlQldQdPlQPl">; +def ST1 : WInst<"vst1", "vpd", "dQdPlQPl">; +def ST2 : WInst<"vst2", "vp2", "QUlQldQdPlQPl">; +def ST3 : WInst<"vst3", "vp3", "QUlQldQdPlQPl">; +def ST4 : WInst<"vst4", "vp4", "QUlQldQdPlQPl">; def LD1_X2 : WInst<"vld1_x2", "2c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; + "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; def LD3_x3 : WInst<"vld1_x3", "3c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; + "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; def LD4_x4 : WInst<"vld1_x4", "4c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; + "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; def ST1_X2 : WInst<"vst1_x2", "vp2", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; + "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; def ST1_X3 : WInst<"vst1_x3", "vp3", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; + "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; def ST1_X4 : WInst<"vst1_x4", "vp4", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; - -// With additional QUl, Ql, d, Qd, Pl, QPl type. -def LD1_LANE : WInst<"vld1_lane", "dcdi", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; -def LD2_LANE : WInst<"vld2_lane", "2c2i", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; -def LD3_LANE : WInst<"vld3_lane", "3c3i", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; -def LD4_LANE : WInst<"vld4_lane", "4c4i", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; -def ST1_LANE : WInst<"vst1_lane", "vpdi", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; -def ST2_LANE : WInst<"vst2_lane", "vp2i", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; -def ST3_LANE : WInst<"vst3_lane", "vp3i", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; -def ST4_LANE : WInst<"vst4_lane", "vp4i", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; - -def LD1_DUP : WInst<"vld1_dup", "dc", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; + "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; + +def LD1_LANE : WInst<"vld1_lane", "dcdi", "dQdPlQPl">; +def LD2_LANE : WInst<"vld2_lane", "2c2i", "lUlQcQUcQPcQlQUldQdPlQPl">; +def LD3_LANE : WInst<"vld3_lane", "3c3i", "lUlQcQUcQPcQlQUldQdPlQPl">; +def LD4_LANE : WInst<"vld4_lane", "4c4i", "lUlQcQUcQPcQlQUldQdPlQPl">; +def ST1_LANE : WInst<"vst1_lane", "vpdi", "dQdPlQPl">; +def ST2_LANE : WInst<"vst2_lane", "vp2i", "lUlQcQUcQPcQlQUldQdPlQPl">; +def ST3_LANE : WInst<"vst3_lane", "vp3i", "lUlQcQUcQPcQlQUldQdPlQPl">; +def ST4_LANE : WInst<"vst4_lane", "vp4i", "lUlQcQUcQPcQlQUldQdPlQPl">; + +def LD1_DUP : WInst<"vld1_dup", "dc", "dQdPlQPl">; def LD2_DUP : WInst<"vld2_dup", "2c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; + "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">; def LD3_DUP : WInst<"vld3_dup", "3c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; + "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">; def LD4_DUP : WInst<"vld4_dup", "4c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">; + "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">; + +def VLDRQ : WInst<"vldrq", "sc", "Pk">; +def VSTRQ : WInst<"vstrq", "vps", "Pk">; //////////////////////////////////////////////////////////////////////////////// // Addition -// With additional d, Qd type. -def ADD : IOpInst<"vadd", "ddd", "csilfdUcUsUiUlQcQsQiQlQfQUcQUsQUiQUlQd", - OP_ADD>; +def ADD : IOpInst<"vadd", "ddd", "dQd", OP_ADD>; //////////////////////////////////////////////////////////////////////////////// // Subtraction -// With additional Qd type. -def SUB : IOpInst<"vsub", "ddd", "csildfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUlQd", - OP_SUB>; +def SUB : IOpInst<"vsub", "ddd", "dQd", OP_SUB>; //////////////////////////////////////////////////////////////////////////////// // Multiplication -// With additional Qd type. -def MUL : IOpInst<"vmul", "ddd", "csifdUcUsUiQcQsQiQfQUcQUsQUiQd", OP_MUL>; -def MLA : IOpInst<"vmla", "dddd", "csifdUcUsUiQcQsQiQfQUcQUsQUiQd", OP_MLA>; -def MLS : IOpInst<"vmls", "dddd", "csifdUcUsUiQcQsQiQfQUcQUsQUiQd", OP_MLS>; +def MUL : IOpInst<"vmul", "ddd", "dQd", OP_MUL>; +def MLA : IOpInst<"vmla", "dddd", "dQd", OP_MLA>; +def MLS : IOpInst<"vmls", "dddd", "dQd", OP_MLS>; //////////////////////////////////////////////////////////////////////////////// // Multiplication Extended @@ -632,34 +876,33 @@ def FDIV : IOpInst<"vdiv", "ddd", "fdQfQd", OP_DIV>; //////////////////////////////////////////////////////////////////////////////// // Vector fused multiply-add operations -// With additional d, Qd type. -def FMLA : SInst<"vfma", "dddd", "fdQfQd">; +def FMLA : SInst<"vfma", "dddd", "dQd">; def FMLS : SInst<"vfms", "dddd", "fdQfQd">; //////////////////////////////////////////////////////////////////////////////// -// MUL, FMA, FMS definitions with scalar argument +// MUL, MLA, MLS, FMA, FMS definitions with scalar argument def VMUL_N_A64 : IOpInst<"vmul_n", "dds", "Qd", OP_MUL_N>; -def FMLA_N : SOpInst<"vfma_n", "ddds", "fQf", OP_FMLA_N>; -def FMLS_N : SOpInst<"vfms_n", "ddds", "fQf", OP_FMLS_N>; + +def FMLA_N : SOpInst<"vfma_n", "ddds", "fQfQd", OP_FMLA_N>; +def FMLS_N : SOpInst<"vfms_n", "ddds", "fQfQd", OP_FMLS_N>; + +def MLA_N : SOpInst<"vmla_n", "ddds", "Qd", OP_MLA_N>; +def MLS_N : SOpInst<"vmls_n", "ddds", "Qd", OP_MLS_N>; //////////////////////////////////////////////////////////////////////////////// // Logical operations -// With additional Qd, Ql, QPl type. -def BSL : SInst<"vbsl", "dudd", - "csilUcUsUiUlfdPcPsQcQsQiQlQUcQUsQUiQUlQfQPcQPsQdPlQPl">; +def BSL : SInst<"vbsl", "dudd", "dPlQdQPl">; //////////////////////////////////////////////////////////////////////////////// // Absolute Difference -// With additional Qd type. -def ABD : SInst<"vabd", "ddd", "csiUcUsUifdQcQsQiQUcQUsQUiQfQd">; +def ABD : SInst<"vabd", "ddd", "dQd">; //////////////////////////////////////////////////////////////////////////////// // saturating absolute/negate -// With additional Qd/Ql type. -def ABS : SInst<"vabs", "dd", "csilfdQcQsQiQfQlQd">; -def QABS : SInst<"vqabs", "dd", "csilQcQsQiQl">; -def NEG : SOpInst<"vneg", "dd", "csilfdQcQsQiQfQdQl", OP_NEG>; -def QNEG : SInst<"vqneg", "dd", "csilQcQsQiQl">; +def ABS : SInst<"vabs", "dd", "dQdlQl">; +def QABS : SInst<"vqabs", "dd", "lQl">; +def NEG : SOpInst<"vneg", "dd", "dlQdQl", OP_NEG>; +def QNEG : SInst<"vqneg", "dd", "lQl">; //////////////////////////////////////////////////////////////////////////////// // Signed Saturating Accumulated of Unsigned Value @@ -671,9 +914,8 @@ def USQADD : SInst<"vsqadd", "ddd", "UcUsUiUlQUcQUsQUiQUl">; //////////////////////////////////////////////////////////////////////////////// // Reciprocal/Sqrt -// With additional d, Qd type. -def FRECPS : IInst<"vrecps", "ddd", "fdQfQd">; -def FRSQRTS : IInst<"vrsqrts", "ddd", "fdQfQd">; +def FRECPS : IInst<"vrecps", "ddd", "dQd">; +def FRSQRTS : IInst<"vrsqrts", "ddd", "dQd">; //////////////////////////////////////////////////////////////////////////////// // bitwise reverse @@ -693,13 +935,13 @@ def QXTN2 : SOpInst<"vqmovn_high", "qhk", "silUsUiUl", OP_QXTN>; //////////////////////////////////////////////////////////////////////////////// // Converting vectors -def VCVT_HIGH_F16 : SOpInst<"vcvt_high_f16", "qhj", "f", OP_VCVT_NA_HI>; -def VCVT_HIGH_F32_F16 : SOpInst<"vcvt_high_f32", "wk", "h", OP_VCVT_EX_HI>; -def VCVT_F32_F64 : SInst<"vcvt_f32_f64", "fj", "d">; -def VCVT_HIGH_F32_F64 : SOpInst<"vcvt_high_f32", "qfj", "d", OP_VCVT_NA_HI>; +def VCVT_HIGH_F16 : SOpInst<"vcvt_high_f16", "qhj", "f", OP_VCVT_NA_HI_F16>; +def VCVT_HIGH_F32_F16 : SOpInst<"vcvt_high_f32", "wk", "h", OP_VCVT_EX_HI_F32>; +def VCVT_F32_F64 : SInst<"vcvt_f32_f64", "md", "Qd">; +def VCVT_HIGH_F32_F64 : SOpInst<"vcvt_high_f32", "qfj", "d", OP_VCVT_NA_HI_F32>; def VCVT_F64_F32 : SInst<"vcvt_f64_f32", "wd", "f">; def VCVT_F64 : SInst<"vcvt_f64", "Fd", "lUlQlQUl">; -def VCVT_HIGH_F64_F32 : SOpInst<"vcvt_high_f64", "wj", "f", OP_VCVT_EX_HI>; +def VCVT_HIGH_F64_F32 : SOpInst<"vcvt_high_f64", "wj", "f", OP_VCVT_EX_HI_F64>; def VCVTX_F32_F64 : SInst<"vcvtx_f32", "fj", "d">; def VCVTX_HIGH_F32_F64 : SOpInst<"vcvtx_high_f32", "qfj", "d", OP_VCVTX_HI>; def FRINTN : SInst<"vrndn", "dd", "fdQfQd">; @@ -711,47 +953,22 @@ def FRINTZ : SInst<"vrnd", "dd", "fdQfQd">; def FRINTI : SInst<"vrndi", "dd", "fdQfQd">; def VCVT_S64 : SInst<"vcvt_s64", "xd", "dQd">; def VCVT_U64 : SInst<"vcvt_u64", "ud", "dQd">; -def FCVTNS_S32 : SInst<"vcvtn_s32", "xd", "fQf">; -def FCVTNS_S64 : SInst<"vcvtn_s64", "xd", "dQd">; -def FCVTNU_S32 : SInst<"vcvtn_u32", "ud", "fQf">; -def FCVTNU_S64 : SInst<"vcvtn_u64", "ud", "dQd">; -def FCVTPS_S32 : SInst<"vcvtp_s32", "xd", "fQf">; -def FCVTPS_S64 : SInst<"vcvtp_s64", "xd", "dQd">; -def FCVTPU_S32 : SInst<"vcvtp_u32", "ud", "fQf">; -def FCVTPU_S64 : SInst<"vcvtp_u64", "ud", "dQd">; -def FCVTMS_S32 : SInst<"vcvtm_s32", "xd", "fQf">; -def FCVTMS_S64 : SInst<"vcvtm_s64", "xd", "dQd">; -def FCVTMU_S32 : SInst<"vcvtm_u32", "ud", "fQf">; -def FCVTMU_S64 : SInst<"vcvtm_u64", "ud", "dQd">; -def FCVTAS_S32 : SInst<"vcvta_s32", "xd", "fQf">; -def FCVTAS_S64 : SInst<"vcvta_s64", "xd", "dQd">; -def FCVTAU_S32 : SInst<"vcvta_u32", "ud", "fQf">; -def FCVTAU_S64 : SInst<"vcvta_u64", "ud", "dQd">; -def FRECPE : SInst<"vrecpe", "dd", "fdUiQfQUiQd">; -def FRSQRTE : SInst<"vrsqrte", "dd", "fdUiQfQUiQd">; +def FRECPE : SInst<"vrecpe", "dd", "dQd">; +def FRSQRTE : SInst<"vrsqrte", "dd", "dQd">; def FSQRT : SInst<"vsqrt", "dd", "fdQfQd">; //////////////////////////////////////////////////////////////////////////////// // Comparison -// With additional Qd, Ql, QPl type. -def FCAGE : IInst<"vcage", "udd", "fdQfQd">; -def FCAGT : IInst<"vcagt", "udd", "fdQfQd">; -def FCALE : IInst<"vcale", "udd", "fdQfQd">; -def FCALT : IInst<"vcalt", "udd", "fdQfQd">; -// With additional Ql, QUl, Qd types. -def CMTST : WInst<"vtst", "udd", - "csiUcUsUiPcPsQcQsQiQUcQUsQUiQPcQPslUlQlQUlPlQPl">; -// With additional l, Ul,d, Qd, Ql, QUl, Qd types. -def CFMEQ : SOpInst<"vceq", "udd", - "csilfUcUsUiUlPcQcdQdQsQiQfQUcQUsQUiQUlQlQPcPlQPl", OP_EQ>; -def CFMGE : SOpInst<"vcge", "udd", - "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_GE>; -def CFMLE : SOpInst<"vcle", "udd", - "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_LE>; -def CFMGT : SOpInst<"vcgt", "udd", - "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_GT>; -def CFMLT : SOpInst<"vclt", "udd", - "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_LT>; +def FCAGE : IInst<"vcage", "udd", "dQd">; +def FCAGT : IInst<"vcagt", "udd", "dQd">; +def FCALE : IInst<"vcale", "udd", "dQd">; +def FCALT : IInst<"vcalt", "udd", "dQd">; +def CMTST : WInst<"vtst", "udd", "lUlPlQlQUlQPl">; +def CFMEQ : SOpInst<"vceq", "udd", "lUldQdQlQUlPlQPl", OP_EQ>; +def CFMGE : SOpInst<"vcge", "udd", "lUldQdQlQUl", OP_GE>; +def CFMLE : SOpInst<"vcle", "udd", "lUldQdQlQUl", OP_LE>; +def CFMGT : SOpInst<"vcgt", "udd", "lUldQdQlQUl", OP_GT>; +def CFMLT : SOpInst<"vclt", "udd", "lUldQdQlQUl", OP_LT>; def CMEQ : SInst<"vceqz", "ud", "csilfUcUsUiUlPcPsPlQcQsQiQlQfQUcQUsQUiQUlQPcQPsdQdQPl">; @@ -762,9 +979,8 @@ def CMLT : SInst<"vcltz", "ud", "csilfdQcQsQiQlQfQd">; //////////////////////////////////////////////////////////////////////////////// // Max/Min Integer -// With additional Qd type. -def MAX : SInst<"vmax", "ddd", "csiUcUsUifdQcQsQiQUcQUsQUiQfQd">; -def MIN : SInst<"vmin", "ddd", "csiUcUsUifdQcQsQiQUcQUsQUiQfQd">; +def MAX : SInst<"vmax", "ddd", "dQd">; +def MIN : SInst<"vmin", "ddd", "dQd">; //////////////////////////////////////////////////////////////////////////////// // MaxNum/MinNum Floating Point @@ -773,9 +989,8 @@ def FMINNM : SInst<"vminnm", "ddd", "fdQfQd">; //////////////////////////////////////////////////////////////////////////////// // Pairwise Max/Min -// With additional Qc Qs Qi QUc QUs QUi Qf Qd types. -def MAXP : SInst<"vpmax", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQfQd">; -def MINP : SInst<"vpmin", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQfQd">; +def MAXP : SInst<"vpmax", "ddd", "QcQsQiQUcQUsQUiQfQd">; +def MINP : SInst<"vpmin", "ddd", "QcQsQiQUcQUsQUiQfQd">; //////////////////////////////////////////////////////////////////////////////// // Pairwise MaxNum/MinNum Floating Point @@ -784,8 +999,7 @@ def FMINNMP : SInst<"vpminnm", "ddd", "fQfQd">; //////////////////////////////////////////////////////////////////////////////// // Pairwise Addition -// With additional Qc Qs Qi QUc QUs QUi Qf Qd types. -def ADDP : IInst<"vpadd", "ddd", "csiUcUsUifQcQsQiQlQUcQUsQUiQUlQfQd">; +def ADDP : IInst<"vpadd", "ddd", "QcQsQiQlQUcQUsQUiQUlQfQd">; //////////////////////////////////////////////////////////////////////////////// // Shifts by constant @@ -795,11 +1009,8 @@ def SHLL_HIGH_N : SOpInst<"vshll_high_n", "ndi", "HcHsHiHUcHUsHUi", OP_LONG_HI>; //////////////////////////////////////////////////////////////////////////////// -// Shifts with insert, with additional Ql, QPl type. -def SRI_N : WInst<"vsri_n", "dddi", - "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPsPlQPl">; -def SLI_N : WInst<"vsli_n", "dddi", - "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPsPlQPl">; +def SRI_N : WInst<"vsri_n", "dddi", "PlQPl">; +def SLI_N : WInst<"vsli_n", "dddi", "PlQPl">; // Right shift narrow high def SHRN_HIGH_N : IOpInst<"vshrn_high_n", "hmdi", @@ -854,44 +1065,40 @@ def VQDMLAL_HIGH : SOpInst<"vqdmlal_high", "wwkk", "si", OP_QDMLALHi>; def VQDMLAL_HIGH_N : SOpInst<"vqdmlal_high_n", "wwks", "si", OP_QDMLALHi_N>; def VQDMLSL_HIGH : SOpInst<"vqdmlsl_high", "wwkk", "si", OP_QDMLSLHi>; def VQDMLSL_HIGH_N : SOpInst<"vqdmlsl_high_n", "wwks", "si", OP_QDMLSLHi_N>; +def VMULL_P64 : SInst<"vmull", "rss", "Pl">; +def VMULL_HIGH_P64 : SOpInst<"vmull_high", "rdd", "HPl", OP_MULLHi_P64>; + //////////////////////////////////////////////////////////////////////////////// // Extract or insert element from vector -def GET_LANE : IInst<"vget_lane", "sdi", - "csilPcPsUcUsUiUlQcQsQiQlQUcQUsQUiQUlPcPsQPcQPsfdQfQdPlQPl">; -def SET_LANE : IInst<"vset_lane", "dsdi", - "csilPcPsUcUsUiUlQcQsQiQlQUcQUsQUiQUlPcPsQPcQPsfdQfQdPlQPl">; +def GET_LANE : IInst<"vget_lane", "sdi", "dQdPlQPl">; +def SET_LANE : IInst<"vset_lane", "dsdi", "dQdPlQPl">; def COPY_LANE : IOpInst<"vcopy_lane", "ddidi", - "csilPcPsUcUsUiUlPcPsPlfd", OP_COPY_LN>; + "csilUcUsUiUlPcPsPlfd", OP_COPY_LN>; def COPYQ_LANE : IOpInst<"vcopy_lane", "ddigi", - "QcQsQiQlQUcQUsQUiQUlQPcQPsQfQdQPl", OP_COPYQ_LN>; + "QcQsQiQlQUcQUsQUiQUlQPcQPsQfQdQPl", OP_COPY_LN>; def COPY_LANEQ : IOpInst<"vcopy_laneq", "ddiki", - "csilPcPsPlUcUsUiUlfd", OP_COPY_LNQ>; + "csilPcPsPlUcUsUiUlfd", OP_COPY_LN>; def COPYQ_LANEQ : IOpInst<"vcopy_laneq", "ddidi", "QcQsQiQlQUcQUsQUiQUlQPcQPsQfQdQPl", OP_COPY_LN>; //////////////////////////////////////////////////////////////////////////////// // Set all lanes to same value -def VDUP_LANE1: WOpInst<"vdup_lane", "dgi", - "csilPcPsUcUsUiUlhfdQcQsQiQlQPcQPsQUcQUsQUiQUlQhQfQdPlQPl", - OP_DUP_LN>; -def VDUP_LANE2: WOpInst<"vdup_laneq", "dki", - "csilPcPsUcUsUiUlhfdQcQsQiQlQPcQPsQUcQUsQUiQUlQhQfQdPlQPl", +def VDUP_LANE1: WOpInst<"vdup_lane", "dgi", "hdQhQdPlQPl", OP_DUP_LN>; +def VDUP_LANE2: WOpInst<"vdup_laneq", "dji", + "csilUcUsUiUlPcPshfdQcQsQiQlQPcQPsQUcQUsQUiQUlQhQfQdPlQPl", OP_DUP_LN>; -def DUP_N : WOpInst<"vdup_n", "ds", - "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUldQdPlQPl", - OP_DUP>; -def MOV_N : WOpInst<"vmov_n", "ds", - "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUldQd", - OP_DUP>; +def DUP_N : WOpInst<"vdup_n", "ds", "dQdPlQPl", OP_DUP>; +def MOV_N : WOpInst<"vmov_n", "ds", "dQd", OP_DUP>; //////////////////////////////////////////////////////////////////////////////// -// Combining vectors, with additional Pl -def COMBINE : NoTestOpInst<"vcombine", "kdd", "csilhfdUcUsUiUlPcPsPl", OP_CONC>; +def COMBINE : NoTestOpInst<"vcombine", "kdd", "dPl", OP_CONC>; //////////////////////////////////////////////////////////////////////////////// -//Initialize a vector from bit pattern, with additional Pl -def CREATE : NoTestOpInst<"vcreate", "dl", "csihfdUcUsUiUlPcPslPl", OP_CAST>; +//Initialize a vector from bit pattern +def CREATE : NoTestOpInst<"vcreate", "dl", "dPl", OP_CAST> { + let BigEndianSafe = 1; +} //////////////////////////////////////////////////////////////////////////////// @@ -901,7 +1108,9 @@ def VMLS_LANEQ : IOpInst<"vmls_laneq", "dddji", "siUsUifQsQiQUsQUiQf", OP_MLS_LN>; def VFMA_LANE : IInst<"vfma_lane", "dddgi", "fdQfQd">; -def VFMA_LANEQ : IInst<"vfma_laneq", "dddji", "fdQfQd">; +def VFMA_LANEQ : IInst<"vfma_laneq", "dddji", "fdQfQd"> { + let isLaneQ = 1; +} def VFMS_LANE : IOpInst<"vfms_lane", "dddgi", "fdQfQd", OP_FMS_LN>; def VFMS_LANEQ : IOpInst<"vfms_laneq", "dddji", "fdQfQd", OP_FMS_LNQ>; @@ -933,7 +1142,7 @@ def VMUL_LANE_A64 : IOpInst<"vmul_lane", "ddgi", "Qd", OP_MUL_LN>; // Note: d type is handled by SCALAR_VMUL_LANEQ def VMUL_LANEQ : IOpInst<"vmul_laneq", "ddji", - "sifUsUiQsQiQfQUsQUiQfQd", OP_MUL_LN>; + "sifUsUiQsQiQUsQUiQfQd", OP_MUL_LN>; def VMULL_LANEQ : SOpInst<"vmull_laneq", "wdki", "siUsUi", OP_MULL_LN>; def VMULL_HIGH_LANE : SOpInst<"vmull_high_lane", "wkdi", "siUsUi", OP_MULLHi_LN>; @@ -965,12 +1174,11 @@ def FMINNMV : SInst<"vminnmv", "sd", "fQfQd">; //////////////////////////////////////////////////////////////////////////////// // Newly added Vector Extract for f64 -def VEXT_A64 : WInst<"vext", "dddi", - "cUcPcsUsPsiUilUlfdQcQUcQPcQsQUsQPsQiQUiQlQUlQfQdPlQPl">; +def VEXT_A64 : WInst<"vext", "dddi", "dQdPlQPl">; //////////////////////////////////////////////////////////////////////////////// // Crypto -let isCrypto = 1 in { +let ArchGuard = "__ARM_FEATURE_CRYPTO" in { def AESE : SInst<"vaese", "ddd", "QUc">; def AESD : SInst<"vaesd", "ddd", "QUc">; def AESMC : SInst<"vaesmc", "dd", "QUc">; @@ -990,6 +1198,31 @@ def SHA256SU1 : SInst<"vsha256su1", "dddd", "QUi">; } //////////////////////////////////////////////////////////////////////////////// +// Float -> Int conversions with explicit rounding mode + +let ArchGuard = "__ARM_ARCH >= 8" in { +def FCVTNS_S32 : SInst<"vcvtn_s32", "xd", "fQf">; +def FCVTNU_S32 : SInst<"vcvtn_u32", "ud", "fQf">; +def FCVTPS_S32 : SInst<"vcvtp_s32", "xd", "fQf">; +def FCVTPU_S32 : SInst<"vcvtp_u32", "ud", "fQf">; +def FCVTMS_S32 : SInst<"vcvtm_s32", "xd", "fQf">; +def FCVTMU_S32 : SInst<"vcvtm_u32", "ud", "fQf">; +def FCVTAS_S32 : SInst<"vcvta_s32", "xd", "fQf">; +def FCVTAU_S32 : SInst<"vcvta_u32", "ud", "fQf">; +} + +let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__)" in { +def FCVTNS_S64 : SInst<"vcvtn_s64", "xd", "dQd">; +def FCVTNU_S64 : SInst<"vcvtn_u64", "ud", "dQd">; +def FCVTPS_S64 : SInst<"vcvtp_s64", "xd", "dQd">; +def FCVTPU_S64 : SInst<"vcvtp_u64", "ud", "dQd">; +def FCVTMS_S64 : SInst<"vcvtm_s64", "xd", "dQd">; +def FCVTMU_S64 : SInst<"vcvtm_u64", "ud", "dQd">; +def FCVTAS_S64 : SInst<"vcvta_s64", "xd", "dQd">; +def FCVTAU_S64 : SInst<"vcvta_u64", "ud", "dQd">; +} + +//////////////////////////////////////////////////////////////////////////////// // Permutation def VTRN1 : SOpInst<"vtrn1", "ddd", "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_TRN1>; @@ -1021,11 +1254,17 @@ def VQTBX4_A64 : WInst<"vqtbx4", "ddDt", "UccPcQUcQcQPc">; //////////////////////////////////////////////////////////////////////////////// // Vector reinterpret cast operations -// With additional d, Qd, pl, Qpl types -def REINTERPRET - : NoTestOpInst<"vreinterpret", "dd", - "csilUcUsUiUlhfdPcPsPlQcQsQiQlQUcQUsQUiQUlQhQfQdQPcQPsQPl", OP_REINT>; +// NeonEmitter implicitly takes the cartesian product of the type string with +// itself during generation so, unlike all other intrinsics, this one should +// include *all* types, not just additional ones. +def VVREINTERPRET + : NoTestOpInst<"vreinterpret", "dd", + "csilUcUsUiUlhfdPcPsPlQcQsQiQlQUcQUsQUiQUlQhQfQdQPcQPsQPlQPk", OP_REINT> { + let CartesianProductOfTypes = 1; + let BigEndianSafe = 1; + let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__)"; +} //////////////////////////////////////////////////////////////////////////////// // Scalar Intrinsics @@ -1042,10 +1281,8 @@ def SCALAR_SUB : SInst<"vsub", "sss", "SlSUl">; def SCALAR_QSUB : SInst<"vqsub", "sss", "ScSsSiSlSUcSUsSUiSUl">; let InstName = "vmov" in { -def VGET_HIGH_A64 : NoTestOpInst<"vget_high", "dk", "csilhfdUcUsUiUlPcPsPl", - OP_HI>; -def VGET_LOW_A64 : NoTestOpInst<"vget_low", "dk", "csilhfdUcUsUiUlPcPsPl", - OP_LO>; +def VGET_HIGH_A64 : NoTestOpInst<"vget_high", "dk", "dPl", OP_HI>; +def VGET_LOW_A64 : NoTestOpInst<"vget_low", "dk", "dPl", OP_LO>; } //////////////////////////////////////////////////////////////////////////////// @@ -1282,11 +1519,11 @@ def SCALAR_UQXTN : SInst<"vqmovn", "zs", "SUsSUiSUl">; // Scalar Floating Point multiply (scalar, by element) def SCALAR_FMUL_LANE : IOpInst<"vmul_lane", "ssdi", "SfSd", OP_SCALAR_MUL_LN>; -def SCALAR_FMUL_LANEQ : IOpInst<"vmul_laneq", "ssji", "SfSd", OP_SCALAR_MUL_LNQ>; +def SCALAR_FMUL_LANEQ : IOpInst<"vmul_laneq", "ssji", "SfSd", OP_SCALAR_MUL_LN>; // Scalar Floating Point multiply extended (scalar, by element) def SCALAR_FMULX_LANE : IOpInst<"vmulx_lane", "ssdi", "SfSd", OP_SCALAR_MULX_LN>; -def SCALAR_FMULX_LANEQ : IOpInst<"vmulx_laneq", "ssji", "SfSd", OP_SCALAR_MULX_LNQ>; +def SCALAR_FMULX_LANEQ : IOpInst<"vmulx_laneq", "ssji", "SfSd", OP_SCALAR_MULX_LN>; def SCALAR_VMUL_N : IInst<"vmul_n", "dds", "d">; @@ -1294,7 +1531,9 @@ def SCALAR_VMUL_N : IInst<"vmul_n", "dds", "d">; def SCALAR_VMUL_LANE : IInst<"vmul_lane", "ddgi", "d">; // VMUL_LANEQ d type implemented using scalar mul lane -def SCALAR_VMUL_LANEQ : IInst<"vmul_laneq", "ddji", "d">; +def SCALAR_VMUL_LANEQ : IInst<"vmul_laneq", "ddji", "d"> { + let isLaneQ = 1; +} // VMULX_LANE d type implemented using scalar vmulx_lane def SCALAR_VMULX_LANE : IOpInst<"vmulx_lane", "ddgi", "d", OP_SCALAR_VMULX_LN>; @@ -1312,7 +1551,7 @@ def SCALAR_FMLS_LANEQ : IOpInst<"vfms_laneq", "sssji", "SfSd", OP_FMS_LNQ>; // Signed Saturating Doubling Multiply Long (scalar by element) def SCALAR_SQDMULL_LANE : SOpInst<"vqdmull_lane", "rsdi", "SsSi", OP_SCALAR_QDMULL_LN>; -def SCALAR_SQDMULL_LANEQ : SOpInst<"vqdmull_laneq", "rsji", "SsSi", OP_SCALAR_QDMULL_LNQ>; +def SCALAR_SQDMULL_LANEQ : SOpInst<"vqdmull_laneq", "rsji", "SsSi", OP_SCALAR_QDMULL_LN>; // Signed Saturating Doubling Multiply-Add Long (scalar by element) def SCALAR_SQDMLAL_LANE : SInst<"vqdmlal_lane", "rrsdi", "SsSi">; @@ -1324,15 +1563,18 @@ def SCALAR_SQDMLS_LANEQ : SInst<"vqdmlsl_laneq", "rrsji", "SsSi">; // Scalar Integer Saturating Doubling Multiply Half High (scalar by element) def SCALAR_SQDMULH_LANE : SOpInst<"vqdmulh_lane", "ssdi", "SsSi", OP_SCALAR_QDMULH_LN>; -def SCALAR_SQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QDMULH_LNQ>; +def SCALAR_SQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QDMULH_LN>; // Scalar Integer Saturating Rounding Doubling Multiply Half High def SCALAR_SQRDMULH_LANE : SOpInst<"vqrdmulh_lane", "ssdi", "SsSi", OP_SCALAR_QRDMULH_LN>; -def SCALAR_SQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QRDMULH_LNQ>; +def SCALAR_SQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QRDMULH_LN>; def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">; def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">; -def SCALAR_GET_LANE : IOpInst<"vget_lane", "sdi", "hQh", OP_SCALAR_GET_LN>; -def SCALAR_SET_LANE : IOpInst<"vset_lane", "dsdi", "hQh", OP_SCALAR_SET_LN>; +// FIXME: Rename so it is obvious this only applies to halfs. +def SCALAR_HALF_GET_LANE : IOpInst<"vget_lane", "sdi", "h", OP_SCALAR_HALF_GET_LN>; +def SCALAR_HALF_SET_LANE : IOpInst<"vset_lane", "dsdi", "h", OP_SCALAR_HALF_SET_LN>; +def SCALAR_HALF_GET_LANEQ : IOpInst<"vget_lane", "sdi", "Qh", OP_SCALAR_HALF_GET_LNQ>; +def SCALAR_HALF_SET_LANEQ : IOpInst<"vset_lane", "dsdi", "Qh", OP_SCALAR_HALF_SET_LNQ>; } diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h b/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h index 135b6a9..f8b90b3 100644 --- a/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h +++ b/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h @@ -21,7 +21,7 @@ namespace clang { class CodeGenOptions; class TargetOptions; class LangOptions; - + enum BackendAction { Backend_EmitAssembly, ///< Emit native assembly files Backend_EmitBC, ///< Emit LLVM bitcode files @@ -30,11 +30,11 @@ namespace clang { Backend_EmitMCNull, ///< Run CodeGen, but don't emit anything Backend_EmitObj ///< Emit native object files }; - + void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, const TargetOptions &TOpts, const LangOptions &LOpts, - llvm::Module *M, - BackendAction Action, raw_ostream *OS); + StringRef TDesc, llvm::Module *M, BackendAction Action, + raw_ostream *OS); } #endif diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h index 96da0e9..449827e 100644 --- a/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h +++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h @@ -19,21 +19,23 @@ #include "clang/AST/CanonicalType.h" #include "clang/AST/Type.h" #include "llvm/ADT/FoldingSet.h" - #include <cassert> namespace llvm { class Type; + class StructType; } namespace clang { +class Decl; + namespace CodeGen { /// ABIArgInfo - Helper class to encapsulate information about how a /// specific C type should be passed to or returned from a function. class ABIArgInfo { public: - enum Kind { + enum Kind : uint8_t { /// Direct - Pass the argument directly using the normal converted LLVM /// type, or by coercing to another specified type stored in /// 'CoerceToType'). If an offset is specified (in UIntData), then the @@ -60,86 +62,130 @@ public: /// are all scalar types or are themselves expandable types. Expand, - KindFirst=Direct, KindLast=Expand + /// InAlloca - Pass the argument directly using the LLVM inalloca attribute. + /// This is similar to 'direct', except it only applies to arguments stored + /// in memory and forbids any implicit copies. When applied to a return + /// type, it means the value is returned indirectly via an implicit sret + /// parameter stored in the argument struct. + InAlloca, + KindFirst = Direct, + KindLast = InAlloca }; private: - Kind TheKind; - llvm::Type *TypeData; + llvm::Type *TypeData; // isDirect() || isExtend() llvm::Type *PaddingType; - unsigned UIntData; - bool BoolData0; - bool BoolData1; - bool InReg; - bool PaddingInReg; + union { + unsigned DirectOffset; // isDirect() || isExtend() + unsigned IndirectAlign; // isIndirect() + unsigned AllocaFieldIndex; // isInAlloca() + }; + Kind TheKind; + bool PaddingInReg : 1; + bool InAllocaSRet : 1; // isInAlloca() + bool IndirectByVal : 1; // isIndirect() + bool IndirectRealign : 1; // isIndirect() + bool SRetAfterThis : 1; // isIndirect() + bool InReg : 1; // isDirect() || isExtend() || isIndirect() - ABIArgInfo(Kind K, llvm::Type *TD, unsigned UI, bool B0, bool B1, bool IR, - bool PIR, llvm::Type* P) - : TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0), - BoolData1(B1), InReg(IR), PaddingInReg(PIR) {} + ABIArgInfo(Kind K) + : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {} public: - ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {} - - static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0, - llvm::Type *Padding = 0) { - return ABIArgInfo(Direct, T, Offset, false, false, false, false, Padding); - } - static ABIArgInfo getDirectInReg(llvm::Type *T = 0) { - return ABIArgInfo(Direct, T, 0, false, false, true, false, 0); - } - static ABIArgInfo getExtend(llvm::Type *T = 0) { - return ABIArgInfo(Extend, T, 0, false, false, false, false, 0); - } - static ABIArgInfo getExtendInReg(llvm::Type *T = 0) { - return ABIArgInfo(Extend, T, 0, false, false, true, false, 0); + ABIArgInfo() + : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0), + TheKind(Direct), PaddingInReg(false), InReg(false) {} + + static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, + llvm::Type *Padding = nullptr) { + auto AI = ABIArgInfo(Direct); + AI.setCoerceToType(T); + AI.setDirectOffset(Offset); + AI.setPaddingType(Padding); + return AI; + } + static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) { + auto AI = getDirect(T); + AI.setInReg(true); + return AI; + } + static ABIArgInfo getExtend(llvm::Type *T = nullptr) { + auto AI = ABIArgInfo(Extend); + AI.setCoerceToType(T); + AI.setDirectOffset(0); + return AI; + } + static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) { + auto AI = getExtend(T); + AI.setInReg(true); + return AI; } static ABIArgInfo getIgnore() { - return ABIArgInfo(Ignore, 0, 0, false, false, false, false, 0); - } - static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true - , bool Realign = false - , llvm::Type *Padding = 0) { - return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, false, - Padding); - } - static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true - , bool Realign = false) { - return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, false, 0); + return ABIArgInfo(Ignore); + } + static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true, + bool Realign = false, + llvm::Type *Padding = nullptr) { + auto AI = ABIArgInfo(Indirect); + AI.setIndirectAlign(Alignment); + AI.setIndirectByVal(ByVal); + AI.setIndirectRealign(Realign); + AI.setSRetAfterThis(false); + AI.setPaddingType(Padding); + return AI; + } + static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true, + bool Realign = false) { + auto AI = getIndirect(Alignment, ByVal, Realign); + AI.setInReg(true); + return AI; + } + static ABIArgInfo getInAlloca(unsigned FieldIndex) { + auto AI = ABIArgInfo(InAlloca); + AI.setInAllocaFieldIndex(FieldIndex); + return AI; } static ABIArgInfo getExpand() { - return ABIArgInfo(Expand, 0, 0, false, false, false, false, 0); + return ABIArgInfo(Expand); } static ABIArgInfo getExpandWithPadding(bool PaddingInReg, llvm::Type *Padding) { - return ABIArgInfo(Expand, 0, 0, false, false, false, PaddingInReg, - Padding); + auto AI = getExpand(); + AI.setPaddingInReg(PaddingInReg); + AI.setPaddingType(Padding); + return AI; } Kind getKind() const { return TheKind; } bool isDirect() const { return TheKind == Direct; } + bool isInAlloca() const { return TheKind == InAlloca; } bool isExtend() const { return TheKind == Extend; } bool isIgnore() const { return TheKind == Ignore; } bool isIndirect() const { return TheKind == Indirect; } bool isExpand() const { return TheKind == Expand; } - bool canHaveCoerceToType() const { - return TheKind == Direct || TheKind == Extend; - } + bool canHaveCoerceToType() const { return isDirect() || isExtend(); } // Direct/Extend accessors unsigned getDirectOffset() const { assert((isDirect() || isExtend()) && "Not a direct or extend kind"); - return UIntData; + return DirectOffset; } - - llvm::Type *getPaddingType() const { - return PaddingType; + void setDirectOffset(unsigned Offset) { + assert((isDirect() || isExtend()) && "Not a direct or extend kind"); + DirectOffset = Offset; } + llvm::Type *getPaddingType() const { return PaddingType; } + + void setPaddingType(llvm::Type *T) { PaddingType = T; } + bool getPaddingInReg() const { return PaddingInReg; } + void setPaddingInReg(bool PIR) { + PaddingInReg = PIR; + } llvm::Type *getCoerceToType() const { assert(canHaveCoerceToType() && "Invalid kind!"); @@ -156,20 +202,67 @@ public: return InReg; } + void setInReg(bool IR) { + assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); + InReg = IR; + } + // Indirect accessors unsigned getIndirectAlign() const { - assert(TheKind == Indirect && "Invalid kind!"); - return UIntData; + assert(isIndirect() && "Invalid kind!"); + return IndirectAlign; + } + void setIndirectAlign(unsigned IA) { + assert(isIndirect() && "Invalid kind!"); + IndirectAlign = IA; } bool getIndirectByVal() const { - assert(TheKind == Indirect && "Invalid kind!"); - return BoolData0; + assert(isIndirect() && "Invalid kind!"); + return IndirectByVal; + } + void setIndirectByVal(unsigned IBV) { + assert(isIndirect() && "Invalid kind!"); + IndirectByVal = IBV; } bool getIndirectRealign() const { - assert(TheKind == Indirect && "Invalid kind!"); - return BoolData1; + assert(isIndirect() && "Invalid kind!"); + return IndirectRealign; + } + void setIndirectRealign(bool IR) { + assert(isIndirect() && "Invalid kind!"); + IndirectRealign = IR; + } + + bool isSRetAfterThis() const { + assert(isIndirect() && "Invalid kind!"); + return SRetAfterThis; + } + void setSRetAfterThis(bool AfterThis) { + assert(isIndirect() && "Invalid kind!"); + SRetAfterThis = AfterThis; + } + + unsigned getInAllocaFieldIndex() const { + assert(isInAlloca() && "Invalid kind!"); + return AllocaFieldIndex; + } + void setInAllocaFieldIndex(unsigned FieldIndex) { + assert(isInAlloca() && "Invalid kind!"); + AllocaFieldIndex = FieldIndex; + } + + /// \brief Return true if this field of an inalloca struct should be returned + /// to implement a struct return calling convention. + bool getInAllocaSRet() const { + assert(isInAlloca() && "Invalid kind!"); + return InAllocaSRet; + } + + void setInAllocaSRet(bool SRet) { + assert(isInAlloca() && "Invalid kind!"); + InAllocaSRet = SRet; } void dump() const; @@ -195,7 +288,7 @@ public: static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional) { if (!prototype->isVariadic()) return All; - return RequiredArgs(prototype->getNumArgs() + additional); + return RequiredArgs(prototype->getNumParams() + additional); } static RequiredArgs forPrototype(const FunctionProtoType *prototype) { @@ -243,6 +336,9 @@ class CGFunctionInfo : public llvm::FoldingSetNode { /// The clang::CallingConv that this was originally created with. unsigned ASTCallingConvention : 8; + /// Whether this is an instance method. + unsigned InstanceMethod : 1; + /// Whether this function is noreturn. unsigned NoReturn : 1; @@ -255,6 +351,10 @@ class CGFunctionInfo : public llvm::FoldingSetNode { RequiredArgs Required; + /// The struct representing all arguments passed in memory. Only used when + /// passing non-trivial types with inalloca. Not part of the profile. + llvm::StructType *ArgStruct; + unsigned NumArgs; ArgInfo *getArgsBuffer() { return reinterpret_cast<ArgInfo*>(this+1); @@ -267,6 +367,7 @@ class CGFunctionInfo : public llvm::FoldingSetNode { public: static CGFunctionInfo *create(unsigned llvmCC, + bool InstanceMethod, const FunctionType::ExtInfo &extInfo, CanQualType resultType, ArrayRef<CanQualType> argTypes, @@ -275,6 +376,14 @@ public: typedef const ArgInfo *const_arg_iterator; typedef ArgInfo *arg_iterator; + typedef llvm::iterator_range<arg_iterator> arg_range; + typedef llvm::iterator_range<const_arg_iterator> arg_const_range; + + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } + arg_const_range arguments() const { + return arg_const_range(arg_begin(), arg_end()); + } + const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } arg_iterator arg_begin() { return getArgsBuffer() + 1; } @@ -285,6 +394,8 @@ public: bool isVariadic() const { return Required.allowsOptionalArgs(); } RequiredArgs getRequiredArgs() const { return Required; } + bool isInstanceMethod() const { return InstanceMethod; } + bool isNoReturn() const { return NoReturn; } /// In ARC, whether this function retains its return value. This @@ -325,23 +436,33 @@ public: ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } + /// \brief Return true if this function uses inalloca arguments. + bool usesInAlloca() const { return ArgStruct; } + + /// \brief Get the struct type used to represent all the arguments in memory. + llvm::StructType *getArgStruct() const { return ArgStruct; } + void setArgStruct(llvm::StructType *Ty) { ArgStruct = Ty; } + void Profile(llvm::FoldingSetNodeID &ID) { ID.AddInteger(getASTCallingConvention()); + ID.AddBoolean(InstanceMethod); ID.AddBoolean(NoReturn); ID.AddBoolean(ReturnsRetained); ID.AddBoolean(HasRegParm); ID.AddInteger(RegParm); ID.AddInteger(Required.getOpaqueData()); getReturnType().Profile(ID); - for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it) - it->type.Profile(ID); + for (const auto &I : arguments()) + I.type.Profile(ID); } static void Profile(llvm::FoldingSetNodeID &ID, + bool InstanceMethod, const FunctionType::ExtInfo &info, RequiredArgs required, CanQualType resultType, ArrayRef<CanQualType> argTypes) { ID.AddInteger(info.getCC()); + ID.AddBoolean(InstanceMethod); ID.AddBoolean(info.getNoReturn()); ID.AddBoolean(info.getProducesResult()); ID.AddBoolean(info.getHasRegParm()); diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h index 81e2cdc..2502982 100644 --- a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h +++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h @@ -47,10 +47,7 @@ class CodeGenModule; class CodeGenABITypes { public: - CodeGenABITypes(ASTContext &C, const CodeGenOptions &CodeGenOpts, - llvm::Module &M, const llvm::DataLayout &TD, - DiagnosticsEngine &Diags); - + CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD); ~CodeGenABITypes(); /// These methods all forward to methods in the private implementation class @@ -65,12 +62,18 @@ public: CanQual<FunctionNoProtoType> Ty); const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD, const FunctionProtoType *FTP); - const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType, - llvm::ArrayRef<CanQualType> argTypes, - FunctionType::ExtInfo info, - RequiredArgs args); + const CGFunctionInfo &arrangeFreeFunctionCall(CanQualType returnType, + ArrayRef<CanQualType> argTypes, + FunctionType::ExtInfo info, + RequiredArgs args); private: + /// Default CodeGenOptions object used to initialize the + /// CodeGenModule and otherwise not used. More specifically, it is + /// not used in ABI type generation, so none of the options matter. + CodeGenOptions *CGO; + + /// The CodeGenModule we use get to the CodeGenTypes object. CodeGen::CodeGenModule *CGM; }; diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h index 912ef01..37819c7 100644 --- a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h +++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h @@ -11,7 +11,7 @@ #define LLVM_CLANG_CODEGEN_CODE_GEN_ACTION_H #include "clang/Frontend/FrontendAction.h" -#include "llvm/ADT/OwningPtr.h" +#include <memory> namespace llvm { class LLVMContext; @@ -24,7 +24,7 @@ class BackendConsumer; class CodeGenAction : public ASTFrontendAction { private: unsigned Act; - OwningPtr<llvm::Module> TheModule; + std::unique_ptr<llvm::Module> TheModule; llvm::Module *LinkModule; llvm::LLVMContext *VMContext; bool OwnsVMContext; @@ -33,16 +33,16 @@ protected: /// Create a new code generation action. If the optional \p _VMContext /// parameter is supplied, the action uses it without taking ownership, /// otherwise it creates a fresh LLVM context and takes ownership. - CodeGenAction(unsigned _Act, llvm::LLVMContext *_VMContext = 0); + CodeGenAction(unsigned _Act, llvm::LLVMContext *_VMContext = nullptr); - virtual bool hasIRSupport() const; + bool hasIRSupport() const override; - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; - virtual void ExecuteAction(); + void ExecuteAction() override; - virtual void EndSourceFileAction(); + void EndSourceFileAction() override; public: ~CodeGenAction(); @@ -65,37 +65,37 @@ public: class EmitAssemblyAction : public CodeGenAction { virtual void anchor(); public: - EmitAssemblyAction(llvm::LLVMContext *_VMContext = 0); + EmitAssemblyAction(llvm::LLVMContext *_VMContext = nullptr); }; class EmitBCAction : public CodeGenAction { virtual void anchor(); public: - EmitBCAction(llvm::LLVMContext *_VMContext = 0); + EmitBCAction(llvm::LLVMContext *_VMContext = nullptr); }; class EmitLLVMAction : public CodeGenAction { virtual void anchor(); public: - EmitLLVMAction(llvm::LLVMContext *_VMContext = 0); + EmitLLVMAction(llvm::LLVMContext *_VMContext = nullptr); }; class EmitLLVMOnlyAction : public CodeGenAction { virtual void anchor(); public: - EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = 0); + EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = nullptr); }; class EmitCodeGenOnlyAction : public CodeGenAction { virtual void anchor(); public: - EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = 0); + EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = nullptr); }; class EmitObjAction : public CodeGenAction { virtual void anchor(); public: - EmitObjAction(llvm::LLVMContext *_VMContext = 0); + EmitObjAction(llvm::LLVMContext *_VMContext = nullptr); }; } diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h index cda7863..4b7236b 100644 --- a/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h +++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h @@ -27,12 +27,14 @@ namespace clang { class LangOptions; class CodeGenOptions; class TargetOptions; + class Decl; class CodeGenerator : public ASTConsumer { virtual void anchor(); public: virtual llvm::Module* GetModule() = 0; virtual llvm::Module* ReleaseModule() = 0; + virtual const Decl *GetDeclForMangledName(llvm::StringRef MangledName) = 0; }; /// CreateLLVMCodeGen - Create a CodeGenerator instance. diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Action.h b/contrib/llvm/tools/clang/include/clang/Driver/Action.h index 289dbe3..2cdb581 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Action.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Action.h @@ -50,10 +50,11 @@ public: LinkJobClass, LipoJobClass, DsymutilJobClass, - VerifyJobClass, + VerifyDebugInfoJobClass, + VerifyPCHJobClass, JobClassFirst=PreprocessJobClass, - JobClassLast=VerifyJobClass + JobClassLast=VerifyPCHJobClass }; static const char *getClassName(ActionClass AC); @@ -141,7 +142,7 @@ public: }; class PreprocessJobAction : public JobAction { - virtual void anchor(); + void anchor() override; public: PreprocessJobAction(Action *Input, types::ID OutputType); @@ -151,7 +152,7 @@ public: }; class PrecompileJobAction : public JobAction { - virtual void anchor(); + void anchor() override; public: PrecompileJobAction(Action *Input, types::ID OutputType); @@ -161,7 +162,7 @@ public: }; class AnalyzeJobAction : public JobAction { - virtual void anchor(); + void anchor() override; public: AnalyzeJobAction(Action *Input, types::ID OutputType); @@ -171,7 +172,7 @@ public: }; class MigrateJobAction : public JobAction { - virtual void anchor(); + void anchor() override; public: MigrateJobAction(Action *Input, types::ID OutputType); @@ -181,7 +182,7 @@ public: }; class CompileJobAction : public JobAction { - virtual void anchor(); + void anchor() override; public: CompileJobAction(Action *Input, types::ID OutputType); @@ -191,7 +192,7 @@ public: }; class AssembleJobAction : public JobAction { - virtual void anchor(); + void anchor() override; public: AssembleJobAction(Action *Input, types::ID OutputType); @@ -201,7 +202,7 @@ public: }; class LinkJobAction : public JobAction { - virtual void anchor(); + void anchor() override; public: LinkJobAction(ActionList &Inputs, types::ID Type); @@ -211,7 +212,7 @@ public: }; class LipoJobAction : public JobAction { - virtual void anchor(); + void anchor() override; public: LipoJobAction(ActionList &Inputs, types::ID Type); @@ -221,7 +222,7 @@ public: }; class DsymutilJobAction : public JobAction { - virtual void anchor(); + void anchor() override; public: DsymutilJobAction(ActionList &Inputs, types::ID Type); @@ -231,11 +232,31 @@ public: }; class VerifyJobAction : public JobAction { - virtual void anchor(); + void anchor() override; +public: + VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type); + VerifyJobAction(ActionClass Kind, ActionList &Inputs, types::ID Type); + static bool classof(const Action *A) { + return A->getKind() == VerifyDebugInfoJobClass || + A->getKind() == VerifyPCHJobClass; + } +}; + +class VerifyDebugInfoJobAction : public VerifyJobAction { + void anchor() override; +public: + VerifyDebugInfoJobAction(Action *Input, types::ID Type); + static bool classof(const Action *A) { + return A->getKind() == VerifyDebugInfoJobClass; + } +}; + +class VerifyPCHJobAction : public VerifyJobAction { + void anchor() override; public: - VerifyJobAction(ActionList &Inputs, types::ID Type); + VerifyPCHJobAction(Action *Input, types::ID Type); static bool classof(const Action *A) { - return A->getKind() == VerifyJobClass; + return A->getKind() == VerifyPCHJobClass; } }; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h deleted file mode 100644 index 345f50a..0000000 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h +++ /dev/null @@ -1,37 +0,0 @@ -//===--- CC1AsOptions.h - Clang Assembler 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_CC1ASOPTIONS_H -#define CLANG_DRIVER_CC1ASOPTIONS_H - -namespace llvm { -namespace opt { - class OptTable; -} -} - -namespace clang { -namespace driver { - -namespace cc1asoptions { - enum ID { - OPT_INVALID = 0, // This is not an option ID. -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) OPT_##ID, -#include "clang/Driver/CC1AsOptions.inc" - LastOption -#undef OPTION - }; -} - -llvm::opt::OptTable *createCC1AsOptTable(); -} -} - -#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td deleted file mode 100644 index b536724..0000000 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td +++ /dev/null @@ -1,95 +0,0 @@ -//===--- CC1AsOptions.td - Options for clang -cc1as -----------------------===// -// -// 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 options accepted by clang -cc1as. -// -//===----------------------------------------------------------------------===// - -// Include the common option parsing interfaces. -include "llvm/Option/OptParser.td" - -//===----------------------------------------------------------------------===// -// Target Options -//===----------------------------------------------------------------------===// - -def triple : Separate<["-"], "triple">, - HelpText<"Specify target triple (e.g. x86_64-pc-linux-gnu)">; -def target_cpu : Separate<["-"], "target-cpu">, - HelpText<"Target a specific cpu type">; -def target_feature : Separate<["-"], "target-feature">, - HelpText<"Target specific attributes">; - -//===----------------------------------------------------------------------===// -// Language Options -//===----------------------------------------------------------------------===// - -def I : JoinedOrSeparate<["-"], "I">, MetaVarName<"<directory>">, - HelpText<"Add directory to include search path">; -def n : Flag<["-"], "n">, - HelpText<"Don't automatically start assembly file with a text section">; -def msave_temp_labels : Flag<["-"], "msave-temp-labels">, - HelpText<"Save temporary labels in the symbol table. " - "Note this may change .s semantics, it should almost never be used " - "on compiler generated code!">; -def main_file_name : Separate<["-"], "main-file-name">, - HelpText<"Main file name to use for debug info">; - -//===----------------------------------------------------------------------===// -// Frontend Options -//===----------------------------------------------------------------------===// - -def o : Separate<["-"], "o">, MetaVarName<"<path>">, - HelpText<"Specify output file">; - -def filetype : Separate<["-"], "filetype">, - HelpText<"Specify the output file type ('asm', 'null', or 'obj')">; - -def help : Flag<["-", "--"], "help">, - HelpText<"Print this help text">; - -def version : Flag<["-", "--"], "version">, - HelpText<"Print the assembler version">; -def v : Flag<["-"], "v">, Alias<version>; - -// 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">; - -//===----------------------------------------------------------------------===// -// Transliterate Options -//===----------------------------------------------------------------------===// - -def output_asm_variant : Separate<["-"], "output-asm-variant">, - HelpText<"Select the asm variant index to use for output">; -def show_encoding : Flag<["-"], "show-encoding">, - HelpText<"Show instruction encoding information in transliterate mode">; -def show_inst : Flag<["-"], "show-inst">, - HelpText<"Show internal instruction representation in transliterate mode">; - -//===----------------------------------------------------------------------===// -// Assemble Options -//===----------------------------------------------------------------------===// - -def mrelax_all : Flag<["-"], "mrelax-all">, - HelpText<"Relax all fixups (for performance testing)">; - -def mno_exec_stack : Flag<["-"], "mnoexecstack">, - HelpText<"Mark the file as not needing an executable stack">; - -def g : Flag<["-"], "g">, HelpText<"Generate source level debug information">; - -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 dwarf_debug_producer : Separate<["-"], "dwarf-debug-producer">, - HelpText<"The string to embed in the Dwarf debug AT_producer record.">; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h deleted file mode 100644 index e69de29..0000000 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h +++ /dev/null diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td index 85cfdcf..d25560c 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the options accepted by clang -cc1. +// This file defines the options accepted by clang -cc1 and clang -cc1as. // //===----------------------------------------------------------------------===// @@ -17,21 +17,24 @@ let Flags = [CC1Option, NoDriverOption] in { // Target Options //===----------------------------------------------------------------------===// -def cxx_abi : Separate<["-"], "cxx-abi">, - HelpText<"Target a particular C++ ABI type">; -def target_abi : Separate<["-"], "target-abi">, - HelpText<"Target a particular ABI type">; +let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { + def target_cpu : Separate<["-"], "target-cpu">, HelpText<"Target a specific cpu type">; -def mfpmath : Separate<["-"], "mfpmath">, - HelpText<"Which unit to use for fp math">; def target_feature : Separate<["-"], "target-feature">, HelpText<"Target specific attributes">; -def target_linker_version : Separate<["-"], "target-linker-version">, - HelpText<"Target linker version">; def triple : Separate<["-"], "triple">, HelpText<"Specify target triple (e.g. i686-apple-darwin9)">; + +} + +def target_abi : Separate<["-"], "target-abi">, + HelpText<"Target a particular ABI type">; +def target_linker_version : Separate<["-"], "target-linker-version">, + HelpText<"Target linker version">; def triple_EQ : Joined<["-"], "triple=">, Alias<triple>; +def mfpmath : Separate<["-"], "mfpmath">, + HelpText<"Which unit to use for fp math">; //===----------------------------------------------------------------------===// // Analyzer Options @@ -124,22 +127,37 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">, // CodeGen Options //===----------------------------------------------------------------------===// +let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { + +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 mno_exec_stack : Flag<["-"], "mnoexecstack">, + HelpText<"Mark the file as not needing an executable stack">; +def compress_debug_sections : Flag<["-"], "compress-debug-sections">, + HelpText<"Compress DWARF debug sections using zlib">; +def msave_temp_labels : Flag<["-"], "msave-temp-labels">, + HelpText<"Save temporary labels in the symbol table. " + "Note this may change .s semantics and shouldn't generally be used " + "on compiler-generated code.">; + +} + def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">, HelpText<"Don't run LLVM optimization passes">; def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">, HelpText<"Don't run the LLVM IR verifier pass">; def disable_red_zone : Flag<["-"], "disable-red-zone">, HelpText<"Do not emit code that uses the red zone.">; -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 dwarf_column_info : Flag<["-"], "dwarf-column-info">, HelpText<"Turn on column location information.">; def split_dwarf : Flag<["-"], "split-dwarf">, HelpText<"Split out the dwarf .dwo sections">; def gnu_pubnames : Flag<["-"], "gnu-pubnames">, HelpText<"Emit newer GNU style pubnames">; +def arange_sections : Flag<["-"], "arange_sections">, + HelpText<"Emit DWARF .debug_arange sections">; def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; def no_implicit_float : Flag<["-"], "no-implicit-float">, @@ -188,8 +206,6 @@ def mfloat_abi : Separate<["-"], "mfloat-abi">, HelpText<"The float ABI to use">; 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 split_stacks : Flag<["-"], "split-stacks">, HelpText<"Try to use a split stack if possible.">; def mno_zero_initialized_in_bss : Flag<["-"], "mno-zero-initialized-in-bss">, @@ -198,8 +214,6 @@ 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 msave_temp_labels : Flag<["-"], "msave-temp-labels">, - HelpText<"(integrated-as) Save temporary labels">; def mrelocation_model : Separate<["-"], "mrelocation-model">, HelpText<"The relocation model to use">; def munwind_tables : Flag<["-"], "munwind-tables">, @@ -223,10 +237,12 @@ def dependent_lib : Joined<["--"], "dependent-lib=">, def sys_header_deps : Flag<["-"], "sys-header-deps">, HelpText<"Include system headers in dependency output">; +def module_file_deps : Flag<["-"], "module-file-deps">, + HelpText<"Include module files in dependency output">; def header_include_file : Separate<["-"], "header-include-file">, HelpText<"Filename (or -) to write header include output to">; def show_includes : Flag<["--"], "show-includes">, - HelpText<"Print cl.exe style /showIncludes to stderr">; + HelpText<"Print cl.exe style /showIncludes to stdout">; //===----------------------------------------------------------------------===// // Diagnostic Options @@ -256,6 +272,8 @@ def fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">, 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 verify : Flag<["-"], "verify">, + HelpText<"Verify diagnostic output using comment directives">; def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">, HelpText<"Silence ObjC rewriting warnings">; @@ -266,6 +284,7 @@ def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">, // This isn't normally used, it is just here so we can parse a // CompilerInvocation out of a driver-derived argument vector. def cc1 : Flag<["-"], "cc1">; +def cc1as : Flag<["-"], "cc1as">; def ast_merge : Separate<["-"], "ast-merge">, MetaVarName<"<ast file>">, @@ -297,8 +316,6 @@ def plugin_arg : JoinedAndSeparate<["-"], "plugin-arg-">, HelpText<"Pass <arg> to plugin <name>">; def add_plugin : Separate<["-"], "add-plugin">, MetaVarName<"<name>">, HelpText<"Use the named plugin action in addition to the default action">; -def version : Flag<["-"], "version">, - HelpText<"Print the compiler 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" @@ -308,6 +325,8 @@ def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">, HelpText<"Include name lookup table dumps in AST dumps">; def fno_modules_global_index : Flag<["-"], "fno-modules-global-index">, HelpText<"Do not automatically generate or update the global module index">; +def fno_modules_error_recovery : Flag<["-"], "fno-modules-error-recovery">, + HelpText<"Do not automatically import modules for error recovery">; let Group = Action_Group in { @@ -393,14 +412,19 @@ def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">, // Language Options //===----------------------------------------------------------------------===// +let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { + +def version : Flag<["-"], "version">, + HelpText<"Print the compiler version">; +def main_file_name : Separate<["-"], "main-file-name">, + HelpText<"Main file name to use for debug info">; + +} + def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">, HelpText<"Weakly link in the blocks runtime">; def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, HelpText<"Use SjLj style exceptions">; -def fhidden_weak_vtables : Flag<["-"], "fhidden-weak-vtables">, - HelpText<"Generate weak vtables and RTTI with hidden visibility">; -def main_file_name : Separate<["-"], "main-file-name">, - HelpText<"Main file name to use for debug info">; def split_dwarf_file : Separate<["-"], "split-dwarf-file">, HelpText<"File name to use for split dwarf debug info output">; def fno_wchar : Flag<["-"], "fno-wchar">, @@ -476,6 +500,10 @@ def fsized_deallocation : Flag<["-"], "fsized-deallocation">, HelpText<"Enable C++1y sized global deallocation functions">; def fobjc_subscripting_legacy_runtime : Flag<["-"], "fobjc-subscripting-legacy-runtime">, HelpText<"Allow Objective-C array and dictionary subscripting in legacy runtime">; +def vtordisp_mode_EQ : Joined<["-"], "vtordisp-mode=">, + HelpText<"Control vtordisp placement on win32 targets">; +def fno_rtti_data : Flag<["-"], "fno-rtti-data">, + HelpText<"Control emission of RTTI data">; //===----------------------------------------------------------------------===// // Header Search Options @@ -504,14 +532,6 @@ 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 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 @@ -539,6 +559,8 @@ def cl_single_precision_constant : Flag<["-"], "cl-single-precision-constant">, HelpText<"OpenCL only. Treat double precision floating-point constant as single precision constant.">; def cl_finite_math_only : Flag<["-"], "cl-finite-math-only">, HelpText<"OpenCL only. Allow floating-point optimizations that assume arguments and results are not NaNs or +-Inf.">; +def cl_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">, + HelpText<"OpenCL only. Generate kernel argument metadata.">; def cl_unsafe_math_optimizations : Flag<["-"], "cl-unsafe-math-optimizations">, HelpText<"OpenCL only. Allow unsafe floating-point optimizations. Also implies -cl-no-signed-zeros and -cl-mad-enable">; def cl_fast_relaxed_math : Flag<["-"], "cl-fast-relaxed-math">, @@ -556,3 +578,32 @@ def fcuda_is_device : Flag<["-"], "fcuda-is-device">, HelpText<"Generate code for CUDA device">; } // let Flags = [CC1Option] + + +//===----------------------------------------------------------------------===// +// cc1as-only Options +//===----------------------------------------------------------------------===// + +let Flags = [CC1AsOption, NoDriverOption] in { + +// Language Options +def n : Flag<["-"], "n">, + HelpText<"Don't automatically start assembly file with a text section">; + +// Frontend Options +def filetype : Separate<["-"], "filetype">, + HelpText<"Specify the output file type ('asm', 'null', or 'obj')">; + +// Transliterate Options +def output_asm_variant : Separate<["-"], "output-asm-variant">, + HelpText<"Select the asm variant index to use for output">; +def show_encoding : Flag<["-"], "show-encoding">, + HelpText<"Show instruction encoding information in transliterate mode">; +def show_inst : Flag<["-"], "show-inst">, + HelpText<"Show internal instruction representation in transliterate mode">; + +// Assemble Options +def dwarf_debug_producer : Separate<["-"], "dwarf-debug-producer">, + HelpText<"The string to embed in the Dwarf debug AT_producer record.">; + +} // let Flags = [CC1AsOption] diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td index d17a63c..7278bf8 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td @@ -57,10 +57,19 @@ def _SLASH_C : CLFlag<"C">, HelpText<"Don't discard comments when preprocessing" def _SLASH_c : CLFlag<"c">, HelpText<"Compile only">, Alias<c>; def _SLASH_D : CLJoinedOrSeparate<"D">, HelpText<"Define macro">, MetaVarName<"<macro[=value]>">, Alias<D>; -def _SLASH_GR : CLFlag<"GR">, HelpText<"Enable RTTI">, Alias<frtti>; -def _SLASH_GR_ : CLFlag<"GR-">, HelpText<"Disable RTTI">, Alias<fno_rtti>; +def _SLASH_E : CLFlag<"E">, HelpText<"Preprocess to stdout">, Alias<E>; +def _SLASH_GR : CLFlag<"GR">, HelpText<"Enable emission of RTTI data">; +def _SLASH_GR_ : CLFlag<"GR-">, HelpText<"Disable emission of RTTI data">; def _SLASH_GF_ : CLFlag<"GF-">, HelpText<"Disable string pooling">, Alias<fwritable_strings>; +def _SLASH_Gy : CLFlag<"Gy">, HelpText<"Put each function in its own section">, + Alias<ffunction_sections>; +def _SLASH_Gy_ : CLFlag<"Gy-">, HelpText<"Don't put each function in its own section">, + Alias<fno_function_sections>; +def _SLASH_Gw : CLFlag<"Gw">, HelpText<"Put each data item in its own section">, + Alias<fdata_sections>; +def _SLASH_Gw_ : CLFlag<"Gw-">, HelpText<"Don't put each data item in its own section">, + Alias<fno_data_sections>; def _SLASH_help : CLFlag<"help">, Alias<help>, HelpText<"Display available options">; def _SLASH_HELP : CLFlag<"HELP">, Alias<help>; @@ -88,7 +97,6 @@ def _SLASH_Oy : CLFlag<"Oy">, HelpText<"Enable frame pointer omission">, Alias<fomit_frame_pointer>; def _SLASH_Oy_ : CLFlag<"Oy-">, HelpText<"Disable frame pointer omission">, Alias<fno_omit_frame_pointer>; -def _SLASH_P : CLFlag<"P">, HelpText<"Only run the preprocessor">, Alias<E>; def _SLASH_QUESTION : CLFlag<"?">, Alias<help>, HelpText<"Display available options">; def _SLASH_showIncludes : CLFlag<"showIncludes">, @@ -96,6 +104,16 @@ def _SLASH_showIncludes : CLFlag<"showIncludes">, Alias<show_includes>; def _SLASH_U : CLJoinedOrSeparate<"U">, HelpText<"Undefine macro">, MetaVarName<"<macro>">, Alias<U>; +def _SLASH_vmb : CLFlag<"vmb">, + HelpText<"Use a best-case representation method for member pointers">; +def _SLASH_vmg : CLFlag<"vmg">, + HelpText<"Use a most-general representation for member pointers">; +def _SLASH_vms : CLFlag<"vms">, + HelpText<"Set the default most-general representation to single inheritance">; +def _SLASH_vmm : CLFlag<"vmm">, + HelpText<"Set the default most-general representation to multiple inheritance">; +def _SLASH_vmv : CLFlag<"vmv">, + HelpText<"Set the default most-general representation to virtual inheritance">; def _SLASH_W0 : CLFlag<"W0">, HelpText<"Disable all warnings">, Alias<w>; def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias<Wall>; def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias<Wall>; @@ -107,14 +125,27 @@ def _SLASH_WX : CLFlag<"WX">, HelpText<"Treat warnings as errors">, def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors">, Alias<W_Joined>, AliasArgs<["no-error"]>; def _SLASH_w_flag : CLFlag<"w">, HelpText<"Disable all warnings">, Alias<w>; +def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>, + AliasArgs<["no-macro-redefined"]>; +def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">, + Alias<vtordisp_mode_EQ>; +def _SLASH_Z7 : CLFlag<"Z7">, Alias<gline_tables_only>; +def _SLASH_Zi : CLFlag<"Zi">, HelpText<"Enable debug information">, + Alias<gline_tables_only>; def _SLASH_Zs : CLFlag<"Zs">, HelpText<"Syntax-check only">, Alias<fsyntax_only>; // Non-aliases: +def _SLASH_arch : CLCompileJoined<"arch:">, + HelpText<"Set architecture for code generation">; + def _SLASH_M_Group : OptionGroup<"</M group>">, Group<cl_compile_Group>; +def _SLASH_EH : CLJoined<"EH">, HelpText<"Exception handling model">; +def _SLASH_EP : CLFlag<"EP">, + HelpText<"Disable linemarker output and preprocess to stdout">; def _SLASH_FA : CLFlag<"FA">, HelpText<"Output assembly code file during compilation">; def _SLASH_Fa : CLJoined<"Fa">, @@ -127,6 +158,9 @@ def _SLASH_FI : CLJoinedOrSeparate<"FI">, def _SLASH_Fe : CLJoined<"Fe">, HelpText<"Set output executable file or directory (ends in / or \\)">, MetaVarName<"<file or directory>">; +def _SLASH_Fi : CLCompileJoined<"Fi">, + HelpText<"Set preprocess output file name">, + MetaVarName<"<file>">; def _SLASH_Fo : CLCompileJoined<"Fo">, HelpText<"Set output object file, or directory (ends in / or \\)">, MetaVarName<"<file or directory>">; @@ -142,6 +176,7 @@ def _SLASH_MT : Option<["/", "-"], "MT", KIND_FLAG>, Group<_SLASH_M_Group>, Flags<[CLOption, DriverOption]>, HelpText<"Use static run-time">; def _SLASH_MTd : Option<["/", "-"], "MTd", KIND_FLAG>, Group<_SLASH_M_Group>, Flags<[CLOption, DriverOption]>, HelpText<"Use static debug run-time">; +def _SLASH_P : CLFlag<"P">, HelpText<"Preprocess to file">; def _SLASH_Tc : CLCompileJoinedOrSeparate<"Tc">, HelpText<"Specify a C source file">, MetaVarName<"<filename>">; def _SLASH_TC : CLCompileFlag<"TC">, HelpText<"Treat all source files as C">; @@ -164,9 +199,10 @@ def _SLASH_Ob2 : CLIgnoredFlag<"Ob2">; def _SLASH_RTC : CLIgnoredJoined<"RTC">; def _SLASH_sdl : CLIgnoredFlag<"sdl">; def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">; -def _SLASH_vmg : CLIgnoredFlag<"vmg">; def _SLASH_w : CLIgnoredJoined<"w">; def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">; +def _SLASH_Zc_inline : CLIgnoredFlag<"Zc:inline">; +def _SLASH_Zc_rvalueCast : CLIgnoredFlag<"Zc:rvalueCast">; def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">; def _SLASH_Zm : CLIgnoredJoined<"Zm">; @@ -174,19 +210,15 @@ def _SLASH_Zm : CLIgnoredJoined<"Zm">; // Unsupported: def _SLASH_AI : CLJoined<"AI">; -def _SLASH_arch : CLJoined<"arch:">; def _SLASH_bigobj : CLFlag<"bigobj">; def _SLASH_clr : CLJoined<"clr">; +def _SLASH_d2Zi_PLUS : CLFlag<"d2Zi+">; def _SLASH_doc : CLJoined<"doc">; -def _SLASH_E : CLFlag<"E">; -def _SLASH_EH : CLJoined<"EH">; -def _SLASH_EP : CLFlag<"EP">; def _SLASH_FA_joined : CLJoined<"FA">; def _SLASH_favor : CLJoined<"favor">; def _SLASH_FC : CLFlag<"FC">; def _SLASH_F : CLFlag<"F">; def _SLASH_Fd : CLJoined<"Fd">; -def _SLASH_Fi : CLJoined<"Fi">; def _SLASH_Fm : CLJoined<"Fm">; def _SLASH_fp : CLJoined<"fp">; def _SLASH_Fp : CLJoined<"Fp">; @@ -210,8 +242,6 @@ def _SLASH_GS : CLFlag<"GS">; def _SLASH_Gs : CLJoined<"Gs">; def _SLASH_GT : CLFlag<"GT">; def _SLASH_GX : CLFlag<"GX">; -def _SLASH_Gy : CLFlag<"Gy">; -def _SLASH_Gy_ : CLFlag<"Gy-">; def _SLASH_Gz : CLFlag<"Gz">; def _SLASH_GZ : CLFlag<"GZ">; def _SLASH_H : CLFlag<"H">; @@ -229,11 +259,6 @@ def _SLASH_Qpar : CLFlag<"Qpar">; def _SLASH_Qvec_report : CLJoined<"Qvec-report">; def _SLASH_u : CLFlag<"u">; def _SLASH_V : CLFlag<"V">; -def _SLASH_vd : CLJoined<"vd">; -def _SLASH_vmb : CLFlag<"vmb">; -def _SLASH_vmm : CLFlag<"vmm">; -def _SLASH_vms : CLFlag<"vms">; -def _SLASH_vmv : CLFlag<"vmv">; def _SLASH_volatile : CLFlag<"volatile">; def _SLASH_WL : CLFlag<"WL">; def _SLASH_Wp64 : CLFlag<"Wp64">; @@ -243,13 +268,11 @@ def _SLASH_Y_ : CLFlag<"Y-">; def _SLASH_Yd : CLFlag<"Yd">; def _SLASH_Yl : CLJoined<"Yl">; def _SLASH_Yu : CLJoined<"Yu">; -def _SLASH_Z7 : CLFlag<"Z7">; def _SLASH_Za : CLFlag<"Za">; def _SLASH_Zc : CLJoined<"Zc:">; def _SLASH_Ze : CLFlag<"Ze">; def _SLASH_Zg : CLFlag<"Zg">; -def _SLASH_Zi : CLFlag<"Zi">; def _SLASH_ZI : CLFlag<"ZI">; def _SLASH_Zl : CLFlag<"Zl">; -def _SLASH_Zp : CLFlag<"Zp">; +def _SLASH_Zp : CLJoined<"Zp">; def _SLASH_ZW : CLJoined<"ZW">; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h index 3493e4f..c1c0f43 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h @@ -69,6 +69,9 @@ class Compilation { /// Redirection for stdout, stderr, etc. const StringRef **Redirects; + /// Whether we're compiling for diagnostic purposes. + bool ForDiagnostics; + public: Compilation(const Driver &D, const ToolChain &DefaultToolChain, llvm::opt::InputArgList *Args, @@ -173,6 +176,9 @@ public: /// so compilation can be reexecuted to generate additional diagnostic /// information (e.g., preprocessed source(s)). void initCompilationForDiagnostics(); + + /// Return true if we're compiling for diagnostics. + bool isForDiagnostics() { return ForDiagnostics; } }; } // end namespace driver diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h index 73c8086..df974ad 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h @@ -15,11 +15,11 @@ #include "clang/Driver/Phases.h" #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo +#include <memory> // lands. #include <list> #include <set> @@ -188,12 +188,11 @@ private: // getFinalPhase - Determine which compilation mode we are in and record // which option we used to determine the final phase. phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL, - llvm::opt::Arg **FinalPhaseArg = 0) const; + llvm::opt::Arg **FinalPhaseArg = nullptr) const; public: Driver(StringRef _ClangExecutable, StringRef _DefaultTargetTriple, - StringRef _DefaultImageName, DiagnosticsEngine &_Diags); ~Driver(); @@ -259,7 +258,7 @@ public: /// \param Args - The input arguments. /// \param Inputs - The list to store the resulting compilation /// inputs onto. - void BuildInputs(const ToolChain &TC, const llvm::opt::DerivedArgList &Args, + void BuildInputs(const ToolChain &TC, llvm::opt::DerivedArgList &Args, InputList &Inputs) const; /// BuildActions - Construct the list of actions to perform for the diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Job.h b/contrib/llvm/tools/clang/include/clang/Driver/Job.h index 1dd49a7..5b19efe 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Job.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Job.h @@ -11,9 +11,9 @@ #define CLANG_DRIVER_JOB_H_ #include "clang/Basic/LLVM.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Option/Option.h" +#include <memory> namespace llvm { class raw_ostream; @@ -76,8 +76,8 @@ public: Command(const Action &_Source, const Tool &_Creator, const char *_Executable, const llvm::opt::ArgStringList &_Arguments); - virtual void Print(llvm::raw_ostream &OS, const char *Terminator, - bool Quote, bool CrashReport = false) const; + void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, + bool CrashReport = false) const override; virtual int Execute(const StringRef **Redirects, std::string *ErrMsg, bool *ExecutionFailed) const; @@ -88,6 +88,8 @@ public: /// getCreator - Return the Tool which caused the creation of this job. const Tool &getCreator() const { return Creator; } + const char *getExecutable() const { return Executable; } + const llvm::opt::ArgStringList &getArguments() const { return Arguments; } static bool classof(const Job *J) { @@ -104,18 +106,18 @@ public: const char *Executable_, const ArgStringList &Arguments_, Command *Fallback_); - virtual void Print(llvm::raw_ostream &OS, const char *Terminator, - bool Quote, bool CrashReport = false) const; + void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, + bool CrashReport = false) const override; - virtual int Execute(const StringRef **Redirects, std::string *ErrMsg, - bool *ExecutionFailed) const; + int Execute(const StringRef **Redirects, std::string *ErrMsg, + bool *ExecutionFailed) const override; static bool classof(const Job *J) { return J->getKind() == FallbackCommandClass; } private: - OwningPtr<Command> Fallback; + std::unique_ptr<Command> Fallback; }; /// JobList - A sequence of jobs to perform. @@ -133,8 +135,8 @@ public: JobList(); virtual ~JobList(); - virtual void Print(llvm::raw_ostream &OS, const char *Terminator, - bool Quote, bool CrashReport = false) const; + void Print(llvm::raw_ostream &OS, const char *Terminator, + bool Quote, bool CrashReport = false) const override; /// Add a job to the list (taking ownership). void addJob(Job *J) { Jobs.push_back(J); } diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h b/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h new file mode 100644 index 0000000..6c3738a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h @@ -0,0 +1,167 @@ +//===--- Multilib.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_LIB_DRIVER_MULTILIB_H_ +#define CLANG_LIB_DRIVER_MULTILIB_H_ + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Option/Option.h" +#include <string> +#include <vector> + +namespace clang { +namespace driver { + +/// This corresponds to a single GCC Multilib, or a segment of one controlled +/// by a command line flag +class Multilib { +public: + typedef std::vector<std::string> flags_list; + +private: + std::string GCCSuffix; + std::string OSSuffix; + std::string IncludeSuffix; + flags_list Flags; + +public: + Multilib(StringRef GCCSuffix = "", StringRef OSSuffix = "", + StringRef IncludeSuffix = ""); + + /// \brief Get the detected GCC installation path suffix for the multi-arch + /// target variant. Always starts with a '/', unless empty + const std::string &gccSuffix() const { + assert(GCCSuffix.empty() || + (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1)); + return GCCSuffix; + } + /// Set the GCC installation path suffix. + Multilib &gccSuffix(StringRef S); + + /// \brief Get the detected os path suffix for the multi-arch + /// target variant. Always starts with a '/', unless empty + const std::string &osSuffix() const { + assert(OSSuffix.empty() || + (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1)); + return OSSuffix; + } + /// Set the os path suffix. + Multilib &osSuffix(StringRef S); + + /// \brief Get the include directory suffix. Always starts with a '/', unless + /// empty + const std::string &includeSuffix() const { + assert(IncludeSuffix.empty() || + (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1)); + return IncludeSuffix; + } + /// Set the include directory suffix + Multilib &includeSuffix(StringRef S); + + /// \brief Get the flags that indicate or contraindicate this multilib's use + /// All elements begin with either '+' or '-' + const flags_list &flags() const { return Flags; } + flags_list &flags() { return Flags; } + /// Add a flag to the flags list + Multilib &flag(StringRef F) { + assert(F.front() == '+' || F.front() == '-'); + Flags.push_back(F); + return *this; + } + + /// \brief print summary of the Multilib + void print(raw_ostream &OS) const; + + /// Check whether any of the 'against' flags contradict the 'for' flags. + bool isValid() const; + + /// Check whether the default is selected + bool isDefault() const + { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); } + + bool operator==(const Multilib &Other) const; +}; + +raw_ostream &operator<<(raw_ostream &OS, const Multilib &M); + +class MultilibSet { +public: + typedef std::vector<Multilib> multilib_list; + typedef multilib_list::iterator iterator; + typedef multilib_list::const_iterator const_iterator; + + struct FilterCallback { + virtual ~FilterCallback() {}; + /// \return true iff the filter should remove the Multilib from the set + virtual bool operator()(const Multilib &M) const = 0; + }; + +private: + multilib_list Multilibs; + +public: + MultilibSet() {} + + /// Add an optional Multilib segment + MultilibSet &Maybe(const Multilib &M); + + /// Add a set of mutually incompatible Multilib segments + MultilibSet &Either(const Multilib &M1, const Multilib &M2); + MultilibSet &Either(const Multilib &M1, const Multilib &M2, + const Multilib &M3); + MultilibSet &Either(const Multilib &M1, const Multilib &M2, + const Multilib &M3, const Multilib &M4); + MultilibSet &Either(const Multilib &M1, const Multilib &M2, + const Multilib &M3, const Multilib &M4, + const Multilib &M5); + MultilibSet &Either(const std::vector<Multilib> &Ms); + + /// Filter out some subset of the Multilibs using a user defined callback + MultilibSet &FilterOut(const FilterCallback &F); + /// Filter out those Multilibs whose gccSuffix matches the given expression + MultilibSet &FilterOut(std::string Regex); + + /// Add a completed Multilib to the set + void push_back(const Multilib &M); + + /// Union this set of multilibs with another + void combineWith(const MultilibSet &MS); + + /// Remove all of thie multilibs from the set + void clear() { Multilibs.clear(); } + + iterator begin() { return Multilibs.begin(); } + const_iterator begin() const { return Multilibs.begin(); } + + iterator end() { return Multilibs.end(); } + const_iterator end() const { return Multilibs.end(); } + + /// Pick the best multilib in the set, \returns false if none are compatible + bool select(const Multilib::flags_list &Flags, Multilib &M) const; + + unsigned size() const { return Multilibs.size(); } + + void print(raw_ostream &OS) const; + +private: + /// Apply the filter to Multilibs and return the subset that remains + static multilib_list filterCopy(const FilterCallback &F, + const multilib_list &Ms); + + /// Apply the filter to the multilib_list, removing those that don't match + static void filterInPlace(const FilterCallback &F, multilib_list &Ms); +}; + +raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS); +} +} + +#endif + diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.h b/contrib/llvm/tools/clang/include/clang/Driver/Options.h index 28948be..cee705d 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Options.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.h @@ -30,7 +30,8 @@ enum ClangFlags { CoreOption = (1 << 8), CLOption = (1 << 9), CC1Option = (1 << 10), - NoDriverOption = (1 << 11) + CC1AsOption = (1 << 11), + NoDriverOption = (1 << 12) }; enum ID { diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td index 5e7c76d..a48b7ad 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Options.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td @@ -44,6 +44,9 @@ def CLOption : OptionFlag; // CC1Option - This option should be accepted by clang -cc1. def CC1Option : OptionFlag; +// CC1AsOption - This option should be accepted by clang -cc1as. +def CC1AsOption : OptionFlag; + // NoDriverOption - This option should not be accepted by the driver. def NoDriverOption : OptionFlag; @@ -60,7 +63,10 @@ def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>; def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>; def T_Group : OptionGroup<"<T group>">; def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>; +def R_Group : OptionGroup<"<R group>">, Group<CompileOnly_Group>; +def R_value_Group : OptionGroup<"<R (with value) group>">, Group<R_Group>; def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>; +def W_value_Group : OptionGroup<"<W (with value) group>">, Group<W_Group>; 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>; @@ -69,11 +75,11 @@ 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_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>, Flags<[CoreOption]>; def m_hexagon_Features_Group : OptionGroup<"<m hexagon features group>">, Group<m_Group>; def m_arm_Features_Group : OptionGroup<"<m arm features group>">, Group<m_Group>; +def m_aarch64_Features_Group : OptionGroup<"<m aarch64 features group>">, Group<m_Group>; def m_ppc_Features_Group : OptionGroup<"<m ppc features group>">, Group<m_Group>; -def opencl_Group : OptionGroup<"<opencl group>">; def u_Group : OptionGroup<"<u group>">; def pedantic_Group : OptionGroup<"<pedantic group>">, @@ -87,6 +93,10 @@ def clang_ignored_f_Group : OptionGroup<"<clang ignored f group>">, def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">, Group<m_Group>; +// Group that ignores all gcc optimizations that won't be implemented +def clang_ignored_gcc_optimization_f_Group : OptionGroup< + "<clang_ignored_gcc_optimization_f_Group>">, Group<f_Group>; + ///////// // Options @@ -184,8 +194,13 @@ def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpoin HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">; def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>, HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">; -def objcmt_white_list_dir_path: Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>, +def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>, + HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">; +def objcmt_whitelist_dir_path: Joined<["-"], "objcmt-whitelist-dir-path=">, Flags<[CC1Option]>, HelpText<"Only modify files with a filename contained in the provided directory path">; +// The misspelt "white-list" [sic] alias is due for removal. +def : Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>, + Alias<objcmt_whitelist_dir_path>; // Make sure all other -ccc- options are rejected. def ccc_ : Joined<["-"], "ccc-">, Group<internal_Group>, Flags<[Unsupported]>; @@ -193,7 +208,7 @@ def ccc_ : Joined<["-"], "ccc-">, Group<internal_Group>, Flags<[Unsupported]>; // Standard Options def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[DriverOption, CoreOption]>, - HelpText<"Print the commands to run for this compilation">; + HelpText<"Print (but do not run) the commands to run for this compilation">; def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>, Flags<[DriverOption, CoreOption]>; def A : JoinedOrSeparate<["-"], "A">, Flags<[RenderJoined]>; @@ -210,23 +225,29 @@ def G_EQ : Joined<["-"], "G=">, Flags<[DriverOption]>; 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>, Flags<[CC1Option]>, +def I : JoinedOrSeparate<["-"], "I">, Group<I_Group>, Flags<[CC1Option,CC1AsOption]>, 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 MD : Flag<["-"], "MD">, Group<M_Group>, + HelpText<"Write a depfile containing user and system headers">; +def MMD : Flag<["-"], "MMD">, Group<M_Group>, + HelpText<"Write a depfile containing user headers">; +def M : Flag<["-"], "M">, Group<M_Group>, + HelpText<"Like -MD, but also implies -E and writes to stdout by default">; +def MM : Flag<["-"], "MM">, Group<M_Group>, + HelpText<"Like -MMD, but also implies -E and writes to stdout by default">; +def MF : JoinedOrSeparate<["-"], "MF">, Group<M_Group>, + HelpText<"Write depfile output from -MMD, -MD, -MM, or -M to <file>">, + MetaVarName<"<file>">; 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>; + HelpText<"Add missing headers to depfile">; 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">; + HelpText<"Specify name of main file output to quote in depfile">; def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>, - HelpText<"Specify target for dependency">; + HelpText<"Specify name of main file output in depfile">; def Mach : Flag<["-"], "Mach">; -def M : Flag<["-"], "M">, Group<M_Group>; def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option]>; def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option]>; def ObjCXX : Flag<["-"], "ObjC++">, Flags<[DriverOption]>, @@ -242,7 +263,19 @@ def Qn : Flag<["-"], "Qn">; def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>, HelpText<"Don't emit warning for unused driver arguments">; def Q : Flag<["-"], "Q">; -def R : Flag<["-"], "R">; +def Rpass_EQ : Joined<["-"], "Rpass=">, Group<R_value_Group>, Flags<[CC1Option]>, + HelpText<"Report transformations performed by optimization passes whose " + "name matches the given POSIX regular expression">; +def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">, Group<R_value_Group>, + Flags<[CC1Option]>, + HelpText<"Report missed transformations by optimization passes whose " + "name matches the given POSIX regular expression">; +def Rpass_analysis_EQ : Joined<["-"], "Rpass-analysis=">, Group<R_value_Group>, + Flags<[CC1Option]>, + HelpText<"Report transformation analysis from optimization passes whose " + "name matches the given POSIX regular expression">; +def R_Joined : Joined<["-"], "R">, Group<R_Group>, Flags<[CC1Option, CoreOption]>, + MetaVarName<"<remark>">, HelpText<"Enable the specified remark">; def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>, HelpText<"Only run preprocess and compilation steps">; def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>; @@ -261,6 +294,7 @@ 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>">; +// FIXME: This is broken; these should not be Joined arguments. def Wno_nonportable_cfstrings : Joined<["-"], "Wno-nonportable-cfstrings">, Group<W_Group>, Flags<[CC1Option]>; def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group<W_Group>, @@ -268,6 +302,8 @@ def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group<W_Gr 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>, 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, CoreOption]>, MetaVarName<"<warning>">, HelpText<"Enable the specified warning">; def Xanalyzer : Separate<["-"], "Xanalyzer">, @@ -278,6 +314,8 @@ def Xassembler : Separate<["-"], "Xassembler">, def Xclang : Separate<["-"], "Xclang">, HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">, Flags<[DriverOption, CoreOption]>; +def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>, + HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">; def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">; def Xpreprocessor : Separate<["-"], "Xpreprocessor">, @@ -297,8 +335,6 @@ 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">; @@ -320,6 +356,8 @@ 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 module_dependency_dir : Separate<["-"], "module-dependency-dir">, + Flags<[CC1Option]>, HelpText<"Directory to dump module dependencies to">; def dumpmachine : Flag<["-"], "dumpmachine">; def dumpspecs : Flag<["-"], "dumpspecs">, Flags<[Unsupported]>; def dumpversion : Flag<["-"], "dumpversion">; @@ -346,10 +384,7 @@ 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>; -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 shared_libasan : Flag<["-"], "shared-libasan">; def fasm : Flag<["-"], "fasm">, Group<f_Group>; def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>, Flags<[CC1Option]>; @@ -369,19 +404,23 @@ def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>, def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">, Group<f_Group>, Flags<[DriverOption, CC1Option]>, HelpText<"Enable sample-based profile guided optimizations">; +def fauto_profile_EQ : Joined<["-"], "fauto-profile=">, + Alias<fprofile_sample_use_EQ>; +def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Generate instrumented code to collect execution counts">; +def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>; +def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Use instrumentation data for profile-guided optimization">; 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>, 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 : 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>; def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>; def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use colors in diagnostics">; @@ -417,8 +456,6 @@ def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-sourc 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>; @@ -428,8 +465,8 @@ def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tr 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>, Flags<[CC1Option]>; +def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group<clang_ignored_f_Group>; +def fno_dwarf2_cfi_asm : Flag<["-"], "fno-dwarf2-cfi-asm">, Group<clang_ignored_f_Group>; def fdwarf_directory_asm : Flag<["-"], "fdwarf-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>; @@ -440,18 +477,16 @@ def feliminate_unused_debug_symbols : Flag<["-"], "feliminate-unused-debug-symbo 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 ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>, Flags<[CoreOption]>; def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable support for exception handling">; -def fexpensive_optimizations : Flag<["-"], "fexpensive-optimizations">, - Group<clang_ignored_f_Group>; -def fno_expensive_optimizations : Flag<["-"], "fno-expensive-optimizations">, - Group<clang_ignored_f_Group>; +def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>; +def : Flag<["-"], "fno-expensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>; def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group<f_Group>; -def fextended_identifiers : Flag<["-"], "fextended-identifiers">, - Group<clang_ignored_f_Group>; -def fno_extended_identifiers : Flag<["-"], "fno-extended-identifiers">, - Group<f_Group>, Flags<[Unsupported]>; +def : Flag<["-"], "fdefer-pop">, Group<clang_ignored_gcc_optimization_f_Group>; +def : Flag<["-"], "fno-defer-pop">, Group<clang_ignored_gcc_optimization_f_Group>; +def : Flag<["-"], "fextended-identifiers">, Group<clang_ignored_f_Group>; +def : Flag<["-"], "fno-extended-identifiers">, Group<f_Group>, Flags<[Unsupported]>; def fhosted : Flag<["-"], "fhosted">, 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 " @@ -470,23 +505,21 @@ def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>, "address (memory errors) | thread (race detection) | " "undefined (miscellaneous undefined behavior)">; def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>; -def fsanitize_address_zero_base_shadow : Flag<["-"], "fsanitize-address-zero-base-shadow">, - Group<f_clang_Group>, Flags<[CC1Option]>, - HelpText<"Make AddressSanitizer map shadow memory " - "at zero offset">; -def fno_sanitize_address_zero_base_shadow : Flag<["-"], "fno-sanitize-address-zero-base-shadow">, - Group<f_clang_Group>; def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">, - Group<f_clang_Group>, Flags<[CC1Option]>, + Group<f_clang_Group>, Flags<[CC1Option, CoreOption]>, HelpText<"Path to blacklist file for sanitizers">; def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">, Group<f_clang_Group>, HelpText<"Don't use blacklist file for sanitizers">; +def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Enable origins tracking in MemorySanitizer">; def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Enable origins tracking in MemorySanitizer">; def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">, - Group<f_clang_Group>; + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Disable origins tracking in MemorySanitizer">; def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>; def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, @@ -512,9 +545,9 @@ def fhonor_nans : Flag<["-"], "fhonor-nans">, Group<f_Group>; 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">, Alias<fhonor_infinities>; -def fno_honor_infinites : Flag<["-"], "fno-honor-infinites">, Alias<fno_honor_infinities>; +// This option was originally misspelt "infinites" [sic]. +def : Flag<["-"], "fhonor-infinites">, Alias<fhonor_infinities>; +def : 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>, @@ -541,12 +574,12 @@ 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 : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>; +def finline_functions : Flag<["-"], "finline-functions">, Group<clang_ignored_gcc_optimization_f_Group>; def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>; +def finput_charset_EQ : Joined<["-"], "finput-charset=">, 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 flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>; @@ -559,21 +592,45 @@ def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, 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 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, CoreOption]>, - HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">; + HelpText<"Enable full Microsoft Visual C++ compatibility">; +def fmsc_version : Joined<["-"], "fmsc-version=">, Group<f_Group>, Flags<[DriverOption, CoreOption]>, + HelpText<"Microsoft compiler version number to report in _MSC_VER (0 = don't define it (default))">; +def fms_compatibility_version + : Joined<["-"], "fms-compatibility-version=">, + Group<f_Group>, + Flags<[ CC1Option, CoreOption ]>, + HelpText<"Dot-separated value representing the Microsoft compiler " + "version number 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]>; + "translation unit">, Flags<[CC1Option]>; +def fms_memptr_rep_EQ : Joined<["-"], "fms-memptr-rep=">, Group<f_Group>, Flags<[CC1Option]>; def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group<i_Group>, Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">, HelpText<"Specify the module cache path">; +def fmodules_user_build_path : Separate<["-"], "fmodules-user-build-path">, Group<i_Group>, + Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">, + HelpText<"Specify the module user build path">; def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i_Group>, Flags<[CC1Option]>, MetaVarName<"<seconds>">, HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">; def fmodules_prune_after : Joined<["-"], "fmodules-prune-after=">, Group<i_Group>, Flags<[CC1Option]>, MetaVarName<"<seconds>">, HelpText<"Specify the interval (in seconds) after which a module file will be considered unused">; +def fmodules_search_all : Flag <["-"], "fmodules-search-all">, Group<f_Group>, + Flags<[DriverOption, CC1Option]>, + HelpText<"Search even non-imported modules to resolve references">; +def fbuild_session_timestamp : Joined<["-"], "fbuild-session-timestamp=">, + Group<i_Group>, Flags<[CC1Option]>, MetaVarName<"<time since Epoch in seconds>">, + HelpText<"Time when the current build session started">; +def fmodules_validate_once_per_build_session : Flag<["-"], "fmodules-validate-once-per-build-session">, + Group<i_Group>, Flags<[CC1Option]>, + HelpText<"Don't verify input files for the modules if the module has been " + "successfully validate or loaded during this build session">; +def fmodules_validate_system_headers : Flag<["-"], "fmodules-validate-system-headers">, + Group<i_Group>, Flags<[CC1Option]>, + HelpText<"Validate the system headers that a module depends on when loading the module">; def fmodules : Flag <["-"], "fmodules">, Group<f_Group>, Flags<[DriverOption, CC1Option]>, HelpText<"Enable the 'modules' language feature">; @@ -591,6 +648,11 @@ def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Gro def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group<f_Group>, Flags<[DriverOption,CC1Option]>, HelpText<"Require declaration of modules used within a module">; +def fmodules_strict_decluse : Flag <["-"], "fmodules-strict-decluse">, Group<f_Group>, + Flags<[DriverOption,CC1Option]>, + HelpText<"Like -fmodules-decluse but requires all headers to be in modules">; +def fno_modules_search_all : Flag <["-"], "fno-modules-search-all">, Group<f_Group>, + Flags<[DriverOption, CC1Option]>; def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>; def fmudflapth : Flag<["-"], "fmudflapth">, Group<f_Group>; @@ -627,7 +689,6 @@ def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group<f_Group>, Flags<[DriverOption]>; 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">, Flags<[CC1Option]>, Group<f_Group>; @@ -640,7 +701,6 @@ def fno_exceptions : Flag<["-"], "fno-exceptions">, 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>, HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>; def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>, @@ -651,6 +711,8 @@ def fno_module_maps : Flag <["-"], "fno-module-maps">, Group<f_Group>, Flags<[DriverOption]>; def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group<f_Group>, Flags<[DriverOption]>; +def fno_modules_strict_decluse : Flag <["-"], "fno-strict-modules-decluse">, Group<f_Group>, + Flags<[DriverOption]>; def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>; def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>; def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group<f_Group>; @@ -670,8 +732,10 @@ def fno_show_source_location : Flag<["-"], "fno-show-source-location">, Group<f_ 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_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>, + HelpText<"Disable the use of stack protectors">; +def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>, + Flags<[DriverOption, CoreOption]>; def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>; def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group<f_Group>; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>; @@ -724,7 +788,8 @@ def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Gr def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>; def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>; -def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option]>; +def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>; +def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>, Flags<[CC1Option]>; def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>; def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>; def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">; @@ -751,12 +816,14 @@ def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group<clang_ignored_f_Grou def freg_struct_return : Flag<["-"], "freg-struct-return">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Override the default ABI to return small structs in registers">; def frtti : Flag<["-"], "frtti">, Group<f_Group>; -def fsched_interblock : Flag<["-"], "fsched-interblock">, Group<clang_ignored_f_Group>; +def : Flag<["-"], "fsched-interblock">, Group<clang_ignored_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 : Flag<["-"], "freorder-blocks">, Group<clang_ignored_gcc_optimization_f_Group>; def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Force wchar_t to be a short unsigned int">; +def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Force wchar_t to be an 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">; @@ -768,15 +835,20 @@ def fsigned_char : Flag<["-"], "fsigned-char">, Group<f_Group>; def fno_signed_char : Flag<["-"], "fno-signed-char">, Flags<[CC1Option]>, Group<clang_ignored_f_Group>, HelpText<"Char is unsigned">; def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>; -def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>; -def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>; +def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>, + HelpText<"Force the usage of stack protectors for all functions">; +def fstack_protector_strong : Flag<["-"], "fstack-protector-strong">, Group<f_Group>, + HelpText<"Use a strong heuristic to apply stack protectors to functions">; +def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>, + HelpText<"Enable stack protectors for functions potentially vulnerable to stack smashing">; def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Emit full debug info for all types used by the program">; def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Limit debug information produced to reduce size of debug binary">; def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Alias<fno_standalone_debug>; def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Alias<fstandalone_debug>; -def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>; +def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>, + Flags<[DriverOption, CoreOption]>; 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">; @@ -793,29 +865,28 @@ def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>; def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>, HelpText<"Enable the loop vectorization passes">; def fno_vectorize : Flag<["-"], "fno-vectorize">, Group<f_Group>; -def ftree_vectorize : Flag<["-"], "ftree-vectorize">, Alias<fvectorize>; -def fno_tree_vectorize : Flag<["-"], "fno-tree-vectorize">, Alias<fno_vectorize>; +def : Flag<["-"], "ftree-vectorize">, Alias<fvectorize>; +def : Flag<["-"], "fno-tree-vectorize">, Alias<fno_vectorize>; def fslp_vectorize : Flag<["-"], "fslp-vectorize">, Group<f_Group>, HelpText<"Enable the superword-level parallelism vectorization passes">; def fno_slp_vectorize : Flag<["-"], "fno-slp-vectorize">, Group<f_Group>; def fslp_vectorize_aggressive : Flag<["-"], "fslp-vectorize-aggressive">, Group<f_Group>, HelpText<"Enable the BB vectorization passes">; def fno_slp_vectorize_aggressive : Flag<["-"], "fno-slp-vectorize-aggressive">, Group<f_Group>; -def ftree_slp_vectorize : Flag<["-"], "ftree-slp-vectorize">, Alias<fslp_vectorize>; -def fno_tree_slp_vectorize : Flag<["-"], "fno-tree-slp-vectorize">, Alias<fno_slp_vectorize>; +def : Flag<["-"], "ftree-slp-vectorize">, Alias<fslp_vectorize>; +def : Flag<["-"], "fno-tree-slp-vectorize">, Alias<fno_slp_vectorize>; 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 than a given value">, Flags<[HelpHidden]>; 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>; -def Wlarger_than_EQ : Joined<["-"], "Wlarger-than=">, Alias<Wlarger_than>; -def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias<Wlarger_than>; -def Wframe_larger_than : Separate<["-"], "Wframe-larger-than">, Group<clang_ignored_f_Group>; -def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Alias<Wframe_larger_than>; +// These "special" warning flags are effectively processed as f_Group flags by the driver: +// Just silence warnings about -Wlarger-than for now. +def Wlarger_than_EQ : Joined<["-"], "Wlarger-than=">, Group<clang_ignored_f_Group>; +def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias<Wlarger_than_EQ>; +def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Group<f_Group>, Flags<[DriverOption]>; -def fterminated_vtables : Flag<["-"], "fterminated-vtables">, Alias<fapple_kext>; +def : Flag<["-"], "fterminated-vtables">, Alias<fapple_kext>; def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, 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]>; @@ -870,10 +941,13 @@ def fno_data_sections : Flag <["-"], "fno-data-sections">, Group<f_Group>, Flags<[CC1Option]>; def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">; +def fno_debug_types_section: Flag<["-"], "fno-debug-types-section">, Group<f_Group>, + Flags<[CC1Option]>; def g_Flag : Flag<["-"], "g">, Group<g_Group>, - HelpText<"Generate source level debug information">, Flags<[CC1Option]>; + HelpText<"Generate source-level debug information">, Flags<[CC1Option,CC1AsOption]>; def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<g_Group>, HelpText<"Emit debug line number tables only">, Flags<[CC1Option]>; +def gmlt : Flag<["-"], "gmlt">, Alias<gline_tables_only>; def g0 : Flag<["-"], "g0">, Group<g_Group>; def g1 : Flag<["-"], "g1">, Group<g_Group>; def g2 : Flag<["-"], "g2">, Group<g_Group>; @@ -884,11 +958,11 @@ 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>, - HelpText<"Generate source level debug information with dwarf version 2">, Flags<[CC1Option]>; + HelpText<"Generate source-level debug information with dwarf version 2">, Flags<[CC1Option,CC1AsOption]>; def gdwarf_3 : Flag<["-"], "gdwarf-3">, Group<g_Group>, - HelpText<"Generate source level debug information with dwarf version 3">, Flags<[CC1Option]>; + HelpText<"Generate source-level debug information with dwarf version 3">, Flags<[CC1Option,CC1AsOption]>; def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group<g_Group>, - HelpText<"Generate source level debug information with dwarf version 4">, Flags<[CC1Option]>; + HelpText<"Generate source-level debug information with dwarf version 4">, Flags<[CC1Option,CC1AsOption]>; def gfull : Flag<["-"], "gfull">, Group<g_Group>; def gused : Flag<["-"], "gused">, Group<g_Group>; def gstabs : Joined<["-"], "gstabs">, Group<g_Group>, Flags<[Unsupported]>; @@ -902,10 +976,12 @@ def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">, def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group<g_flags_Group>; def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>; def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>; +def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>; def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>; def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>; +def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group<g_flags_Group>; def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; -def help : Flag<["-", "--"], "help">, Flags<[CC1Option]>, +def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption]>, 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">; @@ -922,9 +998,10 @@ def include_pch : Separate<["-"], "include-pch">, Group<clang_i_Group>, Flags<[C HelpText<"Include precompiled header file">, MetaVarName<"<file>">; def relocatable_pch : Flag<["-", "--"], "relocatable-pch">, Flags<[CC1Option]>, HelpText<"Whether to build a relocatable precompiled header">; +def verify_pch : Flag<["-"], "verify-pch">, Group<Action_Group>, Flags<[CC1Option]>, + HelpText<"Load and verify that a pre-compiled header file is not stale">; 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>, Flags<[CC1Option]>, HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">, MetaVarName<"<dir>">; def iquote : JoinedOrSeparate<["-"], "iquote">, Group<clang_i_Group>, Flags<[CC1Option]>, @@ -942,21 +1019,28 @@ 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 ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Overlay the virtual filesystem described by file over the real file system">; 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 EL : Flag<["-"], "EL">, Flags<[DriverOption]>; -def EB : Flag<["-"], "EB">, Flags<[DriverOption]>; +def mlittle_endian : Flag<["-"], "mlittle-endian">, Flags<[DriverOption]>; +def EL : Flag<["-"], "EL">, Alias<mlittle_endian>; +def mbig_endian : Flag<["-"], "mbig-endian">, Flags<[DriverOption]>; +def EB : Flag<["-"], "EB">, Alias<mbig_endian>; +def m16 : Flag<["-"], "m16">, Group<m_Group>, Flags<[DriverOption, CoreOption]>; def m32 : Flag<["-"], "m32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>; 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, CoreOption]>; +def mx32 : Flag<["-"], "mx32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>; def mabi_EQ : Joined<["-"], "mabi=">, Group<m_Group>; def march_EQ : Joined<["-"], "march=">, Group<m_Group>; +def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[DriverOption]>; 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>; @@ -977,7 +1061,7 @@ def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min="> def mkernel : Flag<["-"], "mkernel">, Group<m_Group>; def mlinker_version_EQ : Joined<["-"], "mlinker-version=">, Flags<[DriverOption]>; -def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option]>, +def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option,CC1AsOption,CoreOption]>, 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>, Flags<[CC1Option]>, @@ -1032,11 +1116,11 @@ def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>; def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>; def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>, - HelpText<"Allow memory accesses to be unaligned (ARM only)">; + HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">; def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_arm_Features_Group>, - HelpText<"Force all memory accesses to be aligned (ARM only)">; + HelpText<"Force all memory accesses to be aligned (AArch32/AArch64 only)">; def mstrict_align : Flag<["-"], "mstrict-align">, Alias<mno_unaligned_access>, Flags<[CC1Option,HelpHidden]>, - HelpText<"Force all memory accesses to be aligned (ARM only, same as mno-unaligned-access)">; + HelpText<"Force all memory accesses to be aligned (AArch64 only, same as mno-unaligned-access)">; def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_arm_Features_Group>; def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>, HelpText<"Disallow generation of deprecated IT blocks for ARMv8. It is on by default for ARMv8 Thumb mode.">; @@ -1049,6 +1133,13 @@ def mcrc : Flag<["-"], "mcrc">, Group<m_arm_Features_Group>, HelpText<"Allow use of CRC instructions (ARM only)">; def mnocrc : Flag<["-"], "mnocrc">, Group<m_arm_Features_Group>, HelpText<"Disallow use of CRC instructions (ARM only)">; +def mlong_calls : Flag<["-"], "mlong-calls">, Group<m_arm_Features_Group>, + HelpText<"Generate an indirect jump to enable jumps further than 64M">; +def mno_long_calls : Flag<["-"], "mno-long-calls">, Group<m_arm_Features_Group>, + HelpText<"Restore the default behaviour of not generating long calls">; + +def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group<m_aarch64_Features_Group>, + HelpText<"Generate code which only uses the general purpose registers (AArch64 only)">; def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>; def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>; @@ -1060,6 +1151,8 @@ def mpopcntd : Flag<["-"], "mpopcntd">, Group<m_ppc_Features_Group>; def mno_popcntd : Flag<["-"], "mno-popcntd">, Group<m_ppc_Features_Group>; def mqpx : Flag<["-"], "mqpx">, Group<m_ppc_Features_Group>; def mno_qpx : Flag<["-"], "mno-qpx">, Group<m_ppc_Features_Group>; +def mcrbits : Flag<["-"], "mcrbits">, Group<m_ppc_Features_Group>; +def mno_crbits : Flag<["-"], "mno-crbits">, Group<m_ppc_Features_Group>; def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable AltiVec vector initializer syntax">; @@ -1075,7 +1168,7 @@ def moslib_EQ : Joined<["-"], "moslib=">, Group<m_Group>; def mpascal_strings : Flag<["-"], "mpascal-strings">, Alias<fpascal_strings>; 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>, Flags<[CC1Option]>, +def mrelax_all : Flag<["-"], "mrelax-all">, Group<m_Group>, Flags<[CC1Option,CC1AsOption]>, HelpText<"(integrated-as) Relax all machine instructions">; def mrtd : Flag<["-"], "mrtd">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Make StdCall calling convention the default">; @@ -1142,18 +1235,48 @@ def mfp64 : Flag<["-"], "mfp64">, Group<m_Group>, def mfp32 : Flag<["-"], "mfp32">, Group<m_Group>, HelpText<"Use 32-bit floating point registers (MIPS only)">; def mnan_EQ : Joined<["-"], "mnan=">, Group<m_Group>; +def mips1 : Flag<["-"], "mips1">, + Alias<march_EQ>, AliasArgs<["mips1"]>, + HelpText<"Equivalent to -march=mips1">, Flags<[HelpHidden]>; +def mips2 : Flag<["-"], "mips2">, + Alias<march_EQ>, AliasArgs<["mips2"]>, + HelpText<"Equivalent to -march=mips2">, Flags<[HelpHidden]>; +def mips3 : Flag<["-"], "mips3">, + Alias<march_EQ>, AliasArgs<["mips3"]>, + HelpText<"Equivalent to -march=mips3">, Flags<[HelpHidden]>; +def mips4 : Flag<["-"], "mips4">, + Alias<march_EQ>, AliasArgs<["mips4"]>, + HelpText<"Equivalent to -march=mips4">, Flags<[HelpHidden]>; +def mips5 : Flag<["-"], "mips5">, + Alias<march_EQ>, AliasArgs<["mips5"]>, + HelpText<"Equivalent to -march=mips5">, Flags<[HelpHidden]>; def mips32 : Flag<["-"], "mips32">, Alias<march_EQ>, AliasArgs<["mips32"]>, HelpText<"Equivalent to -march=mips32">, Flags<[HelpHidden]>; def mips32r2 : Flag<["-"], "mips32r2">, Alias<march_EQ>, AliasArgs<["mips32r2"]>, HelpText<"Equivalent to -march=mips32r2">, Flags<[HelpHidden]>; +def mips32r6 : Flag<["-"], "mips32r6">, + Alias<march_EQ>, AliasArgs<["mips32r6"]>, + HelpText<"Equivalent to -march=mips32r6">, Flags<[HelpHidden]>; def mips64 : Flag<["-"], "mips64">, Alias<march_EQ>, AliasArgs<["mips64"]>, HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>; def mips64r2 : Flag<["-"], "mips64r2">, Alias<march_EQ>, AliasArgs<["mips64r2"]>, HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>; +def mips64r6 : Flag<["-"], "mips64r6">, + Alias<march_EQ>, AliasArgs<["mips64r6"]>, + HelpText<"Equivalent to -march=mips64r6">, Flags<[HelpHidden]>; +def mfpxx : Flag<["-"], "mfpxx">, Group<m_Group>, + HelpText<"Avoid FPU mode dependent operations when used with the O32 ABI">, + Flags<[HelpHidden]>; +def modd_spreg : Flag<["-"], "modd-spreg">, Group<m_Group>, + HelpText<"Enable odd single-precision floating point registers">, + Flags<[HelpHidden]>; +def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_Group>, + HelpText<"Disable odd single-precision floating point registers">, + Flags<[HelpHidden]>; def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>; def mthumb : Flag<["-"], "mthumb">, Group<m_Group>; def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>; @@ -1164,7 +1287,6 @@ def mwarn_nonportable_cfstrings : Flag<["-"], "mwarn-nonportable-cfstrings">, Gr def no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden]>, HelpText<"Use relative instead of canonical paths">; 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">; @@ -1184,7 +1306,7 @@ 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, CC1Option]>, +def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option, CC1AsOption]>, HelpText<"Write output to <file>">, MetaVarName<"<file>">; def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">; def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>; @@ -1232,6 +1354,8 @@ def rtlib_EQ : Joined<["-", "--"], "rtlib=">; def r : Flag<["-"], "r">; def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>, HelpText<"Save intermediate compilation results">; +def via_file_asm : Flag<["-", "--"], "via-file-asm">, InternalDebugOpt, + HelpText<"Write assembly to file for input to assemble jobs">; def sectalign : MultiArg<["-"], "sectalign", 3>; def sectcreate : MultiArg<["-"], "sectcreate", 3>; def sectobjectsymbols : MultiArg<["-"], "sectobjectsymbols", 2>; @@ -1261,8 +1385,18 @@ 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 system_header_prefix : Joined<["--"], "system-header-prefix=">, + Group<clang_i_Group>, Flags<[CC1Option]>, MetaVarName<"<prefix>">, + HelpText<"Treat all #include paths starting with <prefix> as including a " + "system header.">; +def : Separate<["--"], "system-header-prefix">, Alias<system_header_prefix>; +def no_system_header_prefix : Joined<["--"], "no-system-header-prefix=">, + Group<clang_i_Group>, Flags<[CC1Option]>, MetaVarName<"<prefix>">, + HelpText<"Treat all #include paths starting with <prefix> as not including a " + "system header.">; +def : Separate<["--"], "no-system-header-prefix">, Alias<no_system_header_prefix>; def s : Flag<["-"], "s">; -def target : Joined<["--"], "target=">, Flags<[DriverOption]>, +def target : Joined<["--"], "target=">, Flags<[DriverOption, CoreOption]>, HelpText<"Generate code for the given target">; def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>, HelpText<"Use the gcc toolchain at the given directory">; @@ -1282,10 +1416,10 @@ 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 v : Flag<["-"], "v">, Flags<[CC1Option]>, +def v : Flag<["-"], "v">, Flags<[CC1Option, CoreOption]>, HelpText<"Show commands to run and use verbose output">; -def verify : Flag<["-"], "verify">, Flags<[DriverOption,CC1Option]>, - HelpText<"Verify output using a verifier">; +def verify_debug_info : Flag<["--"], "verify-debug-info">, Flags<[DriverOption]>, + HelpText<"Verify the binary representation of debug output">; def weak_l : Joined<["-"], "weak-l">, Flags<[LinkerInput]>; def weak__framework : Separate<["-"], "weak_framework">, Flags<[LinkerInput]>; def weak__library : Separate<["-"], "weak_library">, Flags<[LinkerInput]>; @@ -1298,6 +1432,15 @@ def x : JoinedOrSeparate<["-"], "x">, Flags<[DriverOption,CC1Option]>, MetaVarName<"<language>">; def y : Joined<["-"], "y">; +def fintegrated_as : Flag<["-"], "fintegrated-as">, Flags<[DriverOption]>, + Group<f_Group>, HelpText<"Enable the integrated assembler">; +def fno_integrated_as : Flag<["-"], "fno-integrated-as">, + Flags<[CC1Option, DriverOption]>, Group<f_Group>, + HelpText<"Disable the integrated assembler">; +def : Flag<["-"], "integrated-as">, Alias<fintegrated_as>, Flags<[DriverOption]>; +def : Flag<["-"], "no-integrated-as">, Alias<fno_integrated_as>, + Flags<[CC1Option, DriverOption]>; + def working_directory : JoinedOrSeparate<["-"], "working-directory">, Flags<[CC1Option]>, HelpText<"Resolve file paths relative to the specified directory">; def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option]>, @@ -1306,7 +1449,8 @@ def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option // Double dash options, which are usually an alias for one of the previous // options. -def _mhwdiv_EQ : Separate<["--"], "mhwdiv">, Alias<mhwdiv_EQ>; +def _mhwdiv_EQ : Joined<["--"], "mhwdiv=">, Alias<mhwdiv_EQ>; +def _mhwdiv : Separate<["--"], "mhwdiv">, Alias<mhwdiv_EQ>; def _CLASSPATH_EQ : Joined<["--"], "CLASSPATH=">, Alias<fclasspath_EQ>; def _CLASSPATH : Separate<["--"], "CLASSPATH">, Alias<fclasspath_EQ>; def _all_warnings : Flag<["--"], "all-warnings">, Alias<Wall>; @@ -1449,52 +1593,55 @@ multiclass BooleanFFlag<string name> { def _fno : Flag<["-"], "fno-"#name>; } -def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_f_Group>; +defm : BooleanFFlag<"no-keep-inline-functions">, Group<clang_ignored_gcc_optimization_f_Group>; + +def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_gcc_optimization_f_Group>; -defm profile_use : BooleanFFlag<"profile-use">, Group<clang_ignored_f_Group>; -def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Group<clang_ignored_f_Group>; -def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<clang_ignored_f_Group>; +defm profile_use : BooleanFFlag<"profile-use">, Group<clang_ignored_gcc_optimization_f_Group>; +def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Group<clang_ignored_gcc_optimization_f_Group>; +def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>; -defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_f_Group>; -def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<clang_ignored_f_Group>; +defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_gcc_optimization_f_Group>; +def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<clang_ignored_gcc_optimization_f_Group>; // FIXME: This option should be supported and wired up to our diognostics, but // ignore it for now to avoid breaking builds that use it. def fdiagnostics_show_location_EQ : Joined<["-"], "fdiagnostics-show-location=">, Group<clang_ignored_f_Group>; defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group<clang_ignored_f_Group>; -defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_f_Group>; +defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_gcc_optimization_f_Group>; defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group<clang_ignored_f_Group>; -defm gcse : BooleanFFlag<"gcse">, Group<clang_ignored_f_Group>; +defm gcse : BooleanFFlag<"gcse">, Group<clang_ignored_gcc_optimization_f_Group>; defm gnu : BooleanFFlag<"gnu">, Group<clang_ignored_f_Group>; defm ident : BooleanFFlag<"ident">, Group<clang_ignored_f_Group>; defm implicit_templates : BooleanFFlag<"implicit-templates">, Group<clang_ignored_f_Group>; -defm inline_limit : BooleanFFlag<"inline-limit">, Group<clang_ignored_f_Group>; -defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_f_Group>; +def finline_limit_EQ : Joined<["-"], "finline-limit=">, Group<clang_ignored_gcc_optimization_f_Group>; +defm finline_limit : BooleanFFlag<"inline-limit">, Group<clang_ignored_gcc_optimization_f_Group>; +defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_gcc_optimization_f_Group>; defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group<clang_ignored_f_Group>; defm permissive : BooleanFFlag<"permissive">, Group<clang_ignored_f_Group>; -defm prefetch_loop_arrays : BooleanFFlag<"prefetch-loop-arrays">, Group<clang_ignored_f_Group>; +defm prefetch_loop_arrays : BooleanFFlag<"prefetch-loop-arrays">, Group<clang_ignored_gcc_optimization_f_Group>; defm printf : BooleanFFlag<"printf">, Group<clang_ignored_f_Group>; defm profile : BooleanFFlag<"profile">, Group<clang_ignored_f_Group>; -defm profile_correction : BooleanFFlag<"profile-correction">, Group<clang_ignored_f_Group>; +defm profile_correction : BooleanFFlag<"profile-correction">, Group<clang_ignored_gcc_optimization_f_Group>; defm profile_generate_sampling : BooleanFFlag<"profile-generate-sampling">, Group<clang_ignored_f_Group>; defm profile_reusedist : BooleanFFlag<"profile-reusedist">, Group<clang_ignored_f_Group>; -defm profile_values : BooleanFFlag<"profile-values">, Group<clang_ignored_f_Group>; +defm profile_values : BooleanFFlag<"profile-values">, Group<clang_ignored_gcc_optimization_f_Group>; defm regs_graph : BooleanFFlag<"regs-graph">, Group<clang_ignored_f_Group>; defm ripa : BooleanFFlag<"ripa">, Group<clang_ignored_f_Group>; -defm rounding_math : BooleanFFlag<"rounding-math">, Group<clang_ignored_f_Group>; -defm schedule_insns : BooleanFFlag<"schedule-insns">, Group<clang_ignored_f_Group>; +defm rounding_math : BooleanFFlag<"rounding-math">, Group<clang_ignored_gcc_optimization_f_Group>; +defm schedule_insns : BooleanFFlag<"schedule-insns">, Group<clang_ignored_gcc_optimization_f_Group>; defm see : BooleanFFlag<"see">, Group<clang_ignored_f_Group>; -defm signaling_nans : BooleanFFlag<"signaling-nans">, Group<clang_ignored_f_Group>; +defm signaling_nans : BooleanFFlag<"signaling-nans">, Group<clang_ignored_gcc_optimization_f_Group>; defm spec_constr_count : BooleanFFlag<"spec-constr-count">, Group<clang_ignored_f_Group>; defm strength_reduce : - BooleanFFlag<"strength-reduce">, Group<clang_ignored_f_Group>; + BooleanFFlag<"strength-reduce">, Group<clang_ignored_gcc_optimization_f_Group>; defm tls_model : BooleanFFlag<"tls-model">, Group<clang_ignored_f_Group>; -defm tracer : BooleanFFlag<"tracer">, Group<clang_ignored_f_Group>; +defm tracer : BooleanFFlag<"tracer">, Group<clang_ignored_gcc_optimization_f_Group>; defm tree_salias : BooleanFFlag<"tree-salias">, Group<clang_ignored_f_Group>; defm tree_vectorizer_verbose : BooleanFFlag<"tree-vectorizer-verbose">, Group<clang_ignored_f_Group>; -defm unroll_all_loops : BooleanFFlag<"unroll-all-loops">, Group<clang_ignored_f_Group>; -defm unswitch_loops : BooleanFFlag<"unswitch-loops">, Group<clang_ignored_f_Group>; +defm unroll_all_loops : BooleanFFlag<"unroll-all-loops">, Group<clang_ignored_gcc_optimization_f_Group>; +defm unswitch_loops : BooleanFFlag<"unswitch-loops">, Group<clang_ignored_gcc_optimization_f_Group>; // gfortran options that we recognize in the driver and pass along when diff --git a/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h index 35b8f89..c79c471 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h @@ -9,10 +9,9 @@ #ifndef CLANG_LIB_DRIVER_SANITIZERARGS_H_ #define CLANG_LIB_DRIVER_SANITIZERARGS_H_ -#include <string> - #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" +#include <string> namespace clang { namespace driver { @@ -43,14 +42,16 @@ class SanitizerArgs { NeedsLeakDetection = Leak, NeedsUbsanRt = Undefined | Integer, NotAllowedWithTrap = Vptr, - HasZeroBaseShadow = Thread | Memory | DataFlow + HasZeroBaseShadow = Thread | Memory | DataFlow, + NeedsUnwindTables = Address | Thread | Memory | DataFlow }; unsigned Kind; std::string BlacklistFile; - bool MsanTrackOrigins; + int MsanTrackOrigins; bool AsanZeroBaseShadow; bool UbsanTrapOnError; + bool AsanSharedRuntime; public: SanitizerArgs(); @@ -58,6 +59,7 @@ class SanitizerArgs { SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args); bool needsAsanRt() const { return Kind & NeedsAsanRt; } + bool needsSharedAsanRt() const { return AsanSharedRuntime; } bool needsTsanRt() const { return Kind & NeedsTsanRt; } bool needsMsanRt() const { return Kind & NeedsMsanRt; } bool needsLeakDetection() const { return Kind & NeedsLeakDetection; } @@ -74,6 +76,7 @@ class SanitizerArgs { bool hasZeroBaseShadow() const { return (Kind & HasZeroBaseShadow) || AsanZeroBaseShadow; } + bool needsUnwindTables() const { return Kind & NeedsUnwindTables; } void addArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; @@ -99,7 +102,7 @@ class SanitizerArgs { /// Produce an argument string from ArgList \p Args, which shows how it /// provides a sanitizer kind in \p Mask. For example, the argument list - /// "-fsanitize=thread,vptr -faddress-sanitizer" with mask \c NeedsUbsanRt + /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt /// would produce "-fsanitize=vptr". static std::string lastArgumentForKind(const Driver &D, const llvm::opt::ArgList &Args, diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h index c212a83..550e4df 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h @@ -11,12 +11,13 @@ #define CLANG_DRIVER_TOOLCHAIN_H_ #include "clang/Driver/Action.h" +#include "clang/Driver/Multilib.h" #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Path.h" +#include <memory> #include <string> namespace llvm { @@ -65,17 +66,19 @@ private: /// programs. path_list ProgramPaths; - mutable OwningPtr<Tool> Clang; - mutable OwningPtr<Tool> Assemble; - mutable OwningPtr<Tool> Link; + mutable std::unique_ptr<Tool> Clang; + mutable std::unique_ptr<Tool> Assemble; + mutable std::unique_ptr<Tool> Link; Tool *getClang() const; Tool *getAssemble() const; Tool *getLink() const; Tool *getClangAs() const; - mutable OwningPtr<SanitizerArgs> SanitizerArguments; + mutable std::unique_ptr<SanitizerArgs> SanitizerArguments; protected: + MultilibSet Multilibs; + ToolChain(const Driver &D, const llvm::Triple &T, const llvm::opt::ArgList &Args); @@ -127,6 +130,8 @@ public: path_list &getProgramPaths() { return ProgramPaths; } const path_list &getProgramPaths() const { return ProgramPaths; } + const MultilibSet &getMultilibs() const { return Multilibs; } + const SanitizerArgs& getSanitizerArgs() const; // Tool access. @@ -139,7 +144,7 @@ public: virtual llvm::opt::DerivedArgList * TranslateArgs(const llvm::opt::DerivedArgList &Args, const char *BoundArch) const { - return 0; + return nullptr; } /// Choose a tool to use to handle the action \p JA. @@ -150,6 +155,10 @@ public: std::string GetFilePath(const char *Name) const; std::string GetProgramPath(const char *Name) const; + /// Returns the linker path, respecting the -fuse-ld= argument to determine + /// the linker suffix or name. + std::string GetLinkerPath() const; + /// \brief Dispatch to the specific toolchain for verbose printing. /// /// This is used when handling the verbose option to print detailed, @@ -159,6 +168,10 @@ public: // Platform defaults information + /// \brief Returns true if the toolchain is targeting a non-native + /// architecture. + virtual bool isCrossCompiling() const; + /// HasNativeLTOLinker - Check whether the linker and related tools have /// native LLVM support. virtual bool HasNativeLLVMSupport() const; @@ -193,7 +206,7 @@ public: virtual bool UseObjCMixedDispatch() const { return false; } /// GetDefaultStackProtectorLevel - Get the default stack protector level for - /// this tool chain (0=off, 1=on, 2=all). + /// this tool chain (0=off, 1=on, 2=strong, 3=all). virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const { return 0; } @@ -275,6 +288,9 @@ public: virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; + /// \brief Add warning options that need to be passed to cc1 for this target. + virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const; + // GetRuntimeLibType - Determine the runtime library type to use with the // given compilation arguments. virtual RuntimeLibType diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Types.def b/contrib/llvm/tools/clang/include/clang/Driver/Types.def index d4f52d3..3209679 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Types.def +++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.def @@ -54,22 +54,22 @@ TYPE("objective-c++", ObjCXX, PP_ObjCXX, "mm", "u") // C family input files to precompile. TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", "p") -TYPE("c-header", CHeader, PP_CHeader, 0, "pu") -TYPE("cl-header", CLHeader, PP_CHeader, 0, "pu") +TYPE("c-header", CHeader, PP_CHeader, nullptr, "pu") +TYPE("cl-header", CLHeader, PP_CHeader, nullptr, "pu") TYPE("objective-c-header-cpp-output", PP_ObjCHeader, INVALID, "mi", "p") -TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, 0, "pu") +TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, nullptr, "pu") TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", "p") -TYPE("c++-header", CXXHeader, PP_CXXHeader, 0, "pu") +TYPE("c++-header", CXXHeader, PP_CXXHeader, nullptr, "pu") TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", "p") -TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, 0, "pu") +TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, nullptr, "pu") // Other languages. -TYPE("ada", Ada, INVALID, 0, "u") +TYPE("ada", Ada, INVALID, nullptr, "u") TYPE("assembler", PP_Asm, INVALID, "s", "au") TYPE("assembler-with-cpp", Asm, PP_Asm, "S", "au") -TYPE("f95", PP_Fortran, INVALID, 0, "u") -TYPE("f95-cpp-input", Fortran, PP_Fortran, 0, "u") -TYPE("java", Java, INVALID, 0, "u") +TYPE("f95", PP_Fortran, INVALID, nullptr, "u") +TYPE("f95-cpp-input", Fortran, PP_Fortran, nullptr, "u") +TYPE("java", Java, INVALID, nullptr, "u") // LLVM IR/LTO types. We define separate types for IR and LTO because LTO // outputs should use the standard suffixes. @@ -87,8 +87,8 @@ TYPE("rewritten-legacy-objc", RewrittenLegacyObjC,INVALID, "cpp", "") TYPE("remap", Remap, INVALID, "remap", "") TYPE("precompiled-header", PCH, INVALID, "gch", "A") TYPE("object", Object, INVALID, "o", "") -TYPE("treelang", Treelang, INVALID, 0, "u") +TYPE("treelang", Treelang, INVALID, nullptr, "u") TYPE("image", Image, INVALID, "out", "") TYPE("dSYM", dSYM, INVALID, "dSYM", "A") TYPE("dependencies", Dependencies, INVALID, "d", "") -TYPE("none", Nothing, INVALID, 0, "u") +TYPE("none", Nothing, INVALID, nullptr, "u") diff --git a/contrib/llvm/tools/clang/include/clang/Edit/Commit.h b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h index 626b1dd..5cc5b9c 100644 --- a/contrib/llvm/tools/clang/include/clang/Edit/Commit.h +++ b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h @@ -49,8 +49,7 @@ private: const LangOptions &LangOpts; const PPConditionalDirectiveRecord *PPRec; EditedSource *Editor; - - const bool ForceCommitInSystemHeader; + bool IsCommitable; SmallVector<Edit, 8> CachedEdits; @@ -59,9 +58,9 @@ private: public: explicit Commit(EditedSource &Editor); Commit(const SourceManager &SM, const LangOptions &LangOpts, - const PPConditionalDirectiveRecord *PPRec = 0) - : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(0), - ForceCommitInSystemHeader(true), IsCommitable(true) { } + const PPConditionalDirectiveRecord *PPRec = nullptr) + : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(nullptr), + IsCommitable(true) { } bool isCommitable() const { return IsCommitable; } @@ -132,9 +131,9 @@ private: void commitRemove(FileOffset offset, unsigned length); bool isAtStartOfMacroExpansion(SourceLocation loc, - SourceLocation *MacroBegin = 0) const; + SourceLocation *MacroBegin = nullptr) const; bool isAtEndOfMacroExpansion(SourceLocation loc, - SourceLocation *MacroEnd = 0) const; + SourceLocation *MacroEnd = nullptr) const; StringRef copyString(StringRef str) { char *buf = StrAlloc.Allocate<char>(str.size()); diff --git a/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h index 3ad5a6b..150a5b41 100644 --- a/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h +++ b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h @@ -28,7 +28,6 @@ class EditedSource { const SourceManager &SourceMgr; const LangOptions &LangOpts; const PPConditionalDirectiveRecord *PPRec; - const bool ForceCommitInSystemHeader; struct FileEdit { StringRef Text; @@ -46,21 +45,15 @@ class EditedSource { public: EditedSource(const SourceManager &SM, const LangOptions &LangOpts, - const PPConditionalDirectiveRecord *PPRec = 0, - const bool FCommitInSystemHeader = true) + const PPConditionalDirectiveRecord *PPRec = nullptr) : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), - ForceCommitInSystemHeader(FCommitInSystemHeader), - StrAlloc(/*size=*/512) { } + StrAlloc() { } const SourceManager &getSourceManager() const { return SourceMgr; } const LangOptions &getLangOpts() const { return LangOpts; } const PPConditionalDirectiveRecord *getPPCondDirectiveRecord() const { return PPRec; } - - bool getForceCommitInSystemHeader() const { - return ForceCommitInSystemHeader; - } bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs); diff --git a/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h b/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h index 675ad18..0c1e72b 100644 --- a/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h +++ b/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h @@ -41,20 +41,16 @@ public: return !(LHS == RHS); } friend bool operator<(FileOffset LHS, FileOffset RHS) { - if (LHS.FID != RHS.FID) - return LHS.FID < RHS.FID; - return LHS.Offs < RHS.Offs; + return std::tie(LHS.FID, LHS.Offs) < std::tie(RHS.FID, RHS.Offs); } friend bool operator>(FileOffset LHS, FileOffset RHS) { - if (LHS.FID != RHS.FID) - return LHS.FID > RHS.FID; - return LHS.Offs > RHS.Offs; + return RHS < LHS; } friend bool operator>=(FileOffset LHS, FileOffset RHS) { - return LHS > RHS || LHS == RHS; + return !(LHS < RHS); } friend bool operator<=(FileOffset LHS, FileOffset RHS) { - return LHS < RHS || LHS == RHS; + return !(RHS < LHS); } }; diff --git a/contrib/llvm/tools/clang/include/clang/Format/Format.h b/contrib/llvm/tools/clang/include/clang/Format/Format.h index 0f27467..45cccaa 100644 --- a/contrib/llvm/tools/clang/include/clang/Format/Format.h +++ b/contrib/llvm/tools/clang/include/clang/Format/Format.h @@ -17,7 +17,7 @@ #include "clang/Frontend/FrontendAction.h" #include "clang/Tooling/Refactoring.h" -#include "llvm/Support/system_error.h" +#include <system_error> namespace clang { @@ -27,19 +27,49 @@ class DiagnosticConsumer; namespace format { +enum class ParseError { Success = 0, Error, Unsuitable }; +class ParseErrorCategory final : public std::error_category { +public: + const char *name() const LLVM_NOEXCEPT override; + std::string message(int EV) const override; +}; +const std::error_category &getParseCategory(); +std::error_code make_error_code(ParseError e); + /// \brief The \c FormatStyle is used to configure the formatting to follow /// specific guidelines. struct FormatStyle { + /// \brief Supported languages. When stored in a configuration file, specifies + /// the language, that the configuration targets. When passed to the + /// reformat() function, enables syntax features specific to the language. + enum LanguageKind { + /// Do not use. + LK_None, + /// Should be used for C, C++, ObjectiveC, ObjectiveC++. + LK_Cpp, + /// Should be used for JavaScript. + LK_JavaScript, + /// Should be used for Protocol Buffers + /// (https://developers.google.com/protocol-buffers/). + LK_Proto + }; + + /// \brief Language, this format style is targeted at. + LanguageKind Language; + /// \brief The column limit. /// /// A column limit of \c 0 means that there is no column limit. In this case, /// clang-format will respect the input's line breaking decisions within - /// statements. + /// statements unless they contradict other rules. unsigned ColumnLimit; /// \brief The maximum number of consecutive empty lines to keep. unsigned MaxEmptyLinesToKeep; + /// \brief If true, empty lines at the start of blocks are kept. + bool KeepEmptyLinesAtTheStartOfBlocks; + /// \brief The penalty for each line break introduced inside a comment. unsigned PenaltyBreakComment; @@ -55,11 +85,22 @@ struct FormatStyle { /// \brief The penalty for breaking a function call after "call(". unsigned PenaltyBreakBeforeFirstCallParameter; - /// \brief Set whether & and * bind to the type as opposed to the variable. - bool PointerBindsToType; + /// \brief The & and * alignment style. + enum PointerAlignmentStyle { + /// Align pointer to the left. + PAS_Left, + /// Align pointer to the right. + PAS_Right, + /// Align pointer in the middle. + PAS_Middle + }; + + /// Pointer and reference alignment style. + PointerAlignmentStyle PointerAlignment; - /// \brief If \c true, analyze the formatted file for the most common binding. - bool DerivePointerBinding; + /// \brief If \c true, analyze the formatted file for the most common + /// alignment of & and *. \c PointerAlignment is then used only as fallback. + bool DerivePointerAlignment; /// \brief The extra indent or outdent of access modifiers, e.g. \c public:. int AccessModifierOffset; @@ -85,6 +126,10 @@ struct FormatStyle { /// Switch statement body is always indented one level more than case labels. bool IndentCaseLabels; + /// \brief Indent if a function definition or declaration is wrapped after the + /// type. + bool IndentWrappedFunctionNames; + /// \brief Different ways to indent namespace contents. enum NamespaceIndentationKind { /// Don't indent in namespaces. @@ -98,7 +143,11 @@ struct FormatStyle { /// \brief The indentation used for namespaces. NamespaceIndentationKind NamespaceIndentation; - /// \brief The number of spaces to before trailing line comments. + /// \brief The number of spaces before trailing line comments + /// (\c // - comments). + /// + /// This does not affect trailing block comments (\c /**/ - comments) as those + /// commonly have different usage patterns and a number of special cases. unsigned SpacesBeforeTrailingComments; /// \brief If \c false, a function call's or function definition's parameters @@ -133,6 +182,11 @@ struct FormatStyle { /// the commas with the colon. bool BreakConstructorInitializersBeforeComma; + /// \brief Allows contracting simple braced statements to a single line. + /// + /// E.g., this allows <tt>if (a) { return; }</tt> to be put on a single line. + bool AllowShortBlocksOnASingleLine; + /// \brief If \c true, <tt>if (a) return;</tt> can be put on a single /// line. bool AllowShortIfStatementsOnASingleLine; @@ -141,6 +195,25 @@ struct FormatStyle { /// single line. bool AllowShortLoopsOnASingleLine; + /// \brief Different styles for merging short functions containing at most one + /// statement. + enum ShortFunctionStyle { + /// \brief Never merge functions into a single line. + SFS_None, + /// \brief Only merge functions defined inside a class. + SFS_Inline, + /// \brief Merge all functions fitting on a single line. + SFS_All, + }; + + /// \brief Dependent on the value, <tt>int f() { return 0; }</tt> can be put + /// on a single line. + ShortFunctionStyle AllowShortFunctionsOnASingleLine; + + /// \brief Add a space after \c @property in Objective-C, i.e. use + /// <tt>\@property (readonly)</tt> instead of <tt>\@property(readonly)</tt>. + bool ObjCSpaceAfterProperty; + /// \brief Add a space in front of an Objective-C protocol list, i.e. use /// <tt>Foo <Protocol></tt> instead of \c Foo<Protocol>. bool ObjCSpaceBeforeProtocolList; @@ -199,7 +272,11 @@ struct FormatStyle { /// Like \c Attach, but break before function definitions. BS_Stroustrup, /// Always break before braces. - BS_Allman + BS_Allman, + /// Always break before braces and add an extra level of indentation to + /// braces of control statements, not to those of class, function + /// or other definitions. + BS_GNU }; /// \brief The brace breaking style to use. @@ -220,10 +297,6 @@ struct FormatStyle { /// a zero-length name is assumed. bool Cpp11BracedListStyle; - /// \brief If \c true, indent when breaking function declarations which - /// are not also definitions after the type. - bool IndentFunctionDeclarationAfterType; - /// \brief If \c true, spaces will be inserted after '(' and before ')'. bool SpacesInParentheses; @@ -231,15 +304,32 @@ struct FormatStyle { /// template argument lists bool SpacesInAngles; - /// \brief If \c false, spaces may be inserted into '()'. + /// \brief If \c true, spaces may be inserted into '()'. bool SpaceInEmptyParentheses; - /// \brief If \c false, spaces may be inserted into C style casts. + /// \brief If \c true, spaces are inserted inside container literals (e.g. + /// ObjC and Javascript array and dict literals). + bool SpacesInContainerLiterals; + + /// \brief If \c true, spaces may be inserted into C style casts. bool SpacesInCStyleCastParentheses; - /// \brief If \c true, spaces will be inserted between 'for'/'if'/'while'/... - /// and '('. - bool SpaceAfterControlStatementKeyword; + /// \brief Different ways to put a space before opening parentheses. + enum SpaceBeforeParensOptions { + /// Never put a space before opening parentheses. + SBPO_Never, + /// Put a space before opening parentheses only after control statement + /// keywords (<tt>for/if/while...</tt>). + SBPO_ControlStatements, + /// Always put a space before opening parentheses, except when it's + /// prohibited by the syntax rules (in function-like macro definitions) or + /// when determined by other style rules (after unary operators, opening + /// parentheses, etc.) + SBPO_Always + }; + + /// \brief Defines in which cases to put a space before opening parentheses. + SpaceBeforeParensOptions SpaceBeforeParens; /// \brief If \c false, spaces will be removed before assignment operators. bool SpaceBeforeAssignmentOperators; @@ -247,6 +337,25 @@ struct FormatStyle { /// \brief Indent width for line continuations. unsigned ContinuationIndentWidth; + /// \brief A regular expression that describes comments with special meaning, + /// which should not be split into lines or otherwise changed. + std::string CommentPragmas; + + /// \brief Disables formatting at all. + bool DisableFormat; + + /// \brief A vector of macros that should be interpreted as foreach loops + /// instead of as function calls. + /// + /// These are expected to be macros of the form: + /// \code + /// FOREACH(<variable-declaration>, ...) + /// <loop-body> + /// \endcode + /// + /// For example: BOOST_FOREACH. + std::vector<std::string> ForEachMacros; + bool operator==(const FormatStyle &R) const { return AccessModifierOffset == R.AccessModifierOffset && ConstructorInitializerIndentWidth == @@ -255,6 +364,9 @@ struct FormatStyle { AlignTrailingComments == R.AlignTrailingComments && AllowAllParametersOfDeclarationOnNextLine == R.AllowAllParametersOfDeclarationOnNextLine && + AllowShortFunctionsOnASingleLine == + R.AllowShortFunctionsOnASingleLine && + AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine && AllowShortIfStatementsOnASingleLine == R.AllowShortIfStatementsOnASingleLine && AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine && @@ -271,33 +383,37 @@ struct FormatStyle { ColumnLimit == R.ColumnLimit && ConstructorInitializerAllOnOneLineOrOnePerLine == R.ConstructorInitializerAllOnOneLineOrOnePerLine && - DerivePointerBinding == R.DerivePointerBinding && + DerivePointerAlignment == R.DerivePointerAlignment && ExperimentalAutoDetectBinPacking == R.ExperimentalAutoDetectBinPacking && IndentCaseLabels == R.IndentCaseLabels && - IndentFunctionDeclarationAfterType == - R.IndentFunctionDeclarationAfterType && - IndentWidth == R.IndentWidth && + IndentWrappedFunctionNames == R.IndentWrappedFunctionNames && + IndentWidth == R.IndentWidth && Language == R.Language && MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep && + KeepEmptyLinesAtTheStartOfBlocks == + R.KeepEmptyLinesAtTheStartOfBlocks && NamespaceIndentation == R.NamespaceIndentation && + ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty && ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList && PenaltyBreakComment == R.PenaltyBreakComment && PenaltyBreakFirstLessLess == R.PenaltyBreakFirstLessLess && PenaltyBreakString == R.PenaltyBreakString && PenaltyExcessCharacter == R.PenaltyExcessCharacter && PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine && - PointerBindsToType == R.PointerBindsToType && + PointerAlignment == R.PointerAlignment && SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments && Cpp11BracedListStyle == R.Cpp11BracedListStyle && Standard == R.Standard && TabWidth == R.TabWidth && UseTab == R.UseTab && SpacesInParentheses == R.SpacesInParentheses && SpacesInAngles == R.SpacesInAngles && SpaceInEmptyParentheses == R.SpaceInEmptyParentheses && + SpacesInContainerLiterals == R.SpacesInContainerLiterals && SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses && - SpaceAfterControlStatementKeyword == - R.SpaceAfterControlStatementKeyword && + SpaceBeforeParens == R.SpaceBeforeParens && SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators && - ContinuationIndentWidth == R.ContinuationIndentWidth; + ContinuationIndentWidth == R.ContinuationIndentWidth && + CommentPragmas == R.CommentPragmas && + ForEachMacros == R.ForEachMacros; } }; @@ -305,13 +421,15 @@ struct FormatStyle { /// http://llvm.org/docs/CodingStandards.html. FormatStyle getLLVMStyle(); -/// \brief Returns a format style complying with Google's C++ style guide: +/// \brief Returns a format style complying with one of Google's style guides: /// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml. -FormatStyle getGoogleStyle(); +/// http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml. +/// https://developers.google.com/protocol-buffers/docs/style. +FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language); /// \brief Returns a format style complying with Chromium's style guide: /// http://www.chromium.org/developers/coding-style. -FormatStyle getChromiumStyle(); +FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language); /// \brief Returns a format style complying with Mozilla's style guide: /// https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style. @@ -321,16 +439,30 @@ FormatStyle getMozillaStyle(); /// http://www.webkit.org/coding/coding-style.html FormatStyle getWebKitStyle(); -/// \brief Gets a predefined style by name. +/// \brief Returns a format style complying with GNU Coding Standards: +/// http://www.gnu.org/prep/standards/standards.html +FormatStyle getGNUStyle(); + +/// \brief Returns style indicating formatting should be not applied at all. +FormatStyle getNoStyle(); + +/// \brief Gets a predefined style for the specified language by name. /// /// Currently supported names: LLVM, Google, Chromium, Mozilla. Names are /// compared case-insensitively. /// /// Returns \c true if the Style has been set. -bool getPredefinedStyle(StringRef Name, FormatStyle *Style); +bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, + FormatStyle *Style); /// \brief Parse configuration from YAML-formatted text. -llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style); +/// +/// Style->Language is used to get the base style, if the \c BasedOnStyle +/// option is present. +/// +/// When \c BasedOnStyle is not present, options not present in the YAML +/// document, are retained in \p Style. +std::error_code parseConfiguration(StringRef Text, FormatStyle *Style); /// \brief Gets configuration in a YAML string. std::string configurationAsText(const FormatStyle &Style); @@ -359,8 +491,8 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, /// /// \param Standard determines lexing mode: LC_Cpp11 and LS_Auto turn on C++11 /// lexing mode, LS_Cpp03 - C++03 mode. -LangOptions getFormattingLangOpts(FormatStyle::LanguageStandard Standard = - FormatStyle::LS_Cpp11); +LangOptions getFormattingLangOpts( + FormatStyle::LanguageStandard Standard = FormatStyle::LS_Cpp11); /// \brief Description to be used for help text for a llvm::cl option for /// specifying format style. The description is closely related to the operation @@ -381,12 +513,20 @@ extern const char *StyleOptionHelpDescription; /// above. /// \param[in] FileName Path to start search for .clang-format if \c StyleName /// == "file". +/// \param[in] FallbackStyle The name of a predefined style used to fallback to +/// in case the style can't be determined from \p StyleName. /// /// \returns FormatStyle as specified by \c StyleName. If no style could be /// determined, the default is LLVM Style (see getLLVMStyle()). -FormatStyle getStyle(StringRef StyleName, StringRef FileName); +FormatStyle getStyle(StringRef StyleName, StringRef FileName, + StringRef FallbackStyle); } // end namespace format } // end namespace clang +namespace std { +template <> +struct is_error_code_enum<clang::format::ParseError> : std::true_type {}; +} + #endif // LLVM_CLANG_FORMAT_FORMAT_H diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h index 43d77f0..42dc69a 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h @@ -27,12 +27,13 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Serialization/ASTBitCodes.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" #include <cassert> #include <map> +#include <memory> #include <string> #include <sys/types.h> #include <utility> @@ -63,33 +64,51 @@ class ASTDeserializationListener; /// \brief Utility class for loading a ASTContext from an AST file. /// class ASTUnit : public ModuleLoader { +public: + struct StandaloneFixIt { + std::pair<unsigned, unsigned> RemoveRange; + std::pair<unsigned, unsigned> InsertFromRange; + std::string CodeToInsert; + bool BeforePreviousInsertions; + }; + + struct StandaloneDiagnostic { + unsigned ID; + DiagnosticsEngine::Level Level; + std::string Message; + std::string Filename; + unsigned LocOffset; + std::vector<std::pair<unsigned, unsigned> > Ranges; + std::vector<StandaloneFixIt> FixIts; + }; + private: - IntrusiveRefCntPtr<LangOptions> LangOpts; + std::shared_ptr<LangOptions> LangOpts; IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; IntrusiveRefCntPtr<FileManager> FileMgr; IntrusiveRefCntPtr<SourceManager> SourceMgr; - OwningPtr<HeaderSearch> HeaderInfo; + std::unique_ptr<HeaderSearch> HeaderInfo; IntrusiveRefCntPtr<TargetInfo> Target; IntrusiveRefCntPtr<Preprocessor> PP; IntrusiveRefCntPtr<ASTContext> Ctx; - IntrusiveRefCntPtr<TargetOptions> TargetOpts; + std::shared_ptr<TargetOptions> TargetOpts; IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts; - ASTReader *Reader; + IntrusiveRefCntPtr<ASTReader> Reader; bool HadModuleLoaderFatalFailure; struct ASTWriterData; - OwningPtr<ASTWriterData> WriterData; + std::unique_ptr<ASTWriterData> WriterData; FileSystemOptions FileSystemOpts; /// \brief The AST consumer that received information about the translation /// unit as it was parsed or loaded. - OwningPtr<ASTConsumer> Consumer; - + std::unique_ptr<ASTConsumer> Consumer; + /// \brief The semantic analysis object used to type-check the translation /// unit. - OwningPtr<Sema> TheSema; - + std::unique_ptr<Sema> TheSema; + /// Optional owned invocation, just used to make the invocation used in /// LoadFromCommandLine available. IntrusiveRefCntPtr<CompilerInvocation> Invocation; @@ -135,7 +154,7 @@ private: std::string OriginalSourceFile; /// \brief The set of diagnostics produced when creating the preamble. - SmallVector<StoredDiagnostic, 4> PreambleDiagnostics; + SmallVector<StandaloneDiagnostic, 4> PreambleDiagnostics; /// \brief The set of diagnostics produced when creating this /// translation unit. @@ -170,7 +189,7 @@ public: mutable unsigned NumLines; public: - PreambleData() : File(0), NumLines(0) { } + PreambleData() : File(nullptr), NumLines(0) { } void assign(const FileEntry *F, const char *begin, const char *end) { File = F; @@ -178,7 +197,7 @@ public: NumLines = 0; } - void clear() { Buffer.clear(); File = 0; NumLines = 0; } + void clear() { Buffer.clear(); File = nullptr; NumLines = 0; } size_t size() const { return Buffer.size(); } bool empty() const { return Buffer.empty(); } @@ -205,8 +224,34 @@ public: return Preamble; } -private: + /// Data used to determine if a file used in the preamble has been changed. + struct PreambleFileHash { + /// All files have size set. + off_t Size; + + /// Modification time is set for files that are on disk. For memory + /// buffers it is zero. + time_t ModTime; + + /// Memory buffers have MD5 instead of modification time. We don't + /// compute MD5 for on-disk files because we hope that modification time is + /// enough to tell if the file was changed. + llvm::MD5::MD5Result MD5; + static PreambleFileHash createForFile(off_t Size, time_t ModTime); + static PreambleFileHash + createForMemoryBuffer(const llvm::MemoryBuffer *Buffer); + + friend bool operator==(const PreambleFileHash &LHS, + const PreambleFileHash &RHS); + + friend bool operator!=(const PreambleFileHash &LHS, + const PreambleFileHash &RHS) { + return !(LHS == RHS); + } + }; + +private: /// \brief The contents of the preamble that has been precompiled to /// \c PreambleFile. PreambleData Preamble; @@ -216,17 +261,13 @@ private: /// Used to inform the lexer as to whether it's starting at the beginning of /// a line after skipping the preamble. bool PreambleEndsAtStartOfLine; - - /// \brief The size of the source buffer that we've reserved for the main - /// file within the precompiled preamble. - unsigned PreambleReservedSize; /// \brief Keeps track of the files that were used when computing the /// preamble, with both their buffer size and their modification time. /// /// If any of the files have changed from one compile to the next, /// the preamble must be thrown away. - llvm::StringMap<std::pair<off_t, time_t> > FilesInPreamble; + llvm::StringMap<PreambleFileHash> FilesInPreamble; /// \brief When non-NULL, this is the buffer used to store the contents of /// the main file when it has been padded for use with the precompiled @@ -268,9 +309,9 @@ private: const char **ArgBegin, const char **ArgEnd, ASTUnit &AST, bool CaptureDiagnostics); - void TranslateStoredDiagnostics(ASTReader *MMan, StringRef ModName, + void TranslateStoredDiagnostics(FileManager &FileMgr, SourceManager &SrcMan, - const SmallVectorImpl<StoredDiagnostic> &Diags, + const SmallVectorImpl<StandaloneDiagnostic> &Diags, SmallVectorImpl<StoredDiagnostic> &Out); void clearFileLevelDecls(); @@ -337,8 +378,8 @@ private: /// \brief Allocator used to store cached code completions. IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> CachedCompletionAllocator; - - OwningPtr<CodeCompletionTUInfo> CCTUInfo; + + std::unique_ptr<CodeCompletionTUInfo> CCTUInfo; /// \brief The set of cached code-completion results. std::vector<CachedCodeCompletionResult> CachedCompletionResults; @@ -406,9 +447,7 @@ 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(); @@ -457,10 +496,15 @@ public: void setASTContext(ASTContext *ctx) { Ctx = ctx; } void setPreprocessor(Preprocessor *pp); - bool hasSema() const { return TheSema.isValid(); } + bool hasSema() const { return (bool)TheSema; } Sema &getSema() const { assert(TheSema && "ASTUnit does not have a Sema object!"); - return *TheSema; + return *TheSema; + } + + const LangOptions &getLangOpts() const { + assert(LangOpts && " ASTUnit does not have language options"); + return *LangOpts; } const FileManager &getFileManager() const { return *FileMgr; } @@ -641,16 +685,14 @@ public: bool isModuleFile(); llvm::MemoryBuffer *getBufferForFile(StringRef Filename, - std::string *ErrorStr = 0); + std::string *ErrorStr = nullptr); /// \brief Determine what kind of translation unit this AST represents. TranslationUnitKind getTranslationUnitKind() const { return TUKind; } - typedef llvm::PointerUnion<const char *, const llvm::MemoryBuffer *> - FilenameOrMemBuf; /// \brief A mapping from a file name to the memory buffer that stores the /// remapped contents of that file. - typedef std::pair<std::string, FilenameOrMemBuf> RemappedFile; + typedef std::pair<std::string, llvm::MemoryBuffer *> RemappedFile; /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation. static ASTUnit *create(CompilerInvocation *CI, @@ -670,8 +712,7 @@ public: IntrusiveRefCntPtr<DiagnosticsEngine> Diags, const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls = false, - RemappedFile *RemappedFiles = 0, - unsigned NumRemappedFiles = 0, + ArrayRef<RemappedFile> RemappedFiles = None, bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false, bool UserFilesAreVolatile = false); @@ -714,19 +755,15 @@ public: /// This will only receive an ASTUnit if a new one was created. If an already /// created ASTUnit was passed in \p Unit then the caller can check that. /// - static ASTUnit *LoadFromCompilerInvocationAction(CompilerInvocation *CI, - IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - ASTFrontendAction *Action = 0, - ASTUnit *Unit = 0, - bool Persistent = true, - StringRef ResourceFilesPath = StringRef(), - bool OnlyLocalDecls = false, - bool CaptureDiagnostics = false, - bool PrecompilePreamble = false, - bool CacheCodeCompletionResults = false, - bool IncludeBriefCommentsInCodeCompletion = false, - bool UserFilesAreVolatile = false, - OwningPtr<ASTUnit> *ErrAST = 0); + static ASTUnit *LoadFromCompilerInvocationAction( + CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + ASTFrontendAction *Action = nullptr, ASTUnit *Unit = nullptr, + bool Persistent = true, StringRef ResourceFilesPath = StringRef(), + bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, + bool PrecompilePreamble = false, bool CacheCodeCompletionResults = false, + bool IncludeBriefCommentsInCodeCompletion = false, + bool UserFilesAreVolatile = false, + std::unique_ptr<ASTUnit> *ErrAST = nullptr); /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a /// CompilerInvocation object. @@ -739,15 +776,13 @@ public: // // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. - static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, - IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - bool OnlyLocalDecls = false, - bool CaptureDiagnostics = false, - bool PrecompilePreamble = false, - TranslationUnitKind TUKind = TU_Complete, - bool CacheCodeCompletionResults = false, - bool IncludeBriefCommentsInCodeCompletion = false, - bool UserFilesAreVolatile = false); + static std::unique_ptr<ASTUnit> LoadFromCompilerInvocation( + CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, + bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete, + 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. @@ -767,32 +802,25 @@ public: /// // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. - static ASTUnit *LoadFromCommandLine(const char **ArgBegin, - const char **ArgEnd, - IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - StringRef ResourceFilesPath, - bool OnlyLocalDecls = false, - bool CaptureDiagnostics = false, - RemappedFile *RemappedFiles = 0, - unsigned NumRemappedFiles = 0, - bool RemappedFilesKeepOriginalName = true, - bool PrecompilePreamble = false, - TranslationUnitKind TUKind = TU_Complete, - bool CacheCodeCompletionResults = false, - bool IncludeBriefCommentsInCodeCompletion = false, - bool AllowPCHWithCompilerErrors = false, - bool SkipFunctionBodies = false, - bool UserFilesAreVolatile = false, - bool ForSerialization = false, - OwningPtr<ASTUnit> *ErrAST = 0); - + static ASTUnit *LoadFromCommandLine( + const char **ArgBegin, const char **ArgEnd, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath, + bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, + ArrayRef<RemappedFile> RemappedFiles = None, + bool RemappedFilesKeepOriginalName = true, + bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete, + bool CacheCodeCompletionResults = false, + bool IncludeBriefCommentsInCodeCompletion = false, + bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false, + bool UserFilesAreVolatile = false, bool ForSerialization = false, + std::unique_ptr<ASTUnit> *ErrAST = nullptr); + /// \brief Reparse the source files using the same command-line options that /// were originally used to produce this translation unit. /// /// \returns True if a failure occurred that causes the ASTUnit not to /// contain any translation-unit information, false otherwise. - bool Reparse(RemappedFile *RemappedFiles = 0, - unsigned NumRemappedFiles = 0); + bool Reparse(ArrayRef<RemappedFile> RemappedFiles = None); /// \brief Perform code completion at the given file, line, and /// column within this translation unit. @@ -815,7 +843,7 @@ public: /// 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, + ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros, bool IncludeCodePatterns, bool IncludeBriefComments, CodeCompleteConsumer &Consumer, @@ -834,20 +862,21 @@ public: /// /// \returns True if an error occurred, false otherwise. bool serialize(raw_ostream &OS); - - virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, - ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) { + + ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) override { // ASTUnit doesn't know how to load modules (not that this matters). return ModuleLoadResult(); } - virtual void makeModuleVisible(Module *Mod, - Module::NameVisibilityKind Visibility, - SourceLocation ImportLoc, - bool Complain) { } + void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility, + SourceLocation ImportLoc, bool Complain) override {} + GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override + { return nullptr; } + bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override + { return 0; }; }; } // namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h index b7dc7c7..11762a9 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h @@ -11,7 +11,7 @@ #define LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCONSUMER_H #include "clang/Basic/Diagnostic.h" -#include "llvm/ADT/OwningPtr.h" +#include <memory> namespace clang { class LangOptions; @@ -22,8 +22,8 @@ class LangOptions; /// diagnostics should be included in counts. class ChainedDiagnosticConsumer : public DiagnosticConsumer { virtual void anchor(); - OwningPtr<DiagnosticConsumer> Primary; - OwningPtr<DiagnosticConsumer> Secondary; + std::unique_ptr<DiagnosticConsumer> Primary; + std::unique_ptr<DiagnosticConsumer> Secondary; public: ChainedDiagnosticConsumer(DiagnosticConsumer *_Primary, @@ -32,28 +32,28 @@ public: Secondary.reset(_Secondary); } - virtual void BeginSourceFile(const LangOptions &LO, - const Preprocessor *PP) { + void BeginSourceFile(const LangOptions &LO, + const Preprocessor *PP) override { Primary->BeginSourceFile(LO, PP); Secondary->BeginSourceFile(LO, PP); } - virtual void EndSourceFile() { + void EndSourceFile() override { Secondary->EndSourceFile(); Primary->EndSourceFile(); } - virtual void finish() { + void finish() override { Secondary->finish(); Primary->finish(); } - virtual bool IncludeInDiagnosticCounts() const { + bool IncludeInDiagnosticCounts() const override { return Primary->IncludeInDiagnosticCounts(); } - virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info) { + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override { // Default implementation (Warnings/errors count). DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info); diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedIncludesSource.h b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedIncludesSource.h deleted file mode 100644 index aa30460..0000000 --- a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedIncludesSource.h +++ /dev/null @@ -1,75 +0,0 @@ -//===- ChainedIncludesSource.h - Chained PCHs in Memory ---------*- 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 ChainedIncludesSource class, which converts headers -// to chained PCHs in memory, mainly used for testing. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SERIALIZATION_CHAINEDINCLUDESSOURCE_H -#define LLVM_CLANG_SERIALIZATION_CHAINEDINCLUDESSOURCE_H - -#include "clang/Sema/ExternalSemaSource.h" -#include <vector> - -namespace clang { - class CompilerInstance; - -class ChainedIncludesSource : public ExternalSemaSource { -public: - virtual ~ChainedIncludesSource(); - - static ChainedIncludesSource *create(CompilerInstance &CI); - - ExternalSemaSource &getFinalReader() const { return *FinalReader; } - -private: - std::vector<CompilerInstance *> CIs; - OwningPtr<ExternalSemaSource> FinalReader; - - -protected: - -//===----------------------------------------------------------------------===// -// ExternalASTSource interface. -//===----------------------------------------------------------------------===// - - virtual Decl *GetExternalDecl(uint32_t ID); - virtual Selector GetExternalSelector(uint32_t ID); - virtual uint32_t GetNumExternalSelectors(); - virtual Stmt *GetExternalDeclStmt(uint64_t Offset); - virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); - virtual bool FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name); - virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, - bool (*isKindWeWant)(Decl::Kind), - SmallVectorImpl<Decl*> &Result); - virtual void CompleteType(TagDecl *Tag); - virtual void CompleteType(ObjCInterfaceDecl *Class); - virtual void StartedDeserializing(); - virtual void FinishedDeserializing(); - virtual void StartTranslationUnit(ASTConsumer *Consumer); - virtual void PrintStats(); - - /// Return the amount of memory used by memory buffers, breaking down - /// by heap-backed versus mmap'ed memory. - virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; - -//===----------------------------------------------------------------------===// -// ExternalSemaSource interface. -//===----------------------------------------------------------------------===// - - virtual void InitializeSema(Sema &S); - virtual void ForgetSema(); - virtual void ReadMethodPool(Selector Sel); - virtual bool LookupUnqualified(LookupResult &R, Scope *S); -}; - -} - -#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def index 78b825d..1d92efe 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def @@ -28,6 +28,8 @@ CODEGENOPT(Name, Bits, Default) CODEGENOPT(Name, Bits, Default) #endif +CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as +CODEGENOPT(CompressDebugSections, 1, 0) ///< -Wa,-compress-debug-sections CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. @@ -59,8 +61,6 @@ ENUM_CODEGENOPT(FPContractMode, FPContractModeKind, 2, FPC_On) CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables ///< are required. CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled. -CODEGENOPT(HiddenWeakVTables , 1, 0) ///< Emit weak vtables, RTTI, and thunks with - ///< hidden visibility. CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is ///< enabled. CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. @@ -68,7 +68,6 @@ CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions t ///< be generated. CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants. CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled. -CODEGENOPT(NoDwarf2CFIAsm , 1, 0) ///< Set when -fno-dwarf2-cfi-asm is enabled. CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is ///< enabled. CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled. @@ -87,6 +86,9 @@ CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified. VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. +CODEGENOPT(ProfileInstrGenerate , 1, 0) ///< Instrument code to generate + ///< execution counts to use with PGO. + /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) @@ -96,7 +98,7 @@ CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero ///< offset in AddressSanitizer. -CODEGENOPT(SanitizeMemoryTrackOrigins, 1, 0) ///< Enable tracking origins in +CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in ///< MemorySanitizer CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on /// -fsanitize-undefined-trap-on-error @@ -138,7 +140,7 @@ VALUE_CODEGENOPT(NumRegisterParameters, 32, 0) VALUE_CODEGENOPT(SSPBufferSize, 32, 0) /// The kind of generated debug info. -ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 2, NoDebugInfo) +ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 3, NoDebugInfo) /// Dwarf version. VALUE_CODEGENOPT(DwarfVersion, 3, 0) diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h index 0d24697..3d532ce 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h @@ -16,6 +16,7 @@ #include <string> #include <vector> +#include "llvm/Support/Regex.h" namespace clang { @@ -52,6 +53,13 @@ public: enum DebugInfoKind { NoDebugInfo, /// Don't generate debug info. + LocTrackingOnly, /// Emit location information but do not generate + /// debug info in the output. This is useful in + /// cases where the backend wants to track source + /// locations for instructions without actually + /// emitting debug info for them (e.g., when -Rpass + /// is used). + DebugLineTablesOnly, /// Emit only debug info necessary for generating /// line number tables (-gline-tables-only). @@ -142,6 +150,31 @@ public: /// Name of the profile file to use with -fprofile-sample-use. std::string SampleProfileFile; + /// Name of the profile file to use as input for -fprofile-instr-use + std::string InstrProfileInput; + + /// Regular expression to select optimizations for which we should enable + /// optimization remarks. Transformation passes whose name matches this + /// expression (and support this feature), will emit a diagnostic + /// whenever they perform a transformation. This is enabled by the + /// -Rpass=regexp flag. + std::shared_ptr<llvm::Regex> OptimizationRemarkPattern; + + /// Regular expression to select optimizations for which we should enable + /// missed optimization remarks. Transformation passes whose name matches this + /// expression (and support this feature), will emit a diagnostic + /// whenever they tried but failed to perform a transformation. This is + /// enabled by the -Rpass-missed=regexp flag. + std::shared_ptr<llvm::Regex> OptimizationRemarkMissedPattern; + + /// Regular expression to select optimizations for which we should enable + /// optimization analyses. Transformation passes whose name matches this + /// expression (and support this feature), will emit a diagnostic + /// whenever they want to explain why they decided to apply or not apply + /// a given transformation. This is enabled by the -Rpass-analysis=regexp + /// flag. + std::shared_ptr<llvm::Regex> OptimizationRemarkAnalysisPattern; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h index 5673c59..44e9102 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h @@ -13,14 +13,15 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/Utils.h" #include "clang/Lex/ModuleLoader.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include <cassert> #include <list> +#include <memory> #include <string> #include <utility> @@ -74,6 +75,9 @@ class CompilerInstance : public ModuleLoader { /// The target being compiled for. IntrusiveRefCntPtr<TargetInfo> Target; + /// The virtual file system. + IntrusiveRefCntPtr<vfs::FileSystem> VirtualFileSystem; + /// The file manager. IntrusiveRefCntPtr<FileManager> FileMgr; @@ -87,19 +91,27 @@ class CompilerInstance : public ModuleLoader { IntrusiveRefCntPtr<ASTContext> Context; /// The AST consumer. - OwningPtr<ASTConsumer> Consumer; + std::unique_ptr<ASTConsumer> Consumer; /// The code completion consumer. - OwningPtr<CodeCompleteConsumer> CompletionConsumer; + std::unique_ptr<CodeCompleteConsumer> CompletionConsumer; /// \brief The semantic analysis object. - OwningPtr<Sema> TheSema; + std::unique_ptr<Sema> TheSema; /// \brief The frontend timer - OwningPtr<llvm::Timer> FrontendTimer; + std::unique_ptr<llvm::Timer> FrontendTimer; + + /// \brief The ASTReader, if one exists. + IntrusiveRefCntPtr<ASTReader> ModuleManager; + + /// \brief The module dependency collector for crashdumps + std::shared_ptr<ModuleDependencyCollector> ModuleDepCollector; + + /// \brief The dependency file generator. + std::unique_ptr<DependencyFileGenerator> TheDependencyFileGenerator; - /// \brief Non-owning reference to the ASTReader, if one exists. - ASTReader *ModuleManager; + std::vector<std::shared_ptr<DependencyCollector>> DependencyCollectors; /// \brief The set of top-level modules that has already been loaded, /// along with the module map @@ -117,13 +129,16 @@ class CompilerInstance : public ModuleLoader { /// have finished with this translation unit. bool BuildGlobalModuleIndex; + /// \brief We have a full global module index, with all modules. + bool HaveFullGlobalModuleIndex; + /// \brief One or more modules failed to build. bool ModuleBuildFailed; /// \brief Holds information about the output file. /// /// If TempFilename is not empty we must rename it to Filename at the end. - /// TempFilename may be empty and Filename non empty if creating the temporary + /// TempFilename may be empty and Filename non-empty if creating the temporary /// failed. struct OutputFile { std::string Filename; @@ -141,7 +156,7 @@ class CompilerInstance : public ModuleLoader { CompilerInstance(const CompilerInstance &) LLVM_DELETED_FUNCTION; void operator=(const CompilerInstance &) LLVM_DELETED_FUNCTION; public: - CompilerInstance(); + explicit CompilerInstance(bool BuildingModule = false); ~CompilerInstance(); /// @name High-Level Operations @@ -183,7 +198,7 @@ public: /// @name Compiler Invocation and Options /// { - bool hasInvocation() const { return Invocation != 0; } + bool hasInvocation() const { return Invocation != nullptr; } CompilerInvocation &getInvocation() { assert(Invocation && "Compiler instance has no invocation!"); @@ -281,7 +296,7 @@ public: /// @name Diagnostics Engine /// { - bool hasDiagnostics() const { return Diagnostics != 0; } + bool hasDiagnostics() const { return Diagnostics != nullptr; } /// Get the current diagnostics engine. DiagnosticsEngine &getDiagnostics() const { @@ -302,7 +317,7 @@ public: /// @name Target Info /// { - bool hasTarget() const { return Target != 0; } + bool hasTarget() const { return Target != nullptr; } TargetInfo &getTarget() const { assert(Target && "Compiler instance has no target!"); @@ -313,10 +328,30 @@ public: void setTarget(TargetInfo *Value); /// } + /// @name Virtual File System + /// { + + bool hasVirtualFileSystem() const { return VirtualFileSystem != nullptr; } + + vfs::FileSystem &getVirtualFileSystem() const { + assert(hasVirtualFileSystem() && + "Compiler instance has no virtual file system"); + return *VirtualFileSystem; + } + + /// \brief Replace the current virtual file system. + /// + /// \note Most clients should use setFileManager, which will implicitly reset + /// the virtual file system to the one contained in the file manager. + void setVirtualFileSystem(IntrusiveRefCntPtr<vfs::FileSystem> FS) { + VirtualFileSystem = FS; + } + + /// } /// @name File Manager /// { - bool hasFileManager() const { return FileMgr != 0; } + bool hasFileManager() const { return FileMgr != nullptr; } /// Return the current file manager to the caller. FileManager &getFileManager() const { @@ -325,17 +360,18 @@ public: } void resetAndLeakFileManager() { + BuryPointer(FileMgr.get()); FileMgr.resetWithoutRelease(); } - /// setFileManager - Replace the current file manager. + /// \brief Replace the current file manager and virtual file system. void setFileManager(FileManager *Value); /// } /// @name Source Manager /// { - bool hasSourceManager() const { return SourceMgr != 0; } + bool hasSourceManager() const { return SourceMgr != nullptr; } /// Return the current source manager. SourceManager &getSourceManager() const { @@ -344,6 +380,7 @@ public: } void resetAndLeakSourceManager() { + BuryPointer(SourceMgr.get()); SourceMgr.resetWithoutRelease(); } @@ -354,7 +391,7 @@ public: /// @name Preprocessor /// { - bool hasPreprocessor() const { return PP != 0; } + bool hasPreprocessor() const { return PP != nullptr; } /// Return the current preprocessor. Preprocessor &getPreprocessor() const { @@ -363,6 +400,7 @@ public: } void resetAndLeakPreprocessor() { + BuryPointer(PP.get()); PP.resetWithoutRelease(); } @@ -373,7 +411,7 @@ public: /// @name ASTContext /// { - bool hasASTContext() const { return Context != 0; } + bool hasASTContext() const { return Context != nullptr; } ASTContext &getASTContext() const { assert(Context && "Compiler instance has no AST context!"); @@ -381,6 +419,7 @@ public: } void resetAndLeakASTContext() { + BuryPointer(Context.get()); Context.resetWithoutRelease(); } @@ -395,7 +434,7 @@ public: /// @name ASTConsumer /// { - bool hasASTConsumer() const { return Consumer.isValid(); } + bool hasASTConsumer() const { return (bool)Consumer; } ASTConsumer &getASTConsumer() const { assert(Consumer && "Compiler instance has no AST consumer!"); @@ -404,7 +443,7 @@ public: /// takeASTConsumer - Remove the current AST consumer and give ownership to /// the caller. - ASTConsumer *takeASTConsumer() { return Consumer.take(); } + ASTConsumer *takeASTConsumer() { return Consumer.release(); } /// setASTConsumer - Replace the current AST consumer; the compiler instance /// takes ownership of \p Value. @@ -413,29 +452,32 @@ public: /// } /// @name Semantic analysis /// { - bool hasSema() const { return TheSema.isValid(); } - + bool hasSema() const { return (bool)TheSema; } + Sema &getSema() const { assert(TheSema && "Compiler instance has no Sema object!"); return *TheSema; } - - Sema *takeSema() { return TheSema.take(); } - + + Sema *takeSema() { return TheSema.release(); } + void resetAndLeakSema() { BuryPointer(TheSema.release()); } + /// } /// @name Module Management /// { - ASTReader *getModuleManager() const { return ModuleManager; } - void setModuleManager(ASTReader *Reader) { ModuleManager = Reader; } + IntrusiveRefCntPtr<ASTReader> getModuleManager() const; + void setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader); + + std::shared_ptr<ModuleDependencyCollector> getModuleDepCollector() const; + void setModuleDepCollector( + std::shared_ptr<ModuleDependencyCollector> Collector); /// } /// @name Code Completion /// { - bool hasCodeCompletionConsumer() const { - return CompletionConsumer.isValid(); - } + bool hasCodeCompletionConsumer() const { return (bool)CompletionConsumer; } CodeCompleteConsumer &getCodeCompletionConsumer() const { assert(CompletionConsumer && @@ -446,7 +488,7 @@ public: /// takeCodeCompletionConsumer - Remove the current code completion consumer /// and give ownership to the caller. CodeCompleteConsumer *takeCodeCompletionConsumer() { - return CompletionConsumer.take(); + return CompletionConsumer.release(); } /// setCodeCompletionConsumer - Replace the current code completion consumer; @@ -457,7 +499,7 @@ public: /// @name Frontend timer /// { - bool hasFrontendTimer() const { return FrontendTimer.isValid(); } + bool hasFrontendTimer() const { return (bool)FrontendTimer; } llvm::Timer &getFrontendTimer() const { assert(FrontendTimer && "Compiler instance has no frontend timer!"); @@ -495,7 +537,7 @@ public: /// /// \param ShouldOwnClient If Client is non-NULL, specifies whether /// the diagnostic object should take ownership of the client. - void createDiagnostics(DiagnosticConsumer *Client = 0, + void createDiagnostics(DiagnosticConsumer *Client = nullptr, bool ShouldOwnClient = true); /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter. @@ -518,9 +560,9 @@ public: /// \return The new object on success, or null on failure. static IntrusiveRefCntPtr<DiagnosticsEngine> createDiagnostics(DiagnosticOptions *Opts, - DiagnosticConsumer *Client = 0, + DiagnosticConsumer *Client = nullptr, bool ShouldOwnClient = true, - const CodeGenOptions *CodeGenOpts = 0); + const CodeGenOptions *CodeGenOpts = nullptr); /// Create the file manager and replace any existing one with it. void createFileManager(); @@ -530,28 +572,26 @@ public: /// Create the preprocessor, using the invocation, file, and source managers, /// and replace any existing one with it. - void createPreprocessor(); + void createPreprocessor(TranslationUnitKind TUKind); /// Create the AST context. void createASTContext(); /// Create an external AST source to read a PCH file and attach it to the AST /// context. - void createPCHExternalASTSource(StringRef Path, - bool DisablePCHValidation, + void createPCHExternalASTSource(StringRef Path, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors, - void *DeserializationListener); + void *DeserializationListener, + bool OwnDeserializationListener); /// Create an external AST source to read a PCH file. /// /// \return - The new object on success, or null on failure. - static ExternalASTSource * - createPCHExternalASTSource(StringRef Path, const std::string &Sysroot, - bool DisablePCHValidation, - bool AllowPCHWithCompilerErrors, - Preprocessor &PP, ASTContext &Context, - void *DeserializationListener, bool Preamble, - bool UseGlobalModuleIndex); + static ExternalASTSource *createPCHExternalASTSource( + StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, + bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, + void *DeserializationListener, bool OwnDeserializationListener, + bool Preamble, bool UseGlobalModuleIndex); /// Create a code completion consumer using the invocation; note that this /// will cause the source manager to truncate the input source file at the @@ -632,6 +672,8 @@ public: std::string *ResultPathName, std::string *TempPathName); + llvm::raw_null_ostream *createNullOutputFile(); + /// } /// @name Initialization Utility Methods /// { @@ -653,21 +695,28 @@ public: const FrontendOptions &Opts); /// } - - virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, - ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective); - virtual void makeModuleVisible(Module *Mod, - Module::NameVisibilityKind Visibility, - SourceLocation ImportLoc, - bool Complain); + // Create module manager. + void createModuleManager(); + + ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) override; + + void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility, + SourceLocation ImportLoc, bool Complain) override; bool hadModuleLoaderFatalFailure() const { return ModuleLoader::HadFatalFailure; } + GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override; + + bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override; + + void addDependencyCollector(std::shared_ptr<DependencyCollector> Listener) { + DependencyCollectors.push_back(std::move(Listener)); + } }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h index f64773c..f05ab80 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h @@ -47,15 +47,17 @@ class DiagnosticsEngine; /// When errors are encountered, return false and, if Diags is non-null, /// report the error(s). bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args, - DiagnosticsEngine *Diags = 0); + DiagnosticsEngine *Diags = nullptr); class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> { -protected: + void operator=(const CompilerInvocationBase &) LLVM_DELETED_FUNCTION; + +public: /// Options controlling the language variant. - IntrusiveRefCntPtr<LangOptions> LangOpts; + std::shared_ptr<LangOptions> LangOpts; /// Options controlling the target. - IntrusiveRefCntPtr<TargetOptions> TargetOpts; + std::shared_ptr<TargetOptions> TargetOpts; /// Options controlling the diagnostic engine. IntrusiveRefCntPtr<DiagnosticOptions> DiagnosticOpts; @@ -66,17 +68,17 @@ protected: /// Options controlling the preprocessor (aside from \#include handling). IntrusiveRefCntPtr<PreprocessorOptions> PreprocessorOpts; -public: CompilerInvocationBase(); + ~CompilerInvocationBase(); CompilerInvocationBase(const CompilerInvocationBase &X); - LangOptions *getLangOpts() { return LangOpts.getPtr(); } - const LangOptions *getLangOpts() const { return LangOpts.getPtr(); } + LangOptions *getLangOpts() { return LangOpts.get(); } + const LangOptions *getLangOpts() const { return LangOpts.get(); } - TargetOptions &getTargetOpts() { return *TargetOpts.getPtr(); } + TargetOptions &getTargetOpts() { return *TargetOpts.get(); } const TargetOptions &getTargetOpts() const { - return *TargetOpts.getPtr(); + return *TargetOpts.get(); } DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; } @@ -204,6 +206,14 @@ public: /// @} }; +namespace vfs { + class FileSystem; +} + +IntrusiveRefCntPtr<vfs::FileSystem> +createVFSFromCompilerInvocation(const CompilerInvocation &CI, + DiagnosticsEngine &Diags); + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h index fefb6f3..5da1459 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h @@ -26,6 +26,7 @@ public: /// problems. unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info. + unsigned IncludeModuleFiles : 1; ///< Include module file dependencies. /// The file to write dependency output to. std::string OutputFile; @@ -42,7 +43,10 @@ public: /// \brief The file to write GraphViz-formatted header dependencies to. std::string DOTOutputFile; - + + /// \brief The directory to copy module dependencies to when collecting them. + std::string ModuleDependencyOutputDir; + public: DependencyOutputOptions() { IncludeSystemHeaders = 0; @@ -50,6 +54,7 @@ public: UsePhonyTargets = 0; AddMissingHeaderDeps = 0; PrintShowIncludes = 0; + IncludeModuleFiles = 0; } }; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h index f3cd054..ce1dc90 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h @@ -83,9 +83,7 @@ protected: DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges, const SourceManager &SM) = 0; - - virtual void emitBasicNote(StringRef Message) = 0; - + virtual void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange>& Ranges, @@ -108,6 +106,7 @@ protected: private: + void emitBasicNote(StringRef Message); void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, const SourceManager &SM); void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM); @@ -144,7 +143,7 @@ public: StringRef Message, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> FixItHints, const SourceManager *SM, - DiagOrStoredDiag D = (Diagnostic *)0); + DiagOrStoredDiag D = (Diagnostic *)nullptr); void emitStoredDiagnostic(StoredDiagnostic &Diag); }; @@ -158,20 +157,17 @@ public: : DiagnosticRenderer(LangOpts, DiagOpts) {} virtual ~DiagnosticNoteRenderer(); - - virtual void emitBasicNote(StringRef Message); - - virtual void emitIncludeLocation(SourceLocation Loc, - PresumedLoc PLoc, - const SourceManager &SM); - virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM); + void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, + const SourceManager &SM) override; - virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM); + void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM) override; + + void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM) override; virtual void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM) = 0; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h index a568ba0..9ac9d28 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h @@ -21,8 +21,8 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Frontend/FrontendOptions.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" +#include <memory> #include <string> #include <vector> @@ -35,7 +35,7 @@ class CompilerInstance; /// Abstract base class for actions which can be performed by the frontend. class FrontendAction { FrontendInputFile CurrentInput; - OwningPtr<ASTUnit> CurrentASTUnit; + std::unique_ptr<ASTUnit> CurrentASTUnit; CompilerInstance *Instance; friend class ASTMergeAction; friend class WrapperFrontendAction; @@ -124,7 +124,7 @@ public: bool isCurrentFileAST() const { assert(!CurrentInput.isEmpty() && "No current file!"); - return CurrentASTUnit.isValid(); + return (bool)CurrentASTUnit; } const FrontendInputFile &getCurrentInput() const { @@ -146,11 +146,10 @@ public: return *CurrentASTUnit; } - ASTUnit *takeCurrentASTUnit() { - return CurrentASTUnit.take(); - } + ASTUnit *takeCurrentASTUnit() { return CurrentASTUnit.release(); } - void setCurrentInput(const FrontendInputFile &CurrentInput, ASTUnit *AST = 0); + void setCurrentInput(const FrontendInputFile &CurrentInput, + ASTUnit *AST = nullptr); /// @} /// @name Supported Modes @@ -220,17 +219,17 @@ protected: /// /// This will also take care of instantiating a code completion consumer if /// the user requested it and the action supports it. - virtual void ExecuteAction(); + void ExecuteAction() override; public: - virtual bool usesPreprocessorOnly() const { return false; } + bool usesPreprocessorOnly() const override { return false; } }; class PluginASTAction : public ASTFrontendAction { virtual void anchor(); protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) = 0; + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override = 0; public: /// \brief Parse the given plugin command line arguments. @@ -248,11 +247,11 @@ class PreprocessorFrontendAction : public FrontendAction { protected: /// \brief Provide a default implementation which returns aborts; /// this method should never be called by FrontendAction clients. - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; public: - virtual bool usesPreprocessorOnly() const { return true; } + bool usesPreprocessorOnly() const override { return true; } }; /// \brief A frontend action which simply wraps some other runtime-specified @@ -262,28 +261,27 @@ public: /// some existing action's behavior. It implements every virtual method in /// the FrontendAction interface by forwarding to the wrapped action. class WrapperFrontendAction : public FrontendAction { - OwningPtr<FrontendAction> WrappedAction; + std::unique_ptr<FrontendAction> WrappedAction; protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); - virtual bool BeginInvocation(CompilerInstance &CI); - virtual bool BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename); - virtual void ExecuteAction(); - virtual void EndSourceFileAction(); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + bool BeginInvocation(CompilerInstance &CI) override; + bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override; + void ExecuteAction() override; + void EndSourceFileAction() override; public: /// Construct a WrapperFrontendAction from an existing action, taking /// ownership of it. WrapperFrontendAction(FrontendAction *WrappedAction); - virtual bool usesPreprocessorOnly() const; - virtual TranslationUnitKind getTranslationUnitKind(); - virtual bool hasPCHSupport() const; - virtual bool hasASTFileSupport() const; - virtual bool hasIRSupport() const; - virtual bool hasCodeCompletionSupport() const; + bool usesPreprocessorOnly() const override; + TranslationUnitKind getTranslationUnitKind() override; + bool hasPCHSupport() const override; + bool hasASTFileSupport() const override; + bool hasIRSupport() const override; + bool hasCodeCompletionSupport() const override; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h index f3d1276..84cc82c 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h @@ -17,21 +17,22 @@ namespace clang { class Module; +class FileEntry; //===----------------------------------------------------------------------===// // Custom Consumer Actions //===----------------------------------------------------------------------===// class InitOnlyAction : public FrontendAction { - virtual void ExecuteAction(); + void ExecuteAction() override; - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; public: // Don't claim to only use the preprocessor, we want to follow the AST path, // but do nothing. - virtual bool usesPreprocessorOnly() const { return false; } + bool usesPreprocessorOnly() const override { return false; } }; //===----------------------------------------------------------------------===// @@ -40,44 +41,44 @@ public: class ASTPrintAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class ASTDumpAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class ASTDeclListAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class ASTViewAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class DeclContextPrintAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class GeneratePCHAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; - virtual TranslationUnitKind getTranslationUnitKind() { + TranslationUnitKind getTranslationUnitKind() override { return TU_Prefix; } - virtual bool hasASTFileSupport() const { return false; } + bool hasASTFileSupport() const override { return false; } public: /// \brief Compute the AST consumer arguments that will be used to @@ -93,57 +94,71 @@ public: class GenerateModuleAction : public ASTFrontendAction { clang::Module *Module; + const FileEntry *ModuleMapForUniquing; bool IsSystem; protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); - - virtual TranslationUnitKind getTranslationUnitKind() { + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + TranslationUnitKind getTranslationUnitKind() override { return TU_Module; } - - virtual bool hasASTFileSupport() const { return false; } - + + bool hasASTFileSupport() const override { return false; } + public: - explicit GenerateModuleAction(bool IsSystem = false) - : ASTFrontendAction(), IsSystem(IsSystem) { } + GenerateModuleAction(const FileEntry *ModuleMap = nullptr, + bool IsSystem = false) + : ASTFrontendAction(), ModuleMapForUniquing(ModuleMap), IsSystem(IsSystem) + { } + + bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override; - virtual bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename); - /// \brief Compute the AST consumer arguments that will be used to /// create the PCHGenerator instance returned by CreateASTConsumer. /// /// \returns true if an error occurred, false otherwise. - static bool ComputeASTConsumerArguments(CompilerInstance &CI, - StringRef InFile, - std::string &Sysroot, - std::string &OutputFile, - raw_ostream *&OS); + bool ComputeASTConsumerArguments(CompilerInstance &CI, + StringRef InFile, + std::string &Sysroot, + std::string &OutputFile, + raw_ostream *&OS); }; class SyntaxOnlyAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; public: - virtual bool hasCodeCompletionSupport() const { return true; } + bool hasCodeCompletionSupport() const override { return true; } }; /// \brief Dump information about the given module file, to be used for /// basic debugging and discovery. class DumpModuleInfoAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); - virtual void ExecuteAction(); - + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + void ExecuteAction() override; + public: - virtual bool hasPCHSupport() const { return false; } - virtual bool hasASTFileSupport() const { return true; } - virtual bool hasIRSupport() const { return false; } - virtual bool hasCodeCompletionSupport() const { return false; } + bool hasPCHSupport() const override { return false; } + bool hasASTFileSupport() const override { return true; } + bool hasIRSupport() const override { return false; } + bool hasCodeCompletionSupport() const override { return false; } +}; + +class VerifyPCHAction : public ASTFrontendAction { +protected: + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + void ExecuteAction() override; + +public: + bool hasCodeCompletionSupport() const override { return false; } }; /** @@ -162,34 +177,34 @@ class ASTMergeAction : public FrontendAction { std::vector<std::string> ASTFiles; protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; - virtual bool BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename); + bool BeginSourceFileAction(CompilerInstance &CI, + StringRef Filename) override; - virtual void ExecuteAction(); - virtual void EndSourceFileAction(); + void ExecuteAction() override; + void EndSourceFileAction() override; public: ASTMergeAction(FrontendAction *AdaptedAction, ArrayRef<std::string> ASTFiles); virtual ~ASTMergeAction(); - virtual bool usesPreprocessorOnly() const; - virtual TranslationUnitKind getTranslationUnitKind(); - virtual bool hasPCHSupport() const; - virtual bool hasASTFileSupport() const; - virtual bool hasCodeCompletionSupport() const; + bool usesPreprocessorOnly() const override; + TranslationUnitKind getTranslationUnitKind() override; + bool hasPCHSupport() const override; + bool hasASTFileSupport() const override; + bool hasCodeCompletionSupport() const override; }; class PrintPreambleAction : public FrontendAction { protected: - void ExecuteAction(); - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &, StringRef) { - return 0; + void ExecuteAction() override; + ASTConsumer *CreateASTConsumer(CompilerInstance &, StringRef) override { + return nullptr; } - - virtual bool usesPreprocessorOnly() const { return true; } + + bool usesPreprocessorOnly() const override { return true; } }; //===----------------------------------------------------------------------===// @@ -198,29 +213,29 @@ protected: class DumpRawTokensAction : public PreprocessorFrontendAction { protected: - void ExecuteAction(); + void ExecuteAction() override; }; class DumpTokensAction : public PreprocessorFrontendAction { protected: - void ExecuteAction(); + void ExecuteAction() override; }; class GeneratePTHAction : public PreprocessorFrontendAction { protected: - void ExecuteAction(); + void ExecuteAction() override; }; class PreprocessOnlyAction : public PreprocessorFrontendAction { protected: - void ExecuteAction(); + void ExecuteAction() override; }; class PrintPreprocessedAction : public PreprocessorFrontendAction { protected: - void ExecuteAction(); + void ExecuteAction() override; - virtual bool hasPCHSupport() const { return true; } + bool hasPCHSupport() const override { return true; } }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h index 4b321e8..e87da8d 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h @@ -43,6 +43,7 @@ namespace frontend { GeneratePTH, ///< Generate pre-tokenized header. InitOnly, ///< Only execute frontend initialization. ModuleFileInfo, ///< Dump information about a module file. + VerifyPCH, ///< Load and verify that a PCH file is usable. ParseSyntaxOnly, ///< Parse and perform semantic analysis. PluginAction, ///< Run a plugin action, \see ActionName. PrintDeclContext, ///< Print DeclContext and their Decls. @@ -89,9 +90,9 @@ class FrontendInputFile { bool IsSystem; public: - FrontendInputFile() : Buffer(0), Kind(IK_None) { } + FrontendInputFile() : Buffer(nullptr), Kind(IK_None) { } FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false) - : File(File.str()), Buffer(0), Kind(Kind), IsSystem(IsSystem) { } + : File(File.str()), Buffer(nullptr), Kind(Kind), IsSystem(IsSystem) { } FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind, bool IsSystem = false) : Buffer(buffer), Kind(Kind), IsSystem(IsSystem) { } @@ -99,9 +100,9 @@ public: InputKind getKind() const { return Kind; } bool isSystem() const { return IsSystem; } - bool isEmpty() const { return File.empty() && Buffer == 0; } + bool isEmpty() const { return File.empty() && Buffer == nullptr; } bool isFile() const { return !isBuffer(); } - bool isBuffer() const { return Buffer != 0; } + bool isBuffer() const { return Buffer != nullptr; } StringRef getFile() const { assert(isFile()); @@ -179,10 +180,13 @@ public: ObjCMT_ReturnsInnerPointerProperty = 0x200, /// \brief use NS_NONATOMIC_IOSONLY for property 'atomic' attribute ObjCMT_NsAtomicIOSOnlyProperty = 0x400, + /// \brief Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods. + ObjCMT_DesignatedInitializer = 0x800, ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty | ObjCMT_Annotation | ObjCMT_Instancetype | ObjCMT_NsMacros | ObjCMT_ProtocolConformance | - ObjCMT_NsAtomicIOSOnlyProperty), + ObjCMT_NsAtomicIOSOnlyProperty | + ObjCMT_DesignatedInitializer), ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting | ObjCMT_MigrateDecls) }; unsigned ObjCMTAction; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h index ec925ad..49be495 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h @@ -13,6 +13,9 @@ #include "clang/Frontend/FrontendAction.h" #include "llvm/Support/Registry.h" +// Instantiated in FrontendAction.cpp. +extern template class llvm::Registry<clang::PluginASTAction>; + namespace clang { /// The frontend plugin registry. diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h index 1124d53..9680e1f 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h @@ -25,10 +25,11 @@ enum LangFeatures { CPlusPlus = (1 << 4), CPlusPlus11 = (1 << 5), CPlusPlus1y = (1 << 6), - Digraphs = (1 << 7), - GNUMode = (1 << 8), - HexFloat = (1 << 9), - ImplicitInt = (1 << 10) + CPlusPlus1z = (1 << 7), + Digraphs = (1 << 8), + GNUMode = (1 << 9), + HexFloat = (1 << 10), + ImplicitInt = (1 << 11) }; } @@ -69,12 +70,15 @@ public: /// isCPlusPlus - Language is a C++ variant. bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; } - /// isCPlusPlus11 - Language is a C++0x variant. + /// isCPlusPlus11 - Language is a C++11 variant (or later). bool isCPlusPlus11() const { return Flags & frontend::CPlusPlus11; } - /// isCPlusPlus1y - Language is a C++1y variant. + /// isCPlusPlus1y - Language is a C++14 variant (or later). bool isCPlusPlus1y() const { return Flags & frontend::CPlusPlus1y; } + /// isCPlusPlus1z - Language is a C++17 variant (or later). + bool isCPlusPlus1z() const { return Flags & frontend::CPlusPlus1z; } + /// hasDigraphs - Language supports digraphs. bool hasDigraphs() const { return Flags & frontend::Digraphs; } diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def index 7b2516b..90a27b5 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def @@ -108,13 +108,29 @@ LANGSTANDARD(gnucxx11, "gnu++11", LineComment | CPlusPlus | CPlusPlus11 | Digraphs | GNUMode) LANGSTANDARD(cxx1y, "c++1y", - "Working draft for ISO C++ 2014", + "ISO C++ 2014 with amendments", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs) +LANGSTANDARD(cxx14, "c++14", + "ISO C++ 2014 with amendments", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs) LANGSTANDARD(gnucxx1y, "gnu++1y", - "Working draft for ISO C++ 2014 with GNU extensions", + "ISO C++ 2014 with amendments and GNU extensions", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs | + GNUMode) +LANGSTANDARD(gnucxx14, "gnu++14", + "ISO C++ 2014 with amendments and GNU extensions", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs | GNUMode) +LANGSTANDARD(cxx1z, "c++1z", + "Working draft for ISO C++ 2017", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | CPlusPlus1z | + Digraphs) +LANGSTANDARD(gnucxx1z, "gnu++1z", + "Working draft for ISO C++ 2017 with GNU extensions", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | CPlusPlus1z | + Digraphs | GNUMode) + // OpenCL LANGSTANDARD(opencl, "cl", "OpenCL 1.0", diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h b/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h index ec34e14..16d032b 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h @@ -47,12 +47,13 @@ namespace clang { /// \brief If this particular record type has an overridden layout, /// return that layout. - virtual bool + bool layoutRecordType(const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, - llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets); + llvm::DenseMap<const CXXRecordDecl *, + CharUnits> &VirtualBaseOffsets) override; /// \brief Dump the overridden layouts. void dump(); diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h index e8a6bb3..0130319 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h @@ -39,7 +39,10 @@ class LogDiagnosticPrinter : public DiagnosticConsumer { /// The level of the diagnostic. DiagnosticsEngine::Level DiagnosticLevel; }; - + + void EmitDiagEntry(llvm::raw_ostream &OS, + const LogDiagnosticPrinter::DiagEntry &DE); + raw_ostream &OS; const LangOptions *LangOpts; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; @@ -62,14 +65,14 @@ public: DwarfDebugFlags = Value; } - void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) { + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override { LangOpts = &LO; } - void EndSourceFile(); + void EndSourceFile() override; - virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info); + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h index 6ea7547..4d31104 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h @@ -17,7 +17,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Sema/SemaConsumer.h" -#include "llvm/ADT/OwningPtr.h" +#include <memory> #include <vector> namespace clang { @@ -33,28 +33,35 @@ public: ~MultiplexConsumer(); // ASTConsumer - virtual void Initialize(ASTContext &Context); - virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *VD); - virtual bool HandleTopLevelDecl(DeclGroupRef D); - virtual void HandleInterestingDecl(DeclGroupRef D); - virtual void HandleTranslationUnit(ASTContext &Ctx); - virtual void HandleTagDeclDefinition(TagDecl *D); - virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D); - virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); - virtual void CompleteTentativeDefinition(VarDecl *D); - virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired); - virtual ASTMutationListener *GetASTMutationListener(); - virtual ASTDeserializationListener *GetASTDeserializationListener(); - virtual void PrintStats(); + void Initialize(ASTContext &Context) override; + void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override; + bool HandleTopLevelDecl(DeclGroupRef D) override; + void HandleInlineMethodDefinition(CXXMethodDecl *D) override; + void HandleInterestingDecl(DeclGroupRef D) override; + void HandleTranslationUnit(ASTContext &Ctx) override; + void HandleTagDeclDefinition(TagDecl *D) override; + void HandleTagDeclRequiredDefinition(const TagDecl *D) override; + void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override; + void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override; + void HandleImplicitImportDecl(ImportDecl *D) override; + void HandleLinkerOptionPragma(llvm::StringRef Opts) override; + void HandleDetectMismatch(llvm::StringRef Name, + llvm::StringRef Value) override; + void HandleDependentLibrary(llvm::StringRef Lib) override; + void CompleteTentativeDefinition(VarDecl *D) override; + void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) override; + ASTMutationListener *GetASTMutationListener() override; + ASTDeserializationListener *GetASTDeserializationListener() override; + void PrintStats() override; // SemaConsumer - virtual void InitializeSema(Sema &S); - virtual void ForgetSema(); + void InitializeSema(Sema &S) override; + void ForgetSema() override; private: std::vector<ASTConsumer*> Consumers; // Owns these. - OwningPtr<MultiplexASTMutationListener> MutationListener; - OwningPtr<MultiplexASTDeserializationListener> DeserializationListener; + std::unique_ptr<MultiplexASTMutationListener> MutationListener; + std::unique_ptr<MultiplexASTDeserializationListener> DeserializationListener; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h index 117771d..4dda1fa 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -46,6 +46,19 @@ enum RecordIDs { RECORD_LAST = RECORD_FIXIT }; +/// A stable version of DiagnosticIDs::Level. +/// +/// Do not change the order of values in this enum, and please increment the +/// serialized diagnostics version number when you add to it. +enum Level { + Ignored = 0, + Note, + Warning, + Error, + Fatal, + Remark +}; + /// \brief Returns a DiagnosticConsumer that serializes diagnostics to /// a bitcode file. /// diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h index c8d01b0..acebb90 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h @@ -63,52 +63,48 @@ public: /// formatting of their diagnostic messages. /// /// \param OS Where the message is printed - /// \param Level Used to colorizing the message + /// \param IsSupplemental true if this is a continuation note diagnostic /// \param Message The text actually printed /// \param CurrentColumn The starting column of the first line, accounting /// for any prefix. /// \param Columns The number of columns to use in line-wrapping, 0 disables /// all line-wrapping. /// \param ShowColors Enable colorizing of the message. - static void printDiagnosticMessage(raw_ostream &OS, - DiagnosticsEngine::Level Level, - StringRef Message, - unsigned CurrentColumn, unsigned Columns, - bool ShowColors); + static void printDiagnosticMessage(raw_ostream &OS, bool IsSupplemental, + StringRef Message, unsigned CurrentColumn, + unsigned Columns, bool ShowColors); protected: - virtual void emitDiagnosticMessage(SourceLocation Loc,PresumedLoc PLoc, - 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, - const SourceManager &SM); - - virtual void emitCodeContext(SourceLocation Loc, - DiagnosticsEngine::Level Level, - SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints, - const SourceManager &SM) { + void emitDiagnosticMessage(SourceLocation Loc,PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + StringRef Message, + ArrayRef<CharSourceRange> Ranges, + const SourceManager *SM, + DiagOrStoredDiag D) override; + + void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges, + const SourceManager &SM) override; + + void emitCodeContext(SourceLocation Loc, + DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange>& Ranges, + ArrayRef<FixItHint> Hints, + const SourceManager &SM) override { emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM); } - - virtual void emitBasicNote(StringRef Message); - - virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, - const SourceManager &SM); - virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM); + void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, + const SourceManager &SM) override; + + void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM) override; - virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM); + void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, + StringRef ModuleName, + const SourceManager &SM) override; private: void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h index 93ac299..fe5aa3e 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h @@ -28,7 +28,7 @@ public: typedef DiagList::iterator iterator; typedef DiagList::const_iterator const_iterator; private: - DiagList Errors, Warnings, Notes; + DiagList Errors, Warnings, Remarks, Notes; public: const_iterator err_begin() const { return Errors.begin(); } const_iterator err_end() const { return Errors.end(); } @@ -36,11 +36,14 @@ public: const_iterator warn_begin() const { return Warnings.begin(); } const_iterator warn_end() const { return Warnings.end(); } + const_iterator remark_begin() const { return Remarks.begin(); } + const_iterator remark_end() const { return Remarks.end(); } + const_iterator note_begin() const { return Notes.begin(); } const_iterator note_end() const { return Notes.end(); } - virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info); + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override; /// FlushDiagnostics - Flush the buffered diagnostics to an given /// diagnostic engine. diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h index dc80470..9f6d5ff 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h @@ -18,7 +18,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" +#include <memory> namespace clang { class DiagnosticOptions; @@ -30,7 +30,7 @@ class TextDiagnosticPrinter : public DiagnosticConsumer { IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; /// \brief Handle to the currently active text diagnostic emitter. - OwningPtr<TextDiagnostic> TextDiag; + std::unique_ptr<TextDiagnostic> TextDiag; /// A string to prefix to error messages. std::string Prefix; @@ -47,9 +47,10 @@ public: /// used. void setPrefix(std::string Value) { Prefix = Value; } - void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP); - void EndSourceFile(); - void HandleDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info); + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override; + void EndSourceFile() override; + void HandleDiagnostic(DiagnosticsEngine::Level Level, + const Diagnostic &Info) override; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h index dff56c3..4c0a7b7 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h @@ -15,8 +15,10 @@ #define LLVM_CLANG_FRONTEND_UTILS_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/VirtualFileSystem.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Option/OptSpecifier.h" namespace llvm { @@ -30,12 +32,14 @@ class ArgList; namespace clang { class ASTConsumer; +class ASTReader; class CompilerInstance; class CompilerInvocation; class Decl; class DependencyOutputOptions; class DiagnosticsEngine; class DiagnosticOptions; +class ExternalSemaSource; class FileManager; class HeaderSearch; class HeaderSearchOptions; @@ -59,23 +63,81 @@ void ApplyHeaderSearchOptions(HeaderSearch &HS, /// environment ready to process a single file. void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts, - const HeaderSearchOptions &HSOpts, const FrontendOptions &FEOpts); -/// ProcessWarningOptions - Initialize the diagnostic client and process the -/// warning options specified on the command line. -void ProcessWarningOptions(DiagnosticsEngine &Diags, - const DiagnosticOptions &Opts, - bool ReportDiags = true); - /// DoPrintPreprocessedInput - Implement -E mode. void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS, const PreprocessorOutputOptions &Opts); -/// AttachDependencyFileGen - Create a dependency file generator, and attach -/// it to the given preprocessor. This takes ownership of the output stream. -void AttachDependencyFileGen(Preprocessor &PP, - const DependencyOutputOptions &Opts); +/// An interface for collecting the dependencies of a compilation. Users should +/// use \c attachToPreprocessor and \c attachToASTReader to get all of the +/// dependencies. +// FIXME: Migrate DependencyFileGen, DependencyGraphGen, ModuleDepCollectory to +// use this interface. +class DependencyCollector { +public: + void attachToPreprocessor(Preprocessor &PP); + void attachToASTReader(ASTReader &R); + llvm::ArrayRef<std::string> getDependencies() const { return Dependencies; } + + /// Called when a new file is seen. Return true if \p Filename should be added + /// to the list of dependencies. + /// + /// The default implementation ignores <built-in> and system files. + virtual bool sawDependency(StringRef Filename, bool FromModule, + bool IsSystem, bool IsModuleFile, bool IsMissing); + /// Called when the end of the main file is reached. + virtual void finishedMainFile() { } + /// Return true if system files should be passed to sawDependency(). + virtual bool needSystemDependencies() { return false; } + virtual ~DependencyCollector(); + +public: // implementation detail + /// Add a dependency \p Filename if it has not been seen before and + /// sawDependency() returns true. + void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, + bool IsModuleFile, bool IsMissing); +private: + llvm::StringSet<> Seen; + std::vector<std::string> Dependencies; +}; + +/// Builds a depdenency file when attached to a Preprocessor (for includes) and +/// ASTReader (for module imports), and writes it out at the end of processing +/// a source file. Users should attach to the ast reader whenever a module is +/// loaded. +class DependencyFileGenerator { + void *Impl; // Opaque implementation + DependencyFileGenerator(void *Impl); +public: + static DependencyFileGenerator *CreateAndAttachToPreprocessor( + Preprocessor &PP, const DependencyOutputOptions &Opts); + void AttachToASTReader(ASTReader &R); +}; + +/// Collects the dependencies for imported modules into a directory. Users +/// should attach to the AST reader whenever a module is loaded. +class ModuleDependencyCollector { + std::string DestDir; + bool HasErrors; + llvm::StringSet<> Seen; + vfs::YAMLVFSWriter VFSWriter; + +public: + StringRef getDest() { return DestDir; } + bool insertSeen(StringRef Filename) { return Seen.insert(Filename); } + void setHasErrors() { HasErrors = true; } + void addFileMapping(StringRef VPath, StringRef RPath) { + VFSWriter.addFileMapping(VPath, RPath); + } + + void attachToASTReader(ASTReader &R); + void writeFileMap(); + bool hasErrors() { return HasErrors; } + ModuleDependencyCollector(std::string DestDir) + : DestDir(DestDir), HasErrors(false) {} + ~ModuleDependencyCollector() { writeFileMap(); } +}; /// AttachDependencyGraphGen - Create a dependency graph generator, and attach /// it to the given preprocessor. @@ -101,6 +163,12 @@ void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false, /// a seekable stream. void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS); +/// The ChainedIncludesSource class converts headers to chained PCHs in +/// memory, mainly for testing. +IntrusiveRefCntPtr<ExternalSemaSource> +createChainedIncludesSource(CompilerInstance &CI, + IntrusiveRefCntPtr<ExternalSemaSource> &Reader); + /// createInvocationFromCommandLine - Construct a compiler invocation object for /// a command line argument vector. /// @@ -115,7 +183,7 @@ createInvocationFromCommandLine(ArrayRef<const char *> Args, /// is non-null, emits an error if the argument is given, but non-integral. int getLastArgIntValue(const llvm::opt::ArgList &Args, llvm::opt::OptSpecifier Id, int Default, - DiagnosticsEngine *Diags = 0); + DiagnosticsEngine *Diags = nullptr); inline int getLastArgIntValue(const llvm::opt::ArgList &Args, llvm::opt::OptSpecifier Id, int Default, @@ -123,6 +191,22 @@ inline int getLastArgIntValue(const llvm::opt::ArgList &Args, return getLastArgIntValue(Args, Id, Default, &Diags); } +uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args, + llvm::opt::OptSpecifier Id, uint64_t Default, + DiagnosticsEngine *Diags = nullptr); + +inline uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args, + llvm::opt::OptSpecifier Id, + uint64_t Default, + DiagnosticsEngine &Diags) { + return getLastArgUInt64Value(Args, Id, Default, &Diags); +} + +// When Clang->getFrontendOpts().DisableFree is set we don't delete some of the +// global objects, but we don't want LeakDetectors to complain, so we bury them +// in a globally visible array. +void BuryPointer(const void *Ptr); + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h index 95d7752..9273fac 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h @@ -13,10 +13,10 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" #include <climits> +#include <memory> namespace clang { @@ -34,12 +34,12 @@ class FileEntry; /// comment on the line that has the diagnostic, use: /// /// \code -/// expected-{error,warning,note} +/// expected-{error,warning,remark,note} /// \endcode /// -/// to tag if it's an expected error or warning, and place the expected text -/// between {{ and }} markers. The full text doesn't have to be included, only -/// enough to ensure that the correct diagnostic was emitted. +/// to tag if it's an expected error, remark or warning, and place the expected +/// text between {{ and }} markers. The full text doesn't have to be included, +/// only enough to ensure that the correct diagnostic was emitted. /// /// Here's an example: /// @@ -71,7 +71,10 @@ class FileEntry; /// \endcode /// /// The path can be absolute or relative and the same search paths will be used -/// as for #include directives. +/// as for #include directives. The line number in an external file may be +/// substituted with '*' meaning that any line number will match (useful where +/// the included file is, for example, a system header where the actual line +/// number may change and is not critical). /// /// The simple syntax above allows each specification to match exactly one /// error. You can use the extended syntax to customize this. The extended @@ -108,10 +111,11 @@ class FileEntry; /// /// In this example, the diagnostic may appear only once, if at all. /// -/// Regex matching mode may be selected by appending '-re' to type, such as: +/// Regex matching mode may be selected by appending '-re' to type and +/// including regexes wrapped in double curly braces in the directive, such as: /// /// \code -/// expected-error-re +/// expected-error-re {{format specifies type 'wchar_t **' (aka '{{.+}}')}} /// \endcode /// /// Examples matching error: "variable has incomplete type 'struct s'" @@ -120,10 +124,10 @@ class FileEntry; /// // expected-error {{variable has incomplete type 'struct s'}} /// // expected-error {{variable has incomplete type}} /// -/// // expected-error-re {{variable has has type 'struct .'}} -/// // expected-error-re {{variable has has type 'struct .*'}} -/// // expected-error-re {{variable has has type 'struct (.*)'}} -/// // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}} +/// // expected-error-re {{variable has type 'struct {{.}}'}} +/// // expected-error-re {{variable has type 'struct {{.*}}'}} +/// // expected-error-re {{variable has type 'struct {{(.*)}}'}} +/// // expected-error-re {{variable has type 'struct{{[[:space:]](.*)}}'}} /// \endcode /// /// VerifyDiagnosticConsumer expects at least one expected-* directive to @@ -142,7 +146,7 @@ public: class Directive { public: static Directive *create(bool RegexKind, SourceLocation DirectiveLoc, - SourceLocation DiagnosticLoc, + SourceLocation DiagnosticLoc, bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max); public: /// Constant representing n or more matches. @@ -152,6 +156,7 @@ public: SourceLocation DiagnosticLoc; const std::string Text; unsigned Min, Max; + bool MatchAnyLine; virtual ~Directive() { } @@ -164,9 +169,9 @@ public: protected: Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, - StringRef Text, unsigned Min, unsigned Max) + bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max) : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc), - Text(Text), Min(Min), Max(Max) { + Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) { assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!"); assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!"); } @@ -183,13 +188,17 @@ public: struct ExpectedData { DirectiveList Errors; DirectiveList Warnings; + DirectiveList Remarks; DirectiveList Notes; - ~ExpectedData() { + void Reset() { llvm::DeleteContainerPointers(Errors); llvm::DeleteContainerPointers(Warnings); + llvm::DeleteContainerPointers(Remarks); llvm::DeleteContainerPointers(Notes); } + + ~ExpectedData() { Reset(); } }; enum DirectiveStatus { @@ -203,7 +212,7 @@ private: DiagnosticsEngine &Diags; DiagnosticConsumer *PrimaryClient; bool OwnsPrimaryClient; - OwningPtr<TextDiagnosticBuffer> Buffer; + std::unique_ptr<TextDiagnosticBuffer> Buffer; const Preprocessor *CurrentPreprocessor; const LangOptions *LangOpts; SourceManager *SrcManager; @@ -217,24 +226,19 @@ private: SrcManager = &SM; } -#ifndef NDEBUG + // These facilities are used for validation in debug builds. class UnparsedFileStatus { llvm::PointerIntPair<const FileEntry *, 1, bool> Data; - public: UnparsedFileStatus(const FileEntry *File, bool FoundDirectives) : Data(File, FoundDirectives) {} - const FileEntry *getFile() const { return Data.getPointer(); } bool foundDirectives() const { return Data.getInt(); } }; - typedef llvm::DenseMap<FileID, const FileEntry *> ParsedFilesMap; typedef llvm::DenseMap<FileID, UnparsedFileStatus> UnparsedFilesMap; - ParsedFilesMap ParsedFiles; UnparsedFilesMap UnparsedFiles; -#endif public: /// Create a new verifying diagnostic client, which will issue errors to @@ -243,10 +247,10 @@ public: VerifyDiagnosticConsumer(DiagnosticsEngine &Diags); ~VerifyDiagnosticConsumer(); - virtual void BeginSourceFile(const LangOptions &LangOpts, - const Preprocessor *PP); + void BeginSourceFile(const LangOptions &LangOpts, + const Preprocessor *PP) override; - virtual void EndSourceFile(); + void EndSourceFile() override; enum ParsedStatus { /// File has been processed via HandleComment. @@ -262,10 +266,10 @@ public: /// \brief Update lists of parsed and unparsed files. void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS); - virtual bool HandleComment(Preprocessor &PP, SourceRange Comment); + bool HandleComment(Preprocessor &PP, SourceRange Comment) override; - virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info); + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override; }; } // end namspace clang diff --git a/contrib/llvm/tools/clang/include/clang/Index/CommentToXML.h b/contrib/llvm/tools/clang/include/clang/Index/CommentToXML.h index 8444b14..bb7b71a 100644 --- a/contrib/llvm/tools/clang/include/clang/Index/CommentToXML.h +++ b/contrib/llvm/tools/clang/include/clang/Index/CommentToXML.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_INDEX_COMMENTTOXML_H #include "clang/Basic/LLVM.h" +#include <memory> namespace clang { class ASTContext; @@ -24,11 +25,12 @@ namespace index { class SimpleFormatContext; class CommentToXMLConverter { - SimpleFormatContext *FormatContext; + std::unique_ptr<SimpleFormatContext> FormatContext; unsigned FormatInMemoryUniqueId; public: - CommentToXMLConverter() : FormatContext(0), FormatInMemoryUniqueId(0) {} + CommentToXMLConverter(); + ~CommentToXMLConverter(); void convertCommentToHTML(const comments::FullComment *FC, SmallVectorImpl<char> &HTML, diff --git a/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h b/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h index 7b0fd50..3195dee 100644 --- a/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h +++ b/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h @@ -14,7 +14,9 @@ #include "llvm/ADT/StringRef.h" namespace clang { - class Decl; +class Decl; +class MacroDefinition; +class SourceManager; namespace index { @@ -22,7 +24,7 @@ static inline StringRef getUSRSpacePrefix() { return "c:"; } -/// \brief Generate a USR for a Decl, including the prefix. +/// \brief Generate a USR for a Decl, including the USR prefix. /// \returns true if the results should be ignored, false otherwise. bool generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf); @@ -47,6 +49,12 @@ void generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS); /// \brief Generate a USR fragment for an Objective-C protocol. void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS); +/// \brief Generate a USR for a macro, including the USR prefix. +/// +/// \returns true on error, false on success. +bool generateUSRForMacro(const MacroDefinition *MD, const SourceManager &SM, + SmallVectorImpl<char> &Buf); + } // namespace index } // namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h index dff3e8c..9edf119 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h @@ -92,17 +92,21 @@ public: /// getDir - Return the directory that this entry refers to. /// - const DirectoryEntry *getDir() const { return isNormalDir() ? u.Dir : 0; } + const DirectoryEntry *getDir() const { + return isNormalDir() ? u.Dir : nullptr; + } /// getFrameworkDir - Return the directory that this framework refers to. /// const DirectoryEntry *getFrameworkDir() const { - return isFramework() ? u.Dir : 0; + return isFramework() ? u.Dir : nullptr; } /// getHeaderMap - Return the directory that this entry refers to. /// - const HeaderMap *getHeaderMap() const { return isHeaderMap() ? u.Map : 0; } + const HeaderMap *getHeaderMap() const { + return isHeaderMap() ? u.Map : nullptr; + } /// isNormalDir - Return true if this is a normal directory, not a header map. bool isNormalDir() const { return getLookupType() == LT_NormalDir; } @@ -161,11 +165,17 @@ public: /// \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, + /// + /// \param [out] MappedName if this is a headermap which maps the filename to + /// a framework include ("Foo.h" -> "Foo/Foo.h"), set the new name to this + /// vector and point Filename to it. + const FileEntry *LookupFile(StringRef &Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, ModuleMap::KnownHeader *SuggestedModule, - bool &InUserSpecifiedSystemFramework) const; + bool &InUserSpecifiedSystemFramework, + bool &HasBeenMapped, + SmallVectorImpl<char> &MappedName) const; private: const FileEntry *DoFrameworkLookup( diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h index 8473a6a..8e78b5a 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h @@ -55,6 +55,11 @@ public: /// "../../file.h". const FileEntry *LookupFile(StringRef Filename, FileManager &FM) const; + /// If the specified relative filename is located in this HeaderMap return + /// the filename it is mapped to, otherwise return an empty StringRef. + StringRef lookupFilename(StringRef Filename, + SmallVectorImpl<char> &DestPath) const; + /// getFileName - Return the filename of the headermap. const char *getFileName() const; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h index fb1a8620..0342629 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h @@ -18,10 +18,10 @@ #include "clang/Lex/ModuleMap.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" +#include <memory> #include <vector> namespace clang { @@ -73,6 +73,9 @@ struct HeaderFileInfo { /// provided via a header map. This bit indicates when this is one of /// those framework headers. unsigned IndexHeaderMapHeader : 1; + + /// \brief Whether this file had been looked up as a header. + unsigned IsValid : 1; /// \brief The number of times the file has been included already. unsigned short NumIncludes; @@ -102,8 +105,8 @@ struct HeaderFileInfo { : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), External(false), isModuleHeader(false), isCompilingModuleHeader(false), HeaderRole(ModuleMap::NormalHeader), - Resolved(false), IndexHeaderMapHeader(false), - NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {} + Resolved(false), IndexHeaderMapHeader(false), IsValid(0), + NumIncludes(0), ControllingMacroID(0), ControllingMacro(nullptr) {} /// \brief Retrieve the controlling macro for this header file, if /// any. @@ -158,6 +161,7 @@ class HeaderSearch { /// \brief Header-search options used to initialize this header search. IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts; + DiagnosticsEngine &Diags; FileManager &FileMgr; /// \#include search path information. Requests for \#include "x" search the /// directory of the \#including file first, then each directory in SearchDirs @@ -185,15 +189,27 @@ class HeaderSearch { /// included, indexed by the FileEntry's UID. std::vector<HeaderFileInfo> FileInfo; - /// \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; + /// Keeps track of each lookup performed by LookupFile. + struct LookupFileCacheInfo { + /// 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. + unsigned StartIdx; + /// The entry in SearchDirs that satisfied the query. + unsigned HitIdx; + /// This is non-null if the original filename was mapped to a framework + /// include via a headermap. + const char *MappedName; + + /// Default constructor -- Initialize all members with zero. + LookupFileCacheInfo(): StartIdx(0), HitIdx(0), MappedName(nullptr) {} + + void reset(unsigned StartIdx) { + this->StartIdx = StartIdx; + this->MappedName = nullptr; + } + }; + llvm::StringMap<LookupFileCacheInfo, llvm::BumpPtrAllocator> LookupFileCache; /// \brief Collection mapping a framework or subframework /// name like "Carbon" to the Carbon.framework directory. @@ -204,7 +220,7 @@ class HeaderSearch { /// include_alias pragma for Microsoft compatibility. typedef llvm::StringMap<std::string, llvm::BumpPtrAllocator> IncludeAliasMap; - OwningPtr<IncludeAliasMap> IncludeAliases; + std::unique_ptr<IncludeAliasMap> IncludeAliases; /// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing /// headermaps. This vector owns the headermap. @@ -232,6 +248,8 @@ class HeaderSearch { unsigned NumMultiIncludeFileOptzn; unsigned NumFrameworkLookups, NumSubFrameworkLookups; + bool EnabledModules; + // HeaderSearch doesn't support default or copy construction. HeaderSearch(const HeaderSearch&) LLVM_DELETED_FUNCTION; void operator=(const HeaderSearch&) LLVM_DELETED_FUNCTION; @@ -278,9 +296,7 @@ public: } /// \brief Checks whether the map exists or not. - bool HasIncludeAliasMap() const { - return IncludeAliases.isValid(); - } + bool HasIncludeAliasMap() const { return (bool)IncludeAliases; } /// \brief Map the source include name to the dest include name. /// @@ -347,13 +363,15 @@ public: /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member /// the file was found in, or null if not applicable. /// + /// \param IncludeLoc Used for diagnostics if valid. + /// /// \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. /// - /// \param CurFileEnt If non-null, indicates where the \#including file is, in - /// case a relative search is needed. + /// \param Includers Indicates where the \#including file(s) are, in case + /// relative searches are needed. In reverse order of inclusion. /// /// \param SearchPath If non-null, will be set to the search path relative /// to which the file was found. If the include path is absolute, SearchPath @@ -366,10 +384,10 @@ public: /// \param SuggestedModule If non-null, and the file found is semantically /// part of a known module, this will be set to the module that should /// be imported instead of preprocessing/parsing the file found. - const FileEntry *LookupFile(StringRef Filename, bool isAngled, - const DirectoryLookup *FromDir, + const FileEntry *LookupFile(StringRef Filename, SourceLocation IncludeLoc, + bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, - const FileEntry *CurFileEnt, + ArrayRef<const FileEntry *> Includers, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, ModuleMap::KnownHeader *SuggestedModule, @@ -458,6 +476,9 @@ public: /// FileEntry, uniquing them through the 'HeaderMaps' datastructure. const HeaderMap *CreateHeaderMap(const FileEntry *FE); + /// Returns true if modules are enabled. + bool enabledModules() const { return EnabledModules; } + /// \brief Retrieve the name of the module file that should be used to /// load the given module. /// @@ -472,9 +493,12 @@ public: /// /// \param ModuleName The module whose module file name will be returned. /// + /// \param ModuleMapPath A path that when combined with \c ModuleName + /// uniquely identifies this module. See Module::ModuleMap. + /// /// \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. - std::string getModuleFileName(StringRef ModuleName); + std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath); /// \brief Lookup a module Search for a module with the given name. /// @@ -486,11 +510,17 @@ public: /// /// \returns The module with the given name. Module *lookupModule(StringRef ModuleName, bool AllowSearch = true); + + /// \brief Try to find a module map file in the given directory, returning + /// \c nullptr if none is found. + const FileEntry *lookupModuleMapFile(const DirectoryEntry *Dir, + bool IsFramework); void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; } /// \brief Determine whether there is a module map that may map the header /// with the given file name to a (sub)module. + /// Always returns false if modules are disabled. /// /// \param Filename The name of the file. /// @@ -543,16 +573,20 @@ private: /// of the given search directory. void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir); + /// \brief Return the HeaderFileInfo structure for the specified FileEntry. + const HeaderFileInfo &getFileInfo(const FileEntry *FE) const { + return const_cast<HeaderSearch*>(this)->getFileInfo(FE); + } + public: /// \brief Retrieve the module map. ModuleMap &getModuleMap() { return ModMap; } unsigned header_file_size() const { return FileInfo.size(); } - /// \brief Return the HeaderFileInfo structure for the specified FileEntry. - const HeaderFileInfo &getFileInfo(const FileEntry *FE) const { - return const_cast<HeaderSearch*>(this)->getFileInfo(FE); - } + /// \brief Get a \c HeaderFileInfo structure for the specified \c FileEntry, + /// if one exists. + bool tryGetFileInfo(const FileEntry *FE, HeaderFileInfo &Result) const; // Used by external tools typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator; @@ -602,26 +636,32 @@ private: /// invalid. LMM_InvalidModuleMap }; - + + LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File, + bool IsSystem); + /// \brief Try to load the module map file in the given directory. /// /// \param DirName The name of the directory where we will look for a module /// map file. /// \param IsSystem Whether this is a system header directory. + /// \param IsFramework Whether this is a framework directory. /// /// \returns The result of attempting to load the module map file from the /// named directory. - LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem); + LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem, + bool IsFramework); /// \brief Try to load the module map file in the given directory. /// /// \param Dir The directory where we will look for a module map file. /// \param IsSystem Whether this is a system header directory. + /// \param IsFramework Whether this is a framework directory. /// /// \returns The result of attempting to load the module map file from the /// named directory. LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir, - bool IsSystem); + bool IsSystem, bool IsFramework); /// \brief Return the HeaderFileInfo structure for the specified FileEntry. HeaderFileInfo &getFileInfo(const FileEntry *FE); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h index 0b21c0d..06024b2 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h @@ -89,6 +89,9 @@ public: /// \brief The directory used for the module cache. std::string ModuleCachePath; + /// \brief The directory used for a user build. + std::string ModuleUserBuildPath; + /// \brief Whether we should disable the use of the hash string within the /// module cache. /// @@ -116,6 +119,12 @@ public: /// regenerated often. unsigned ModuleCachePruneAfter; + /// \brief The time in seconds when the build session started. + /// + /// This time is used by other optimizations in header search and module + /// loading. + uint64_t BuildSessionTimestamp; + /// \brief The set of macro names that should be ignored for the purposes /// of computing the module hash. llvm::SetVector<std::string> ModulesIgnoreMacros; @@ -123,6 +132,9 @@ public: /// \brief The set of user-provided module-map-files. llvm::SetVector<std::string> ModuleMapFiles; + /// \brief The set of user-provided virtual filesystem overlay files. + std::vector<std::string> VFSOverlayFiles; + /// Include the compiler builtin includes. unsigned UseBuiltinIncludes : 1; @@ -138,14 +150,25 @@ public: /// Whether header search information should be output as for -v. unsigned Verbose : 1; + /// \brief If true, skip verifying input files used by modules if the + /// module was already verified during this build session (see + /// \c BuildSessionTimestamp). + unsigned ModulesValidateOncePerBuildSession : 1; + + /// \brief Whether to validate system input files when a module is loaded. + unsigned ModulesValidateSystemHeaders : 1; + public: HeaderSearchOptions(StringRef _Sysroot = "/") : Sysroot(_Sysroot), DisableModuleHash(0), ModuleMaps(0), ModuleCachePruneInterval(7*24*60*60), ModuleCachePruneAfter(31*24*60*60), + BuildSessionTimestamp(0), UseBuiltinIncludes(true), UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), - UseLibcxx(false), Verbose(false) {} + UseLibcxx(false), Verbose(false), + ModulesValidateOncePerBuildSession(false), + ModulesValidateSystemHeaders(false) {} /// AddPath - Add the \p Path path to the specified \p Group list. void AddPath(StringRef Path, frontend::IncludeDirGroup Group, @@ -159,6 +182,10 @@ public: void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) { SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader)); } + + void AddVFSOverlayFile(StringRef Name) { + VFSOverlayFiles.push_back(Name); + } }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h index f456fa9..edcf883 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h @@ -44,7 +44,7 @@ enum ConflictMarkerKind { /// or buffering/seeking of tokens, only forward lexing is supported. It relies /// on the specified Preprocessor object to handle preprocessor directives, etc. class Lexer : public PreprocessorLexer { - virtual void anchor(); + void anchor() override; //===--------------------------------------------------------------------===// // Constant configuration values for this lexer. @@ -145,7 +145,7 @@ public: private: /// IndirectLex - An indirect call to 'Lex' that can be invoked via /// the PreprocessorLexer interface. - void IndirectLex(Token &Result) { Lex(Result); } + void IndirectLex(Token &Result) override { Lex(Result); } public: /// LexFromRawLexer - Lex a token from a designated raw lexer (one with no @@ -205,7 +205,7 @@ public: /// ReadToEndOfLine - Read the rest of the current preprocessor line as an /// uninterpreted string. This switches the lexer out of directive mode. - void ReadToEndOfLine(SmallVectorImpl<char> *Result = 0); + void ReadToEndOfLine(SmallVectorImpl<char> *Result = nullptr); /// Diag - Forwarding function for diagnostics. This translate a source @@ -218,7 +218,9 @@ public: /// getSourceLocation - Return a source location for the next character in /// the current file. - SourceLocation getSourceLocation() { return getSourceLocation(BufferPtr); } + SourceLocation getSourceLocation() override { + return getSourceLocation(BufferPtr); + } /// \brief Return the current location in the buffer. const char *getBufferLocation() const { return BufferPtr; } @@ -246,7 +248,7 @@ public: static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, - bool *Invalid = 0); + bool *Invalid = nullptr); /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a /// token is the characters used to represent the token in the source file @@ -256,7 +258,7 @@ public: static std::string getSpelling(const Token &Tok, const SourceManager &SourceMgr, const LangOptions &LangOpts, - bool *Invalid = 0); + bool *Invalid = nullptr); /// getSpelling - This method is used to get the spelling of the /// token at the given source location. If, as is usually true, it @@ -270,7 +272,7 @@ public: SmallVectorImpl<char> &buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, - bool *invalid = 0); + bool *invalid = nullptr); /// MeasureTokenLength - Relex the token at the specified location and return /// its length in bytes in the input file. If the token needs cleaning (e.g. @@ -329,7 +331,7 @@ public: static bool isAtStartOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, - SourceLocation *MacroBegin = 0); + SourceLocation *MacroBegin = nullptr); /// \brief Returns true if the given MacroID location points at the last /// token of the macro expansion. @@ -339,7 +341,7 @@ public: static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, - SourceLocation *MacroEnd = 0); + SourceLocation *MacroEnd = nullptr); /// \brief Accepts a range and returns a character range with file locations. /// @@ -375,7 +377,7 @@ public: static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, - bool *Invalid = 0); + bool *Invalid = nullptr); /// \brief Retrieve the name of the immediate macro expansion. /// @@ -546,7 +548,8 @@ private: /// getCharAndSizeSlow - Handle the slow/uncommon case of the getCharAndSize /// method. - char getCharAndSizeSlow(const char *Ptr, unsigned &Size, Token *Tok = 0); + char getCharAndSizeSlow(const char *Ptr, unsigned &Size, + Token *Tok = nullptr); /// getEscapedNewLineSize - Return the size of the specified escaped newline, /// or 0 if it is not an escaped newline. P[-1] is known to be a "\" on entry @@ -614,8 +617,28 @@ private: /// \return The Unicode codepoint specified by the UCN, or 0 if the UCN is /// invalid. uint32_t tryReadUCN(const char *&CurPtr, const char *SlashLoc, Token *Tok); -}; + /// \brief Try to consume a UCN as part of an identifier at the current + /// location. + /// \param CurPtr Initially points to the range of characters in the source + /// buffer containing the '\'. Updated to point past the end of + /// the UCN on success. + /// \param Size The number of characters occupied by the '\' (including + /// trigraphs and escaped newlines). + /// \param Result The token being produced. Marked as containing a UCN on + /// success. + /// \return \c true if a UCN was lexed and it produced an acceptable + /// identifier character, \c false otherwise. + bool tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size, + Token &Result); + + /// \brief Try to consume an identifier character encoded in UTF-8. + /// \param CurPtr Points to the start of the (potential) UTF-8 code unit + /// sequence. On success, updated to point past the end of it. + /// \return \c true if a UTF-8 sequence mapping to an acceptable identifier + /// character was lexed, \c false otherwise. + bool tryConsumeIdentifierUTF8Char(const char *&CurPtr); +}; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h index 64d5aa2..b7fcc5d 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h @@ -33,6 +33,9 @@ class TargetInfo; class SourceManager; class LangOptions; +/// Copy characters from Input to Buf, expanding any UCNs. +void expandUCNs(SmallVectorImpl<char> &Buf, StringRef Input); + /// NumericLiteralParser - This performs strict semantic analysis of the content /// of a ppnumber, classifying it as either integer, floating, or erroneous, /// determines the radix of the value and can convert it to a useful value. @@ -48,6 +51,8 @@ class NumericLiteralParser { bool saw_exponent, saw_period, saw_ud_suffix; + SmallString<32> UDSuffixBuf; + public: NumericLiteralParser(StringRef TokSpelling, SourceLocation TokLoc, @@ -58,7 +63,7 @@ public: bool isLongLong; bool isFloat; // 1.0f bool isImaginary; // 1.0i - bool isMicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. + uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. bool isIntegerLiteral() const { return !saw_period && !saw_exponent; @@ -72,7 +77,7 @@ public: } StringRef getUDSuffix() const { assert(saw_ud_suffix); - return StringRef(SuffixBegin, ThisTokEnd - SuffixBegin); + return UDSuffixBuf; } unsigned getUDSuffixOffset() const { assert(saw_ud_suffix); @@ -191,15 +196,16 @@ class StringLiteralParser { unsigned UDSuffixToken; unsigned UDSuffixOffset; public: - StringLiteralParser(const Token *StringToks, unsigned NumStringToks, + StringLiteralParser(ArrayRef<Token> StringToks, Preprocessor &PP, bool Complain = true); - StringLiteralParser(const Token *StringToks, unsigned NumStringToks, + StringLiteralParser(ArrayRef<Token> StringToks, const SourceManager &sm, const LangOptions &features, - const TargetInfo &target, DiagnosticsEngine *diags = 0) + const TargetInfo &target, + DiagnosticsEngine *diags = nullptr) : SM(sm), Features(features), Target(target), Diags(diags), MaxTokenLength(0), SizeBound(0), CharByteWidth(0), Kind(tok::unknown), ResultPtr(ResultBuf.data()), hadError(false), Pascal(false) { - init(StringToks, NumStringToks); + init(StringToks); } @@ -243,7 +249,7 @@ public: } private: - void init(const Token *StringToks, unsigned NumStringToks); + void init(ArrayRef<Token> StringToks); bool CopyStringFragment(const Token &Tok, const char *TokBegin, StringRef Fragment); void DiagnoseLexingError(SourceLocation Loc); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h index 1fd295e..4c0120c 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h @@ -52,9 +52,10 @@ class MacroArgs { /// ArgCache - This is a linked list of MacroArgs objects that the /// Preprocessor owns which we use to avoid thrashing malloc/free. MacroArgs *ArgCache; - + MacroArgs(unsigned NumToks, bool varargsElided) - : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided), ArgCache(0) {} + : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided), + ArgCache(nullptr) {} ~MacroArgs() {} public: /// MacroArgs ctor function - Create a new MacroArgs object with the specified diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h index 8cb370e..e9a66e8 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h @@ -21,7 +21,7 @@ #include <cassert> namespace clang { - class Preprocessor; +class Preprocessor; /// \brief Encapsulates the data about a macro definition (e.g. its tokens). /// @@ -104,8 +104,11 @@ private: /// \brief Whether this macro info was loaded from an AST file. unsigned FromASTFile : 1; + /// \brief Whether this macro was used as header guard. + bool UsedForHeaderGuard : 1; + ~MacroInfo() { - assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); + assert(!ArgumentList && "Didn't call destroy before dtor!"); } public: @@ -116,7 +119,7 @@ public: /// This restores this MacroInfo to a state where it can be reused for other /// devious purposes. void FreeArgumentList() { - ArgumentList = 0; + ArgumentList = nullptr; NumArguments = 0; } @@ -176,7 +179,7 @@ public: /// this macro. void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs, llvm::BumpPtrAllocator &PPAllocator) { - assert(ArgumentList == 0 && NumArguments == 0 && + assert(ArgumentList == nullptr && NumArguments == 0 && "Argument list already set!"); if (NumArgs == 0) return; @@ -282,6 +285,11 @@ public: /// a precompiled header or module) rather than having been parsed. bool isFromASTFile() const { return FromASTFile; } + /// \brief Determine whether this macro was used for a header guard. + bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; } + + void setUsedForHeaderGuard(bool Val) { UsedForHeaderGuard = Val; } + /// \brief Retrieve the global ID of the module that owns this particular /// macro info. unsigned getOwningModuleID() const { @@ -291,6 +299,8 @@ public: return 0; } + void dump() const; + private: unsigned getDefinitionLengthSlow(SourceManager &SM) const; @@ -338,12 +348,6 @@ protected: /// \brief True if the macro directive was loaded from a PCH file. bool IsFromPCH : 1; - /// \brief Whether the macro directive is currently "hidden". - /// - /// Note that this is transient state that is never serialized to the AST - /// file. - bool IsHidden : 1; - // Used by DefMacroDirective -----------------------------------------------// /// \brief True if this macro was imported from a module. @@ -360,10 +364,10 @@ protected: bool IsPublic : 1; MacroDirective(Kind K, SourceLocation Loc) - : Previous(0), Loc(Loc), MDKind(K), IsFromPCH(false), IsHidden(false), + : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false), IsImported(false), IsAmbiguous(false), IsPublic(true) { - } + } public: Kind getKind() const { return Kind(MDKind); } @@ -386,19 +390,13 @@ public: void setIsFromPCH() { IsFromPCH = true; } - /// \brief Determine whether this macro directive is hidden. - bool isHidden() const { return IsHidden; } - - /// \brief Set whether this macro directive is hidden. - void setHidden(bool Val) { IsHidden = Val; } - class DefInfo { DefMacroDirective *DefDirective; SourceLocation UndefLoc; bool IsPublic; public: - DefInfo() : DefDirective(0) { } + DefInfo() : DefDirective(nullptr) { } DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc, bool isPublic) @@ -418,42 +416,44 @@ public: bool isPublic() const { return IsPublic; } - bool isValid() const { return DefDirective != 0; } + bool isValid() const { return DefDirective != nullptr; } bool isInvalid() const { return !isValid(); } LLVM_EXPLICIT operator bool() const { return isValid(); } - inline DefInfo getPreviousDefinition(bool AllowHidden = false); - const DefInfo getPreviousDefinition(bool AllowHidden = false) const { - return const_cast<DefInfo*>(this)->getPreviousDefinition(AllowHidden); + inline DefInfo getPreviousDefinition(); + const DefInfo getPreviousDefinition() const { + return const_cast<DefInfo*>(this)->getPreviousDefinition(); } }; /// \brief Traverses the macro directives history and returns the next /// macro definition directive along with info about its undefined location /// (if there is one) and if it is public or private. - DefInfo getDefinition(bool AllowHidden = false); - const DefInfo getDefinition(bool AllowHidden = false) const { - return const_cast<MacroDirective*>(this)->getDefinition(AllowHidden); + DefInfo getDefinition(); + const DefInfo getDefinition() const { + return const_cast<MacroDirective*>(this)->getDefinition(); } - bool isDefined(bool AllowHidden = false) const { - if (const DefInfo Def = getDefinition(AllowHidden)) + bool isDefined() const { + if (const DefInfo Def = getDefinition()) return !Def.isUndefined(); return false; } - const MacroInfo *getMacroInfo(bool AllowHidden = false) const { - return getDefinition(AllowHidden).getMacroInfo(); + const MacroInfo *getMacroInfo() const { + return getDefinition().getMacroInfo(); } - MacroInfo *getMacroInfo(bool AllowHidden = false) { - return getDefinition(AllowHidden).getMacroInfo(); + MacroInfo *getMacroInfo() { + return getDefinition().getMacroInfo(); } /// \brief Find macro definition active in the specified source location. If /// this macro was not defined there, return NULL. const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const; + void dump() const; + static bool classof(const MacroDirective *) { return true; } }; @@ -533,15 +533,15 @@ inline SourceLocation MacroDirective::DefInfo::getLocation() const { inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() { if (isInvalid()) - return 0; + return nullptr; return DefDirective->getInfo(); } inline MacroDirective::DefInfo -MacroDirective::DefInfo::getPreviousDefinition(bool AllowHidden) { - if (isInvalid() || DefDirective->getPrevious() == 0) +MacroDirective::DefInfo::getPreviousDefinition() { + if (isInvalid() || DefDirective->getPrevious() == nullptr) return DefInfo(); - return DefDirective->getPrevious()->getDefinition(AllowHidden); + return DefDirective->getPrevious()->getDefinition(); } } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h index 254ab36..7869799 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h @@ -21,6 +21,7 @@ namespace clang { +class GlobalModuleIndex; class IdentifierInfo; class Module; @@ -53,11 +54,24 @@ public: /// for resolving a module name (e.g., "std") to an actual module file, and /// then loading that module. class ModuleLoader { + // Building a module if true. + bool BuildingModule; public: - ModuleLoader() : HadFatalFailure(false) {} + explicit ModuleLoader(bool BuildingModule = false) : + BuildingModule(BuildingModule), + HadFatalFailure(false) {} virtual ~ModuleLoader(); + /// \brief Returns true if this instance is building a module. + bool buildingModule() const { + return BuildingModule; + } + /// \brief Flag indicating whether this instance is building a module. + void setBuildingModule(bool BuildingModuleFlag) { + BuildingModule = BuildingModuleFlag; + } + /// \brief Attempt to load the given module. /// /// This routine attempts to load the module described by the given @@ -88,6 +102,26 @@ public: SourceLocation ImportLoc, bool Complain) = 0; + /// \brief Load, create, or return global module. + /// This function returns an existing global module index, if one + /// had already been loaded or created, or loads one if it + /// exists, or creates one if it doesn't exist. + /// Also, importantly, if the index doesn't cover all the modules + /// in the module map, it will be update to do so here, because + /// of its use in searching for needed module imports and + /// associated fixit messages. + /// \param TriggerLoc The location for what triggered the load. + /// \returns Returns null if load failed. + virtual GlobalModuleIndex *loadGlobalModuleIndex( + SourceLocation TriggerLoc) = 0; + + /// Check global module index for missing imports. + /// \param Name The symbol name to look for. + /// \param TriggerLoc The location for what triggered the load. + /// \returns Returns true if any modules with that symbol found. + virtual bool lookupMissingImports(StringRef Name, + SourceLocation TriggerLoc) = 0; + bool HadFatalFailure; }; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h index 3a17157..a86a927 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h @@ -38,7 +38,7 @@ class ModuleMapParser; class ModuleMap { SourceManager &SourceMgr; - IntrusiveRefCntPtr<DiagnosticsEngine> Diags; + DiagnosticsEngine &Diags; const LangOptions &LangOpts; const TargetInfo *Target; HeaderSearch &HeaderInfo; @@ -86,7 +86,7 @@ public: llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage; public: - KnownHeader() : Storage(0, NormalHeader) { } + KnownHeader() : Storage(nullptr, NormalHeader) { } KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { } /// \brief Retrieve the module the header is stored in. @@ -102,7 +102,9 @@ public: // \brief Whether this known header is valid (i.e., it has an // associated module). - LLVM_EXPLICIT operator bool() const { return Storage.getPointer() != 0; } + LLVM_EXPLICIT operator bool() const { + return Storage.getPointer() != nullptr; + } }; private: @@ -131,6 +133,10 @@ private: /// \brief Whether the modules we infer are [system] modules. unsigned InferSystemModules : 1; + /// \brief If \c InferModules is non-zero, the module map file that allowed + /// inferred modules. Otherwise, nullptr. + const FileEntry *ModuleMapFile; + /// \brief The names of modules that cannot be inferred within this /// directory. SmallVector<std::string, 2> ExcludedModules; @@ -175,6 +181,29 @@ private: /// resolved. Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const; + /// \brief Looks up the modules that \p File corresponds to. + /// + /// If \p File represents a builtin header within Clang's builtin include + /// directory, this also loads all of the module maps to see if it will get + /// associated with a specific module (e.g. in /usr/include). + HeadersMap::iterator findKnownHeader(const FileEntry *File); + + /// \brief Searches for a module whose umbrella directory contains \p File. + /// + /// \param File The header to search for. + /// + /// \param IntermediateDirs On success, contains the set of directories + /// searched before finding \p File. + KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File, + SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs); + + /// \brief A convenience method to determine if \p File is (possibly nested) + /// in an umbrella directory. + bool isHeaderInUmbrellaDirs(const FileEntry *File) { + SmallVector<const DirectoryEntry *, 2> IntermediateDirs; + return static_cast<bool>(findHeaderInUmbrellaDirs(File, IntermediateDirs)); + } + public: /// \brief Construct a new module map. /// @@ -182,13 +211,12 @@ public: /// This source manager should be shared with the header-search mechanism, /// since they will refer to the same headers. /// - /// \param DC A diagnostic consumer that will be cloned for use in generating - /// diagnostics. + /// \param Diags A diagnostic engine used for diagnostics. /// /// \param LangOpts Language options for this translation unit. /// /// \param Target The target for this translation unit. - ModuleMap(SourceManager &SourceMgr, DiagnosticConsumer &DC, + ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target, HeaderSearch &HeaderInfo); @@ -217,12 +245,30 @@ public: /// given header file. The KnownHeader is default constructed to indicate /// that no module owns this header file. KnownHeader findModuleForHeader(const FileEntry *File, - Module *RequestingModule = NULL); + Module *RequestingModule = nullptr); + + /// \brief Reports errors if a module must not include a specific file. + /// + /// \param RequestingModule The module including a file. + /// + /// \param FilenameLoc The location of the inclusion's filename. + /// + /// \param Filename The included filename as written. + /// + /// \param File The included file. + void diagnoseHeaderInclusion(Module *RequestingModule, + SourceLocation FilenameLoc, StringRef Filename, + const FileEntry *File); /// \brief Determine whether the given header is part of a module /// marked 'unavailable'. bool isHeaderInUnavailableModule(const FileEntry *Header) const; + /// \brief Determine whether the given header is unavailable as part + /// of the specified module. + bool isHeaderUnavailableInModule(const FileEntry *Header, + const Module *RequestingModule) const; + /// \brief Retrieve a module with the given name. /// /// \param Name The name of the module to look up. @@ -260,13 +306,17 @@ public: /// \param Parent The module that will act as the parent of this submodule, /// or NULL to indicate that this is a top-level module. /// + /// \param ModuleMap The module map that defines or allows the inference of + /// this module. + /// /// \param IsFramework Whether this is a framework module. /// /// \param IsExplicit Whether this is an explicit submodule. /// /// \returns The found or newly-created module, along with a boolean value /// that will be true if the module is newly-created. - std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent, + std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent, + const FileEntry *ModuleMap, bool IsFramework, bool IsExplicit); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h index b532bf8..e3c6de5 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h @@ -60,8 +60,8 @@ public: ReadAnyTokens = false; ImmediatelyAfterTopLevelIfndef = false; DidMacroExpansion = false; - TheMacro = 0; - DefinedMacro = 0; + TheMacro = nullptr; + DefinedMacro = nullptr; } SourceLocation GetMacroLocation() const { @@ -88,8 +88,8 @@ public: // below can never "accept". ReadAnyTokens = true; ImmediatelyAfterTopLevelIfndef = false; - DefinedMacro = 0; - TheMacro = 0; + DefinedMacro = nullptr; + TheMacro = nullptr; } /// getHasReadAnyTokensVal - This is used for the \#ifndef hande-shake at the @@ -166,7 +166,7 @@ public: // macro if it's valid (if it isn't, it will be null). if (!ReadAnyTokens) return TheMacro; - return 0; + return nullptr; } /// \brief If the ControllingMacro is followed by a macro definition, return diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h index 0e11218..7f1ea34 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h @@ -214,8 +214,7 @@ public: /// \brief Callback invoked when a \#pragma gcc dianostic directive is read. virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, - diag::Mapping mapping, StringRef Str) { - } + diag::Severity mapping, StringRef Str) {} /// \brief Called when an OpenCL extension is either disabled or /// enabled with a pragma. @@ -267,6 +266,10 @@ public: virtual void SourceRangeSkipped(SourceRange Range) { } + enum ConditionValueKind { + CVK_NotEvaluated, CVK_False, CVK_True + }; + /// \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. @@ -274,7 +277,7 @@ public: /// // FIXME: better to pass in a list (or tree!) of Tokens. virtual void If(SourceLocation Loc, SourceRange ConditionRange, - bool ConditionValue) { + ConditionValueKind ConditionValue) { } /// \brief Hook called whenever an \#elif is seen. @@ -284,7 +287,7 @@ public: /// \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, - bool ConditionValue, SourceLocation IfLoc) { + ConditionValueKind ConditionValue, SourceLocation IfLoc) { } /// \brief Hook called whenever an \#ifdef is seen. @@ -329,35 +332,31 @@ public: delete First; } - virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) { + void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID) override { First->FileChanged(Loc, Reason, FileType, PrevFID); Second->FileChanged(Loc, Reason, FileType, PrevFID); } - virtual void FileSkipped(const FileEntry &ParentFile, - const Token &FilenameTok, - SrcMgr::CharacteristicKind FileType) { + void FileSkipped(const FileEntry &ParentFile, + const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) override { First->FileSkipped(ParentFile, FilenameTok, FileType); Second->FileSkipped(ParentFile, FilenameTok, FileType); } - virtual bool FileNotFound(StringRef FileName, - SmallVectorImpl<char> &RecoveryPath) { + bool FileNotFound(StringRef FileName, + SmallVectorImpl<char> &RecoveryPath) override { return First->FileNotFound(FileName, RecoveryPath) || Second->FileNotFound(FileName, RecoveryPath); } - virtual void InclusionDirective(SourceLocation HashLoc, - const Token &IncludeTok, - StringRef FileName, - bool IsAngled, - CharSourceRange FilenameRange, - const FileEntry *File, - StringRef SearchPath, - StringRef RelativePath, - const Module *Imported) { + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, + StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, + StringRef SearchPath, StringRef RelativePath, + const Module *Imported) override { First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, FilenameRange, File, SearchPath, RelativePath, Imported); @@ -366,147 +365,142 @@ public: Imported); } - virtual void moduleImport(SourceLocation ImportLoc, - ModuleIdPath Path, - const Module *Imported) { + void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, + const Module *Imported) override { First->moduleImport(ImportLoc, Path, Imported); Second->moduleImport(ImportLoc, Path, Imported); } - virtual void EndOfMainFile() { + void EndOfMainFile() override { First->EndOfMainFile(); Second->EndOfMainFile(); } - virtual void Ident(SourceLocation Loc, const std::string &str) { + void Ident(SourceLocation Loc, const std::string &str) override { First->Ident(Loc, str); Second->Ident(Loc, str); } - virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, - const std::string &Str) { + void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, + const std::string &Str) override { First->PragmaComment(Loc, Kind, Str); Second->PragmaComment(Loc, Kind, Str); } - virtual void PragmaDetectMismatch(SourceLocation Loc, - const std::string &Name, - const std::string &Value) { + void PragmaDetectMismatch(SourceLocation Loc, const std::string &Name, + const std::string &Value) override { First->PragmaDetectMismatch(Loc, Name, Value); Second->PragmaDetectMismatch(Loc, Name, Value); } - virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace, - PragmaMessageKind Kind, StringRef Str) { + void PragmaMessage(SourceLocation Loc, StringRef Namespace, + PragmaMessageKind Kind, StringRef Str) override { First->PragmaMessage(Loc, Namespace, Kind, Str); Second->PragmaMessage(Loc, Namespace, Kind, Str); } - virtual void PragmaDiagnosticPush(SourceLocation Loc, - StringRef Namespace) { + void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override { First->PragmaDiagnosticPush(Loc, Namespace); Second->PragmaDiagnosticPush(Loc, Namespace); } - virtual void PragmaDiagnosticPop(SourceLocation Loc, - StringRef Namespace) { + void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override { First->PragmaDiagnosticPop(Loc, Namespace); Second->PragmaDiagnosticPop(Loc, Namespace); } - virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, - diag::Mapping mapping, StringRef Str) { + void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, + diag::Severity mapping, StringRef Str) override { First->PragmaDiagnostic(Loc, Namespace, mapping, Str); Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); } - virtual void PragmaOpenCLExtension(SourceLocation NameLoc, - const IdentifierInfo *Name, - SourceLocation StateLoc, unsigned State) { + void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name, + SourceLocation StateLoc, unsigned State) override { First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State); Second->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State); } - virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, - ArrayRef<int> Ids) { + void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, + ArrayRef<int> Ids) override { First->PragmaWarning(Loc, WarningSpec, Ids); Second->PragmaWarning(Loc, WarningSpec, Ids); } - virtual void PragmaWarningPush(SourceLocation Loc, int Level) { + void PragmaWarningPush(SourceLocation Loc, int Level) override { First->PragmaWarningPush(Loc, Level); Second->PragmaWarningPush(Loc, Level); } - virtual void PragmaWarningPop(SourceLocation Loc) { + void PragmaWarningPop(SourceLocation Loc) override { First->PragmaWarningPop(Loc); Second->PragmaWarningPop(Loc); } - virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD, - SourceRange Range, const MacroArgs *Args) { + void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD, + SourceRange Range, const MacroArgs *Args) override { First->MacroExpands(MacroNameTok, MD, Range, Args); Second->MacroExpands(MacroNameTok, MD, Range, Args); } - virtual void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) { + void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override { First->MacroDefined(MacroNameTok, MD); Second->MacroDefined(MacroNameTok, MD); } - virtual void MacroUndefined(const Token &MacroNameTok, - const MacroDirective *MD) { + void MacroUndefined(const Token &MacroNameTok, + const MacroDirective *MD) override { First->MacroUndefined(MacroNameTok, MD); Second->MacroUndefined(MacroNameTok, MD); } - virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD, - SourceRange Range) { + void Defined(const Token &MacroNameTok, const MacroDirective *MD, + SourceRange Range) override { First->Defined(MacroNameTok, MD, Range); Second->Defined(MacroNameTok, MD, Range); } - virtual void SourceRangeSkipped(SourceRange Range) { + void SourceRangeSkipped(SourceRange Range) override { First->SourceRangeSkipped(Range); Second->SourceRangeSkipped(Range); } /// \brief Hook called whenever an \#if is seen. - virtual void If(SourceLocation Loc, SourceRange ConditionRange, - bool ConditionValue) { + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind ConditionValue) override { First->If(Loc, ConditionRange, ConditionValue); Second->If(Loc, ConditionRange, ConditionValue); } /// \brief Hook called whenever an \#elif is seen. - virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, - bool ConditionValue, SourceLocation IfLoc) { + void Elif(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind ConditionValue, SourceLocation IfLoc) override { First->Elif(Loc, ConditionRange, ConditionValue, IfLoc); Second->Elif(Loc, ConditionRange, ConditionValue, IfLoc); } /// \brief Hook called whenever an \#ifdef is seen. - virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDirective *MD) { + void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) override { First->Ifdef(Loc, MacroNameTok, MD); Second->Ifdef(Loc, MacroNameTok, MD); } /// \brief Hook called whenever an \#ifndef is seen. - virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDirective *MD) { + void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) override { First->Ifndef(Loc, MacroNameTok, MD); Second->Ifndef(Loc, MacroNameTok, MD); } /// \brief Hook called whenever an \#else is seen. - virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { + void Else(SourceLocation Loc, SourceLocation IfLoc) override { First->Else(Loc, IfLoc); Second->Else(Loc, IfLoc); } /// \brief Hook called whenever an \#endif is seen. - virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { + void Endif(SourceLocation Loc, SourceLocation IfLoc) override { First->Endif(Loc, IfLoc); Second->Endif(Loc, IfLoc); } diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h index 54a132d..00d2d57 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h @@ -86,16 +86,16 @@ public: SourceLocation findConditionalDirectiveRegionLoc(SourceLocation Loc) const; private: - virtual void If(SourceLocation Loc, SourceRange ConditionRange, - bool ConditionValue); - virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, - bool ConditionValue, SourceLocation IfLoc); - virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDirective *MD); - virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDirective *MD); - virtual void Else(SourceLocation Loc, SourceLocation IfLoc); - virtual void Endif(SourceLocation Loc, SourceLocation IfLoc); + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind ConditionValue) override; + void Elif(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind ConditionValue, SourceLocation IfLoc) override; + void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) override; + void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) override; + void Else(SourceLocation Loc, SourceLocation IfLoc) override; + void Endif(SourceLocation Loc, SourceLocation IfLoc) override; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h index d748bc1..2352cce 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h @@ -90,11 +90,11 @@ public: /// IndirectLex - An indirect call to 'Lex' that can be invoked via /// the PreprocessorLexer interface. - void IndirectLex(Token &Result) { Lex(Result); } + void IndirectLex(Token &Result) override { Lex(Result); } /// getSourceLocation - Return a source location for the token in /// the current file. - SourceLocation getSourceLocation(); + SourceLocation getSourceLocation() override; /// SkipBlock - Used by Preprocessor to skip the current conditional block. bool SkipBlock(); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h index fad0806..11b5cea 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h @@ -114,7 +114,7 @@ public: /// Unlike the version in IdentifierTable, this returns a pointer instead /// of a reference. If the pointer is NULL then the IdentifierInfo cannot /// be found. - IdentifierInfo *get(StringRef Name); + IdentifierInfo *get(StringRef Name) override; /// Create - This method creates PTHManager objects. The 'file' argument /// is the name of the PTH file. This method returns NULL upon failure. diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h index 087448f..4a695a0 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h @@ -69,7 +69,7 @@ public: /// getIfNamespace - If this is a namespace, return it. This is equivalent to /// using a dynamic_cast, but doesn't require RTTI. - virtual PragmaNamespace *getIfNamespace() { return 0; } + virtual PragmaNamespace *getIfNamespace() { return nullptr; } }; /// EmptyPragmaHandler - A pragma handler which takes no action, which can be @@ -78,8 +78,8 @@ class EmptyPragmaHandler : public PragmaHandler { public: EmptyPragmaHandler(); - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; }; /// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas, @@ -114,10 +114,10 @@ public: return Handlers.empty(); } - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; - virtual PragmaNamespace *getIfNamespace() { return this; } + PragmaNamespace *getIfNamespace() override { return this; } }; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h index 2584340..4609fe3 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h @@ -304,6 +304,9 @@ namespace clang { /// and are referenced by the iterator using negative indices. std::vector<PreprocessedEntity *> LoadedPreprocessedEntities; + /// \brief The set of ranges that were skipped by the preprocessor, + std::vector<SourceRange> SkippedRanges; + /// \brief Global (loaded or local) ID for a preprocessed entity. /// Negative values are used to indicate preprocessed entities /// loaded from the external source while non-negative values are used to @@ -400,7 +403,7 @@ namespace clang { typedef std::random_access_iterator_tag iterator_category; typedef int difference_type; - iterator() : Self(0), Position(0) { } + iterator() : Self(nullptr), Position(0) { } iterator(PreprocessingRecord *Self, int Position) : Self(Self), Position(Position) { } @@ -556,28 +559,32 @@ namespace clang { /// \brief Retrieve the macro definition that corresponds to the given /// \c MacroInfo. MacroDefinition *findMacroDefinition(const MacroInfo *MI); + + /// \brief Retrieve all ranges that got skipped while preprocessing. + const std::vector<SourceRange> &getSkippedRanges() const { + return SkippedRanges; + } private: - virtual void MacroExpands(const Token &Id, const MacroDirective *MD, - SourceRange Range, const MacroArgs *Args); - virtual void MacroDefined(const Token &Id, const MacroDirective *MD); - virtual void MacroUndefined(const Token &Id, const MacroDirective *MD); - virtual void InclusionDirective(SourceLocation HashLoc, - const Token &IncludeTok, - StringRef FileName, - bool IsAngled, - CharSourceRange FilenameRange, - const FileEntry *File, - StringRef SearchPath, - StringRef RelativePath, - const Module *Imported); - virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDirective *MD); - virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDirective *MD); + void MacroExpands(const Token &Id, const MacroDirective *MD, + SourceRange Range, const MacroArgs *Args) override; + void MacroDefined(const Token &Id, const MacroDirective *MD) override; + void MacroUndefined(const Token &Id, const MacroDirective *MD) override; + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, + StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, + const FileEntry *File, StringRef SearchPath, + StringRef RelativePath, + const Module *Imported) override; + void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) override; + void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) override; /// \brief Hook called whenever the 'defined' operator is seen. - virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD, - SourceRange Range); + void Defined(const Token &MacroNameTok, const MacroDirective *MD, + SourceRange Range) override; + + void SourceRangeSkipped(SourceRange Range) override; void addMacroExpansion(const Token &Id, const MacroInfo *MI, SourceRange Range); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h index 223fd47..d4b4ba2 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the Preprocessor interface. -// +/// +/// \file +/// \brief Defines the clang::Preprocessor interface. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LEX_PREPROCESSOR_H @@ -28,10 +29,10 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" +#include <memory> #include <vector> namespace llvm { @@ -64,7 +65,7 @@ class TokenValue { IdentifierInfo *II; public: - TokenValue(tok::TokenKind Kind) : Kind(Kind), II(0) { + TokenValue(tok::TokenKind Kind) : Kind(Kind), II(nullptr) { assert(Kind != tok::raw_identifier && "Raw identifiers are not supported."); assert(Kind != tok::identifier && "Identifiers should be created by TokenValue(IdentifierInfo *)"); @@ -78,11 +79,12 @@ public: } }; -/// 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. +/// \brief 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. class Preprocessor : public RefCountedBase<Preprocessor> { IntrusiveRefCntPtr<PreprocessorOptions> PPOpts; DiagnosticsEngine *Diags; @@ -98,12 +100,12 @@ class Preprocessor : public RefCountedBase<Preprocessor> { ExternalPreprocessorSource *ExternalSource; - /// PTH - An optional PTHManager object used for getting tokens from - /// a token cache rather than lexing the original source file. - OwningPtr<PTHManager> PTH; + /// An optional PTHManager object used for getting tokens from + /// a token cache rather than lexing the original source file. + std::unique_ptr<PTHManager> PTH; - /// BP - A BumpPtrAllocator object used to quickly allocate and release - /// objects internal to the Preprocessor. + /// A BumpPtrAllocator object used to quickly allocate and release + /// objects internal to the Preprocessor. llvm::BumpPtrAllocator BP; /// Identifiers for builtin macros and other builtins. @@ -114,6 +116,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__ IdentifierInfo *Ident__COUNTER__; // __COUNTER__ IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma + IdentifierInfo *Ident__identifier; // __identifier IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_extension; // __has_extension @@ -122,6 +125,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { IdentifierInfo *Ident__has_include; // __has_include IdentifierInfo *Ident__has_include_next; // __has_include_next IdentifierInfo *Ident__has_warning; // __has_warning + IdentifierInfo *Ident__is_identifier; // __is_identifier IdentifierInfo *Ident__building_module; // __building_module IdentifierInfo *Ident__MODULE__; // __MODULE__ @@ -129,7 +133,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { unsigned CounterValue; // Next __COUNTER__ value. enum { - /// MaxIncludeStackDepth - Maximum depth of \#includes. + /// \brief Maximum depth of \#includes. MaxAllowedIncludeStackDepth = 200 }; @@ -144,12 +148,11 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// Whether the preprocessor owns the header search object. bool OwnsHeaderSearch : 1; - /// DisableMacroExpansion - True if macro expansion is disabled. + /// True if macro expansion is disabled. bool DisableMacroExpansion : 1; - /// MacroExpansionInDirectivesOverride - Temporarily disables - /// DisableMacroExpansion (i.e. enables expansion) when parsing preprocessor - /// directives. + /// Temporarily disables DisableMacroExpansion (i.e. enables expansion) + /// when parsing preprocessor directives. bool MacroExpansionInDirectivesOverride : 1; class ResetMacroExpansionHelper; @@ -169,23 +172,25 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief True if we are pre-expanding macro arguments. bool InMacroArgPreExpansion; - /// Identifiers - This is mapping/lookup information for all identifiers in + /// \brief Mapping/lookup information for all identifiers in /// the program, including program keywords. mutable IdentifierTable Identifiers; - /// Selectors - This table contains all the selectors in the program. Unlike - /// IdentifierTable above, this table *isn't* populated by the preprocessor. - /// It is declared/expanded here because it's role/lifetime is - /// conceptually similar the IdentifierTable. In addition, the current control - /// flow (in clang::ParseAST()), make it convenient to put here. + /// \brief This table contains all the selectors in the program. + /// + /// Unlike IdentifierTable above, this table *isn't* populated by the + /// preprocessor. It is declared/expanded here because its role/lifetime is + /// conceptually similar to the IdentifierTable. In addition, the current + /// control flow (in clang::ParseAST()), make it convenient to put here. + /// /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to /// the lifetime of the preprocessor. SelectorTable Selectors; - /// BuiltinInfo - Information about builtins. + /// \brief Information about builtins. Builtin::Context BuiltinInfo; - /// PragmaHandlers - This tracks all of the pragmas that the client registered + /// \brief Tracks all of the pragmas that the client registered /// with this preprocessor. PragmaNamespace *PragmaHandlers; @@ -197,6 +202,9 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// avoid tearing the Lexer and etc. down). bool IncrementalProcessing; + /// The kind of translation unit we are processing. + TranslationUnitKind TUKind; + /// \brief The code-completion handler. CodeCompletionHandler *CodeComplete; @@ -216,7 +224,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// for preprocessing. SourceLocation CodeCompletionFileLoc; - /// \brief The source location of the 'import' contextual keyword we just + /// \brief The source location of the \c import contextual keyword we just /// lexed, if any. SourceLocation ModuleImportLoc; @@ -226,46 +234,53 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief Whether the last token we lexed was an '@'. bool LastTokenWasAt; - /// \brief Whether the module import expectes an identifier next. Otherwise, + /// \brief Whether the module import expects an identifier next. Otherwise, /// it expects a '.' or ';'. bool ModuleImportExpectsIdentifier; /// \brief The source location of the currently-active - /// #pragma clang arc_cf_code_audited begin. + /// \#pragma clang arc_cf_code_audited begin. SourceLocation PragmaARCCFCodeAuditedLoc; /// \brief True if we hit the code-completion point. bool CodeCompletionReached; /// \brief The number of bytes that we will initially skip when entering the - /// main file, which is used when loading a precompiled preamble, along - /// with a flag that indicates whether skipping this number of bytes will - /// place the lexer at the start of a line. + /// main file, along with a flag that indicates whether skipping this number + /// of bytes will place the lexer at the start of a line. + /// + /// This is used when loading a precompiled preamble. std::pair<unsigned, bool> SkipMainFilePreamble; - /// CurLexer - This is the current top of the stack that we're lexing from if + /// \brief The current top of the stack that we're lexing from if /// not expanding a macro and we are lexing directly from source code. - /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. - OwningPtr<Lexer> CurLexer; + /// + /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. + std::unique_ptr<Lexer> CurLexer; - /// CurPTHLexer - This is the current top of stack that we're lexing from if - /// not expanding from a macro and we are lexing from a PTH cache. - /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. - OwningPtr<PTHLexer> CurPTHLexer; + /// \brief The current top of stack that we're lexing from if + /// not expanding from a macro and we are lexing from a PTH cache. + /// + /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. + std::unique_ptr<PTHLexer> CurPTHLexer; - /// CurPPLexer - This is the current top of the stack what we're lexing from - /// if not expanding a macro. This is an alias for either CurLexer or - /// CurPTHLexer. + /// \brief The current top of the stack what we're lexing from + /// if not expanding a macro. + /// + /// This is an alias for either CurLexer or CurPTHLexer. PreprocessorLexer *CurPPLexer; - /// 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. + /// \brief 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. const DirectoryLookup *CurDirLookup; - /// CurTokenLexer - This is the current macro we are expanding, if we are - /// expanding a macro. One of CurLexer and CurTokenLexer must be null. - OwningPtr<TokenLexer> CurTokenLexer; + /// \brief The current macro we are expanding, if we are expanding a macro. + /// + /// One of CurLexer and CurTokenLexer must be null. + std::unique_ptr<TokenLexer> CurTokenLexer; /// \brief The kind of lexer we're currently working with. enum CurLexerKind { @@ -276,26 +291,48 @@ class Preprocessor : public RefCountedBase<Preprocessor> { CLK_LexAfterModuleImport } CurLexerKind; - /// IncludeMacroStack - This keeps track of the stack of files currently + /// \brief If the current lexer is for a submodule that is being built, this + /// is that submodule. + Module *CurSubmodule; + + /// \brief Keeps track of the stack of files currently /// \#included, and macros currently being expanded from, not counting /// CurLexer/CurTokenLexer. struct IncludeStackInfo { - enum CurLexerKind CurLexerKind; - Lexer *TheLexer; - PTHLexer *ThePTHLexer; - PreprocessorLexer *ThePPLexer; - TokenLexer *TheTokenLexer; - const DirectoryLookup *TheDirLookup; - - IncludeStackInfo(enum CurLexerKind K, Lexer *L, PTHLexer* P, - PreprocessorLexer* PPL, - TokenLexer* TL, const DirectoryLookup *D) - : CurLexerKind(K), TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), - TheTokenLexer(TL), TheDirLookup(D) {} + enum CurLexerKind CurLexerKind; + Module *TheSubmodule; + std::unique_ptr<Lexer> TheLexer; + std::unique_ptr<PTHLexer> ThePTHLexer; + PreprocessorLexer *ThePPLexer; + std::unique_ptr<TokenLexer> TheTokenLexer; + const DirectoryLookup *TheDirLookup; + + // The following constructors are completely useless copies of the default + // versions, only needed to pacify MSVC. + IncludeStackInfo(enum CurLexerKind CurLexerKind, Module *TheSubmodule, + std::unique_ptr<Lexer> &&TheLexer, + std::unique_ptr<PTHLexer> &&ThePTHLexer, + PreprocessorLexer *ThePPLexer, + std::unique_ptr<TokenLexer> &&TheTokenLexer, + const DirectoryLookup *TheDirLookup) + : CurLexerKind(std::move(CurLexerKind)), + TheSubmodule(std::move(TheSubmodule)), TheLexer(std::move(TheLexer)), + ThePTHLexer(std::move(ThePTHLexer)), + ThePPLexer(std::move(ThePPLexer)), + TheTokenLexer(std::move(TheTokenLexer)), + TheDirLookup(std::move(TheDirLookup)) {} + IncludeStackInfo(IncludeStackInfo &&RHS) + : CurLexerKind(std::move(RHS.CurLexerKind)), + TheSubmodule(std::move(RHS.TheSubmodule)), + TheLexer(std::move(RHS.TheLexer)), + ThePTHLexer(std::move(RHS.ThePTHLexer)), + ThePPLexer(std::move(RHS.ThePPLexer)), + TheTokenLexer(std::move(RHS.TheTokenLexer)), + TheDirLookup(std::move(RHS.TheDirLookup)) {} }; std::vector<IncludeStackInfo> IncludeMacroStack; - /// Callbacks - These are actions invoked when some preprocessor activity is + /// \brief Actions invoked when some preprocessor activity is /// encountered (e.g. a file is \#included, etc). PPCallbacks *Callbacks; @@ -308,14 +345,16 @@ class Preprocessor : public RefCountedBase<Preprocessor> { }; SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks; - /// Macros - For each IdentifierInfo that was associated with a macro, we + /// For each IdentifierInfo that was associated with a macro, we /// keep a mapping to the history of all macro definitions and #undefs in /// the reverse order (the latest one is in the head of the list). llvm::DenseMap<const IdentifierInfo*, MacroDirective*> Macros; friend class ASTReader; /// \brief Macros that we want to warn because they are not used at the end - /// of the translation unit; we store just their SourceLocations instead + /// of the translation unit. + /// + /// We store just their SourceLocations instead of /// something like MacroInfo*. The benefit of this is that when we are /// deserializing from PCH, we don't need to deserialize identifier & macros /// just so that we can report that they are unused, we just warn using @@ -324,35 +363,36 @@ class Preprocessor : public RefCountedBase<Preprocessor> { typedef llvm::SmallPtrSet<SourceLocation, 32> WarnUnusedMacroLocsTy; WarnUnusedMacroLocsTy WarnUnusedMacroLocs; - /// MacroArgCache - This is a "freelist" of MacroArg objects that can be + /// \brief A "freelist" of MacroArg objects that can be /// reused for quick allocation. MacroArgs *MacroArgCache; friend class MacroArgs; - /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma - /// push_macro directive, we keep a MacroInfo stack used to restore - /// previous macro value. + /// For each IdentifierInfo used in a \#pragma push_macro directive, + /// we keep a MacroInfo stack used to restore the previous macro value. llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo; // Various statistics we track for performance analysis. - unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma; + unsigned NumDirectives, NumDefined, NumUndefined, NumPragma; unsigned NumIf, NumElse, NumEndif; unsigned NumEnteredSourceFiles, MaxIncludeStackDepth; unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded; unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste; unsigned NumSkipped; - /// Predefines - This string is the predefined macros that preprocessor - /// should use from the command line etc. + /// \brief The predefined macros that preprocessor should use from the + /// command line etc. std::string Predefines; /// \brief The file ID for the preprocessor predefines. FileID PredefinesFileID; - /// TokenLexerCache - Cache macro expanders to reduce malloc traffic. + /// \{ + /// \brief Cache of macro expanders to reduce malloc traffic. enum { TokenLexerCacheSize = 8 }; unsigned NumCachedTokenLexers; TokenLexer *TokenLexerCache[TokenLexerCacheSize]; + /// \} /// \brief Keeps macro expanded tokens for TokenLexers. // @@ -372,17 +412,20 @@ class Preprocessor : public RefCountedBase<Preprocessor> { private: // Cached tokens state. typedef SmallVector<Token, 1> CachedTokensTy; - /// CachedTokens - Cached tokens are stored here when we do backtracking or + /// \brief Cached tokens are stored here when we do backtracking or /// lookahead. They are "lexed" by the CachingLex() method. CachedTokensTy CachedTokens; - /// CachedLexPos - The position of the cached token that CachingLex() should - /// "lex" next. If it points beyond the CachedTokens vector, it means that - /// a normal Lex() should be invoked. + /// \brief The position of the cached token that CachingLex() should + /// "lex" next. + /// + /// If it points beyond the CachedTokens vector, it means that a normal + /// Lex() should be invoked. CachedTokensTy::size_type CachedLexPos; - /// BacktrackPositions - Stack of backtrack positions, allowing nested - /// backtracks. The EnableBacktrackAtThisPos() method pushes a position to + /// \brief Stack of backtrack positions, allowing nested backtracks. + /// + /// The EnableBacktrackAtThisPos() method pushes a position to /// indicate where CachedLexPos should be set when the BackTrack() method is /// invoked (at which point the last position is popped). std::vector<CachedTokensTy::size_type> BacktrackPositions; @@ -397,7 +440,7 @@ private: // Cached tokens state. /// of that list. MacroInfoChain *MIChainHead; - /// MICache - A "freelist" of MacroInfo objects that can be reused for quick + /// A "freelist" of MacroInfo objects that can be reused for quick /// allocation. MacroInfoChain *MICache; @@ -412,20 +455,18 @@ private: // Cached tokens state. public: Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, DiagnosticsEngine &diags, LangOptions &opts, - const TargetInfo *target, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, - IdentifierInfoLookup *IILookup = 0, + IdentifierInfoLookup *IILookup = nullptr, bool OwnsHeaderSearch = false, - bool DelayInitialization = false, - bool IncrProcessing = false); + TranslationUnitKind TUKind = TU_Complete); ~Preprocessor(); - /// \brief Initialize the preprocessor, if the constructor did not already - /// perform the initialization. + /// \brief Initialize the preprocessor using information about the target. /// - /// \param Target Information about the target. + /// \param Target is owned by the caller and must remain valid for the + /// lifetime of the preprocessor. void Initialize(const TargetInfo &Target); /// \brief Retrieve the preprocessor options used to initialize this @@ -470,8 +511,7 @@ public: return ParsingIfOrElifDirective; } - /// SetCommentRetentionState - Control whether or not the preprocessor retains - /// comments in output. + /// \brief Control whether the preprocessor retains comments in output. void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) { this->KeepComments = KeepComments | KeepMacroComments; this->KeepMacroComments = KeepMacroComments; @@ -500,26 +540,29 @@ public: /// false if it is producing tokens to be consumed by Parse and Sema. bool isPreprocessedOutput() const { return PreprocessedOutput; } - /// isCurrentLexer - Return true if we are lexing directly from the specified - /// lexer. + /// \brief Return true if we are lexing directly from the specified lexer. bool isCurrentLexer(const PreprocessorLexer *L) const { return CurPPLexer == L; } - /// getCurrentLexer - Return the current lexer being lexed from. Note - /// that this ignores any potentially active macro expansions and _Pragma + /// \brief Return the current lexer being lexed from. + /// + /// Note that this ignores any potentially active macro expansions and _Pragma /// expansions going on at the time. PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; } - /// getCurrentFileLexer - Return the current file lexer being lexed from. + /// \brief Return the current file lexer being lexed from. + /// /// Note that this ignores any potentially active macro expansions and _Pragma /// expansions going on at the time. PreprocessorLexer *getCurrentFileLexer() const; - /// \brief Returns the file ID for the preprocessor predefines. + /// \brief Returns the FileID for the preprocessor predefines. FileID getPredefinesFileID() const { return PredefinesFileID; } - /// getPPCallbacks/addPPCallbacks - Accessors for preprocessor callbacks. + /// \{ + /// \brief Accessors for preprocessor callbacks. + /// /// Note that this class takes ownership of any PPCallbacks object given to /// it. PPCallbacks *getPPCallbacks() const { return Callbacks; } @@ -528,12 +571,13 @@ public: C = new PPChainedCallbacks(C, Callbacks); Callbacks = C; } + /// \} /// \brief Given an identifier, return its latest MacroDirective if it is - // \#defined or null if it isn't \#define'd. + /// \#defined or null if it isn't \#define'd. MacroDirective *getMacroDirective(IdentifierInfo *II) const { if (!II->hasMacroDefinition()) - return 0; + return nullptr; MacroDirective *MD = getMacroDirectiveHistory(II); assert(MD->isDefined() && "Macro is undefined!"); @@ -547,13 +591,14 @@ public: MacroInfo *getMacroInfo(IdentifierInfo *II) { if (MacroDirective *MD = getMacroDirective(II)) return MD->getMacroInfo(); - return 0; + return nullptr; } /// \brief Given an identifier, return the (probably #undef'd) MacroInfo - /// representing the most recent macro definition. One can iterate over all - /// previous macro definitions from it. This method should only be called for - /// identifiers that hadMacroDefinition(). + /// representing the most recent macro definition. + /// + /// One can iterate over all previous macro definitions from the most recent + /// one. This should only be called for identifiers that hadMacroDefinition(). MacroDirective *getMacroDirectiveHistory(const IdentifierInfo *II) const; /// \brief Add a directive to the macro directive history for this identifier. @@ -571,14 +616,15 @@ public: /// \brief Set a MacroDirective that was loaded from a PCH file. void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD); - /// macro_iterator/macro_begin/macro_end - This allows you to walk the macro - /// history table. Currently defined macros have + /// \{ + /// Iterators for the macro history table. Currently defined macros have /// IdentifierInfo::hasMacroDefinition() set and an empty /// MacroInfo::getUndefLoc() at the head of the list. typedef llvm::DenseMap<const IdentifierInfo *, MacroDirective*>::const_iterator macro_iterator; macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; + /// \} /// \brief Return the name of the macro defined before \p Loc that has /// spelling \p Tokens. If there are multiple macros with same spelling, @@ -587,8 +633,9 @@ public: ArrayRef<TokenValue> Tokens) const; const std::string &getPredefines() const { return Predefines; } - /// setPredefines - Set the predefines for this Preprocessor. These - /// predefines are automatically injected when parsing the main file. + /// \brief Set the predefines for this Preprocessor. + /// + /// These predefines are automatically injected when parsing the main file. void setPredefines(const char *P) { Predefines = P; } void setPredefines(const std::string &P) { Predefines = P; } @@ -598,23 +645,28 @@ public: return &Identifiers.get(Name); } - /// AddPragmaHandler - Add the specified pragma handler to the preprocessor. - /// If 'Namespace' is non-null, then it is a token required to exist on the + /// \brief Add the specified pragma handler to this preprocessor. + /// + /// If \p Namespace is non-null, then it is a token required to exist on the /// pragma line before the pragma string starts, e.g. "STDC" or "GCC". void AddPragmaHandler(StringRef Namespace, PragmaHandler *Handler); void AddPragmaHandler(PragmaHandler *Handler) { AddPragmaHandler(StringRef(), Handler); } - /// RemovePragmaHandler - Remove the specific pragma handler from - /// the preprocessor. If \p Namespace is non-null, then it should - /// be the namespace that \p Handler was added to. It is an error - /// to remove a handler that has not been registered. + /// \brief Remove the specific pragma handler from this preprocessor. + /// + /// If \p Namespace is non-null, then it should be the namespace that + /// \p Handler was added to. It is an error to remove a handler that + /// has not been registered. void RemovePragmaHandler(StringRef Namespace, PragmaHandler *Handler); void RemovePragmaHandler(PragmaHandler *Handler) { RemovePragmaHandler(StringRef(), Handler); } + /// Install empty handlers for all pragmas (making them ignored). + void IgnorePragmas(); + /// \brief Add the specified comment handler to the preprocessor. void addCommentHandler(CommentHandler *Handler); @@ -635,7 +687,7 @@ public: /// \brief Clear out the code completion handler. void clearCodeCompletionHandler() { - CodeComplete = 0; + CodeComplete = nullptr; } /// \brief Hook used by the lexer to invoke the "natural language" code @@ -650,51 +702,51 @@ public: /// all macro expansions, macro definitions, etc. void createPreprocessingRecord(); - /// EnterMainSourceFile - Enter the specified FileID as the main source file, + /// \brief Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. void EnterMainSourceFile(); - /// EndSourceFile - Inform the preprocessor callbacks that processing is - /// complete. + /// \brief Inform the preprocessor callbacks that processing is complete. void EndSourceFile(); - /// EnterSourceFile - Add a source file to the top of the include stack and - /// start lexing tokens from it instead of the current buffer. Emit an error - /// and don't enter the file on error. - void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir, + /// \brief Add a source file to the top of the include stack and + /// start lexing tokens from it instead of the current buffer. + /// + /// Emits a diagnostic, doesn't enter the file, and returns true on error. + bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir, SourceLocation Loc); - /// EnterMacro - Add a Macro to the top of the include stack and start lexing - /// tokens from it instead of the current buffer. Args specifies the - /// tokens input to a function-like macro. + /// \brief Add a Macro to the top of the include stack and start lexing + /// tokens from it instead of the current buffer. /// - /// ILEnd specifies the location of the ')' for a function-like macro or the - /// identifier for an object-like macro. + /// \param Args specifies the tokens input to a function-like macro. + /// \param ILEnd specifies the location of the ')' for a function-like macro + /// or the identifier for an object-like macro. void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroInfo *Macro, MacroArgs *Args); - /// EnterTokenStream - Add a "macro" context to the top of the include stack, + /// \brief Add a "macro" context to the top of the include stack, /// which will cause the lexer to start returning the specified tokens. /// - /// If DisableMacroExpansion is true, tokens lexed from the token stream will - /// not be subject to further macro expansion. Otherwise, these tokens will - /// be re-macro-expanded when/if expansion is enabled. - /// - /// If OwnsTokens is false, this method assumes that the specified stream of - /// tokens has a permanent owner somewhere, so they do not need to be copied. - /// If it is true, it assumes the array of tokens is allocated with new[] and - /// must be freed. + /// If \p DisableMacroExpansion is true, tokens lexed from the token stream + /// will not be subject to further macro expansion. Otherwise, these tokens + /// will be re-macro-expanded when/if expansion is enabled. /// + /// If \p OwnsTokens is false, this method assumes that the specified stream + /// of tokens has a permanent owner somewhere, so they do not need to be + /// copied. If it is true, it assumes the array of tokens is allocated with + /// \c new[] and must be freed. void EnterTokenStream(const Token *Toks, unsigned NumToks, bool DisableMacroExpansion, bool OwnsTokens); - /// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the - /// lexer stack. This should only be used in situations where the current - /// state of the top-of-stack lexer is known. + /// \brief Pop the current lexer/macro exp off the top of the lexer stack. + /// + /// This should only be used in situations where the current state of the + /// top-of-stack lexer is known. void RemoveTopOfLexerStack(); - /// EnableBacktrackAtThisPos - From the point that this method is called, and - /// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor + /// From the point that this method is called, and until + /// CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor /// keeps track of the lexed tokens so that a subsequent Backtrack() call will /// make the Preprocessor re-lex the same tokens. /// @@ -708,18 +760,18 @@ public: /// void EnableBacktrackAtThisPos(); - /// CommitBacktrackedTokens - Disable the last EnableBacktrackAtThisPos call. + /// \brief Disable the last EnableBacktrackAtThisPos call. void CommitBacktrackedTokens(); - /// Backtrack - Make Preprocessor re-lex the tokens that were lexed since + /// \brief Make Preprocessor re-lex the tokens that were lexed since /// EnableBacktrackAtThisPos() was previously called. void Backtrack(); - /// isBacktrackEnabled - True if EnableBacktrackAtThisPos() was called and + /// \brief True if EnableBacktrackAtThisPos() was called and /// caching of tokens is on. bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); } - /// Lex - Lex the next token for this preprocessor. + /// \brief Lex the next token for this preprocessor. void Lex(Token &Result); void LexAfterModuleImport(Token &Result); @@ -743,17 +795,18 @@ public: const char *DiagnosticTag, bool AllowMacroExpansion); - /// LexNonComment - Lex a token. If it's a comment, keep lexing until we get - /// something not a comment. This is useful in -E -C mode where comments - /// would foul up preprocessor directive handling. + /// \brief Lex a token. If it's a comment, keep lexing until we get + /// something not a comment. + /// + /// This is useful in -E -C mode where comments would foul up preprocessor + /// directive handling. void LexNonComment(Token &Result) { do Lex(Result); while (Result.getKind() == tok::comment); } - /// LexUnexpandedToken - This is just like Lex, but this disables macro - /// expansion of identifier tokens. + /// \brief Just like Lex, but disables macro expansion of identifier tokens. void LexUnexpandedToken(Token &Result) { // Disable macro expansion. bool OldVal = DisableMacroExpansion; @@ -765,24 +818,31 @@ public: DisableMacroExpansion = OldVal; } - /// LexUnexpandedNonComment - Like LexNonComment, but this disables macro - /// expansion of identifier tokens. + /// \brief Like LexNonComment, but this disables macro expansion of + /// identifier tokens. void LexUnexpandedNonComment(Token &Result) { do LexUnexpandedToken(Result); while (Result.getKind() == tok::comment); } + /// \brief Parses a simple integer literal to get its numeric value. Floating + /// point literals and user defined literals are rejected. Used primarily to + /// handle pragmas that accept integer arguments. + bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value); + /// 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 - /// returns normal tokens after phase 5. As such, it is equivalent to using + /// \brief 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 returns normal + /// tokens after phase 5. As such, it is equivalent to using /// 'Lex', not 'LexUnexpandedToken'. const Token &LookAhead(unsigned N) { if (CachedLexPos + N < CachedTokens.size()) @@ -791,8 +851,9 @@ public: return PeekAhead(N+1); } - /// RevertCachedTokens - When backtracking is enabled and tokens are cached, + /// \brief When backtracking is enabled and tokens are cached, /// this allows to revert a specific number of tokens. + /// /// Note that the number of tokens being reverted should be up to the last /// backtrack position, not more. void RevertCachedTokens(unsigned N) { @@ -805,20 +866,21 @@ public: CachedLexPos -= N; } - /// EnterToken - Enters a token in the token stream to be lexed next. If - /// BackTrack() is called afterwards, the token will remain at the insertion - /// point. + /// \brief Enters a token in the token stream to be lexed next. + /// + /// If BackTrack() is called afterwards, the token will remain at the + /// insertion point. void EnterToken(const Token &Tok) { EnterCachingLexMode(); CachedTokens.insert(CachedTokens.begin()+CachedLexPos, Tok); } - /// AnnotateCachedTokens - We notify the Preprocessor that if it is caching - /// tokens (because backtrack is enabled) it should replace the most recent - /// cached tokens with the given annotation token. This function has no effect - /// if backtracking is not enabled. + /// We notify the Preprocessor that if it is caching tokens (because + /// backtrack is enabled) it should replace the most recent cached tokens + /// with the given annotation token. This function has no effect if + /// backtracking is not enabled. /// - /// Note that the use of this function is just for optimization; so that the + /// Note that the use of this function is just for optimization, so that the /// cached tokens doesn't get re-parsed and re-resolved after a backtrack is /// invoked. void AnnotateCachedTokens(const Token &Tok) { @@ -848,7 +910,7 @@ public: CachedTokens[CachedLexPos-1] = Tok; } - /// TypoCorrectToken - Update the current token to represent the provided + /// Update the current token to represent the provided /// identifier, in order to cache an action performed by typo correction. void TypoCorrectToken(const Token &Tok) { assert(Tok.getIdentifierInfo() && "Expected identifier token"); @@ -886,14 +948,16 @@ public: unsigned Line, unsigned Column); /// \brief Determine if we are performing code completion. - bool isCodeCompletionEnabled() const { return CodeCompletionFile != 0; } + bool isCodeCompletionEnabled() const { return CodeCompletionFile != nullptr; } /// \brief Returns the location of the code-completion point. + /// /// Returns an invalid location if code-completion is not enabled or the file /// containing the code-completion point has not been lexed yet. SourceLocation getCodeCompletionLoc() const { return CodeCompletionLoc; } /// \brief Returns the start location of the file of code-completion point. + /// /// Returns an invalid location if code-completion is not enabled or the file /// containing the code-completion point has not been lexed yet. SourceLocation getCodeCompletionFileLoc() const { @@ -913,8 +977,9 @@ public: } /// \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. + /// arc_cf_code_audited begin. + /// + /// Returns an invalid location if there is no such pragma active. SourceLocation getPragmaARCCFCodeAuditedLoc() const { return PragmaARCCFCodeAuditedLoc; } @@ -936,7 +1001,7 @@ public: SkipMainFilePreamble.second = StartOfLine; } - /// Diag - Forwarding function for diagnostics. This emits a diagnostic at + /// Forwarding function for diagnostics. This emits a diagnostic at /// the specified Token's location, translating the token's start /// position in the current buffer into a SourcePosition object for rendering. DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const { @@ -947,7 +1012,7 @@ public: return Diags->Report(Tok.getLocation(), DiagID); } - /// getSpelling() - Return the 'spelling' of the token at the given + /// Return the 'spelling' of the token at the given /// location; does not go up to the spelling location or down to the /// expansion location. /// @@ -956,25 +1021,28 @@ public: /// \param invalid If non-null, will be set \c true if an error occurs. StringRef getSpelling(SourceLocation loc, SmallVectorImpl<char> &buffer, - bool *invalid = 0) const { + bool *invalid = nullptr) const { return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid); } - /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a - /// token is the characters used to represent the token in the source file - /// after trigraph expansion and escaped-newline folding. In particular, this - /// wants to get the true, uncanonicalized, spelling of things like digraphs - /// UCNs, etc. + /// \brief Return the 'spelling' of the Tok token. + /// + /// The spelling of a token is the characters used to represent the token in + /// the source file after trigraph expansion and escaped-newline folding. In + /// particular, this wants to get the true, uncanonicalized, spelling of + /// things like digraphs, UCNs, etc. /// /// \param Invalid If non-null, will be set \c true if an error occurs. - std::string getSpelling(const Token &Tok, bool *Invalid = 0) const { + std::string getSpelling(const Token &Tok, bool *Invalid = nullptr) const { return Lexer::getSpelling(Tok, SourceMgr, LangOpts, Invalid); } - /// getSpelling - This method is used to get the spelling of a token into a - /// preallocated buffer, instead of as an std::string. The caller is required - /// to allocate enough space for the token, which is guaranteed to be at least - /// Tok.getLength() bytes long. The length of the actual result is returned. + /// \brief Get the spelling of a token into a preallocated buffer, instead + /// of as an std::string. + /// + /// The caller is required to allocate enough space for the token, which is + /// guaranteed to be at least Tok.getLength() bytes long. The length of the + /// actual result is returned. /// /// Note that this method may do two possible things: it may either fill in /// the buffer specified with characters, or it may *change the input pointer* @@ -982,16 +1050,17 @@ public: /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. unsigned getSpelling(const Token &Tok, const char *&Buffer, - bool *Invalid = 0) const { + bool *Invalid = nullptr) const { return Lexer::getSpelling(Tok, Buffer, SourceMgr, LangOpts, Invalid); } - /// getSpelling - This method is used to get the spelling of a token into a - /// SmallVector. Note that the returned StringRef may not point to the + /// \brief Get the spelling of a token into a SmallVector. + /// + /// Note that the returned StringRef may not point to the /// supplied buffer if a copy can be avoided. StringRef getSpelling(const Token &Tok, SmallVectorImpl<char> &Buffer, - bool *Invalid = 0) const; + bool *Invalid = nullptr) const; /// \brief Relex the token at the specified location. /// \returns true if there was a failure, false on success. @@ -1000,10 +1069,11 @@ public: return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts, IgnoreWhiteSpace); } - /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant - /// with length 1, return the character. - char getSpellingOfSingleCharacterNumericConstant(const Token &Tok, - bool *Invalid = 0) const { + /// \brief Given a Token \p Tok that is a numeric constant with length 1, + /// return the character. + char + getSpellingOfSingleCharacterNumericConstant(const Token &Tok, + bool *Invalid = nullptr) const { assert(Tok.is(tok::numeric_constant) && Tok.getLength() == 1 && "Called on unsupported token"); assert(!Tok.needsCleaning() && "Token can't need cleaning with length 1"); @@ -1019,18 +1089,21 @@ public: /// \brief Retrieve the name of the immediate macro expansion. /// - /// This routine starts from a source location, and finds the name of the macro - /// responsible for its immediate expansion. It looks through any intervening - /// macro argument expansions to compute this. It returns a StringRef which - /// refers to the SourceManager-owned buffer of the source where that macro - /// name is spelled. Thus, the result shouldn't out-live the SourceManager. + /// This routine starts from a source location, and finds the name of the + /// macro responsible for its immediate expansion. It looks through any + /// intervening macro argument expansions to compute this. It returns a + /// StringRef that refers to the SourceManager-owned buffer of the source + /// where that macro name is spelled. Thus, the result shouldn't out-live + /// the SourceManager. StringRef getImmediateMacroName(SourceLocation Loc) { return Lexer::getImmediateMacroName(Loc, SourceMgr, getLangOpts()); } - /// CreateString - Plop the specified string into a scratch buffer and set the - /// specified token's location and length to it. If specified, the source - /// location provides a location of the expansion point of the token. + /// \brief Plop the specified string into a scratch buffer and set the + /// specified token's location and length to it. + /// + /// If specified, the source location provides a location of the expansion + /// point of the token. void CreateString(StringRef Str, Token &Tok, SourceLocation ExpansionLocStart = SourceLocation(), SourceLocation ExpansionLocEnd = SourceLocation()); @@ -1060,7 +1133,7 @@ public: /// \param MacroBegin If non-null and function returns true, it is set to /// begin location of the macro. bool isAtStartOfMacroExpansion(SourceLocation loc, - SourceLocation *MacroBegin = 0) const { + SourceLocation *MacroBegin = nullptr) const { return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts, MacroBegin); } @@ -1071,27 +1144,26 @@ public: /// \param MacroEnd If non-null and function returns true, it is set to /// end location of the macro. bool isAtEndOfMacroExpansion(SourceLocation loc, - SourceLocation *MacroEnd = 0) const { + SourceLocation *MacroEnd = nullptr) const { return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd); } - /// DumpToken - Print the token to stderr, used for debugging. - /// + /// \brief Print the token to stderr, used for debugging. void DumpToken(const Token &Tok, bool DumpFlags = false) const; void DumpLocation(SourceLocation Loc) const; void DumpMacro(const MacroInfo &MI) const; - /// AdvanceToTokenCharacter - Given a location that specifies the start of a + /// \brief Given a location that specifies the start of a /// token, return a new location that specifies a character within the token. SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const { return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, LangOpts); } - /// IncrementPasteCounter - Increment the counters for the number of token - /// paste operations performed. If fast was specified, this is a 'fast paste' - /// case we handled. + /// \brief Increment the counters for the number of token paste operations + /// performed. /// + /// If fast was specified, this is a 'fast paste' case we handled. void IncrementPasteCounter(bool isFast) { if (isFast) ++NumFastTokenPaste; @@ -1103,16 +1175,16 @@ public: size_t getTotalMemory() const; - /// HandleMicrosoftCommentPaste - When the macro expander pastes together a - /// comment (/##/) in microsoft mode, this method handles updating the current - /// state, returning the token on the next source line. + /// When the macro expander pastes together a comment (/##/) in Microsoft + /// mode, this method handles updating the current state, returning the + /// token on the next source line. void HandleMicrosoftCommentPaste(Token &Tok); //===--------------------------------------------------------------------===// // Preprocessor callback methods. These are invoked by a lexer as various // directives and events are found. - /// LookUpIdentifierInfo - Given a tok::raw_identifier token, look up the + /// Given a tok::raw_identifier token, look up the /// identifier information for the token and install it into the token, /// updating the token kind accordingly. IdentifierInfo *LookUpIdentifierInfo(Token &Identifier) const; @@ -1122,14 +1194,13 @@ private: public: - // SetPoisonReason - Call this function to indicate the reason for - // poisoning an identifier. If that identifier is accessed while - // poisoned, then this reason will be used instead of the default - // "poisoned" diagnostic. + /// \brief Specifies the reason for poisoning an identifier. + /// + /// If that identifier is accessed while poisoned, then this reason will be + /// used instead of the default "poisoned" diagnostic. void SetPoisonReason(IdentifierInfo *II, unsigned DiagID); - // HandlePoisonedIdentifier - Display reason for poisoned - // identifier. + /// \brief Display reason for poisoned identifier. void HandlePoisonedIdentifier(Token & Tok); void MaybeHandlePoisonedIdentifier(Token & Identifier) { @@ -1155,45 +1226,53 @@ private: IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; + + const char *getCurLexerEndPos(); + public: void PoisonSEHIdentifiers(bool Poison = true); // Borland - /// HandleIdentifier - This callback is invoked when the lexer reads an - /// identifier and has filled in the tokens IdentifierInfo member. This - /// callback potentially macro expands it or turns it into a named token (like - /// 'for'). + /// \brief Callback invoked when the lexer reads an identifier and has + /// filled in the tokens IdentifierInfo member. + /// + /// This callback potentially macro expands it or turns it into a named + /// token (like 'for'). /// /// \returns true if we actually computed a token, false if we need to /// lex again. bool HandleIdentifier(Token &Identifier); - /// HandleEndOfFile - This callback is invoked when the lexer hits the end of - /// the current file. This either returns the EOF token and returns true, or + /// \brief Callback invoked when the lexer hits the end of the current file. + /// + /// This either returns the EOF token and returns true, or /// pops a level off the include stack and returns false, at which point the /// client should call lex again. bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false); - /// HandleEndOfTokenLexer - This callback is invoked when the current - /// TokenLexer hits the end of its token stream. + /// \brief Callback invoked when the current TokenLexer hits the end of its + /// token stream. bool HandleEndOfTokenLexer(Token &Result); - /// HandleDirective - This callback is invoked when the lexer sees a # token - /// at the start of a line. This consumes the directive, modifies the - /// lexer/preprocessor state, and advances the lexer(s) so that the next token - /// read is the correct one. + /// \brief Callback invoked when the lexer sees a # token at the start of a + /// line. + /// + /// This consumes the directive, modifies the lexer/preprocessor state, and + /// advances the lexer(s) so that the next token read is the correct one. void HandleDirective(Token &Result); - /// CheckEndOfDirective - Ensure that the next token is a tok::eod token. If - /// not, emit a diagnostic and consume up until the eod. If EnableMacros is - /// true, then we consider macros that expand to zero tokens as being ok. + /// \brief Ensure that the next token is a tok::eod token. + /// + /// If not, emit a diagnostic and consume up until the eod. + /// If \p EnableMacros is true, then we consider macros that expand to zero + /// tokens as being ok. void CheckEndOfDirective(const char *Directive, bool EnableMacros = false); - /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the - /// current line until the tok::eod token is found. + /// \brief Read and discard all tokens remaining on the current line until + /// the tok::eod token is found. void DiscardUntilEndOfDirective(); - /// SawDateOrTime - This returns true if the preprocessor has seen a use of + /// \brief Returns true if the preprocessor has seen a use of /// __DATE__ or __TIME__ in the file so far. bool SawDateOrTime() const { return DATELoc != SourceLocation() || TIMELoc != SourceLocation(); @@ -1234,17 +1313,20 @@ public: ModuleMap::KnownHeader *SuggestedModule, bool SkipCache = false); - /// 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. + /// \brief Get 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. const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; } /// \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 - /// from a macro as multiple tokens, which need to be glued together. This - /// occurs for code like: + /// \brief 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: /// \code /// \#define FOO <x/y.h> /// \#include FOO @@ -1257,28 +1339,28 @@ public: bool ConcatenateIncludeName(SmallString<128> &FilenameBuffer, SourceLocation &End); - /// LexOnOffSwitch - Lex an on-off-switch (C99 6.10.6p2) and verify that it is + /// \brief Lex an on-off-switch (C99 6.10.6p2) and verify that it is /// followed by EOD. Return true if the token is not a valid on-off-switch. bool LexOnOffSwitch(tok::OnOffSwitch &OOS); + bool CheckMacroName(Token &MacroNameTok, char isDefineUndef); + private: void PushIncludeMacroStack() { - IncludeMacroStack.push_back(IncludeStackInfo(CurLexerKind, - CurLexer.take(), - CurPTHLexer.take(), - CurPPLexer, - CurTokenLexer.take(), - CurDirLookup)); - CurPPLexer = 0; + IncludeMacroStack.push_back(IncludeStackInfo( + CurLexerKind, CurSubmodule, std::move(CurLexer), std::move(CurPTHLexer), + CurPPLexer, std::move(CurTokenLexer), CurDirLookup)); + CurPPLexer = nullptr; } void PopIncludeMacroStack() { - CurLexer.reset(IncludeMacroStack.back().TheLexer); - CurPTHLexer.reset(IncludeMacroStack.back().ThePTHLexer); + CurLexer = std::move(IncludeMacroStack.back().TheLexer); + CurPTHLexer = std::move(IncludeMacroStack.back().ThePTHLexer); CurPPLexer = IncludeMacroStack.back().ThePPLexer; - CurTokenLexer.reset(IncludeMacroStack.back().TheTokenLexer); + CurTokenLexer = std::move(IncludeMacroStack.back().TheTokenLexer); CurDirLookup = IncludeMacroStack.back().TheDirLookup; + CurSubmodule = IncludeMacroStack.back().TheSubmodule; CurLexerKind = IncludeMacroStack.back().CurLexerKind; IncludeMacroStack.pop_back(); } @@ -1300,15 +1382,16 @@ private: /// 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, + /// \brief Lex and validate a macro name, which occurs after a + /// \#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); - /// ReadMacroDefinitionArgList - The ( starting an argument list of a macro - /// definition has just been read. Lex the rest of the arguments and the - /// closing ), updating MI with what we learn and saving in LastTok the - /// last token read. + /// The ( starting an argument list of a macro definition has just been read. + /// Lex the rest of the arguments and the closing ), updating \p MI with + /// what we learn and saving in \p LastTok the last token read. /// Return true if an error occurs parsing the arg list. bool ReadMacroDefinitionArgList(MacroInfo *MI, Token& LastTok); @@ -1327,21 +1410,22 @@ private: /// \brief A fast PTH version of SkipExcludedConditionalBlock. void PTHSkipExcludedConditionalBlock(); - /// EvaluateDirectiveExpression - Evaluate an integer constant expression that - /// may occur after a #if or #elif directive and return it as a bool. If the - /// expression is equivalent to "!defined(X)" return X in IfNDefMacro. + /// \brief Evaluate an integer constant expression that may occur after a + /// \#if or \#elif directive and return it as a bool. + /// + /// If the expression is equivalent to "!defined(X)" return X in IfNDefMacro. bool EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro); - /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas: + /// \brief Install the standard preprocessor pragmas: /// \#pragma GCC poison/system_header/dependency and \#pragma once. void RegisterBuiltinPragmas(); /// \brief Register builtin macros such as __LINE__ with the identifier table. void RegisterBuiltinMacros(); - /// HandleMacroExpandedIdentifier - If an identifier token is read that is to - /// be expanded as a macro, handle it and return the next token as 'Tok'. If - /// we lexed a token, return true; otherwise the caller should lex again. + /// If an identifier token is read that is to be expanded as a macro, handle + /// it and return the next token as 'Tok'. If we lexed a token, return true; + /// otherwise the caller should lex again. bool HandleMacroExpandedIdentifier(Token &Tok, MacroDirective *MD); /// \brief Cache macro expanded tokens for TokenLexers. @@ -1354,52 +1438,51 @@ private: void removeCachedMacroExpandedTokensOfLastLexer(); friend void TokenLexer::ExpandFunctionArguments(); - /// isNextPPTokenLParen - Determine whether the next preprocessor token to be + /// Determine whether the next preprocessor token to be /// lexed is a '('. If so, consume the token and return true, if not, this /// method should have no observable side-effect on the lexed tokens. bool isNextPPTokenLParen(); - /// ReadFunctionLikeMacroArgs - After reading "MACRO(", this method is - /// invoked to read all of the formal arguments specified for the macro - /// invocation. This returns null on error. + /// After reading "MACRO(", this method is invoked to read all of the formal + /// arguments specified for the macro invocation. Returns null on error. MacroArgs *ReadFunctionLikeMacroArgs(Token &MacroName, MacroInfo *MI, SourceLocation &ExpansionEnd); - /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded + /// \brief If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. void ExpandBuiltinMacro(Token &Tok); - /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then - /// return the first token after the directive. The _Pragma token has just - /// been read into 'Tok'. + /// \brief Read a \c _Pragma directive, slice it up, process it, then + /// return the first token after the directive. + /// This assumes that the \c _Pragma token has just been read into \p Tok. void Handle_Pragma(Token &Tok); - /// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text - /// is not enclosed within a string literal. + /// \brief Like Handle_Pragma except the pragma text is not enclosed within + /// a string literal. void HandleMicrosoft__pragma(Token &Tok); - /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and + /// \brief Add a lexer to the top of the include stack and /// start lexing tokens from it instead of the current buffer. void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir); - /// EnterSourceFileWithPTH - Add a lexer to the top of the include stack and + /// \brief Add a lexer to the top of the include stack and /// start getting tokens from it using the PTH cache. void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir); - /// \brief Set the file ID for the preprocessor predefines. + /// \brief Set the FileID for the preprocessor predefines. void setPredefinesFileID(FileID FID) { assert(PredefinesFileID.isInvalid() && "PredefinesFileID already set!"); PredefinesFileID = FID; } - /// IsFileLexer - Returns true if we are lexing from a file and not a - /// pragma or a macro. + /// \brief Returns true if we are lexing from a file and not a + /// pragma or a macro. static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) { - return L ? !L->isPragmaLexer() : P != 0; + return L ? !L->isPragmaLexer() : P != nullptr; } static bool IsFileLexer(const IncludeStackInfo& I) { - return IsFileLexer(I.TheLexer, I.ThePPLexer); + return IsFileLexer(I.TheLexer.get(), I.ThePPLexer); } bool IsFileLexer() const { @@ -1437,7 +1520,7 @@ private: // File inclusion. void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok, - const DirectoryLookup *LookupFrom = 0, + const DirectoryLookup *LookupFrom = nullptr, bool isImport = false); void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok); void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok); @@ -1449,25 +1532,6 @@ private: /// points to. Module *getModuleForLocation(SourceLocation FilenameLoc); - /// \brief Verify that a private header is included only from within its - /// module. - bool violatesPrivateInclude(Module *RequestingModule, - const FileEntry *IncFileEnt, - ModuleMap::ModuleHeaderRole Role, - Module *RequestedModule); - - /// \brief Verify that a module includes headers only from modules that it - /// has declared that it uses. - bool violatesUseDeclarations(Module *RequestingModule, - Module *RequestedModule); - - /// \brief Verify that it is legal for the source file that \p FilenameLoc - /// points to to include the file \p Filename. - /// - /// Tries to reuse \p IncFileEnt. - void verifyModuleInclude(SourceLocation FilenameLoc, StringRef Filename, - const FileEntry *IncFileEnt); - // Macro handling. void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef); void HandleUndefDirective(Token &Tok); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h index 27a8df4..ed226ae 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h @@ -76,7 +76,7 @@ protected: PreprocessorLexer(Preprocessor *pp, FileID fid); PreprocessorLexer() - : PP(0), InitialNumSLocEntries(0), + : PP(nullptr), InitialNumSLocEntries(0), ParsingPreprocessorDirective(false), ParsingFilename(false), LexingRawMode(false) {} diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h index eba2a13..135c87f 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h @@ -97,14 +97,13 @@ public: /// the system (the first part of each pair) and gives them the /// contents of other files on the system (the second part of each /// pair). - std::vector<std::pair<std::string, std::string> > RemappedFiles; + std::vector<std::pair<std::string, std::string>> RemappedFiles; /// \brief The set of file-to-buffer remappings, which take existing files /// on the system (the first part of each pair) and gives them the contents /// of the specified memory buffer (the second part of each pair). - std::vector<std::pair<std::string, const llvm::MemoryBuffer *> > - RemappedFileBuffers; - + std::vector<std::pair<std::string, llvm::MemoryBuffer *>> RemappedFileBuffers; + /// \brief Whether the compiler instance should retain (i.e., not free) /// the buffers associated with remapped files. /// @@ -140,40 +139,6 @@ public: /// build it again. IntrusiveRefCntPtr<FailedModulesSet> FailedModules; - typedef std::vector<std::pair<std::string, std::string> >::iterator - remapped_file_iterator; - typedef std::vector<std::pair<std::string, std::string> >::const_iterator - const_remapped_file_iterator; - remapped_file_iterator remapped_file_begin() { - return RemappedFiles.begin(); - } - const_remapped_file_iterator remapped_file_begin() const { - return RemappedFiles.begin(); - } - remapped_file_iterator remapped_file_end() { - return RemappedFiles.end(); - } - const_remapped_file_iterator remapped_file_end() const { - return RemappedFiles.end(); - } - - typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >:: - iterator remapped_file_buffer_iterator; - typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >:: - const_iterator const_remapped_file_buffer_iterator; - remapped_file_buffer_iterator remapped_file_buffer_begin() { - return RemappedFileBuffers.begin(); - } - const_remapped_file_buffer_iterator remapped_file_buffer_begin() const { - return RemappedFileBuffers.begin(); - } - remapped_file_buffer_iterator remapped_file_buffer_end() { - return RemappedFileBuffers.end(); - } - const_remapped_file_buffer_iterator remapped_file_buffer_end() const { - return RemappedFileBuffers.end(); - } - public: PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), DisablePCHValidation(false), @@ -193,20 +158,11 @@ public: void addRemappedFile(StringRef From, StringRef To) { RemappedFiles.push_back(std::make_pair(From, To)); } - - remapped_file_iterator eraseRemappedFile(remapped_file_iterator Remapped) { - return RemappedFiles.erase(Remapped); - } - - void addRemappedFile(StringRef From, const llvm::MemoryBuffer * To) { + + void addRemappedFile(StringRef From, llvm::MemoryBuffer *To) { RemappedFileBuffers.push_back(std::make_pair(From, To)); } - - remapped_file_buffer_iterator - eraseRemappedFile(remapped_file_buffer_iterator Remapped) { - return RemappedFileBuffers.erase(Remapped); - } - + void clearRemappedFiles() { RemappedFiles.clear(); RemappedFileBuffers.clear(); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Token.h b/contrib/llvm/tools/clang/include/clang/Lex/Token.h index 4f6391d..c8b77d1 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Token.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Token.h @@ -18,6 +18,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" +#include "llvm/ADT/StringRef.h" #include <cstdlib> namespace clang { @@ -62,8 +63,7 @@ class Token { void *PtrData; /// Kind - The actual flavor of token this is. - /// - unsigned short Kind; + tok::TokenKind Kind; /// Flags - Bits we track about this token, members of the TokenFlags enum. unsigned char Flags; @@ -83,13 +83,13 @@ public: IgnoredComma = 0x80 // This comma is not a macro argument separator (MS). }; - tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } + tok::TokenKind getKind() const { return Kind; } void setKind(tok::TokenKind K) { Kind = K; } /// is/isNot - Predicates to check if this token is a specific kind, as in /// "if (Tok.is(tok::l_brace)) {...}". - bool is(tok::TokenKind K) const { return Kind == (unsigned) K; } - bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; } + bool is(tok::TokenKind K) const { return Kind == K; } + bool isNot(tok::TokenKind K) const { return Kind != K; } /// \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). @@ -145,15 +145,13 @@ public: setAnnotationEndLoc(R.getEnd()); } - const char *getName() const { - return tok::getTokenName( (tok::TokenKind) Kind); - } + const char *getName() const { return tok::getTokenName(Kind); } /// \brief Reset all flags to cleared. void startToken() { Kind = tok::unknown; Flags = 0; - PtrData = 0; + PtrData = nullptr; UintData = 0; Loc = SourceLocation(); } @@ -163,19 +161,19 @@ public: "getIdentifierInfo() on a tok::raw_identifier token!"); assert(!isAnnotation() && "getIdentifierInfo() on an annotation token!"); - if (isLiteral()) return 0; + if (isLiteral()) return nullptr; return (IdentifierInfo*) PtrData; } void setIdentifierInfo(IdentifierInfo *II) { PtrData = (void*) II; } - /// getRawIdentifierData - For a raw identifier token (i.e., an identifier - /// lexed in raw mode), returns a pointer to the start of it in the text - /// buffer if known, null otherwise. - const char *getRawIdentifierData() const { + /// getRawIdentifier - For a raw identifier token (i.e., an identifier + /// lexed in raw mode), returns a reference to the text substring in the + /// buffer if known. + StringRef getRawIdentifier() const { assert(is(tok::raw_identifier)); - return reinterpret_cast<const char*>(PtrData); + return StringRef(reinterpret_cast<const char *>(PtrData), getLength()); } void setRawIdentifierData(const char *Ptr) { assert(is(tok::raw_identifier)); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h index 7c8cfd0..a873a2e 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h @@ -81,6 +81,14 @@ class TokenLexer { bool AtStartOfLine : 1; bool HasLeadingSpace : 1; + // NextTokGetsSpace - When this is true, the next token appended to the + // output list during function argument expansion will get a leading space, + // regardless of whether it had one to begin with or not. This is used for + // placemarker support. If still true after function argument expansion, the + // leading space will be applied to the first token following the macro + // expansion. + bool NextTokGetsSpace : 1; + /// OwnsTokens - This is true if this TokenLexer allocated the Tokens /// array, and thus needs to free it when destroyed. For simple object-like /// macros (for example) we just point into the token buffer of the macro @@ -100,7 +108,7 @@ public: /// identifier for an object-like macro. TokenLexer(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, MacroArgs *ActualArgs, Preprocessor &pp) - : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) { + : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) { Init(Tok, ILEnd, MI, ActualArgs); } @@ -116,7 +124,7 @@ public: /// the token lexer is empty. TokenLexer(const Token *TokArray, unsigned NumToks, bool DisableExpansion, bool ownsTokens, Preprocessor &pp) - : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) { + : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) { Init(TokArray, NumToks, DisableExpansion, ownsTokens); } @@ -182,6 +190,13 @@ private: void updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc, Token *begin_tokens, Token *end_tokens); + /// Remove comma ahead of __VA_ARGS__, if present, according to compiler + /// dialect settings. Returns true if the comma is removed. + bool MaybeRemoveCommaBeforeVaArgs(SmallVectorImpl<Token> &ResultToks, + bool HasPasteOperator, + MacroInfo *Macro, unsigned MacroArgNo, + Preprocessor &PP); + void PropagateLineStartLeadingSpaceInfo(Token &Result); }; diff --git a/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h index 2405a0c..21f9701 100644 --- a/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h +++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h @@ -36,7 +36,7 @@ namespace clang { void ParseAST(Preprocessor &pp, ASTConsumer *C, ASTContext &Ctx, bool PrintStats = false, TranslationUnitKind TUKind = TU_Complete, - CodeCompleteConsumer *CompletionConsumer = 0, + CodeCompleteConsumer *CompletionConsumer = nullptr, bool SkipFunctionBodies = false); /// \brief Parse the main file known to the preprocessor, producing an diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h index bd49988..c58c41a 100644 --- a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h +++ b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h @@ -20,12 +20,13 @@ #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/LoopHint.h" #include "clang/Sema/Sema.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SaveAndRestore.h" +#include <memory> #include <stack> namespace clang { @@ -40,7 +41,6 @@ namespace clang { class ParsingDeclSpec; class ParsingDeclarator; class ParsingFieldDeclarator; - class PragmaUnusedHandler; class ColonProtectionRAIIObject; class InMessageExpressionRAIIObject; class PoisonSEHIdentifiersRAIIObject; @@ -52,7 +52,6 @@ namespace clang { /// been read. /// class Parser : public CodeCompletionHandler { - friend class PragmaUnusedHandler; friend class ColonProtectionRAIIObject; friend class InMessageExpressionRAIIObject; friend class PoisonSEHIdentifiersRAIIObject; @@ -73,7 +72,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; @@ -136,24 +135,37 @@ class Parser : public CodeCompletionHandler { mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_override; - // C++ type trait keywords that have can be reverted to identifiers and - // still used as type traits. - llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertableTypeTraits; - - OwningPtr<PragmaHandler> AlignHandler; - OwningPtr<PragmaHandler> GCCVisibilityHandler; - OwningPtr<PragmaHandler> OptionsHandler; - OwningPtr<PragmaHandler> PackHandler; - OwningPtr<PragmaHandler> MSStructHandler; - OwningPtr<PragmaHandler> UnusedHandler; - OwningPtr<PragmaHandler> WeakHandler; - OwningPtr<PragmaHandler> RedefineExtnameHandler; - OwningPtr<PragmaHandler> FPContractHandler; - OwningPtr<PragmaHandler> OpenCLExtensionHandler; - OwningPtr<CommentHandler> CommentSemaHandler; - OwningPtr<PragmaHandler> OpenMPHandler; - OwningPtr<PragmaHandler> MSCommentHandler; - OwningPtr<PragmaHandler> MSDetectMismatchHandler; + // Some token kinds such as C++ type traits can be reverted to identifiers and + // still get used as keywords depending on context. + llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind> + ContextualKeywords; + + std::unique_ptr<PragmaHandler> AlignHandler; + std::unique_ptr<PragmaHandler> GCCVisibilityHandler; + std::unique_ptr<PragmaHandler> OptionsHandler; + std::unique_ptr<PragmaHandler> PackHandler; + std::unique_ptr<PragmaHandler> MSStructHandler; + std::unique_ptr<PragmaHandler> UnusedHandler; + std::unique_ptr<PragmaHandler> WeakHandler; + std::unique_ptr<PragmaHandler> RedefineExtnameHandler; + std::unique_ptr<PragmaHandler> FPContractHandler; + std::unique_ptr<PragmaHandler> OpenCLExtensionHandler; + std::unique_ptr<PragmaHandler> OpenMPHandler; + std::unique_ptr<PragmaHandler> MSCommentHandler; + std::unique_ptr<PragmaHandler> MSDetectMismatchHandler; + std::unique_ptr<PragmaHandler> MSPointersToMembers; + std::unique_ptr<PragmaHandler> MSVtorDisp; + std::unique_ptr<PragmaHandler> MSInitSeg; + std::unique_ptr<PragmaHandler> MSDataSeg; + std::unique_ptr<PragmaHandler> MSBSSSeg; + std::unique_ptr<PragmaHandler> MSConstSeg; + std::unique_ptr<PragmaHandler> MSCodeSeg; + std::unique_ptr<PragmaHandler> MSSection; + std::unique_ptr<PragmaHandler> OptimizeHandler; + std::unique_ptr<PragmaHandler> LoopHintHandler; + std::unique_ptr<PragmaHandler> UnrollHintHandler; + + std::unique_ptr<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++ @@ -167,7 +179,7 @@ class Parser : public CodeCompletionHandler { /// ColonProtectionRAIIObject RAII object. bool ColonIsSacred; - /// \brief When true, we are directly inside an Objective-C messsage + /// \brief When true, we are directly inside an Objective-C message /// send expression. /// /// This is managed by the \c InMessageExpressionRAIIObject class, and @@ -193,6 +205,10 @@ class Parser : public CodeCompletionHandler { ++Depth; ++AddedLevels; } + void addDepth(unsigned D) { + Depth += D; + AddedLevels += D; + } unsigned getDepth() const { return Depth; } }; @@ -229,6 +245,9 @@ public: const Token &getCurToken() const { return Tok; } Scope *getCurScope() const { return Actions.getCurScope(); } + void incrementMSLocalManglingNumber() const { + return Actions.incrementMSLocalManglingNumber(); + } Decl *getObjCDeclContext() const { return Actions.getObjCDeclContext(); } @@ -246,7 +265,7 @@ public: typedef clang::TypeResult TypeResult; typedef Expr *ExprArg; - typedef llvm::MutableArrayRef<Stmt*> MultiStmtArg; + typedef MutableArrayRef<Stmt*> MultiStmtArg; typedef Sema::FullExprArg FullExprArg; ExprResult ExprError() { return ExprResult(true); } @@ -266,24 +285,40 @@ public: /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if /// the EOF was encountered. bool ParseTopLevelDecl(DeclGroupPtrTy &Result); + bool ParseTopLevelDecl() { + DeclGroupPtrTy Result; + return ParseTopLevelDecl(Result); + } /// ConsumeToken - Consume the current 'peek token' and lex the next one. - /// This does not work with all kinds of tokens: strings and specific other - /// tokens must be consumed with custom methods below. This returns the - /// location of the consumed token. - SourceLocation ConsumeToken(bool ConsumeCodeCompletionTok = false) { - assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() && - !isTokenBrace() && + /// This does not work with special tokens: string literals, code completion + /// and balanced tokens must be handled using the specific consume methods. + /// Returns the location of the consumed token. + SourceLocation ConsumeToken() { + assert(!isTokenSpecial() && "Should consume special tokens with Consume*Token"); - - if (!ConsumeCodeCompletionTok && Tok.is(tok::code_completion)) - return handleUnexpectedCodeCompletionToken(); - PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); return PrevTokLocation; } + bool TryConsumeToken(tok::TokenKind Expected) { + if (Tok.isNot(Expected)) + return false; + assert(!isTokenSpecial() && + "Should consume special tokens with Consume*Token"); + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return true; + } + + bool TryConsumeToken(tok::TokenKind Expected, SourceLocation &Loc) { + if (!TryConsumeToken(Expected)) + return false; + Loc = PrevTokLocation; + return true; + } + private: //===--------------------------------------------------------------------===// // Low-Level token peeking and consumption methods. @@ -301,12 +336,15 @@ private: bool isTokenBrace() const { return Tok.getKind() == tok::l_brace || Tok.getKind() == tok::r_brace; } - /// isTokenStringLiteral - True if this token is a string-literal. - /// bool isTokenStringLiteral() const { return tok::isStringLiteral(Tok.getKind()); } + /// isTokenSpecial - True if this token requires special consumption methods. + bool isTokenSpecial() const { + return isTokenStringLiteral() || isTokenParen() || isTokenBracket() || + isTokenBrace() || Tok.is(tok::code_completion); + } /// \brief Returns true if the current token is '=' or is a type of '='. /// For typos, give a fixit to '=' @@ -318,14 +356,16 @@ private: SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) { if (isTokenParen()) return ConsumeParen(); - else if (isTokenBracket()) + if (isTokenBracket()) return ConsumeBracket(); - else if (isTokenBrace()) + if (isTokenBrace()) return ConsumeBrace(); - else if (isTokenStringLiteral()) + if (isTokenStringLiteral()) return ConsumeStringToken(); - else - return ConsumeToken(ConsumeCodeCompletionTok); + if (Tok.is(tok::code_completion)) + return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken() + : handleUnexpectedCodeCompletionToken(); + return ConsumeToken(); } /// ConsumeParen - This consume method keeps the paren count up-to-date. @@ -383,8 +423,9 @@ private: /// \brief Consume the current code-completion token. /// - /// This routine should be called to consume the code-completion token once - /// a code-completion action has already been invoked. + /// This routine can be called to consume the code-completion token and + /// continue processing in special cases where \c cutOffParsing() isn't + /// desired, such as token caching or completion with lookahead. SourceLocation ConsumeCodeCompletionToken() { assert(Tok.is(tok::code_completion)); PrevTokLocation = Tok.getLocation(); @@ -408,6 +449,20 @@ private: Tok.setKind(tok::eof); } + /// \brief Determine if we're at the end of the file or at a transition + /// between modules. + bool isEofOrEom() { + tok::TokenKind Kind = Tok.getKind(); + return Kind == tok::eof || Kind == tok::annot_module_begin || + Kind == tok::annot_module_end || Kind == tok::annot_module_include; + } + + /// \brief Initialize all pragma handlers. + void initializePragmaHandlers(); + + /// \brief Destroy and reset all pragma handlers. + void resetPragmaHandlers(); + /// \brief Handle the annotation token produced for #pragma unused(...) void HandlePragmaUnused(); @@ -427,6 +482,18 @@ private: /// #pragma comment... void HandlePragmaMSComment(); + void HandlePragmaMSPointersToMembers(); + + void HandlePragmaMSVtorDisp(); + + void HandlePragmaMSPragma(); + bool HandlePragmaMSSection(StringRef PragmaName, + SourceLocation PragmaLocation); + bool HandlePragmaMSSegment(StringRef PragmaName, + SourceLocation PragmaLocation); + bool HandlePragmaMSInitSeg(StringRef PragmaName, + SourceLocation PragmaLocation); + /// \brief Handle the annotation token produced for /// #pragma align... void HandlePragmaAlign(); @@ -455,6 +522,10 @@ private: /// #pragma clang __debug captured StmtResult HandlePragmaCaptured(); + /// \brief Handle the annotation token produced for + /// #pragma clang loop and #pragma unroll. + LoopHint HandlePragmaLoopHint(); + /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) /// returns the token after Tok, etc. @@ -521,7 +592,7 @@ private: ANK_Success }; AnnotatedNameKind TryAnnotateName(bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC = 0); + CorrectionCandidateCallback *CCC = nullptr); /// Push a tok::annot_cxxscope token onto the token stream. void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation); @@ -562,6 +633,12 @@ private: /// otherwise emits a diagnostic and returns true. bool TryKeywordIdentFallback(bool DisableKeyword); + /// TryIdentKeywordUpgrade - Convert the current identifier token back to + /// its original kind and return true if it was disabled by + /// TryKeywordIdentFallback(), otherwise return false. Use this to + /// contextually enable keywords. + bool TryIdentKeywordUpgrade(); + /// \brief Get the TemplateIdAnnotation from the token. TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok); @@ -628,7 +705,7 @@ private: public: explicit ObjCDeclContextSwitch(Parser &p) : P(p), DC(p.getObjCDeclContext()), - WithinObjCContainer(P.ParsingInObjCContainer, DC != 0) { + WithinObjCContainer(P.ParsingInObjCContainer, DC != nullptr) { if (DC) P.Actions.ActOnObjCTemporaryExitContainerContext(cast<DeclContext>(DC)); } @@ -641,12 +718,14 @@ private: /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the /// input. If so, it is consumed and false is returned. /// - /// If the input is malformed, this emits the specified diagnostic. Next, if - /// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is + /// If a trivial punctuator misspelling is encountered, a FixIt error + /// diagnostic is issued and false is returned after recovery. + /// + /// If the input is malformed, this emits the specified diagnostic and true is /// returned. - bool ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned Diag, - const char *DiagMsg = "", - tok::TokenKind SkipToTok = tok::unknown); + bool ExpectAndConsume(tok::TokenKind ExpectedTok, + unsigned Diag = diag::err_expected, + StringRef DiagMsg = ""); /// \brief The parser expects a semicolon and, if present, will consume it. /// @@ -684,14 +763,18 @@ public: public: // ParseScope - Construct a new object to manage a scope in the // parser Self where the new Scope is created with the flags - // ScopeFlags, but only when ManageScope is true (the default). If - // ManageScope is false, this object does nothing. - ParseScope(Parser *Self, unsigned ScopeFlags, bool ManageScope = true) + // ScopeFlags, but only when we aren't about to enter a compound statement. + ParseScope(Parser *Self, unsigned ScopeFlags, bool EnteredScope = true, + bool BeforeCompoundStmt = false) : Self(Self) { - if (ManageScope) + if (EnteredScope && !BeforeCompoundStmt) Self->EnterScope(ScopeFlags); - else - this->Self = 0; + else { + if (BeforeCompoundStmt) + Self->incrementMSLocalManglingNumber(); + + this->Self = nullptr; + } } // Exit - Exit the scope associated with this object now, rather @@ -699,7 +782,7 @@ public: void Exit() { if (Self) { Self->ExitScope(); - Self = 0; + Self = nullptr; } } @@ -818,10 +901,10 @@ private: LateParsedClass(Parser *P, ParsingClass *C); virtual ~LateParsedClass(); - virtual void ParseLexedMethodDeclarations(); - virtual void ParseLexedMemberInitializers(); - virtual void ParseLexedMethodDefs(); - virtual void ParseLexedAttributes(); + void ParseLexedMethodDeclarations() override; + void ParseLexedMemberInitializers() override; + void ParseLexedMethodDefs() override; + void ParseLexedAttributes() override; private: Parser *Self; @@ -845,7 +928,7 @@ private: SourceLocation Loc) : Self(P), AttrName(Name), AttrNameLoc(Loc) {} - virtual void ParseLexedAttributes(); + void ParseLexedAttributes() override; void addDecl(Decl *D) { Decls.push_back(D); } }; @@ -877,7 +960,7 @@ private: explicit LexedMethod(Parser* P, Decl *MD) : Self(P), D(MD), TemplateScope(false) {} - virtual void ParseLexedMethodDefs(); + void ParseLexedMethodDefs() override; }; /// LateParsedDefaultArgument - Keeps track of a parameter that may @@ -886,7 +969,7 @@ private: /// (C++ [class.mem]p2). struct LateParsedDefaultArgument { explicit LateParsedDefaultArgument(Decl *P, - CachedTokens *Toks = 0) + CachedTokens *Toks = nullptr) : Param(P), Toks(Toks) { } /// Param - The parameter declaration for this parameter. @@ -905,9 +988,10 @@ private: /// argument (C++ [class.mem]p2). struct LateParsedMethodDeclaration : public LateParsedDeclaration { explicit LateParsedMethodDeclaration(Parser *P, Decl *M) - : Self(P), Method(M), TemplateScope(false), ExceptionSpecTokens(0) { } + : Self(P), Method(M), TemplateScope(false), + ExceptionSpecTokens(nullptr) {} - virtual void ParseLexedMethodDeclarations(); + void ParseLexedMethodDeclarations() override; Parser* Self; @@ -938,7 +1022,7 @@ private: LateParsedMemberInitializer(Parser *P, Decl *FD) : Self(P), Field(FD) { } - virtual void ParseLexedMemberInitializers(); + void ParseLexedMemberInitializers() override; Parser *Self; @@ -1028,7 +1112,7 @@ private: /// specifiers. struct ParsedTemplateInfo { ParsedTemplateInfo() - : Kind(NonTemplate), TemplateParams(0), TemplateLoc() { } + : Kind(NonTemplate), TemplateParams(nullptr), TemplateLoc() { } ParsedTemplateInfo(TemplateParameterLists *TemplateParams, bool isSpecialization, @@ -1039,7 +1123,7 @@ private: explicit ParsedTemplateInfo(SourceLocation ExternLoc, SourceLocation TemplateLoc) - : Kind(ExplicitInstantiation), TemplateParams(0), + : Kind(ExplicitInstantiation), TemplateParams(nullptr), ExternLoc(ExternLoc), TemplateLoc(TemplateLoc), LastParameterListWasEmpty(false){ } @@ -1132,12 +1216,12 @@ private: }; DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs, - ParsingDeclSpec *DS = 0); + ParsingDeclSpec *DS = nullptr); bool isDeclarationAfterDeclarator(); bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator); DeclGroupPtrTy ParseDeclarationOrFunctionDefinition( ParsedAttributesWithRange &attrs, - ParsingDeclSpec *DS = 0, + ParsingDeclSpec *DS = nullptr, AccessSpecifier AS = AS_none); DeclGroupPtrTy ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, ParsingDeclSpec &DS, @@ -1145,11 +1229,11 @@ private: Decl *ParseFunctionDefinition(ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), - LateParsedAttrList *LateParsedAttrs = 0); + LateParsedAttrList *LateParsedAttrs = nullptr); void ParseKNRParamDeclarations(Declarator &D); // EndLoc, if non-NULL, is filled with the location of the last token of // the simple-asm. - ExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0); + ExprResult ParseSimpleAsm(SourceLocation *EndLoc = nullptr); ExprResult ParseAsmStringLiteral(); // Objective-C External Declarations @@ -1289,12 +1373,12 @@ private: typedef SmallVector<SourceLocation, 20> CommaLocsTy; /// ParseExpressionList - Used for C/C++ (argument-)expression-list. - bool ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, - SmallVectorImpl<SourceLocation> &CommaLocs, - void (Sema::*Completer)(Scope *S, - Expr *Data, - ArrayRef<Expr *> Args) = 0, - Expr *Data = 0); + bool + ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, + SmallVectorImpl<SourceLocation> &CommaLocs, + void (Sema::*Completer)(Scope *S, Expr *Data, + ArrayRef<Expr *> Args) = nullptr, + Expr *Data = nullptr); /// ParseSimpleExpressionList - A simple comma-separated list of expressions, /// used for misc language extensions. @@ -1315,9 +1399,9 @@ private: ParsedType &CastTy, SourceLocation &RParenLoc); - ExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, - ParsedType &CastTy, - BalancedDelimiterTracker &Tracker); + ExprResult ParseCXXAmbiguousParenExpression( + ParenParseOption &ExprType, ParsedType &CastTy, + BalancedDelimiterTracker &Tracker, ColonProtectionRAIIObject &ColonProt); ExprResult ParseCompoundLiteralExpression(ParsedType Ty, SourceLocation LParenLoc, SourceLocation RParenLoc); @@ -1341,9 +1425,9 @@ private: bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ParsedType ObjectType, bool EnteringContext, - bool *MayBePseudoDestructor = 0, + bool *MayBePseudoDestructor = nullptr, bool IsTypename = false, - IdentifierInfo **LastII = 0); + IdentifierInfo **LastII = nullptr); void CheckForLParenAfterColonColon(); @@ -1354,7 +1438,7 @@ private: ExprResult ParseLambdaExpression(); ExprResult TryParseLambdaExpression(); Optional<unsigned> ParseLambdaIntroducer(LambdaIntroducer &Intro, - bool *SkippedInits = 0); + bool *SkippedInits = nullptr); bool TryParseLambdaIntroducer(LambdaIntroducer &Intro); ExprResult ParseLambdaExpressionAfterIntroducer( LambdaIntroducer &Intro); @@ -1490,10 +1574,10 @@ private: /// A SmallVector of types. typedef SmallVector<ParsedType, 12> TypeVector; - StmtResult ParseStatement(SourceLocation *TrailingElseLoc = 0); - StmtResult ParseStatementOrDeclaration(StmtVector &Stmts, - bool OnlyStatement, - SourceLocation *TrailingElseLoc = 0); + StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr); + StmtResult + ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, + SourceLocation *TrailingElseLoc = nullptr); StmtResult ParseStatementOrDeclarationAfterAttributes( StmtVector &Stmts, bool OnlyStatement, @@ -1524,6 +1608,9 @@ private: StmtResult ParseReturnStatement(); StmtResult ParseAsmStatement(bool &msAsm); StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc); + StmtResult ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement, + SourceLocation *TrailingElseLoc, + ParsedAttributesWithRange &Attrs); /// \brief Describes the behavior that should be taken for an __if_exists /// block. @@ -1582,6 +1669,7 @@ private: StmtResult ParseSEHTryBlockCommon(SourceLocation Loc); StmtResult ParseSEHExceptBlock(SourceLocation Loc); StmtResult ParseSEHFinallyBlock(SourceLocation Loc); + StmtResult ParseSEHLeaveStatement(); //===--------------------------------------------------------------------===// // Objective-C Statements @@ -1604,9 +1692,29 @@ private: DSC_class, // class context, enables 'friend' 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 + DSC_alias_declaration, // C++11 type-specifier-seq in an alias-declaration + DSC_top_level, // top-level/namespace declaration context + DSC_template_type_arg // template type argument context }; + /// Is this a context in which we are parsing just a type-specifier (or + /// trailing-type-specifier)? + static bool isTypeSpecifier(DeclSpecContext DSC) { + switch (DSC) { + case DSC_normal: + case DSC_class: + case DSC_top_level: + return false; + + case DSC_template_type_arg: + case DSC_type_specifier: + case DSC_trailing: + case DSC_alias_declaration: + return true; + } + llvm_unreachable("Missing DeclSpecContext case"); + } + /// Information on a C++0x for-range-initializer found while parsing a /// declaration which turns out to be a for-range-declaration. struct ForRangeInit { @@ -1624,17 +1732,19 @@ private: SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs, bool RequireSemi, - ForRangeInit *FRI = 0); + ForRangeInit *FRI = nullptr); bool MightBeDeclarator(unsigned Context); DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, - SourceLocation *DeclEnd = 0, - ForRangeInit *FRI = 0); + SourceLocation *DeclEnd = nullptr, + ForRangeInit *FRI = nullptr); Decl *ParseDeclarationAfterDeclarator(Declarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); bool ParseAsmAttributesAfterDeclarator(Declarator &D); - Decl *ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); + Decl *ParseDeclarationAfterDeclaratorAndAttributes( + Declarator &D, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + ForRangeInit *FRI = nullptr); Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope); Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope); @@ -1653,10 +1763,10 @@ private: const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none, DeclSpecContext DSC = DSC_normal, - LateParsedAttrList *LateAttrs = 0); + LateParsedAttrList *LateAttrs = nullptr); bool DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, - DeclSpecContext DSContext, - LateParsedAttrList *LateAttrs = 0); + DeclSpecContext DSContext, + LateParsedAttrList *LateAttrs = nullptr); void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none, DeclSpecContext DSC = DSC_normal); @@ -1696,7 +1806,7 @@ private: /// cast. Return false if it's no a decl-specifier, or we're not sure. bool isKnownToBeDeclarationSpecifier() { if (getLangOpts().CPlusPlus) - return isCXXDeclarationSpecifier() == TPResult::True(); + return isCXXDeclarationSpecifier() == TPResult::True; return isDeclarationSpecifier(true); } @@ -1719,6 +1829,9 @@ private: return isDeclarationSpecifier(true); } + /// \brief Determine whether this is a C++1z for-range-identifier. + bool isForRangeIdentifier(); + /// \brief Determine whether we are currently at the start of an Objective-C /// class message that appears to be missing the open bracket '['. bool isStartOfObjCClassMessageMissingOpenBracket(); @@ -1726,12 +1839,13 @@ private: /// \brief Starting with a scope specifier, identifier, or /// template-id that refers to the current class, determine whether /// this is a constructor declarator. - bool isConstructorDeclarator(); + bool isConstructorDeclarator(bool Unqualified); /// \brief Specifies the context in which type-id/expression /// disambiguation will occur. enum TentativeCXXTypeIdContext { TypeIdInParens, + TypeIdUnambiguous, TypeIdAsTemplateArgument }; @@ -1750,6 +1864,16 @@ private: return isTypeIdInParens(isAmbiguous); } + /// \brief Checks if the current tokens form type-id or expression. + /// It is similar to isTypeIdInParens but does not suppose that type-id + /// is in parenthesis. + bool isTypeIdUnambiguously() { + bool IsAmbiguous; + if (getLangOpts().CPlusPlus) + return isCXXTypeId(TypeIdUnambiguous, IsAmbiguous); + return isTypeSpecifierQualifier(); + } + /// isCXXDeclarationStatement - C++-specialized function that disambiguates /// between a declaration or an expression statement, when parsing function /// bodies. Returns true for declaration, false for expression. @@ -1769,7 +1893,7 @@ private: /// 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 *IsAmbiguous = 0); + bool isCXXFunctionDeclarator(bool *IsAmbiguous = nullptr); /// isCXXConditionDeclaration - Disambiguates between a declaration or an /// expression for a condition of a if/switch/while/for statement. @@ -1785,25 +1909,8 @@ private: /// TPResult - Used as the result value for functions whose purpose is to /// disambiguate C++ constructs by "tentatively parsing" them. - /// This is a class instead of a simple enum because the implicit enum-to-bool - /// conversions may cause subtle bugs. - class TPResult { - enum Result { - TPR_true, - TPR_false, - TPR_ambiguous, - TPR_error - }; - Result Res; - TPResult(Result result) : Res(result) {} - public: - static TPResult True() { return TPR_true; } - static TPResult False() { return TPR_false; } - static TPResult Ambiguous() { return TPR_ambiguous; } - static TPResult Error() { return TPR_error; } - - bool operator==(const TPResult &RHS) const { return Res == RHS.Res; } - bool operator!=(const TPResult &RHS) const { return Res != RHS.Res; } + enum class TPResult { + True, False, Ambiguous, Error }; /// \brief Based only on the given token kind, determine whether we know that @@ -1818,16 +1925,16 @@ private: /// tell. TPResult isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind); - /// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a - /// declaration specifier, TPResult::False() if it is not, - /// TPResult::Ambiguous() if it could be either a decl-specifier or a - /// function-style cast, and TPResult::Error() if a parsing error was + /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a + /// declaration specifier, TPResult::False if it is not, + /// TPResult::Ambiguous if it could be either a decl-specifier or a + /// function-style cast, and TPResult::Error if a parsing error was /// encountered. If it could be a braced C++11 function-style cast, returns /// BracedCastResult. /// Doesn't consume tokens. TPResult - isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False(), - bool *HasMissingTypename = 0); + isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False, + bool *HasMissingTypename = nullptr); /// Given that isCXXDeclarationSpecifier returns \c TPResult::True or /// \c TPResult::Ambiguous, determine whether the decl-specifier would be @@ -1840,9 +1947,9 @@ private: bool isTentativelyDeclared(IdentifierInfo *II); // "Tentative parsing" functions, used for disambiguation. If a parsing error - // is encountered they will return TPResult::Error(). - // Returning TPResult::True()/False() indicates that the ambiguity was - // resolved and tentative parsing may stop. TPResult::Ambiguous() indicates + // is encountered they will return TPResult::Error. + // Returning TPResult::True/False indicates that the ambiguity was + // resolved and tentative parsing may stop. TPResult::Ambiguous indicates // that more tentative parsing is necessary for disambiguation. // They all consume tokens, so backtracking should be used after calling them. @@ -1853,19 +1960,20 @@ private: TPResult TryParseOperatorId(); TPResult TryParseInitDeclaratorList(); TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true); - TPResult TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = 0, - bool VersusTemplateArg = false); + TPResult + TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = nullptr, + bool VersusTemplateArg = false); TPResult TryParseFunctionDeclarator(); TPResult TryParseBracketDeclarator(); TPResult TryConsumeDeclarationSpecifier(); public: - TypeResult ParseTypeName(SourceRange *Range = 0, + TypeResult ParseTypeName(SourceRange *Range = nullptr, Declarator::TheContext Context = Declarator::TypeNameContext, AccessSpecifier AS = AS_none, - Decl **OwnedType = 0, - ParsedAttributes *Attrs = 0); + Decl **OwnedType = nullptr, + ParsedAttributes *Attrs = nullptr); private: void ParseBlockId(SourceLocation CaretLoc); @@ -1903,35 +2011,51 @@ private: // for example, attributes appertain to decl specifiers. void ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs); + /// \brief Skip C++11 attributes and return the end location of the last one. + /// \returns SourceLocation() if there are no attributes. + SourceLocation SkipCXX11Attributes(); + /// \brief Diagnose and skip C++11 attributes that appear in syntactic /// locations where attributes are not allowed. void DiagnoseAndSkipCXX11Attributes(); + /// \brief Parses syntax-generic attribute arguments for attributes which are + /// known to the implementation, and adds them to the given ParsedAttributes + /// list with the given attribute syntax. Returns the number of arguments + /// parsed for the attribute. + unsigned + ParseAttributeArgsCommon(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, SourceLocation *EndLoc, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, + AttributeList::Syntax Syntax); + void MaybeParseGNUAttributes(Declarator &D, - LateParsedAttrList *LateAttrs = 0) { + LateParsedAttrList *LateAttrs = nullptr) { if (Tok.is(tok::kw___attribute)) { ParsedAttributes attrs(AttrFactory); SourceLocation endLoc; - ParseGNUAttributes(attrs, &endLoc, LateAttrs); + ParseGNUAttributes(attrs, &endLoc, LateAttrs, &D); D.takeAttributes(attrs, endLoc); } } void MaybeParseGNUAttributes(ParsedAttributes &attrs, - SourceLocation *endLoc = 0, - LateParsedAttrList *LateAttrs = 0) { + SourceLocation *endLoc = nullptr, + LateParsedAttrList *LateAttrs = nullptr) { if (Tok.is(tok::kw___attribute)) ParseGNUAttributes(attrs, endLoc, LateAttrs); } void ParseGNUAttributes(ParsedAttributes &attrs, - SourceLocation *endLoc = 0, - LateParsedAttrList *LateAttrs = 0); + SourceLocation *endLoc = nullptr, + LateParsedAttrList *LateAttrs = nullptr, + Declarator *D = nullptr); void ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + AttributeList::Syntax Syntax, + Declarator *D); IdentifierLoc *ParseIdentifierLoc(); void MaybeParseCXX11Attributes(Declarator &D) { @@ -1943,7 +2067,7 @@ private: } } void MaybeParseCXX11Attributes(ParsedAttributes &attrs, - SourceLocation *endLoc = 0) { + SourceLocation *endLoc = nullptr) { if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrsWithRange(AttrFactory); ParseCXX11Attributes(attrsWithRange, endLoc); @@ -1951,7 +2075,7 @@ private: } } void MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs, - SourceLocation *endLoc = 0, + SourceLocation *endLoc = nullptr, bool OuterMightBeMessageSend = false) { if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) @@ -1959,54 +2083,68 @@ private: } void ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, - SourceLocation *EndLoc = 0); + SourceLocation *EndLoc = nullptr); void ParseCXX11Attributes(ParsedAttributesWithRange &attrs, - SourceLocation *EndLoc = 0); + SourceLocation *EndLoc = nullptr); + /// \brief Parses a C++-style attribute argument list. Returns true if this + /// results in adding an attribute to the ParsedAttributes list. + bool ParseCXX11AttributeArgs(IdentifierInfo *AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc); IdentifierInfo *TryParseCXX11AttributeIdentifier(SourceLocation &Loc); void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs, - SourceLocation *endLoc = 0) { + SourceLocation *endLoc = nullptr) { if (getLangOpts().MicrosoftExt && Tok.is(tok::l_square)) ParseMicrosoftAttributes(attrs, endLoc); } void ParseMicrosoftAttributes(ParsedAttributes &attrs, - SourceLocation *endLoc = 0); + SourceLocation *endLoc = nullptr); void ParseMicrosoftDeclSpec(ParsedAttributes &Attrs); - bool IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident); - void ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, - SourceLocation Loc, - ParsedAttributes &Attrs); - void ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs); + bool ParseMicrosoftDeclSpecArgs(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); + void ParseOpenCLQualifiers(ParsedAttributes &Attrs); VersionTuple ParseVersionTuple(SourceRange &Range); void ParseAvailabilityAttribute(IdentifierInfo &Availability, SourceLocation AvailabilityLoc, ParsedAttributes &attrs, - SourceLocation *endLoc); - - bool IsThreadSafetyAttribute(StringRef AttrName); - void ParseThreadSafetyAttribute(IdentifierInfo &AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc); + SourceLocation *endLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax); + + void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, + SourceLocation ObjCBridgeRelatedLoc, + ParsedAttributes &attrs, + SourceLocation *endLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax); void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, - SourceLocation *EndLoc); + SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax); void ParseAttributeWithTypeArg(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, - SourceLocation *EndLoc); + SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax); void ParseTypeofSpecifier(DeclSpec &DS); SourceLocation ParseDecltypeSpecifier(DeclSpec &DS); @@ -2019,7 +2157,7 @@ private: ExprResult ParseAlignArgument(SourceLocation Start, SourceLocation &EllipsisLoc); void ParseAlignmentSpecifier(ParsedAttributes &Attrs, - SourceLocation *endLoc = 0); + SourceLocation *endLoc = nullptr); VirtSpecifiers::Specifier isCXX11VirtSpecifier(const Token &Tok) const; VirtSpecifiers::Specifier isCXX11VirtSpecifier() const { @@ -2090,6 +2228,7 @@ private: SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo, SourceLocation &EllipsisLoc); void ParseBracketDeclarator(Declarator &D); + void ParseMisplacedBracketDeclarator(Declarator &D); //===--------------------------------------------------------------------===// // C++ 7: Declarations [dcl.dcl] @@ -2123,7 +2262,7 @@ private: const ParsedTemplateInfo &TemplateInfo, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs, - Decl **OwnedType = 0); + Decl **OwnedType = nullptr); Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, SourceLocation &DeclEnd, @@ -2133,7 +2272,7 @@ private: SourceLocation UsingLoc, SourceLocation &DeclEnd, AccessSpecifier AS = AS_none, - Decl **OwnedType = 0); + Decl **OwnedType = nullptr); Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd); Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, @@ -2154,9 +2293,13 @@ private: Decl *TagDecl); ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc); + void ParseCXXMemberDeclaratorBeforeInitializer(Declarator &DeclaratorInfo, + VirtSpecifiers &VS, + ExprResult &BitfieldSize, + LateParsedAttrList &LateAttrs); void ParseCXXClassMemberDeclaration(AccessSpecifier AS, AttributeList *Attr, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), - ParsingDeclRAIIObject *DiagsFromTParams = 0); + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + ParsingDeclRAIIObject *DiagsFromTParams = nullptr); void ParseConstructorInitializer(Decl *ConstructorDecl); MemInitResult ParseMemInitializer(Decl *ConstructorDecl); void HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, @@ -2197,7 +2340,12 @@ private: SmallVectorImpl<Expr *> &VarList, bool AllowScopeSpecifier); /// \brief Parses declarative or executable directive. - StmtResult ParseOpenMPDeclarativeOrExecutableDirective(); + /// + /// \param StandAloneAllowed true if allowed stand-alone directives, + /// false - otherwise + /// + StmtResult + ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed); /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind. /// /// \param DKind Kind of current directive. @@ -2217,6 +2365,17 @@ private: /// \param Kind Kind of current clause. /// OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind); + /// \brief Parses clause with a single expression and an additional argument + /// of a kind \a Kind. + /// + /// \param Kind Kind of current clause. + /// + OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind); + /// \brief Parses clause without any additional arguments. + /// + /// \param Kind Kind of current clause. + /// + OMPClause *ParseOpenMPClause(OpenMPClauseKind Kind); /// \brief Parses clause with the list of variables of a kind \a Kind. /// /// \param Kind Kind of current clause. @@ -2236,9 +2395,9 @@ private: // C++ 14.1: Template Parameters [temp.param] Decl *ParseDeclarationStartingWithTemplate(unsigned Context, - SourceLocation &DeclEnd, - AccessSpecifier AS = AS_none, - AttributeList *AccessAttrs = 0); + SourceLocation &DeclEnd, + AccessSpecifier AS = AS_none, + AttributeList *AccessAttrs = nullptr); Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context, SourceLocation &DeclEnd, AccessSpecifier AS, @@ -2249,7 +2408,7 @@ private: ParsingDeclRAIIObject &DiagsFromParams, SourceLocation &DeclEnd, AccessSpecifier AS=AS_none, - AttributeList *AccessAttrs = 0); + AttributeList *AccessAttrs = nullptr); bool ParseTemplateParameters(unsigned Depth, SmallVectorImpl<Decl*> &TemplateParams, SourceLocation &LAngleLoc, @@ -2261,6 +2420,12 @@ private: Decl *ParseTypeParameter(unsigned Depth, unsigned Position); Decl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position); Decl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position); + void DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc, + SourceLocation CorrectLoc, + bool AlreadyHasEllipsis, + bool IdentifierHasName); + void DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc, + Declarator &D); // C++ 14.3: Template arguments [temp.arg] typedef SmallVector<ParsedTemplateArgument, 16> TemplateArgList; @@ -2295,9 +2460,7 @@ private: DeclGroupPtrTy ParseModuleImport(SourceLocation AtLoc); //===--------------------------------------------------------------------===// - // GNU G++: Type Traits [Type-Traits.html in the GCC manual] - ExprResult ParseUnaryTypeTrait(); - ExprResult ParseBinaryTypeTrait(); + // C++11/G++: Type Traits [Type-Traits.html in the GCC manual] ExprResult ParseTypeTrait(); //===--------------------------------------------------------------------===// @@ -2307,14 +2470,13 @@ private: //===--------------------------------------------------------------------===// // Preprocessor code-completion pass-through - virtual void CodeCompleteDirective(bool InConditional); - virtual void CodeCompleteInConditionalExclusion(); - virtual void CodeCompleteMacroName(bool IsDefinition); - virtual void CodeCompletePreprocessorExpression(); - virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro, - MacroInfo *MacroInfo, - unsigned ArgumentIndex); - virtual void CodeCompleteNaturalLanguage(); + void CodeCompleteDirective(bool InConditional) override; + void CodeCompleteInConditionalExclusion() override; + void CodeCompleteMacroName(bool IsDefinition) override; + void CodeCompletePreprocessorExpression() override; + void CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo, + unsigned ArgumentIndex) override; + void CodeCompleteNaturalLanguage() override; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h index 3cd0461..ec061dc 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h @@ -63,7 +63,7 @@ namespace html { void AddLineNumbers(Rewriter& R, FileID FID); void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID, - const char *title = NULL); + const char *title = nullptr); /// SyntaxHighlight - Relex the specified FileID and annotate the HTML with /// information about keywords, comments, etc. diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h index a5192ef..f312aed 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_REWRITEROPE_H #define LLVM_CLANG_REWRITEROPE_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include <cassert> #include <cstddef> @@ -60,7 +61,7 @@ namespace clang { unsigned StartOffs; unsigned EndOffs; - RopePiece() : StrData(0), StartOffs(0), EndOffs(0) {} + RopePiece() : StrData(nullptr), StartOffs(0), EndOffs(0) {} RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End) : StrData(Str), StartOffs(Start), EndOffs(End) { @@ -121,7 +122,8 @@ namespace clang { // begin iterator. RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N); // end iterator - RopePieceBTreeIterator() : CurNode(0), CurPiece(0), CurChar(0) {} + RopePieceBTreeIterator() + : CurNode(nullptr), CurPiece(nullptr), CurChar(0) {} char operator*() const { return (*CurPiece)[CurChar]; @@ -144,7 +146,11 @@ namespace clang { inline RopePieceBTreeIterator operator++(int) { // Postincrement RopePieceBTreeIterator tmp = *this; ++*this; return tmp; } - private: + + llvm::StringRef piece() const { + return llvm::StringRef(&(*CurPiece)[0], CurPiece->size()); + } + void MoveToNextPiece(); }; @@ -190,9 +196,9 @@ class RewriteRope { enum { AllocChunkSize = 4080 }; public: - RewriteRope() : AllocBuffer(0), AllocOffs(AllocChunkSize) {} + RewriteRope() : AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {} RewriteRope(const RewriteRope &RHS) - : Chunks(RHS.Chunks), AllocBuffer(0), AllocOffs(AllocChunkSize) { + : Chunks(RHS.Chunks), AllocBuffer(nullptr), AllocOffs(AllocChunkSize) { } ~RewriteRope() { diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h index 2d2917b..7b22fb4 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h @@ -151,7 +151,7 @@ public: explicit Rewriter(SourceManager &SM, const LangOptions &LO) : SourceMgr(&SM), LangOpts(&LO) {} - explicit Rewriter() : SourceMgr(0), LangOpts(0) {} + explicit Rewriter() : SourceMgr(nullptr), LangOpts(nullptr) {} void setSourceMgr(SourceManager &SM, const LangOptions &LO) { SourceMgr = &SM; @@ -275,7 +275,7 @@ public: const RewriteBuffer *getRewriteBufferFor(FileID FID) const { std::map<FileID, RewriteBuffer>::const_iterator I = RewriteBuffers.find(FID); - return I == RewriteBuffers.end() ? 0 : &I->second; + return I == RewriteBuffers.end() ? nullptr : &I->second; } // Iterators over rewrite buffers. diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h index ec0bb5b..c313b45 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h @@ -17,9 +17,9 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Token.h" -#include "llvm/ADT/OwningPtr.h" #include <list> #include <map> +#include <memory> namespace clang { class LangOptions; @@ -41,7 +41,7 @@ namespace clang { /// ScratchBuf - This is the buffer that we create scratch tokens from. /// - OwningPtr<ScratchBuffer> ScratchBuf; + std::unique_ptr<ScratchBuffer> ScratchBuf; TokenRewriter(const TokenRewriter &) LLVM_DELETED_FUNCTION; void operator=(const TokenRewriter &) LLVM_DELETED_FUNCTION; diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h index 423f066..3ad8f40 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h @@ -90,7 +90,7 @@ public: /// \brief Check whether there are modifications for a given file. bool IsModified(FileID ID) const { - return Rewrite.getRewriteBufferFor(ID) != NULL; + return Rewrite.getRewriteBufferFor(ID) != nullptr; } // Iteration over files with changes. @@ -106,18 +106,18 @@ public: /// /// \returns true if there was an error, false otherwise. bool WriteFixedFiles( - std::vector<std::pair<std::string, std::string> > *RewrittenFiles = 0); + std::vector<std::pair<std::string, std::string> > *RewrittenFiles=nullptr); /// IncludeInDiagnosticCounts - This method (whose default implementation /// returns true) indicates whether the diagnostics handled by this /// DiagnosticConsumer should be included in the number of diagnostics /// reported by DiagnosticsEngine. - virtual bool IncludeInDiagnosticCounts() const; + bool IncludeInDiagnosticCounts() const override; /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or /// capturing it to a log as needed. - virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info); + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override; /// \brief Emit a diagnostic via the adapted diagnostic client. void Diag(SourceLocation Loc, unsigned DiagID); diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h index ea876d9..fc79270 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h @@ -22,24 +22,24 @@ class FixItOptions; class HTMLPrintAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class FixItAction : public ASTFrontendAction { protected: - OwningPtr<FixItRewriter> Rewriter; - OwningPtr<FixItOptions> FixItOpts; + std::unique_ptr<FixItRewriter> Rewriter; + std::unique_ptr<FixItOptions> FixItOpts; - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; - virtual bool BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename); + bool BeginSourceFileAction(CompilerInstance &CI, + StringRef Filename) override; - virtual void EndSourceFileAction(); + void EndSourceFileAction() override; - virtual bool hasASTFileSupport() const { return false; } + bool hasASTFileSupport() const override { return false; } public: FixItAction(); @@ -54,28 +54,28 @@ public: : WrapperFrontendAction(WrappedAction) {} protected: - virtual bool BeginInvocation(CompilerInstance &CI); + bool BeginInvocation(CompilerInstance &CI) override; }; class RewriteObjCAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class RewriteMacrosAction : public PreprocessorFrontendAction { protected: - void ExecuteAction(); + void ExecuteAction() override; }; class RewriteTestAction : public PreprocessorFrontendAction { protected: - void ExecuteAction(); + void ExecuteAction() override; }; class RewriteIncludesAction : public PreprocessorFrontendAction { protected: - void ExecuteAction(); + void ExecuteAction() override; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h index 508064d..c21c19f 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h @@ -18,8 +18,9 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/VersionTuple.h" #include "clang/Sema/Ownership.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/Allocator.h" #include <cassert> @@ -79,7 +80,9 @@ public: /// __declspec(...) AS_Declspec, /// __ptr16, alignas(...), etc. - AS_Keyword + AS_Keyword, + /// #pragma ... + AS_Pragma }; private: @@ -217,7 +220,7 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), - HasParsedType(false), NextInPosition(0), NextInPool(0) { + HasParsedType(false), NextInPosition(nullptr), NextInPool(nullptr) { if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -236,7 +239,7 @@ private: Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), UnavailableLoc(unavailable), MessageExpr(messageExpr), - NextInPosition(0), NextInPool(0) { + NextInPosition(nullptr), NextInPool(nullptr) { ArgsUnion PVal(Parm); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); @@ -245,6 +248,26 @@ private: AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } + /// Constructor for objc_bridge_related attributes. + AttributeList(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Parm1, + IdentifierLoc *Parm2, + IdentifierLoc *Parm3, + Syntax syntaxUsed) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed), + Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), + IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), + NextInPosition(nullptr), NextInPool(nullptr) { + ArgsVector Args; + Args.push_back(Parm1); + Args.push_back(Parm2); + Args.push_back(Parm3); + memcpy(getArgsBuffer(), &Args[0], 3 * sizeof(ArgsUnion)); + AttrKind = getKind(getName(), getScopeName(), syntaxUsed); + } + /// Constructor for type_tag_for_datatype attribute. AttributeList(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, @@ -254,7 +277,7 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false), - NextInPosition(NULL), NextInPool(NULL) { + NextInPosition(nullptr), NextInPool(nullptr) { ArgsUnion PVal(ArgKind); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); @@ -272,7 +295,7 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true), - NextInPosition(0), NextInPool(0) { + NextInPosition(nullptr), NextInPool(nullptr) { new (&getTypeBuffer()) ParsedType(typeArg); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -286,7 +309,7 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), - NextInPosition(0), NextInPool(0) { + NextInPosition(nullptr), NextInPool(nullptr) { new (&getPropertyDataBuffer()) PropertyData(getterId, setterId); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -368,44 +391,6 @@ public: return getArg(Arg).get<IdentifierLoc*>(); } - class arg_iterator { - ArgsUnion const *X; - unsigned Idx; - public: - arg_iterator(ArgsUnion const *x, unsigned idx) : X(x), Idx(idx) {} - - arg_iterator& operator++() { - ++Idx; - return *this; - } - - bool operator==(const arg_iterator& I) const { - assert (X == I.X && - "compared arg_iterators are for different argument lists"); - return Idx == I.Idx; - } - - bool operator!=(const arg_iterator& I) const { - return !operator==(I); - } - - ArgsUnion operator*() const { - return X[Idx]; - } - - unsigned getArgNum() const { - return Idx+1; - } - }; - - arg_iterator arg_begin() const { - return arg_iterator(getArgsBuffer(), 0); - } - - arg_iterator arg_end() const { - return arg_iterator(getArgsBuffer(), NumArgs); - } - const AvailabilityChange &getAvailabilityIntroduced() const { assert(getKind() == AT_Availability && "Not an availability attribute"); return getAvailabilitySlot(IntroducedSlot); @@ -464,9 +449,23 @@ public: /// to pretty print itself. unsigned getAttributeSpellingListIndex() const; + bool isTargetSpecificAttr() const; + bool isTypeAttr() const; + bool hasCustomParsing() const; unsigned getMinArgs() const; unsigned getMaxArgs() const; + bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; + bool diagnoseLangOpts(class Sema &S) const; + bool existsInTarget(const llvm::Triple &T) const; + bool isKnownToGCC() const; + + /// \brief If the parsed attribute has a semantic equivalent, and it would + /// have a semantic Spelling enumeration (due to having semantically-distinct + /// spelling variations), return the value of that semantic spelling. If the + /// parsed attribute does not have a semantic equivalent, or would not have + /// a Spelling enumeration, the value UINT_MAX is returned. + unsigned getSemanticSpelling() const; }; /// A factory, from which one makes pools, from which one creates @@ -549,11 +548,11 @@ class AttributePool { public: /// Create a new pool for a factory. - AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {} + AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {} /// Move the given pool's allocations to this pool. AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { - pool.Head = 0; + pool.Head = nullptr; } AttributeFactory &getFactory() const { return Factory; } @@ -561,7 +560,7 @@ public: void clear() { if (Head) { Factory.reclaimPool(Head); - Head = 0; + Head = nullptr; } } @@ -569,7 +568,7 @@ public: void takeAllFrom(AttributePool &pool) { if (pool.Head) { takePool(pool.Head); - pool.Head = 0; + pool.Head = nullptr; } } @@ -607,8 +606,19 @@ public: syntax)); } - AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, - SourceLocation TokLoc, int Arg); + AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param1, + IdentifierLoc *Param2, + IdentifierLoc *Param3, + AttributeList::Syntax syntax) { + size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion); + void *memory = allocate(size); + return add(new (memory) AttributeList(attrName, attrRange, + scopeName, scopeLoc, + Param1, Param2, Param3, + syntax)); + } AttributeList *createTypeTagForDatatype( IdentifierInfo *attrName, SourceRange attrRange, @@ -647,40 +657,6 @@ public: } }; -/// addAttributeLists - Add two AttributeLists together -/// The right-hand list is appended to the left-hand list, if any -/// A pointer to the joined list is returned. -/// Note: the lists are not left unmodified. -inline AttributeList *addAttributeLists(AttributeList *Left, - AttributeList *Right) { - if (!Left) - return Right; - - AttributeList *next = Left, *prev; - do { - prev = next; - next = next->getNext(); - } while (next); - prev->setNext(Right); - return Left; -} - -/// CXX11AttributeList - A wrapper around a C++11 attribute list. -/// Stores, in addition to the list proper, whether or not an actual list was -/// (as opposed to an empty list, which may be ill-formed in some places) and -/// the source range of the list. -struct CXX11AttributeList { - AttributeList *AttrList; - SourceRange Range; - bool HasAttr; - CXX11AttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) - : AttrList(attrList), Range(range), HasAttr (hasAttr) { - } - CXX11AttributeList () - : AttrList(0), Range(), HasAttr(false) { - } -}; - /// ParsedAttributes - A collection of parsed attributes. Currently /// we don't differentiate between the various attribute syntaxes, /// which is basically silly. @@ -690,21 +666,18 @@ struct CXX11AttributeList { class ParsedAttributes { public: ParsedAttributes(AttributeFactory &factory) - : pool(factory), list(0) { + : pool(factory), list(nullptr) { } - ParsedAttributes(ParsedAttributes &attrs) - : pool(attrs.pool), list(attrs.list) { - attrs.list = 0; - } + ParsedAttributes(const ParsedAttributes &) LLVM_DELETED_FUNCTION; AttributePool &getPool() const { return pool; } - bool empty() const { return list == 0; } + bool empty() const { return list == nullptr; } void add(AttributeList *newAttr) { assert(newAttr); - assert(newAttr->getNext() == 0); + assert(newAttr->getNext() == nullptr); newAttr->setNext(list); list = newAttr; } @@ -726,11 +699,11 @@ public: void takeAllFrom(ParsedAttributes &attrs) { addAll(attrs.list); - attrs.list = 0; + attrs.list = nullptr; pool.takeAllFrom(attrs.pool); } - void clear() { list = 0; pool.clear(); } + void clear() { list = nullptr; pool.clear(); } AttributeList *getList() const { return list; } /// Returns a reference to the attribute list. Try not to introduce @@ -767,6 +740,20 @@ public: return attr; } + /// Add objc_bridge_related attribute. + AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param1, + IdentifierLoc *Param2, + IdentifierLoc *Param3, + AttributeList::Syntax syntax) { + AttributeList *attr = + pool.create(attrName, attrRange, scopeName, scopeLoc, + Param1, Param2, Param3, syntax); + add(attr); + return attr; + } + /// Add type_tag_for_datatype attribute. AttributeList *addNewTypeTagForDatatype( IdentifierInfo *attrName, SourceRange attrRange, @@ -808,15 +795,6 @@ public: return attr; } - AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name, - SourceLocation loc, int arg) { - AttributeList *attr = - pool.createIntegerAttribute(C, name, loc, arg); - add(attr); - return attr; - } - - private: mutable AttributePool pool; AttributeList *list; @@ -831,6 +809,42 @@ enum AttributeArgumentNType { AANT_ArgumentIdentifier }; +/// These constants match the enumerated choices of +/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. +enum AttributeDeclKind { + ExpectedFunction, + ExpectedUnion, + ExpectedVariableOrFunction, + ExpectedFunctionOrMethod, + ExpectedParameter, + ExpectedFunctionMethodOrBlock, + ExpectedFunctionMethodOrClass, + ExpectedFunctionMethodOrParameter, + ExpectedClass, + ExpectedVariable, + ExpectedMethod, + ExpectedVariableFunctionOrLabel, + ExpectedFieldOrGlobalVar, + ExpectedStruct, + ExpectedVariableFunctionOrTag, + ExpectedTLSVar, + ExpectedVariableOrField, + ExpectedVariableFieldOrTag, + ExpectedTypeOrNamespace, + ExpectedObjectiveCInterface, + ExpectedMethodOrProperty, + ExpectedStructOrUnion, + ExpectedStructOrUnionOrClass, + ExpectedType, + ExpectedObjCInstanceMethod, + ExpectedObjCInterfaceDeclInitMethod, + ExpectedFunctionVariableOrClass, + ExpectedObjectiveCProtocol, + ExpectedFunctionGlobalVarMethodOrProperty, + ExpectedStructOrTypedef, + ExpectedObjectiveCInterfaceOrProtocol +}; + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h index 64de82c..92a4e9a 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -397,7 +397,7 @@ public: CodeCompletionString *Optional; }; - Chunk() : Kind(CK_Text), Text(0) { } + Chunk() : Kind(CK_Text), Text(nullptr) { } explicit Chunk(ChunkKind Kind, const char *Text = ""); @@ -575,14 +575,14 @@ public: CodeCompletionTUInfo &CCTUInfo) : Allocator(Allocator), CCTUInfo(CCTUInfo), Priority(0), Availability(CXAvailability_Available), - BriefComment(NULL) { } + BriefComment(nullptr) { } CodeCompletionBuilder(CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, unsigned Priority, CXAvailabilityKind Availability) : Allocator(Allocator), CCTUInfo(CCTUInfo), Priority(Priority), Availability(Availability), - BriefComment(NULL) { } + BriefComment(nullptr) { } /// \brief Retrieve the allocator into which the code completion /// strings should be allocated. @@ -700,7 +700,7 @@ public: /// \brief Build a result that refers to a declaration. CodeCompletionResult(const NamedDecl *Declaration, unsigned Priority, - NestedNameSpecifier *Qualifier = 0, + NestedNameSpecifier *Qualifier = nullptr, bool QualifierIsInformative = false, bool Accessible = true) : Declaration(Declaration), Priority(Priority), @@ -714,36 +714,34 @@ public: /// \brief Build a result that refers to a keyword or symbol. CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword) - : Declaration(0), Keyword(Keyword), Priority(Priority), StartParameter(0), - Kind(RK_Keyword), CursorKind(CXCursor_NotImplemented), + : Declaration(nullptr), 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) - { - } + AllParametersAreInformative(false), DeclaringEntity(false), + Qualifier(nullptr) {} /// \brief Build a result that refers to a macro. CodeCompletionResult(const IdentifierInfo *Macro, unsigned Priority = CCP_Macro) - : Declaration(0), Macro(Macro), Priority(Priority), StartParameter(0), + : Declaration(nullptr), 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) - { - } + AllParametersAreInformative(false), DeclaringEntity(false), + Qualifier(nullptr) {} /// \brief Build a result that refers to a pattern. CodeCompletionResult(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern, CXCursorKind CursorKind = CXCursor_NotImplemented, CXAvailabilityKind Availability = CXAvailability_Available, - const NamedDecl *D = 0) + const NamedDecl *D = nullptr) : 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) + DeclaringEntity(false), Qualifier(nullptr) { } @@ -754,7 +752,8 @@ public: : 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) { + AllParametersAreInformative(false), DeclaringEntity(false), + Qualifier(nullptr) { computeCursorKindAndAvailability(); } @@ -966,20 +965,19 @@ public: CCTUInfo(new GlobalCodeCompletionAllocator) {} /// \brief Prints the finalized code-completion results. - virtual void ProcessCodeCompleteResults(Sema &S, - CodeCompletionContext Context, - CodeCompletionResult *Results, - unsigned NumResults); + void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, + CodeCompletionResult *Results, + unsigned NumResults) override; - virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, - OverloadCandidate *Candidates, - unsigned NumCandidates); + void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates) override; - virtual CodeCompletionAllocator &getAllocator() { + CodeCompletionAllocator &getAllocator() override { return CCTUInfo.getAllocator(); } - virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() { return CCTUInfo; } + CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h index 8f6bd18..8364dfc 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h @@ -178,9 +178,9 @@ public: bool isNotEmpty() const { return !isEmpty(); } /// An error occurred during parsing of the scope specifier. - bool isInvalid() const { return isNotEmpty() && getScopeRep() == 0; } + bool isInvalid() const { return isNotEmpty() && getScopeRep() == nullptr; } /// A scope specifier is present, and it refers to a real scope. - bool isValid() const { return isNotEmpty() && getScopeRep() != 0; } + bool isValid() const { return isNotEmpty() && getScopeRep() != nullptr; } /// \brief Indicate that this nested-name-specifier is invalid. void SetInvalid(SourceRange R) { @@ -193,7 +193,7 @@ public: /// Deprecated. Some call sites intend isNotEmpty() while others intend /// isValid(). - bool isSet() const { return getScopeRep() != 0; } + bool isSet() const { return getScopeRep() != nullptr; } void clear() { Range = SourceRange(); @@ -285,14 +285,6 @@ public: static const TST TST_auto = clang::TST_auto; static const TST TST_unknown_anytype = clang::TST_unknown_anytype; static const TST TST_atomic = clang::TST_atomic; - static const TST TST_image1d_t = clang::TST_image1d_t; - static const TST TST_image1d_array_t = clang::TST_image1d_array_t; - static const TST TST_image1d_buffer_t = clang::TST_image1d_buffer_t; - static const TST TST_image2d_t = clang::TST_image2d_t; - static const TST TST_image2d_array_t = clang::TST_image2d_array_t; - static const TST TST_image3d_t = clang::TST_image3d_t; - static const TST TST_sampler_t = clang::TST_sampler_t; - static const TST TST_event_t = clang::TST_event_t; static const TST TST_error = clang::TST_error; // type-qualifiers @@ -428,11 +420,11 @@ public: Friend_specified(false), Constexpr_specified(false), Attrs(attrFactory), - ProtocolQualifiers(0), + ProtocolQualifiers(nullptr), NumProtocolQualifiers(0), - ProtocolLocs(0), + ProtocolLocs(nullptr), writtenBS(), - ObjCQualifiers(0) { + ObjCQualifiers(nullptr) { } ~DeclSpec() { delete [] ProtocolQualifiers; @@ -516,7 +508,8 @@ public: bool hasTagDefinition() const; /// \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::TST T, + const PrintingPolicy &Policy); static const char *getSpecifierName(DeclSpec::TQ Q); static const char *getSpecifierName(DeclSpec::TSS S); static const char *getSpecifierName(DeclSpec::TSC C); @@ -604,36 +597,45 @@ public: /// TODO: use a more general approach that still allows these /// diagnostics to be ignored when desired. bool SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, - const char *&PrevSpec, unsigned &DiagID); + const char *&PrevSpec, unsigned &DiagID, + const PrintingPolicy &Policy); bool SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID); + unsigned &DiagID, const PrintingPolicy &Policy); bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID); + unsigned &DiagID, const PrintingPolicy &Policy); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID, ParsedType Rep); + unsigned &DiagID, ParsedType Rep, + const PrintingPolicy &Policy); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID, Decl *Rep, bool Owned); + unsigned &DiagID, Decl *Rep, bool Owned, + const PrintingPolicy &Policy); bool SetTypeSpecType(TST T, SourceLocation TagKwLoc, SourceLocation TagNameLoc, const char *&PrevSpec, - unsigned &DiagID, ParsedType Rep); + unsigned &DiagID, ParsedType Rep, + const PrintingPolicy &Policy); bool SetTypeSpecType(TST T, SourceLocation TagKwLoc, SourceLocation TagNameLoc, const char *&PrevSpec, - unsigned &DiagID, Decl *Rep, bool Owned); + unsigned &DiagID, Decl *Rep, bool Owned, + const PrintingPolicy &Policy); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID, Expr *Rep); + unsigned &DiagID, Expr *Rep, + const PrintingPolicy &policy); bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, - const char *&PrevSpec, unsigned &DiagID); + const char *&PrevSpec, unsigned &DiagID, + const PrintingPolicy &Policy); bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, - const char *&PrevSpec, unsigned &DiagID); + const char *&PrevSpec, unsigned &DiagID, + const PrintingPolicy &Policy); bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc, - const char *&PrevSpec, unsigned &DiagID); + const char *&PrevSpec, unsigned &DiagID, + const PrintingPolicy &Policy); bool SetTypeSpecError(); void UpdateDeclRep(Decl *Rep) { assert(isDeclRep((TST) TypeSpecType)); @@ -707,22 +709,12 @@ public: void addAttributes(AttributeList *AL) { Attrs.addAll(AL); } - void setAttributes(AttributeList *AL) { - Attrs.set(AL); - } bool hasAttributes() const { return !Attrs.empty(); } ParsedAttributes &getAttributes() { return Attrs; } const ParsedAttributes &getAttributes() const { return Attrs; } - /// \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. - return Attrs; - } - void takeAttributesFrom(ParsedAttributes &attrs) { Attrs.takeAllFrom(attrs); } @@ -743,7 +735,8 @@ public: /// Finish - This does final analysis of the declspec, issuing diagnostics for /// things like "_Imaginary" (lacking an FP type). After calling this method, /// DeclSpec is guaranteed self-consistent, even if an error occurred. - void Finish(DiagnosticsEngine &D, Preprocessor &PP); + void Finish(DiagnosticsEngine &D, Preprocessor &PP, + const PrintingPolicy &Policy); const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { return writtenBS; @@ -798,7 +791,7 @@ public: ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr), - GetterName(0), SetterName(0) { } + GetterName(nullptr), SetterName(nullptr) { } ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; } void setObjCDeclQualifier(ObjCDeclQualifier DQVal) { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); @@ -821,15 +814,15 @@ public: void setSetterName(IdentifierInfo *name) { SetterName = name; } private: - // FIXME: These two are unrelated and mutially exclusive. So perhaps - // we can put them in a union to reflect their mutual exclusiveness + // FIXME: These two are unrelated and mutually exclusive. So perhaps + // we can put them in a union to reflect their mutual exclusivity // (space saving is negligible). ObjCDeclQualifier objcDeclQualifier : 6; // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind unsigned PropertyAttributes : 12; - IdentifierInfo *GetterName; // getter name of NULL if no getter - IdentifierInfo *SetterName; // setter name of NULL if no setter + IdentifierInfo *GetterName; // getter name or NULL if no getter + IdentifierInfo *SetterName; // setter name or NULL if no setter }; /// \brief Represents a C++ unqualified-id that has been parsed. @@ -912,13 +905,13 @@ public: /// \brief The location of the last token that describes this unqualified-id. SourceLocation EndLocation; - UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { } + UnqualifiedId() : Kind(IK_Identifier), Identifier(nullptr) { } /// \brief Clear out this unqualified-id, setting it to default (invalid) /// state. void clear() { Kind = IK_Identifier; - Identifier = 0; + Identifier = nullptr; StartLocation = SourceLocation(); EndLocation = SourceLocation(); } @@ -1112,7 +1105,8 @@ struct DeclaratorChunk { }; /// ParamInfo - An array of paraminfo objects is allocated whenever a function - /// declarator is parsed. There are two interesting styles of arguments here: + /// declarator is parsed. There are two interesting styles of parameters + /// here: /// K&R-style identifier lists and parameter type lists. K&R-style identifier /// lists will have information about the identifier, but no type information. /// Parameter type lists will have type info (if the actions module provides @@ -1132,7 +1126,7 @@ struct DeclaratorChunk { ParamInfo() {} ParamInfo(IdentifierInfo *ident, SourceLocation iloc, Decl *param, - CachedTokens *DefArgTokens = 0) + CachedTokens *DefArgTokens = nullptr) : Ident(ident), IdentLoc(iloc), Param(param), DefaultArgTokens(DefArgTokens) {} }; @@ -1144,7 +1138,7 @@ struct DeclaratorChunk { struct FunctionTypeInfo : TypeInfoCommon { /// hasPrototype - This is true if the function had at least one typed - /// argument. If the function is () or (a,b,c), then it has no prototype, + /// parameter. If the function is () or (a,b,c), then it has no prototype, /// and is treated as a K&R-style function. unsigned hasPrototype : 1; @@ -1167,8 +1161,8 @@ struct DeclaratorChunk { /// ExceptionSpecType - An ExceptionSpecificationType value. unsigned ExceptionSpecType : 3; - /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. - unsigned DeleteArgInfo : 1; + /// DeleteParams - If this is true, we need to delete[] Params. + unsigned DeleteParams : 1; /// HasTrailingReturnType - If this is true, a trailing return type was /// specified. @@ -1183,9 +1177,9 @@ struct DeclaratorChunk { /// The location of the right parenthesis in the source. unsigned RParenLoc; - /// NumArgs - This is the number of formal arguments provided for the + /// NumParams - This is the number of formal parameters specified by the /// declarator. - unsigned NumArgs; + unsigned NumParams; /// NumExceptions - This is the number of types in the dynamic-exception- /// decl, if the function has one. @@ -1213,10 +1207,10 @@ struct DeclaratorChunk { /// \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 - /// describe the arguments for this function declarator. This is null if - /// there are no arguments specified. - ParamInfo *ArgInfo; + /// Params - This is a pointer to a new[]'d array of ParamInfo objects that + /// describe the parameters specified by this function declarator. null if + /// there are no parameters specified. + ParamInfo *Params; union { /// \brief Pointer to a new[]'d array of TypeAndRange objects that @@ -1233,30 +1227,32 @@ struct DeclaratorChunk { /// type specified. UnionParsedType TrailingReturnType; - /// \brief Reset the argument list to having zero arguments. + /// \brief Reset the parameter list to having zero parameters. /// /// This is used in various places for error recovery. - void freeArgs() { - if (DeleteArgInfo) { - delete[] ArgInfo; - DeleteArgInfo = false; + void freeParams() { + for (unsigned I = 0; I < NumParams; ++I) { + delete Params[I].DefaultArgTokens; + Params[I].DefaultArgTokens = nullptr; + } + if (DeleteParams) { + delete[] Params; + DeleteParams = false; } - NumArgs = 0; + NumParams = 0; } void destroy() { - if (DeleteArgInfo) - delete[] ArgInfo; + if (DeleteParams) + delete[] Params; if (getExceptionSpecType() == EST_Dynamic) delete[] Exceptions; } /// isKNRPrototype - Return true if this is a K&R style identifier list, /// like "void foo(a,b,c)". In a function definition, this will be followed - /// by the argument type definitions. - bool isKNRPrototype() const { - return !hasPrototype && NumArgs != 0; - } + /// by the parameter type definitions. + bool isKNRPrototype() const { return !hasPrototype && NumParams != 0; } SourceLocation getLParenLoc() const { return SourceLocation::getFromRawEncoding(LParenLoc); @@ -1388,7 +1384,7 @@ struct DeclaratorChunk { I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding(); I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding(); I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); - I.Ptr.AttrList = 0; + I.Ptr.AttrList = nullptr; return I; } @@ -1400,7 +1396,7 @@ struct DeclaratorChunk { I.Loc = Loc; I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; I.Ref.LValueRef = lvalue; - I.Ref.AttrList = 0; + I.Ref.AttrList = nullptr; return I; } @@ -1412,7 +1408,7 @@ struct DeclaratorChunk { I.Kind = Array; I.Loc = LBLoc; I.EndLoc = RBLoc; - I.Arr.AttrList = 0; + I.Arr.AttrList = nullptr; I.Arr.TypeQuals = TypeQuals; I.Arr.hasStatic = isStatic; I.Arr.isStar = isStar; @@ -1422,10 +1418,10 @@ 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 isAmbiguous, + static DeclaratorChunk getFunction(bool HasProto, + bool IsAmbiguous, SourceLocation LParenLoc, - ParamInfo *ArgInfo, unsigned NumArgs, + ParamInfo *Params, unsigned NumParams, SourceLocation EllipsisLoc, SourceLocation RParenLoc, unsigned TypeQuals, @@ -1453,7 +1449,7 @@ struct DeclaratorChunk { I.Kind = BlockPointer; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = 0; + I.Cls.AttrList = nullptr; return I; } @@ -1464,7 +1460,7 @@ struct DeclaratorChunk { I.Kind = MemberPointer; I.Loc = Loc; I.Mem.TypeQuals = TypeQuals; - I.Mem.AttrList = 0; + I.Mem.AttrList = nullptr; new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS); return I; } @@ -1476,7 +1472,7 @@ struct DeclaratorChunk { I.Kind = Paren; I.Loc = LParenLoc; I.EndLoc = RParenLoc; - I.Common.AttrList = 0; + I.Common.AttrList = nullptr; return I; } @@ -1594,7 +1590,7 @@ public: InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), GroupingParens(false), FunctionDefinition(FDK_Declaration), Redeclaration(false), - Attrs(ds.getAttributePool().getFactory()), AsmLabel(0), + Attrs(ds.getAttributePool().getFactory()), AsmLabel(nullptr), InlineParamsUsed(false), Extension(false) { } @@ -1671,7 +1667,7 @@ public: DeclTypeInfo[i].destroy(); DeclTypeInfo.clear(); Attrs.clear(); - AsmLabel = 0; + AsmLabel = nullptr; InlineParamsUsed = false; CommaLoc = SourceLocation(); EllipsisLoc = SourceLocation(); @@ -1844,7 +1840,7 @@ public: if (Name.getKind() == UnqualifiedId::IK_Identifier) return Name.Identifier; - return 0; + return nullptr; } SourceLocation getIdentifierLoc() const { return Name.StartLocation; } @@ -1899,7 +1895,7 @@ public: if (!DeclTypeInfo[i].isParen()) return &DeclTypeInfo[i]; } - return 0; + return nullptr; } /// Return the outermost (furthest from the declarator) chunk of @@ -1910,7 +1906,7 @@ public: if (!DeclTypeInfo[i-1].isParen()) return &DeclTypeInfo[i-1]; } - return 0; + return nullptr; } /// isArrayOfUnknownBound - This method returns true if the declarator @@ -2121,7 +2117,7 @@ struct FieldDeclarator { Declarator D; Expr *BitfieldSize; explicit FieldDeclarator(const DeclSpec &DS) - : D(DS, Declarator::MemberContext), BitfieldSize(0) { } + : D(DS, Declarator::MemberContext), BitfieldSize(nullptr) { } }; /// \brief Represents a C++11 virt-specifier-seq. @@ -2139,6 +2135,8 @@ public: bool SetSpecifier(Specifier VS, SourceLocation Loc, const char *&PrevSpec); + bool isUnset() const { return Specifiers == 0; } + bool isOverrideSpecified() const { return Specifiers & VS_Override; } SourceLocation getOverrideLoc() const { return VS_overrideLoc; } @@ -2159,25 +2157,23 @@ private: SourceLocation LastLocation; }; -/// \brief An individual capture in a lambda introducer. -struct LambdaCapture { - LambdaCaptureKind Kind; - SourceLocation Loc; - IdentifierInfo *Id; - SourceLocation EllipsisLoc; - ExprResult Init; - ParsedType InitCaptureType; - LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc, - IdentifierInfo* Id, - SourceLocation EllipsisLoc, - ExprResult Init, ParsedType InitCaptureType) - : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init), - InitCaptureType(InitCaptureType) - {} -}; - /// \brief Represents a complete lambda introducer. struct LambdaIntroducer { + /// \brief An individual capture in a lambda introducer. + struct LambdaCapture { + LambdaCaptureKind Kind; + SourceLocation Loc; + IdentifierInfo *Id; + SourceLocation EllipsisLoc; + ExprResult Init; + ParsedType InitCaptureType; + LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc, + IdentifierInfo *Id, SourceLocation EllipsisLoc, + ExprResult Init, ParsedType InitCaptureType) + : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init), + InitCaptureType(InitCaptureType) {} + }; + SourceRange Range; SourceLocation DefaultLoc; LambdaCaptureDefault Default; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h index 4f4a87f..85551f8 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h @@ -113,7 +113,7 @@ private: /// the complete parsing of the current declaration. class DelayedDiagnostic { public: - enum DDKind { Deprecation, Access, ForbiddenType }; + enum DDKind { Deprecation, Unavailable, Access, ForbiddenType }; unsigned char Kind; // actually a DDKind bool Triggered; @@ -122,11 +122,14 @@ public: void Destroy(); - static DelayedDiagnostic makeDeprecation(SourceLocation Loc, - const NamedDecl *D, - const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty, - StringRef Msg); + static DelayedDiagnostic makeAvailability(Sema::AvailabilityDiagnostic AD, + SourceLocation Loc, + const NamedDecl *D, + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty, + StringRef Msg, + bool ObjCPropertyAccess); + static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity) { @@ -162,12 +165,14 @@ public: } const NamedDecl *getDeprecationDecl() const { - assert(Kind == Deprecation && "Not a deprecation diagnostic."); + assert((Kind == Deprecation || Kind == Unavailable) && + "Not a deprecation diagnostic."); return DeprecationData.Decl; } StringRef getDeprecationMessage() const { - assert(Kind == Deprecation && "Not a deprecation diagnostic."); + assert((Kind == Deprecation || Kind == Unavailable) && + "Not a deprecation diagnostic."); return StringRef(DeprecationData.Message, DeprecationData.MessageLen); } @@ -198,6 +203,10 @@ public: const ObjCPropertyDecl *getObjCProperty() const { return DeprecationData.ObjCProperty; } + + bool getObjCPropertyAccess() const { + return DeprecationData.ObjCPropertyAccess; + } private: @@ -207,6 +216,7 @@ private: const ObjCPropertyDecl *ObjCProperty; const char *Message; size_t MessageLen; + bool ObjCPropertyAccess; }; struct FTD { @@ -244,7 +254,7 @@ public: /// Does this pool, or any of its ancestors, contain any diagnostics? bool empty() const { - return (Diagnostics.empty() && (Parent == NULL || Parent->empty())); + return (Diagnostics.empty() && (!Parent || Parent->empty())); } /// Add a diagnostic to this pool. @@ -257,7 +267,7 @@ public: if (pool.Diagnostics.empty()) return; if (Diagnostics.empty()) { - Diagnostics = llvm_move(pool.Diagnostics); + Diagnostics = std::move(pool.Diagnostics); } else { Diagnostics.append(pool.pool_begin(), pool.pool_end()); } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h index 99d94a1..b2404bc 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h @@ -150,11 +150,14 @@ public: /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns /// true if 'D' belongs to the given declaration context. /// - /// \param ExplicitInstantiationOrSpecialization When true, we are checking - /// whether the declaration is in scope for the purposes of explicit template - /// instantiation or specialization. The default is false. - bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0, - bool ExplicitInstantiationOrSpecialization = false) const; + /// \param AllowInlineNamespace If \c true, we are checking whether a prior + /// declaration is in scope in a declaration that requires a prior + /// declaration (because it is either explicitly qualified or is a + /// template instantiation or specialization). In this case, a + /// declaration is in scope if it's in the inline namespace set of the + /// context. + bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = nullptr, + bool AllowInlineNamespace = false) const; /// AddDecl - Link the decl to its shadowed decl chain. void AddDecl(NamedDecl *D); diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h index 83fb2be..9f342b2 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h @@ -103,6 +103,9 @@ private: /// \brief The type of the object or reference being initialized. QualType Type; + /// \brief The mangling number for the next reference temporary to be created. + mutable unsigned ManglingNumber; + struct LN { /// \brief When Kind == EK_Result, EK_Exception, EK_New, the /// location of the 'return', 'throw', or 'new' keyword, @@ -155,19 +158,19 @@ private: struct C Capture; }; - InitializedEntity() { } + InitializedEntity() : ManglingNumber(0) {} /// \brief Create the initialization entity for a variable. InitializedEntity(VarDecl *Var) - : Kind(EK_Variable), Parent(0), Type(Var->getType()), - VariableOrMember(Var) { } + : Kind(EK_Variable), Parent(nullptr), Type(Var->getType()), + ManglingNumber(0), VariableOrMember(Var) { } /// \brief Create the initialization entity for the result of a /// function, throwing an object, performing an explicit cast, or /// initializing a parameter for which there is no declaration. InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type, bool NRVO = false) - : Kind(Kind), Parent(0), Type(Type) + : Kind(Kind), Parent(nullptr), Type(Type), ManglingNumber(0) { LocAndNRVO.Location = Loc.getRawEncoding(); LocAndNRVO.NRVO = NRVO; @@ -176,7 +179,7 @@ private: /// \brief Create the initialization entity for a member subobject. InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent) : Kind(EK_Member), Parent(Parent), Type(Member->getType()), - VariableOrMember(Member) { } + ManglingNumber(0), VariableOrMember(Member) { } /// \brief Create the initialization entity for an array element. InitializedEntity(ASTContext &Context, unsigned Index, @@ -184,7 +187,8 @@ private: /// \brief Create the initialization entity for a lambda capture. InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc) - : Kind(EK_LambdaCapture), Parent(0), Type(FieldType) + : Kind(EK_LambdaCapture), Parent(nullptr), Type(FieldType), + ManglingNumber(0) { Capture.VarID = VarID; Capture.Location = Loc.getRawEncoding(); @@ -214,7 +218,7 @@ public: Entity.Kind = EK_Parameter; Entity.Type = Context.getVariableArrayDecayedType(Type.getUnqualifiedType()); - Entity.Parent = 0; + Entity.Parent = nullptr; Entity.Parameter = (static_cast<uintptr_t>(Consumed) | reinterpret_cast<uintptr_t>(Parm)); return Entity; @@ -228,7 +232,7 @@ public: InitializedEntity Entity; Entity.Kind = EK_Parameter; Entity.Type = Context.getVariableArrayDecayedType(Type); - Entity.Parent = 0; + Entity.Parent = nullptr; Entity.Parameter = (Consumed); return Entity; } @@ -258,7 +262,7 @@ public: /// \brief Create the initialization entity for a temporary. static InitializedEntity InitializeTemporary(QualType Type) { InitializedEntity Result(EK_Temporary, SourceLocation(), Type); - Result.TypeInfo = 0; + Result.TypeInfo = nullptr; return Result; } @@ -290,14 +294,16 @@ public: } /// \brief Create the initialization entity for a member subobject. - static InitializedEntity InitializeMember(FieldDecl *Member, - const InitializedEntity *Parent = 0) { + static InitializedEntity + InitializeMember(FieldDecl *Member, + const InitializedEntity *Parent = nullptr) { return InitializedEntity(Member, Parent); } /// \brief Create the initialization entity for a member subobject. - static InitializedEntity InitializeMember(IndirectFieldDecl *Member, - const InitializedEntity *Parent = 0) { + static InitializedEntity + InitializeMember(IndirectFieldDecl *Member, + const InitializedEntity *Parent = nullptr) { return InitializedEntity(Member->getAnonField(), Parent); } @@ -341,7 +347,7 @@ public: if (Kind == EK_Temporary || Kind == EK_CompoundLiteralInit) return TypeInfo; - return 0; + return nullptr; } /// \brief Retrieve the name of the entity being initialized. @@ -395,6 +401,13 @@ public: return SourceLocation::getFromRawEncoding(LocAndNRVO.Location); } + /// \brief If this is an array, vector, or complex number element, get the + /// element's index. + unsigned getElementIndex() const { + assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement || + getKind() == EK_ComplexElement); + return Index; + } /// \brief If this is already the initializer for an array or vector /// element, sets the element index. void setElementIndex(unsigned Index) { @@ -418,6 +431,8 @@ public: Kind = EK_Parameter_CF_Audited; } + unsigned allocateManglingNumber() const { return ++ManglingNumber; } + /// Dump a representation of the initialized entity to standard error, /// for debugging purposes. void dump() const; @@ -648,22 +663,25 @@ public: SK_QualificationConversionXValue, /// \brief Perform a qualification conversion, producing an lvalue. SK_QualificationConversionLValue, + /// \brief Perform a conversion adding _Atomic to a type. + SK_AtomicConversion, /// \brief Perform a load from a glvalue, producing an rvalue. SK_LValueToRValue, /// \brief Perform an implicit conversion sequence. SK_ConversionSequence, /// \brief Perform an implicit conversion sequence without narrowing. SK_ConversionSequenceNoNarrowing, - /// \brief Perform list-initialization without a constructor + /// \brief Perform list-initialization without a constructor. SK_ListInitialization, - /// \brief Perform list-initialization with a constructor. - SK_ListConstructorCall, /// \brief Unwrap the single-element initializer list for a reference. SK_UnwrapInitList, /// \brief Rewrap the single-element initializer list for a reference. SK_RewrapInitList, /// \brief Perform initialization via a constructor. SK_ConstructorInitialization, + /// \brief Perform initialization via a constructor, taking arguments from + /// a single InitListExpr. + SK_ConstructorInitializationFromList, /// \brief Zero-initialize the object SK_ZeroInitialization, /// \brief C assignment @@ -687,6 +705,9 @@ public: SK_ProduceObjCObject, /// \brief Construct a std::initializer_list from an initializer list. SK_StdInitializerList, + /// \brief Perform initialization via a constructor taking a single + /// std::initializer_list argument. + SK_StdInitializerListConstructorCall, /// \brief Initialize an OpenCL sampler from an integer. SK_OCLSamplerInit, /// \brief Passing zero to a function where OpenCL event_t is expected. @@ -843,17 +864,17 @@ public: /// /// \param Args the argument(s) provided for initialization. /// - /// \param InInitList true if we are initializing from an expression within - /// an initializer list. This disallows narrowing conversions in C++11 - /// onwards. + /// \param TopLevelOfInitList true if we are initializing from an expression + /// at the top level inside an initializer list. This disallows + /// narrowing conversions in C++11 onwards. InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - bool InInitList = false); + bool TopLevelOfInitList = false); void InitializeFrom(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - bool InInitList); + bool TopLevelOfInitList); ~InitializationSequence(); @@ -882,7 +903,7 @@ public: const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - QualType *ResultType = 0); + QualType *ResultType = nullptr); /// \brief Diagnose an potentially-invalid initialization sequence. /// @@ -980,7 +1001,11 @@ public: /// given type. void AddQualificationConversionStep(QualType Ty, ExprValueKind Category); - + + /// \brief Add a new step that performs conversion from non-atomic to atomic + /// type. + void AddAtomicConversionStep(QualType Ty); + /// \brief Add a new step that performs a load of the given type. /// /// Although the term "LValueToRValue" is conventional, this applies to both diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h index 105c879..00cc164 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h @@ -130,8 +130,8 @@ public: Sema::LookupNameKind LookupKind, Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) : ResultKind(NotFound), - Paths(0), - NamingClass(0), + Paths(nullptr), + NamingClass(nullptr), SemaRef(SemaRef), NameInfo(NameInfo), LookupKind(LookupKind), @@ -152,8 +152,8 @@ public: SourceLocation NameLoc, Sema::LookupNameKind LookupKind, Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) : ResultKind(NotFound), - Paths(0), - NamingClass(0), + Paths(nullptr), + NamingClass(nullptr), SemaRef(SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind), @@ -172,8 +172,8 @@ public: /// disabled. LookupResult(TemporaryToken _, const LookupResult &Other) : ResultKind(NotFound), - Paths(0), - NamingClass(0), + Paths(nullptr), + NamingClass(nullptr), SemaRef(Other.SemaRef), NameInfo(Other.NameInfo), LookupKind(Other.LookupKind), @@ -259,7 +259,7 @@ public: } LookupResultKind getResultKind() const { - sanity(); + assert(sanity()); return ResultKind; } @@ -303,7 +303,7 @@ public: /// if there is one. NamedDecl *getAcceptableDecl(NamedDecl *D) const { if (!D->isInIdentifierNamespace(IDNS)) - return 0; + return nullptr; if (isHiddenDeclarationVisible() || isVisible(SemaRef, D)) return D; @@ -324,7 +324,7 @@ public: /// \brief Returns whether these results arose from performing a /// lookup into a class. bool isClassLookup() const { - return NamingClass != 0; + return NamingClass != nullptr; } /// \brief Returns the 'naming class' for this lookup, i.e. the @@ -421,7 +421,7 @@ public: if (Paths) { deletePaths(Paths); - Paths = 0; + Paths = nullptr; } } else { AmbiguityKind SavedAK = Ambiguity; @@ -434,14 +434,14 @@ public: Ambiguity = SavedAK; } else if (Paths) { deletePaths(Paths); - Paths = 0; + Paths = nullptr; } } } template <class DeclClass> DeclClass *getAsSingle() const { - if (getResultKind() != Found) return 0; + if (getResultKind() != Found) return nullptr; return dyn_cast<DeclClass>(getFoundDecl()); } @@ -491,8 +491,8 @@ public: ResultKind = NotFound; Decls.clear(); if (Paths) deletePaths(Paths); - Paths = NULL; - NamingClass = 0; + Paths = nullptr; + NamingClass = nullptr; Shadowed = false; } @@ -637,13 +637,7 @@ private: void configure(); // Sanity checks. - void sanityImpl() const; - - void sanity() const { -#ifndef NDEBUG - sanityImpl(); -#endif - } + bool sanity() const; bool sanityCheckUnresolved() const { for (iterator I = begin(), E = end(); I != E; ++I) diff --git a/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h b/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h new file mode 100644 index 0000000..d4b985d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h @@ -0,0 +1,40 @@ +//===--- LoopHint.h - Types for LoopHint ------------------------*- 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_LOOPHINT_H +#define LLVM_CLANG_SEMA_LOOPHINT_H + +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Sema/AttributeList.h" +#include "clang/Sema/Ownership.h" + +namespace clang { + +/// \brief Loop optimization hint for loop and unroll pragmas. +struct LoopHint { + // Source range of the directive. + SourceRange Range; + // Identifier corresponding to the name of the pragma. "loop" for + // "#pragma clang loop" directives and "unroll" for "#pragma unroll" + // hints. + IdentifierLoc *PragmaNameLoc; + // Name of the loop hint. Examples: "unroll", "vectorize". In the + // "#pragma unroll" case, this is identical to PragmaNameLoc. + IdentifierLoc *OptionLoc; + // Identifier for the hint argument. If null, then the hint has no argument + // such as for "#pragma unroll". + IdentifierLoc *ValueLoc; + // Expression for the hint argument if it exists, null otherwise. + Expr *ValueExpr; +}; + +} // end namespace clang + +#endif // LLVM_CLANG_SEMA_LOOPHINT_H diff --git a/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h index e9ba479..7860b6d 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -65,31 +65,35 @@ public: /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. - virtual Decl *GetExternalDecl(uint32_t ID); + Decl *GetExternalDecl(uint32_t ID) override; + + /// \brief Complete the redeclaration chain if it's been extended since the + /// previous generation of the AST source. + void CompleteRedeclChain(const Decl *D) override; /// \brief Resolve a selector ID into a selector. - virtual Selector GetExternalSelector(uint32_t ID); + Selector GetExternalSelector(uint32_t ID) override; /// \brief Returns the number of selectors known to the external AST /// source. - virtual uint32_t GetNumExternalSelectors(); + uint32_t GetNumExternalSelectors() override; /// \brief Resolve the offset of a statement in the decl stream into /// a statement. - virtual Stmt *GetExternalDeclStmt(uint64_t Offset); + Stmt *GetExternalDeclStmt(uint64_t Offset) override; /// \brief Resolve the offset of a set of C++ base specifiers in the decl /// stream into an array of specifiers. - virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); + CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override; /// \brief Find all declarations with the given name in the /// given context. - virtual bool - FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); + bool + FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override; /// \brief Ensures that the table of all visible declarations inside this /// context is up to date. - virtual void completeVisibleDeclsMap(const DeclContext *DC); + void completeVisibleDeclsMap(const DeclContext *DC) override; /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. @@ -99,9 +103,9 @@ public: /// are returned. /// /// \return an indication of whether the load succeeded or failed. - virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, - bool (*isKindWeWant)(Decl::Kind), - SmallVectorImpl<Decl*> &Result); + ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, + bool (*isKindWeWant)(Decl::Kind), + SmallVectorImpl<Decl*> &Result) override; /// \brief Finds all declarations lexically contained within the given /// DeclContext. @@ -109,7 +113,7 @@ public: /// \return true if an error occurred ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, SmallVectorImpl<Decl*> &Result) { - return FindExternalLexicalDecls(DC, 0, Result); + return FindExternalLexicalDecls(DC, nullptr, Result); } template <typename DeclTy> @@ -121,12 +125,12 @@ public: /// \brief Get the decls that are contained in a file in the Offset/Length /// range. \p Length can be 0 to indicate a point at \p Offset instead of /// a range. - virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, - SmallVectorImpl<Decl *> &Decls); + void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, + SmallVectorImpl<Decl *> &Decls) override; /// \brief Gives the external AST source an opportunity to complete /// an incomplete type. - virtual void CompleteType(TagDecl *Tag); + void CompleteType(TagDecl *Tag) override; /// \brief Gives the external AST source an opportunity to complete an /// incomplete Objective-C class. @@ -134,27 +138,27 @@ public: /// This routine will only be invoked if the "externally completed" bit is /// set on the ObjCInterfaceDecl via the function /// \c ObjCInterfaceDecl::setExternallyCompleted(). - virtual void CompleteType(ObjCInterfaceDecl *Class); + void CompleteType(ObjCInterfaceDecl *Class) override; /// \brief Loads comment ranges. - virtual void ReadComments(); + void ReadComments() override; /// \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. - virtual void StartedDeserializing(); + void StartedDeserializing() override; /// \brief Notify ExternalASTSource that we finished the deserialization of /// a decl or type. Must be paired with StartedDeserializing. - virtual void FinishedDeserializing(); + void FinishedDeserializing() override; /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. - virtual void StartTranslationUnit(ASTConsumer *Consumer); + void StartTranslationUnit(ASTConsumer *Consumer) override; /// \brief Print any statistics that have been gathered regarding /// the external AST source. - virtual void PrintStats(); + void PrintStats() override; /// \brief Perform layout on the given record. @@ -184,16 +188,17 @@ public: /// be laid out according to the ABI. /// /// \returns true if the record layout was provided, false otherwise. - virtual bool + bool layoutRecordType(const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, - llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets); + llvm::DenseMap<const CXXRecordDecl *, + CharUnits> &VirtualBaseOffsets) override; /// Return the amount of memory used by memory buffers, breaking down /// by heap-backed versus mmap'ed memory. - virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; + void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override; //===--------------------------------------------------------------------===// // ExternalSemaSource. @@ -202,24 +207,25 @@ public: /// \brief Initialize the semantic source with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. - virtual void InitializeSema(Sema &S); + void InitializeSema(Sema &S) override; /// \brief Inform the semantic consumer that Sema is no longer available. - virtual void ForgetSema(); + void ForgetSema() override; /// \brief Load the contents of the global method pool for a given /// selector. - virtual void ReadMethodPool(Selector Sel); + void ReadMethodPool(Selector Sel) override; /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. - virtual void ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces); + void + ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces) override; /// \brief Load the set of used but not defined functions or variables with /// internal linkage, or used but not defined inline functions. - virtual void ReadUndefinedButUsed( - llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined); - + void ReadUndefinedButUsed( + llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined) override; + /// \brief Do last resort, unqualified lookup on a LookupResult that /// Sema cannot find. /// @@ -228,7 +234,7 @@ public: /// \param S the Scope of the identifier occurrence. /// /// \return true to tell Sema to recover using the LookupResult. - virtual bool LookupUnqualified(LookupResult &R, Scope *S); + bool LookupUnqualified(LookupResult &R, Scope *S) override; /// \brief Read the set of tentative definitions known to the external Sema /// source. @@ -237,8 +243,8 @@ public: /// given vector of tentative definitions. Note that this routine may be /// invoked multiple times; the external source should take care not to /// introduce the same declarations repeatedly. - virtual void ReadTentativeDefinitions(SmallVectorImpl<VarDecl*> &Defs); - + void ReadTentativeDefinitions(SmallVectorImpl<VarDecl*> &Defs) override; + /// \brief Read the set of unused file-scope declarations known to the /// external Sema source. /// @@ -246,9 +252,9 @@ public: /// given vector of declarations. Note that this routine may be /// invoked multiple times; the external source should take care not to /// introduce the same declarations repeatedly. - virtual void ReadUnusedFileScopedDecls( - SmallVectorImpl<const DeclaratorDecl*> &Decls); - + void ReadUnusedFileScopedDecls( + SmallVectorImpl<const DeclaratorDecl*> &Decls) override; + /// \brief Read the set of delegating constructors known to the /// external Sema source. /// @@ -256,8 +262,8 @@ public: /// given vector of declarations. Note that this routine may be /// invoked multiple times; the external source should take care not to /// introduce the same declarations repeatedly. - virtual void ReadDelegatingConstructors( - SmallVectorImpl<CXXConstructorDecl*> &Decls); + void ReadDelegatingConstructors( + SmallVectorImpl<CXXConstructorDecl*> &Decls) override; /// \brief Read the set of ext_vector type declarations known to the /// external Sema source. @@ -266,7 +272,7 @@ public: /// the given vector of declarations. Note that this routine may be /// invoked multiple times; the external source should take care not to /// introduce the same declarations repeatedly. - virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls); + void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls) override; /// \brief Read the set of dynamic classes known to the external Sema source. /// @@ -274,7 +280,7 @@ public: /// the given vector of declarations. Note that this routine may be /// invoked multiple times; the external source should take care not to /// introduce the same declarations repeatedly. - virtual void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl*> &Decls); + void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl*> &Decls) override; /// \brief Read the set of locally-scoped extern "C" declarations known to the /// external Sema source. @@ -283,7 +289,8 @@ public: /// declarations to the given vector of declarations. Note that this routine /// may be invoked multiple times; the external source should take care not /// to introduce the same declarations repeatedly. - virtual void ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl*>&Decls); + void ReadLocallyScopedExternCDecls( + SmallVectorImpl<NamedDecl*> &Decls) override; /// \brief Read the set of referenced selectors known to the /// external Sema source. @@ -292,8 +299,8 @@ public: /// given vector of selectors. Note that this routine /// may be invoked multiple times; the external source should take care not /// to introduce the same selectors repeatedly. - virtual void ReadReferencedSelectors(SmallVectorImpl<std::pair<Selector, - SourceLocation> > &Sels); + void ReadReferencedSelectors(SmallVectorImpl<std::pair<Selector, + SourceLocation> > &Sels) override; /// \brief Read the set of weak, undeclared identifiers known to the /// external Sema source. @@ -302,15 +309,15 @@ public: /// the given vector. Note that this routine may be invoked multiple times; /// the external source should take care not to introduce the same identifiers /// repeatedly. - virtual void ReadWeakUndeclaredIdentifiers( - SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI); + void ReadWeakUndeclaredIdentifiers( + SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI) override; /// \brief Read the set of used vtables known to the external Sema source. /// /// The external source should append its own used vtables to the given /// vector. Note that this routine may be invoked multiple times; the external /// source should take care not to introduce the same vtables repeatedly. - virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables); + void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override; /// \brief Read the set of pending instantiations known to the external /// Sema source. @@ -319,8 +326,8 @@ public: /// given vector. Note that this routine may be invoked multiple times; the /// external source should take care not to introduce the same instantiations /// repeatedly. - virtual void ReadPendingInstantiations( - SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending); + void ReadPendingInstantiations( + SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending) override; /// \brief Read the set of late parsed template functions for this source. /// @@ -328,17 +335,18 @@ public: /// into the map. Note that this routine may be invoked multiple times; the /// external source should take care not to introduce the same map entries /// repeatedly. - virtual void ReadLateParsedTemplates( - llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap); + void ReadLateParsedTemplates( + llvm::DenseMap<const FunctionDecl *, + LateParsedTemplate *> &LPTMap) override; /// \copydoc ExternalSemaSource::CorrectTypo /// \note Returns the first nonempty correction. - virtual TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, - int LookupKind, Scope *S, CXXScopeSpec *SS, - CorrectionCandidateCallback &CCC, - DeclContext *MemberContext, - bool EnteringContext, - const ObjCObjectPointerType *OPT); + TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, + int LookupKind, Scope *S, CXXScopeSpec *SS, + CorrectionCandidateCallback &CCC, + DeclContext *MemberContext, + bool EnteringContext, + const ObjCObjectPointerType *OPT) override; /// \brief Produces a diagnostic note if one of the attached sources /// contains a complete definition for \p T. Queries the sources in list @@ -350,7 +358,8 @@ public: /// \param T the \c QualType that should have been complete at \p Loc /// /// \return true if a diagnostic was produced, false otherwise. - virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc, QualType T); + bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc, + QualType T) override; // isa/cast/dyn_cast support static bool classof(const MultiplexExternalSemaSource*) { return true; } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h b/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h index 94e3807..2003356 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h @@ -26,7 +26,7 @@ struct ObjCMethodList { /// \brief The next list object and 2 bits for extra info. llvm::PointerIntPair<ObjCMethodList *, 2> NextAndExtraBits; - ObjCMethodList() : Method(0) { } + ObjCMethodList() : Method(nullptr) { } ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) : Method(M), NextAndExtraBits(C, 0) { } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h index b8bd14a..7c221a2 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h @@ -262,7 +262,7 @@ namespace clang { StandardConversionSequence Before; /// EllipsisConversion - When this is true, it means user-defined - /// conversion sequence starts with a ... (elipsis) conversion, instead of + /// conversion sequence starts with a ... (ellipsis) conversion, instead of /// a standard conversion. In this case, 'Before' field must be ignored. // FIXME. I much rather put this as the first field. But there seems to be // a gcc code gen. bug which causes a crash in a test. Putting it here seems @@ -339,7 +339,6 @@ namespace clang { enum FailureKind { no_conversion, unrelated_class, - suppressed_user, bad_qualifiers, lvalue_ref_to_rvalue, rvalue_ref_to_lvalue @@ -364,7 +363,7 @@ namespace clang { } void init(FailureKind K, QualType From, QualType To) { Kind = K; - FromExpr = 0; + FromExpr = nullptr; setFromType(From); setToType(To); } @@ -579,7 +578,11 @@ namespace clang { /// (CUDA) This candidate was not viable because the callee /// was not accessible from the caller's target (i.e. host->device, /// global->host, device->host). - ovl_fail_bad_target + ovl_fail_bad_target, + + /// This candidate function was not viable because an enable_if + /// attribute disabled it. + ovl_fail_enable_if }; /// OverloadCandidate - A single candidate in an overload set (C++ 13.3). @@ -675,11 +678,35 @@ namespace clang { return CanFix; } + + unsigned getNumParams() const { + if (IsSurrogate) { + auto STy = Surrogate->getConversionType(); + while (STy->isPointerType() || STy->isReferenceType()) + STy = STy->getPointeeType(); + return STy->getAs<FunctionProtoType>()->getNumParams(); + } + if (Function) + return Function->getNumParams(); + return ExplicitCallArguments; + } }; /// OverloadCandidateSet - A set of overload candidates, used in C++ /// overload resolution (C++ 13.3). class OverloadCandidateSet { + public: + enum CandidateSetKind { + /// Normal lookup. + CSK_Normal, + /// Lookup for candidates for a call using operator syntax. Candidates + /// that have no parameters of class type will be skipped unless there + /// is a parameter of (reference to) enum type and the corresponding + /// argument is of the same enum type. + CSK_Operator + }; + + private: SmallVector<OverloadCandidate, 16> Candidates; llvm::SmallPtrSet<Decl *, 16> Functions; @@ -688,6 +715,7 @@ namespace clang { llvm::BumpPtrAllocator ConversionSequenceAllocator; SourceLocation Loc; + CandidateSetKind Kind; unsigned NumInlineSequences; char InlineSpace[16 * sizeof(ImplicitConversionSequence)]; @@ -698,10 +726,12 @@ namespace clang { void destroyCandidates(); public: - OverloadCandidateSet(SourceLocation Loc) : Loc(Loc), NumInlineSequences(0){} + OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK) + : Loc(Loc), Kind(CSK), NumInlineSequences(0) {} ~OverloadCandidateSet() { destroyCandidates(); } SourceLocation getLocation() const { return Loc; } + CandidateSetKind getKind() const { return Kind; } /// \brief Determine when this overload candidate will be new to the /// overload set. diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h index b7d7710..8031562 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h @@ -49,7 +49,7 @@ namespace clang { typedef llvm::PointerLikeTypeTraits<PtrTy> Traits; public: - OpaquePtr() : Ptr(0) {} + OpaquePtr() : Ptr(nullptr) {} static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; } @@ -79,7 +79,7 @@ namespace clang { Ptr = Traits::getAsVoidPointer(P); } - LLVM_EXPLICIT operator bool() const { return Ptr != 0; } + LLVM_EXPLICIT operator bool() const { return Ptr != nullptr; } void *getAsOpaquePtr() const { return Ptr; } static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); } @@ -158,12 +158,10 @@ namespace clang { bool isInvalid() const { return Invalid; } bool isUsable() const { return !Invalid && Val; } + bool isUnset() const { return !Invalid && !Val; } PtrTy get() const { return Val; } - // FIXME: Replace with get. - PtrTy release() const { return Val; } - PtrTy take() const { return Val; } - template <typename T> T *takeAs() { return static_cast<T*>(get()); } + template <typename T> T *getAs() { return static_cast<T*>(get()); } void set(PtrTy V) { Val = V; } @@ -199,15 +197,13 @@ namespace clang { bool isInvalid() const { return PtrWithInvalid & 0x01; } bool isUsable() const { return PtrWithInvalid > 0x01; } + bool isUnset() const { return PtrWithInvalid == 0; } PtrTy get() const { void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); return PtrTraits::getFromVoidPointer(VP); } - // FIXME: Replace with get. - PtrTy take() const { return get(); } - PtrTy release() const { return get(); } - template <typename T> T *takeAs() { return static_cast<T*>(get()); } + template <typename T> T *getAs() { return static_cast<T*>(get()); } void set(PtrTy V) { void *VP = PtrTraits::getAsVoidPointer(V); @@ -262,11 +258,11 @@ namespace clang { typedef ActionResult<Decl*> DeclResult; typedef OpaquePtr<TemplateName> ParsedTemplateTy; - typedef llvm::MutableArrayRef<Expr*> MultiExprArg; - typedef llvm::MutableArrayRef<Stmt*> MultiStmtArg; - typedef llvm::MutableArrayRef<ParsedTemplateArgument> ASTTemplateArgsPtr; - typedef llvm::MutableArrayRef<ParsedType> MultiTypeArg; - typedef llvm::MutableArrayRef<TemplateParameterList*> MultiTemplateParamsArg; + typedef MutableArrayRef<Expr*> MultiExprArg; + typedef MutableArrayRef<Stmt*> MultiStmtArg; + typedef MutableArrayRef<ParsedTemplateArgument> ASTTemplateArgsPtr; + typedef MutableArrayRef<ParsedType> MultiTypeArg; + typedef MutableArrayRef<TemplateParameterList*> MultiTemplateParamsArg; inline ExprResult ExprError() { return ExprResult(true); } inline StmtResult StmtError() { return StmtResult(true); } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h index 94db454..b36425f 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h @@ -35,7 +35,7 @@ namespace clang { /// \brief Build an empty template argument. /// /// This template argument is invalid. - ParsedTemplateArgument() : Kind(Type), Arg(0) { } + ParsedTemplateArgument() : Kind(Type), Arg(nullptr) { } /// \brief Create a template type argument or non-type template argument. /// @@ -61,7 +61,7 @@ namespace clang { SS(SS), Loc(TemplateLoc), EllipsisLoc() { } /// \brief Determine whether the given template argument is invalid. - bool isInvalid() const { return Arg == 0; } + bool isInvalid() const { return Arg == nullptr; } /// \brief Determine what kind of template argument we have. KindType getKind() const { return Kind; } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h b/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h index aa55705..c0c772d 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h @@ -39,7 +39,7 @@ public: const char *Msg) : S(S), TheDecl(D), Loc(Loc), Message(Msg) {} - virtual void print(raw_ostream &OS) const; + void print(raw_ostream &OS) const override; }; } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h index 249a4c7..8e4e2ef 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h @@ -15,13 +15,21 @@ #define LLVM_CLANG_SEMA_SCOPE_H #include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +namespace llvm { + +class raw_ostream; + +} + namespace clang { class Decl; class UsingDirectiveDecl; +class VarDecl; /// Scope - A scope is a transient data structure that is used while parsing the /// program. It assists with resolving identifiers to the appropriate @@ -93,21 +101,47 @@ public: /// \brief This is the scope for a function-level C++ try or catch scope. FnTryCatchScope = 0x4000, - /// \brief This is the scope of OpenMP executable directive - OpenMPDirectiveScope = 0x8000 + /// \brief This is the scope of OpenMP executable directive. + OpenMPDirectiveScope = 0x8000, + + /// \brief This is the scope of some OpenMP loop directive. + OpenMPLoopDirectiveScope = 0x10000, + + /// \brief This is the scope of some OpenMP simd directive. + /// For example, it is used for 'omp simd', 'omp for simd'. + /// This flag is propagated to children scopes. + OpenMPSimdDirectiveScope = 0x20000, + + /// This scope corresponds to an enum. + EnumScope = 0x40000, + + /// This scope corresponds to a SEH try. + SEHTryScope = 0x80000, }; private: /// The parent scope for this scope. This is null for the translation-unit /// scope. Scope *AnyParent; + /// Flags - This contains a set of ScopeFlags, which indicates how the scope + /// interrelates with other control flow statements. + unsigned Flags; + /// Depth - This is the depth of this scope. The translation-unit scope has /// depth 0. unsigned short Depth; - /// Flags - This contains a set of ScopeFlags, which indicates how the scope - /// interrelates with other control flow statements. - unsigned short Flags; + /// \brief Declarations with static linkage are mangled with the number of + /// scopes seen as a component. + unsigned short MSLocalManglingNumber; + + /// \brief SEH __try blocks get uniquely numbered within a function. This + /// variable holds the index for an SEH try block. + short SEHTryIndex; + + /// \brief SEH __try blocks get uniquely numbered within a function. This + /// variable holds the next free index at a function's scope. + short SEHTryIndexPool; /// PrototypeDepth - This is the number of function prototype scopes /// enclosing this scope, including this scope. @@ -120,6 +154,8 @@ private: /// FnParent - If this scope has a parent scope that is a function body, this /// pointer is non-null and points to it. This is used for label processing. Scope *FnParent; + Scope *MSLocalManglingParent; + Scope *SEHTryParent; /// BreakParent/ContinueParent - This is a direct link to the innermost /// BreakScope/ContinueScope which contains the contents of this scope @@ -156,7 +192,11 @@ private: /// \brief Used to determine if errors occurred in this scope. DiagnosticErrorTrap ErrorTrap; - + + /// A lattice consisting of undefined, a single NRVO candidate variable in + /// this scope, or over-defined. The bit is true when over-defined. + llvm::PointerIntPair<VarDecl *, 1, bool> NRVO; + public: Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag) : ErrorTrap(Diag) { @@ -181,6 +221,11 @@ public: const Scope *getFnParent() const { return FnParent; } Scope *getFnParent() { return FnParent; } + const Scope *getMSLocalManglingParent() const { + return MSLocalManglingParent; + } + Scope *getMSLocalManglingParent() { return MSLocalManglingParent; } + /// getContinueParent - Return the closest scope that a continue statement /// would be affected by. Scope *getContinueParent() { @@ -219,10 +264,11 @@ public: return PrototypeIndex++; } - typedef DeclSetTy::iterator decl_iterator; - decl_iterator decl_begin() const { return DeclsInScope.begin(); } - decl_iterator decl_end() const { return DeclsInScope.end(); } - bool decl_empty() const { return DeclsInScope.empty(); } + typedef llvm::iterator_range<DeclSetTy::iterator> decl_range; + decl_range decls() const { + return decl_range(DeclsInScope.begin(), DeclsInScope.end()); + } + bool decl_empty() const { return DeclsInScope.empty(); } void AddDecl(Decl *D) { DeclsInScope.insert(D); @@ -232,6 +278,30 @@ public: DeclsInScope.erase(D); } + void incrementMSLocalManglingNumber() { + if (Scope *MSLMP = getMSLocalManglingParent()) + MSLMP->MSLocalManglingNumber += 1; + } + + void decrementMSLocalManglingNumber() { + if (Scope *MSLMP = getMSLocalManglingParent()) + MSLMP->MSLocalManglingNumber -= 1; + } + + unsigned getMSLocalManglingNumber() const { + if (const Scope *MSLMP = getMSLocalManglingParent()) + return MSLMP->MSLocalManglingNumber; + return 1; + } + + int getSEHTryIndex() { + return SEHTryIndex; + } + + int getSEHTryParentIndex() const { + return SEHTryParent ? SEHTryParent->SEHTryIndex : -1; + } + /// isDeclScope - Return true if this is the scope that the specified decl is /// declared in. bool isDeclScope(Decl *D) { @@ -273,6 +343,18 @@ public: return false; } + /// isInObjcMethodOuterScope - Return true if this scope is an + /// Objective-C method outer most body. + bool isInObjcMethodOuterScope() const { + if (const Scope *S = this) { + // If this scope is an objc method scope, then we succeed. + if (S->getFlags() & ObjCMethodScope) + return true; + } + return false; + } + + /// isTemplateParamScope - Return true if this scope is a C++ /// template parameter scope. bool isTemplateParamScope() const { @@ -309,39 +391,81 @@ public: return (getFlags() & Scope::OpenMPDirectiveScope); } + /// \brief Determine whether this scope is some OpenMP loop directive scope + /// (for example, 'omp for', 'omp simd'). + bool isOpenMPLoopDirectiveScope() const { + if (getFlags() & Scope::OpenMPLoopDirectiveScope) { + assert(isOpenMPDirectiveScope() && + "OpenMP loop directive scope is not a directive scope"); + return true; + } + return false; + } + + /// \brief Determine whether this scope is (or is nested into) some OpenMP + /// loop simd directive scope (for example, 'omp simd', 'omp for simd'). + bool isOpenMPSimdDirectiveScope() const { + return getFlags() & Scope::OpenMPSimdDirectiveScope; + } + + /// \brief Determine whether this scope is a loop having OpenMP loop + /// directive attached. + bool isOpenMPLoopScope() const { + const Scope *P = getParent(); + return P && P->isOpenMPLoopDirectiveScope(); + } + /// \brief Determine whether this scope is a C++ 'try' block. bool isTryScope() const { return getFlags() & Scope::TryScope; } + /// \brief Determine whether this scope is a SEH '__try' block. + bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; } + /// containedInPrototypeScope - Return true if this or a parent scope /// is a FunctionPrototypeScope. bool containedInPrototypeScope() const; - typedef UsingDirectivesTy::iterator udir_iterator; - typedef UsingDirectivesTy::const_iterator const_udir_iterator; - void PushUsingDirective(UsingDirectiveDecl *UDir) { UsingDirectives.push_back(UDir); } - udir_iterator using_directives_begin() { - return UsingDirectives.begin(); - } + typedef llvm::iterator_range<UsingDirectivesTy::iterator> + using_directives_range; - udir_iterator using_directives_end() { - return UsingDirectives.end(); + using_directives_range using_directives() { + return using_directives_range(UsingDirectives.begin(), + UsingDirectives.end()); } - const_udir_iterator using_directives_begin() const { - return UsingDirectives.begin(); + void addNRVOCandidate(VarDecl *VD) { + if (NRVO.getInt()) + return; + if (NRVO.getPointer() == nullptr) { + NRVO.setPointer(VD); + return; + } + if (NRVO.getPointer() != VD) + setNoNRVO(); } - const_udir_iterator using_directives_end() const { - return UsingDirectives.end(); + void setNoNRVO() { + NRVO.setInt(1); + NRVO.setPointer(nullptr); } + void mergeNRVOIntoParent(); + /// Init - This is used by the parser to implement scope caching. /// void Init(Scope *parent, unsigned flags); + + /// \brief Sets up the specified scope flags and adjusts the scope state + /// variables accordingly. + /// + void AddFlags(unsigned Flags); + + void dumpImpl(raw_ostream &OS) const; + void dump() const; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h index 06afe1a..63427aa 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h @@ -110,6 +110,21 @@ public: /// with \c __attribute__((objc_requires_super)). bool ObjCShouldCallSuper; + /// True when this is a method marked as a designated initializer. + bool ObjCIsDesignatedInit; + /// This starts true for a method marked as designated initializer and will + /// be set to false if there is an invocation to a designated initializer of + /// the super class. + bool ObjCWarnForNoDesignatedInitChain; + + /// True when this is an initializer method not marked as a designated + /// initializer within a class that has at least one initializer marked as a + /// designated initializer. + bool ObjCIsSecondaryInit; + /// This starts true for a secondary initializer method and will be set to + /// false if there is an invocation of an initializer on 'self'. + bool ObjCWarnForNoInitDelegation; + /// \brief Used to determine if errors occurred in this function or block. DiagnosticErrorTrap ErrorTrap; @@ -318,6 +333,10 @@ public: HasIndirectGoto(false), HasDroppedStmt(false), ObjCShouldCallSuper(false), + ObjCIsDesignatedInit(false), + ObjCWarnForNoDesignatedInitChain(false), + ObjCIsSecondaryInit(false), + ObjCWarnForNoInitDelegation(false), ErrorTrap(Diag) { } virtual ~FunctionScopeInfo(); @@ -386,7 +405,7 @@ public: enum IsThisCapture { ThisCapture }; Capture(IsThisCapture, bool IsNested, SourceLocation Loc, QualType CaptureType, Expr *Cpy) - : VarAndNested(0, IsNested), + : VarAndNested(nullptr, IsNested), InitExprAndCaptureKind(Cpy, Cap_This), Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {} @@ -644,10 +663,10 @@ public: SourceLocation PotentialThisCaptureLocation; LambdaScopeInfo(DiagnosticsEngine &Diag) - : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0), - CallOperator(0), NumExplicitCaptures(0), Mutable(false), + : CapturingScopeInfo(Diag, ImpCap_None), Lambda(nullptr), + CallOperator(nullptr), NumExplicitCaptures(0), Mutable(false), ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false), - AutoTemplateParameterDepth(0), GLTemplateParameterList(0) + AutoTemplateParameterDepth(0), GLTemplateParameterList(nullptr) { Kind = SK_Lambda; } @@ -708,10 +727,10 @@ public: /// act of analyzing the enclosing full expression (ActOnFinishFullExpr) /// if we can determine that the full expression is not instantiation- /// dependent, then we can entirely avoid its capture. - ///
- /// const int n = 0;
- /// [&] (auto x) {
- /// (void)+n + x;
+ /// + /// const int n = 0; + /// [&] (auto x) { + /// (void)+n + x; /// }; /// Interestingly, this strategy would involve a capture of n, even though /// it's obviously not odr-used here, because the full-expression is @@ -725,12 +744,12 @@ public: /// Before anyone is tempted to implement a strategy for not-capturing 'n', /// consider the insightful warning in: /// /cfe-commits/Week-of-Mon-20131104/092596.html - /// "The problem is that the set of captures for a lambda is part of the ABI
- /// (since lambda layout can be made visible through inline functions and the
- /// like), and there are no guarantees as to which cases we'll manage to build
- /// an lvalue-to-rvalue conversion in, when parsing a template -- some
- /// seemingly harmless change elsewhere in Sema could cause us to start or stop
- /// building such a node. So we need a rule that anyone can implement and get
+ /// "The problem is that the set of captures for a lambda is part of the ABI + /// (since lambda layout can be made visible through inline functions and the + /// like), and there are no guarantees as to which cases we'll manage to build + /// an lvalue-to-rvalue conversion in, when parsing a template -- some + /// seemingly harmless change elsewhere in Sema could cause us to start or stop + /// building such a node. So we need a rule that anyone can implement and get /// exactly the same result". /// void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) { @@ -738,7 +757,7 @@ public: || isa<MemberExpr>(CapturingVarExpr)); NonODRUsedCapturingExprs.insert(CapturingVarExpr); } - bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) { + bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const { assert(isa<DeclRefExpr>(CapturingVarExpr) || isa<MemberExpr>(CapturingVarExpr)); return NonODRUsedCapturingExprs.count(CapturingVarExpr); @@ -761,16 +780,14 @@ public: return getNumPotentialVariableCaptures() || PotentialThisCaptureLocation.isValid(); } - - // When passed the index, returns the VarDecl and Expr associated + + // When passed the index, returns the VarDecl and Expr associated // with the index. - void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E); - + void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) const; }; - FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy() - : Base(0, false), Property(0) {} + : Base(nullptr, false), Property(nullptr) {} FunctionScopeInfo::WeakObjectProfileTy FunctionScopeInfo::WeakObjectProfileTy::getSentinel() { diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h index 48794d6..e254afd 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h @@ -26,11 +26,11 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/ExpressionTraits.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TypeTraits.h" -#include "clang/Lex/ModuleLoader.h" #include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ExternalSemaSource.h" @@ -38,17 +38,18 @@ #include "clang/Sema/LocInfoType.h" #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Ownership.h" +#include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/TypoCorrection.h" #include "clang/Sema/Weak.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 "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/ADT/TinyPtrVector.h" #include <deque> +#include <memory> #include <string> #include <vector> @@ -57,6 +58,7 @@ namespace llvm { template <typename ValueT> struct DenseMapInfo; template <typename ValueT, typename ValueInfoT> class DenseSet; class SmallBitVector; + class InlineAsmIdentifierInfo; } namespace clang { @@ -101,6 +103,7 @@ namespace clang { class DependentDiagnostic; class DesignatedInitExpr; class Designation; + class EnableIfAttr; class EnumConstantDecl; class Expr; class ExtVectorType; @@ -122,6 +125,8 @@ namespace clang { class LocalInstantiationScope; class LookupResult; class MacroInfo; + typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> ModuleIdPath; + class ModuleLoader; class MultiLevelTemplateArgumentList; class NamedDecl; class NonNullAttr; @@ -152,7 +157,6 @@ namespace clang { class Stmt; class StringLiteral; class SwitchStmt; - class TargetAttributesSema; class TemplateArgument; class TemplateArgumentList; class TemplateArgumentLoc; @@ -204,7 +208,6 @@ typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>, class Sema { Sema(const Sema &) LLVM_DELETED_FUNCTION; void operator=(const Sema &) LLVM_DELETED_FUNCTION; - mutable const TargetAttributesSema* TheTargetAttributesSema; ///\brief Source of additional semantic information. ExternalSemaSource *ExternalSource; @@ -263,9 +266,82 @@ public: bool MSStructPragmaOn; // True when \#pragma ms_struct on + /// \brief Controls member pointer representation format under the MS ABI. + LangOptions::PragmaMSPointersToMembersKind + MSPointerToMemberRepresentationMethod; + + enum PragmaVtorDispKind { + PVDK_Push, ///< #pragma vtordisp(push, mode) + PVDK_Set, ///< #pragma vtordisp(mode) + PVDK_Pop, ///< #pragma vtordisp(pop) + PVDK_Reset ///< #pragma vtordisp() + }; + + enum PragmaMsStackAction { + PSK_Reset, // #pragma () + PSK_Set, // #pragma ("name") + PSK_Push, // #pragma (push[, id]) + PSK_Push_Set, // #pragma (push[, id], "name") + PSK_Pop, // #pragma (pop[, id]) + PSK_Pop_Set, // #pragma (pop[, id], "name") + }; + + /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft + /// C++ ABI. Possible values are 0, 1, and 2, which mean: + /// + /// 0: Suppress all vtordisps + /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial + /// structors + /// 2: Always insert vtordisps to support RTTI on partially constructed + /// objects + /// + /// The stack always has at least one element in it. + SmallVector<MSVtorDispAttr::Mode, 2> VtorDispModeStack; + + /// \brief Source location for newly created implicit MSInheritanceAttrs + SourceLocation ImplicitMSInheritanceAttrLoc; + + template<typename ValueType> + struct PragmaStack { + struct Slot { + llvm::StringRef StackSlotLabel; + ValueType Value; + SourceLocation PragmaLocation; + Slot(llvm::StringRef StackSlotLabel, + ValueType Value, + SourceLocation PragmaLocation) + : StackSlotLabel(StackSlotLabel), Value(Value), + PragmaLocation(PragmaLocation) {} + }; + void Act(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + llvm::StringRef StackSlotLabel, + ValueType Value); + explicit PragmaStack(const ValueType &Value) + : CurrentValue(Value) {} + SmallVector<Slot, 2> Stack; + ValueType CurrentValue; + SourceLocation CurrentPragmaLocation; + }; + // FIXME: We should serialize / deserialize these if they occur in a PCH (but + // we shouldn't do so if they're in a module). + PragmaStack<StringLiteral *> DataSegStack; + PragmaStack<StringLiteral *> BSSSegStack; + PragmaStack<StringLiteral *> ConstSegStack; + PragmaStack<StringLiteral *> CodeSegStack; + + /// Last section used with #pragma init_seg. + StringLiteral *CurInitSeg; + SourceLocation CurInitSegLoc; + /// VisContext - Manages the stack for \#pragma GCC visibility. void *VisContext; // Really a "PragmaVisStack*" + /// \brief This represents the last location of a "#pragma clang optimize off" + /// directive if such a directive has not been closed by an "on" yet. If + /// optimizations are currently "on", this is set to an invalid location. + SourceLocation OptimizeOffPragmaLocation; + /// \brief Flag indicating if Sema is building a recovery call expression. /// /// This flag is used to avoid building recovery call expressions @@ -307,7 +383,7 @@ public: ExtVectorDeclsType ExtVectorDecls; /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. - OwningPtr<CXXFieldCollector> FieldCollector; + std::unique_ptr<CXXFieldCollector> FieldCollector; typedef llvm::SmallSetVector<const NamedDecl*, 16> NamedDeclSetType; @@ -319,7 +395,7 @@ public: /// PureVirtualClassDiagSet - a set of class declarations which we have /// emitted a list of pure virtual functions. Used to prevent emitting the /// same list more than once. - OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet; + std::unique_ptr<RecordDeclSetTy> PureVirtualClassDiagSet; /// ParsingInitForAutoVars - a set of declarations with auto types for which /// we are currently parsing the initializer. @@ -426,13 +502,13 @@ public: sema::DelayedDiagnosticPool *CurPool; public: - DelayedDiagnostics() : CurPool(0) {} + DelayedDiagnostics() : CurPool(nullptr) {} /// Adds a delayed diagnostic. void add(const sema::DelayedDiagnostic &diag); // in DelayedDiagnostic.h /// Determines whether diagnostics should be delayed. - bool shouldDelayDiagnostics() { return CurPool != 0; } + bool shouldDelayDiagnostics() { return CurPool != nullptr; } /// Returns the current delayed-diagnostics pool. sema::DelayedDiagnosticPool *getCurrentPool() const { @@ -460,13 +536,13 @@ public: DelayedDiagnosticsState pushUndelayed() { DelayedDiagnosticsState state; state.SavedPool = CurPool; - CurPool = 0; + CurPool = nullptr; return state; } /// Undo a previous pushUndelayed(). void popUndelayed(DelayedDiagnosticsState state) { - assert(CurPool == NULL); + assert(CurPool == nullptr); CurPool = state.SavedPool; } } DelayedDiagnostics; @@ -480,13 +556,15 @@ public: QualType SavedCXXThisTypeOverride; public: - ContextRAII(Sema &S, DeclContext *ContextToPush) + ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true) : S(S), SavedContext(S.CurContext), SavedContextState(S.DelayedDiagnostics.pushUndelayed()), SavedCXXThisTypeOverride(S.CXXThisTypeOverride) { assert(ContextToPush && "pushing null context"); S.CurContext = ContextToPush; + if (NewThisContext) + S.CXXThisTypeOverride = QualType(); } void pop() { @@ -494,7 +572,7 @@ public: S.CurContext = SavedContext; S.DelayedDiagnostics.popUndelayed(SavedContextState); S.CXXThisTypeOverride = SavedCXXThisTypeOverride; - SavedContext = 0; + SavedContext = nullptr; } ~ContextRAII() { @@ -569,7 +647,7 @@ public: RecordDecl *MSVCGuidDecl; /// \brief Caches identifiers/selectors for NSFoundation APIs. - OwningPtr<NSAPI> NSAPIObj; + std::unique_ptr<NSAPI> NSAPIObj; /// \brief The declaration of the Objective-C NSNumber class. ObjCInterfaceDecl *NSNumberDecl; @@ -772,7 +850,7 @@ public: /// \brief The number of SFINAE diagnostics that have been trapped. unsigned NumSFINAEErrors; - typedef llvm::DenseMap<ParmVarDecl *, SmallVector<ParmVarDecl *, 1> > + typedef llvm::DenseMap<ParmVarDecl *, llvm::TinyPtrVector<ParmVarDecl *>> UnparsedDefaultArgInstantiationsMap; /// \brief A mapping from parameters with unparsed default arguments to the @@ -833,6 +911,7 @@ public: /// Private Helper predicate to check for 'self'. bool isSelfExpr(Expr *RExpr); + bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method); /// \brief Cause the active diagnostic on the DiagosticsEngine to be /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and @@ -853,13 +932,12 @@ public: bool OldFPContractState : 1; }; - typedef llvm::MCAsmParserSemaCallback::InlineAsmIdentifierInfo - InlineAsmIdentifierInfo; + void addImplicitTypedef(StringRef Name, QualType T); public: Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind = TU_Complete, - CodeCompleteConsumer *CompletionConsumer = 0); + CodeCompleteConsumer *CompletionConsumer = nullptr); ~Sema(); /// \brief Perform initialization that occurs after the parser has been @@ -872,7 +950,6 @@ public: DiagnosticsEngine &getDiagnostics() const { return Diags; } SourceManager &getSourceManager() const { return SourceMgr; } - const TargetAttributesSema &getTargetAttributesSema() const; Preprocessor &getPreprocessor() const { return PP; } ASTContext &getASTContext() const { return Context; } ASTConsumer &getASTConsumer() const { return Consumer; } @@ -954,9 +1031,11 @@ public: getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const; std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const; - ExprResult Owned(Expr* E) { return E; } - ExprResult Owned(ExprResult R) { return R; } - StmtResult Owned(Stmt* S) { return S; } + /// \brief Calls \c Lexer::getLocForEndOfToken() + SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0); + + /// \brief Retrieve the module loader associated with the preprocessor. + ModuleLoader &getModuleLoader() const; void ActOnEndOfTranslationUnit(); @@ -967,7 +1046,7 @@ public: void PushFunctionScope(); void PushBlockScope(Scope *BlockScope, BlockDecl *Block); sema::LambdaScopeInfo *PushLambdaScope(); - + /// \brief This is used to inform Sema what the current TemplateParameterDepth /// is during Parsing. Currently it is used to pass on the depth /// when parsing generic lambda 'auto' parameters. @@ -976,13 +1055,27 @@ public: void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD, RecordDecl *RD, CapturedRegionKind K); - void PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP =0, - const Decl *D = 0, const BlockExpr *blkExpr = 0); + void + PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr, + const Decl *D = nullptr, + const BlockExpr *blkExpr = nullptr); sema::FunctionScopeInfo *getCurFunction() const { return FunctionScopes.back(); } + sema::FunctionScopeInfo *getEnclosingFunction() const { + if (FunctionScopes.empty()) + return nullptr; + + for (int e = FunctionScopes.size()-1; e >= 0; --e) { + if (isa<sema::BlockScopeInfo>(FunctionScopes[e])) + continue; + return FunctionScopes[e]; + } + return nullptr; + } + template <typename ExprT> void recordUseOfEvaluatedWeak(const ExprT *E, bool IsRead=true) { if (!isUnevaluatedContext()) @@ -1018,9 +1111,9 @@ public: // QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs, - const DeclSpec *DS = 0); + const DeclSpec *DS = nullptr); QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA, - const DeclSpec *DS = 0); + const DeclSpec *DS = nullptr); QualType BuildPointerType(QualType T, SourceLocation Loc, DeclarationName Entity); QualType BuildReferenceType(QualType T, bool LValueRef, @@ -1061,7 +1154,7 @@ public: /// unqualified type will always be a FunctionProtoType. /// Otherwise, returns a NULL type. QualType BuildFunctionType(QualType T, - llvm::MutableArrayRef<QualType> ParamTypes, + MutableArrayRef<QualType> ParamTypes, SourceLocation Loc, DeclarationName Entity, const FunctionProtoType::ExtProtoInfo &EPI); @@ -1082,10 +1175,13 @@ public: ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo); DeclarationNameInfo GetNameForDeclarator(Declarator &D); DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name); - static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo = 0); + static QualType GetTypeFromParser(ParsedType Ty, + TypeSourceInfo **TInfo = nullptr); CanThrowResult canThrow(const Expr *E); const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT); + void UpdateExceptionSpec(FunctionDecl *FD, + const FunctionProtoType::ExtProtoInfo &EPI); bool CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range); bool CheckDistantExceptionSpec(QualType T); bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); @@ -1096,8 +1192,8 @@ public: const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc, - bool *MissingExceptionSpecification = 0, - bool *MissingEmptyExceptionSpecification = 0, + bool *MissingExceptionSpecification = nullptr, + bool *MissingEmptyExceptionSpecification = nullptr, bool AllowNoexceptAllMatchWithNoSpec = false, bool IsOperatorNew = false); bool CheckExceptionSpecSubset( @@ -1148,7 +1244,7 @@ public: public: BoundTypeDiagnoser1(unsigned DiagID, const T1 &Arg1) : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1) { } - virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + void diagnose(Sema &S, SourceLocation Loc, QualType T) override { if (Suppressed) return; S.Diag(Loc, DiagID) << getPrintable(Arg1) << T; } @@ -1168,7 +1264,7 @@ public: : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1), Arg2(Arg2) { } - virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + void diagnose(Sema &S, SourceLocation Loc, QualType T) override { if (Suppressed) return; S.Diag(Loc, DiagID) << getPrintable(Arg1) << getPrintable(Arg2) << T; } @@ -1189,7 +1285,7 @@ public: : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1), Arg2(Arg2), Arg3(Arg3) { } - virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + void diagnose(Sema &S, SourceLocation Loc, QualType T) override { if (Suppressed) return; S.Diag(Loc, DiagID) << getPrintable(Arg1) << getPrintable(Arg2) << getPrintable(Arg3) << T; @@ -1299,33 +1395,36 @@ public: /// function to pin them on. ActOnFunctionDeclarator reads this list and patches /// them into the FunctionDecl. std::vector<NamedDecl*> DeclsInPrototypeScope; - /// Nonzero if we are currently parsing a function declarator. This is a counter - /// as opposed to a boolean so we can deal with nested function declarators - /// such as: - /// void f(void (*g)(), ...) - unsigned InFunctionDeclarator; - DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = 0); + DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr); void DiagnoseUseOfUnimplementedSelectors(); bool isSimpleTypeSpecifier(tok::TokenKind Kind) const; ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec *SS = 0, + Scope *S, CXXScopeSpec *SS = nullptr, bool isClassName = false, bool HasTrailingDot = false, ParsedType ObjectType = ParsedType(), bool IsCtorOrDtorName = false, bool WantNontrivialTypeSourceInfo = false, - IdentifierInfo **CorrectedII = 0); + IdentifierInfo **CorrectedII = nullptr); TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S); - bool DiagnoseUnknownTypeName(IdentifierInfo *&II, + void DiagnoseUnknownTypeName(IdentifierInfo *&II, SourceLocation IILoc, Scope *S, CXXScopeSpec *SS, - ParsedType &SuggestedType); + ParsedType &SuggestedType, + bool AllowClassTemplates = false); + + /// \brief For compatibility with MSVC, we delay parsing of some default + /// template type arguments until instantiation time. Emits a warning and + /// returns a synthesized DependentNameType that isn't really dependent on any + /// other template arguments. + ParsedType ActOnDelayedDefaultTemplateArg(const IdentifierInfo &II, + SourceLocation NameLoc); /// \brief Describes the result of the name lookup and resolution performed /// by \c ClassifyName(). @@ -1450,7 +1549,7 @@ public: SourceLocation NameLoc, const Token &NextToken, bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC = 0); + CorrectionCandidateCallback *CCC = nullptr); Decl *ActOnDeclarator(Scope *S, Declarator &D); @@ -1461,6 +1560,14 @@ public: bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, DeclarationName Name, SourceLocation Loc); + void + diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, + SourceLocation FallbackLoc, + SourceLocation ConstQualLoc = SourceLocation(), + SourceLocation VolatileQualLoc = SourceLocation(), + SourceLocation RestrictQualLoc = SourceLocation(), + SourceLocation AtomicQualLoc = SourceLocation()); + static bool adjustContextForLocalExternDecl(DeclContext *&DC); void DiagnoseFunctionSpecifiers(const DeclSpec &DS); void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); @@ -1482,8 +1589,6 @@ public: void CheckVariableDeclarationType(VarDecl *NewVD); void CheckCompleteVariableDeclaration(VarDecl *var); void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D); - void ActOnStartFunctionDeclarator(); - void ActOnEndFunctionDeclarator(); NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, TypeSourceInfo *TInfo, @@ -1491,7 +1596,6 @@ public: MultiTemplateParamsArg TemplateParamLists, bool &AddToScope); bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); - void checkVoidParamDecl(ParmVarDecl *Param); bool CheckConstexprFunctionDecl(const FunctionDecl *FD); bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body); @@ -1521,7 +1625,7 @@ public: void ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc, SourceLocation ArgLoc); - void ActOnParamDefaultArgumentError(Decl *param); + void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc); bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, SourceLocation EqualLoc); @@ -1530,12 +1634,16 @@ public: void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto); void ActOnInitializerError(Decl *Dcl); void ActOnCXXForRangeDecl(Decl *D); + StmtResult ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, + IdentifierInfo *Ident, + ParsedAttributes &Attrs, + SourceLocation AttrEnd); void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc); void FinalizeDeclaration(Decl *D); DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, ArrayRef<Decl *> Group); - DeclGroupPtrTy BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *> Group, + DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group, bool TypeMayContainAuto = true); /// Should be called on all declarations that might have attached @@ -1547,7 +1655,7 @@ public: SourceLocation LocAfterDecls); void CheckForFunctionRedefinition(FunctionDecl *FD, const FunctionDecl *EffectiveDefinition = - 0); + nullptr); Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D); Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D); void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); @@ -1555,6 +1663,16 @@ public: return D && isa<ObjCMethodDecl>(D); } + /// \brief Determine whether we can delay parsing the body of a function or + /// function template until it is used, assuming we don't care about emitting + /// code for that function. + /// + /// This will be \c false if we may need the body of the function in the + /// middle of parsing an expression (where it's impractical to switch to + /// parsing a different function), for instance, if it's constexpr in C++11 + /// or has an 'auto' return type in C++14. These cases are essentially bugs. + bool canDelayFunctionBody(const Declarator &D); + /// \brief Determine whether we can skip parsing the body of a function /// definition, assuming we don't care about analyzing its body or emitting /// code for that function. @@ -1568,6 +1686,7 @@ public: Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation); Decl *ActOnSkippedFunctionBody(Decl *Decl); + void ActOnFinishInlineMethodDef(CXXMethodDecl *D); /// ActOnFinishDelayedAttribute - Invoked when we have finished parsing an /// attribute for which parsing is delayed. @@ -1611,12 +1730,13 @@ public: void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod); /// \brief Create an implicit import of the given module at the given - /// source location. + /// source location, for error recovery, if possible. /// - /// This routine is typically used for error recovery, when the entity found - /// by name lookup is actually hidden within a module that we know about but - /// the user has forgotten to import. - void createImplicitModuleImport(SourceLocation Loc, Module *Mod); + /// This routine is typically used when an entity found by name lookup + /// is actually hidden within a module that we know about but the user + /// has forgotten to import. + void createImplicitModuleImportForErrorRecovery(SourceLocation Loc, + Module *Mod); /// \brief Retrieve a suitable printing policy. PrintingPolicy getPrintingPolicy() const { @@ -1640,7 +1760,8 @@ public: Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS, - RecordDecl *Record); + RecordDecl *Record, + const PrintingPolicy &Policy); Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, RecordDecl *Record); @@ -1665,7 +1786,8 @@ public: MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, - bool ScopedEnumUsesClassTag, TypeResult UnderlyingType); + bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, + bool IsTypeSpecifier); Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, @@ -1706,7 +1828,7 @@ public: InClassInitStyle InitStyle, SourceLocation TSSL, AccessSpecifier AS, NamedDecl *PrevDecl, - Declarator *D = 0); + Declarator *D = nullptr); bool CheckNontrivialField(FieldDecl *FD); void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM); @@ -1823,11 +1945,11 @@ public: /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns /// true if 'D' belongs to the given declaration context. /// - /// \param ExplicitInstantiationOrSpecialization When true, we are checking - /// whether the declaration is in scope for the purposes of explicit template - /// instantiation or specialization. The default is false. - bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S = 0, - bool ExplicitInstantiationOrSpecialization = false); + /// \param AllowInlineNamespace If \c true, allow the declaration to be in the + /// enclosing namespace set of the context, rather than contained + /// directly within it. + bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S = nullptr, + bool AllowInlineNamespace = false); /// Finds the scope corresponding to the given decl context, if it /// happens to be an enclosing scope. Otherwise return NULL. @@ -1858,6 +1980,10 @@ public: unsigned AttrSpellingListIndex); DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex); + MSInheritanceAttr * + mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase, + unsigned AttrSpellingListIndex, + MSInheritanceAttr::Spelling SemanticSpelling); FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range, IdentifierInfo *Format, int FormatIdx, int FirstArg, unsigned AttrSpellingListIndex); @@ -1880,7 +2006,7 @@ public: void mergeDeclAttributes(NamedDecl *New, Decl *Old, AvailabilityMergeKind AMK = AMK_Redeclaration); void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls); - bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S, + bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S, bool MergeTypeWithOld); bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, Scope *S, bool MergeTypeWithOld); @@ -1951,9 +2077,9 @@ public: QualType &ConvertedType); bool IsBlockPointerConversion(QualType FromType, QualType ToType, QualType& ConvertedType); - bool FunctionArgTypesAreEqual(const FunctionProtoType *OldType, - const FunctionProtoType *NewType, - unsigned *ArgPos = 0); + bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType, + const FunctionProtoType *NewType, + unsigned *ArgPos = nullptr); void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, QualType FromType, QualType ToType); @@ -2067,10 +2193,10 @@ public: AllowScopedEnumerations(AllowScopedEnumerations) {} /// Match an integral or (possibly scoped) enumeration type. - bool match(QualType T); + bool match(QualType T) override; SemaDiagnosticBuilder - diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) { + diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) override { return diagnoseNotInt(S, Loc, T); } @@ -2123,10 +2249,10 @@ public: bool PartialOverloading = false, bool AllowExplicit = false); void AddFunctionCandidates(const UnresolvedSetImpl &Functions, - ArrayRef<Expr *> Args, - OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions = false, - TemplateArgumentListInfo *ExplicitTemplateArgs = 0); + ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, + bool SuppressUserConversions = false, + TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, @@ -2160,13 +2286,13 @@ public: CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet& CandidateSet, - bool AllowObjCConversionOnExplicit = false); + bool AllowObjCConversionOnExplicit); void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, - bool AllowObjCConversionOnExplicit = false); + bool AllowObjCConversionOnExplicit); void AddSurrogateCandidate(CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -2186,7 +2312,7 @@ public: SourceLocation OpLoc, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet); void AddArgumentDependentLookupCandidates(DeclarationName Name, - bool Operator, SourceLocation Loc, + SourceLocation Loc, ArrayRef<Expr *> Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, @@ -2199,6 +2325,11 @@ public: // identified by the expression Expr void NoteAllOverloadCandidates(Expr* E, QualType DestType = QualType()); + /// Check the enable_if expressions on the given function. Returns the first + /// failing attribute, or NULL if they were all successful. + EnableIfAttr *CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, + bool MissingImplicitThis = false); + // [PossiblyAFunctionType] --> [Return] // NonFunctionType --> NonFunctionType // R (A) --> R(A) @@ -2212,11 +2343,12 @@ public: QualType TargetType, bool Complain, DeclAccessPair &Found, - bool *pHadMultipleCandidates = 0); + bool *pHadMultipleCandidates = nullptr); - FunctionDecl *ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, - bool Complain = false, - DeclAccessPair* Found = 0); + FunctionDecl * + ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, + bool Complain = false, + DeclAccessPair *Found = nullptr); bool ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult &SrcExpr, @@ -2302,7 +2434,7 @@ public: ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, - bool *NoArrowOperatorFound = 0); + bool *NoArrowOperatorFound = nullptr); /// CheckCallReturnType - Checks that a call expression's return type is /// complete. Returns true on failure. The location passed in is the location @@ -2468,6 +2600,9 @@ public: void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, UnresolvedSetImpl &Functions); + void addOverloadedOperatorToUnresolvedSet(UnresolvedSetImpl &Functions, + DeclAccessPair Operator, + QualType T1, QualType T2); LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc, SourceLocation GnuLabelLoc = SourceLocation()); @@ -2484,6 +2619,7 @@ public: bool RValueThis, unsigned ThisQuals); CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); + bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id); LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys, bool AllowRaw, @@ -2491,10 +2627,8 @@ public: bool AllowStringTemplate); bool isKnownName(StringRef name); - void ArgumentDependentLookup(DeclarationName Name, bool Operator, - SourceLocation Loc, - ArrayRef<Expr *> Args, - ADLResult &Functions); + void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, + ArrayRef<Expr *> Args, ADLResult &Functions); void LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer, @@ -2503,13 +2637,19 @@ public: VisibleDeclConsumer &Consumer, bool IncludeGlobalScope = true); + enum CorrectTypoKind { + CTK_NonError, // CorrectTypo used in a non error recovery situation. + CTK_ErrorRecovery // CorrectTypo used in normal error recovery. + }; + TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, - DeclContext *MemberContext = 0, + CorrectTypoKind Mode, + DeclContext *MemberContext = nullptr, bool EnteringContext = false, - const ObjCObjectPointerType *OPT = 0, + const ObjCObjectPointerType *OPT = nullptr, bool RecordFailure = true); void diagnoseTypo(const TypoCorrection &Correction, @@ -2527,8 +2667,7 @@ public: AssociatedClassSet &AssociatedClasses); void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, - bool ConsiderLinkage, - bool ExplicitInstantiationOrSpecialization); + bool ConsiderLinkage, bool AllowInlineNamespace); void DiagnoseAmbiguousLookup(LookupResult &Result); //@} @@ -2557,11 +2696,14 @@ public: bool CheckRegparmAttr(const AttributeList &attr, unsigned &value); bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, - const FunctionDecl *FD = 0); + const FunctionDecl *FD = nullptr); bool CheckNoReturnAttr(const AttributeList &attr); bool checkStringLiteralArgumentAttr(const AttributeList &Attr, unsigned ArgNum, StringRef &Str, - SourceLocation *ArgLocation = 0); + SourceLocation *ArgLocation = nullptr); + bool checkMSInheritanceAttrOnDefinition( + CXXRecordDecl *RD, SourceRange Range, bool BestCase, + MSInheritanceAttr::Spelling SemanticSpelling); void CheckAlignasUnderalignment(Decl *D); @@ -2570,6 +2712,11 @@ public: /// function type typedefs and typename template arguments. void adjustMemberFunctionCC(QualType &T, bool IsStatic); + // Check if there is an explicit attribute, but only look through parens. + // The intent is to look for an attribute on the current declarator, but not + // one that came from a typedef. + bool hasExplicitCallingConv(QualType &T); + /// Get the outermost AttributedType node that sets a calling convention. /// Valid types should not have multiple attributes with different CCs. const AttributedType *getCallingConvAttributedType(QualType T) const; @@ -2578,8 +2725,6 @@ public: StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs, SourceRange Range); - void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, - bool &IncompleteImpl, unsigned DiagID); void WarnConflictingTypedMethods(ObjCMethodDecl *Method, ObjCMethodDecl *MethodDecl, bool IsProtocolMethodDecl); @@ -2597,15 +2742,6 @@ public: 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. - void CheckProtocolMethodDefs(SourceLocation ImpLoc, - ObjCProtocolDecl *PDecl, - bool& IncompleteImpl, - const SelectorSet &InsMap, - const SelectorSet &ClsMap, - ObjCContainerDecl *CDecl); - /// CheckImplementationIvars - This routine checks if the instance variables /// listed in the implelementation match those listed in the interface. void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, @@ -2621,7 +2757,8 @@ public: /// DiagnoseUnimplementedProperties - This routine warns on those properties /// which must be implemented by this implementation. void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, - ObjCContainerDecl *CDecl); + ObjCContainerDecl *CDecl, + bool SynthesizeProperties); /// DefaultSynthesizeProperties - This routine default synthesizes all /// properties which must be synthesized in the class's \@implementation. @@ -2629,12 +2766,6 @@ public: ObjCInterfaceDecl *IDecl); void DefaultSynthesizeProperties(Scope *S, Decl *D); - /// CollectImmediateProperties - This routine collects all properties in - /// the class and its conforming protocols; but not those it its super class. - void CollectImmediateProperties(ObjCContainerDecl *CDecl, - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap); - /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is /// an ivar synthesized for 'Method' and 'Method' is a property accessor /// declared in class 'IFace'. @@ -2643,7 +2774,8 @@ public: /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which /// backs the property is not used in the property's accessor. - void DiagnoseUnusedBackingIvarInAccessor(Scope *S); + void DiagnoseUnusedBackingIvarInAccessor(Scope *S, + const ObjCImplementationDecl *ImplD); /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and /// it property has a backing ivar, returns this ivar; otherwise, returns NULL. @@ -2682,7 +2814,7 @@ public: const unsigned AttributesAsWritten, TypeSourceInfo *T, tok::ObjCKeywordKind MethodImplKind, - DeclContext *lexicalDC = 0); + DeclContext *lexicalDC = nullptr); /// AtomicPropertySetterGetterRules - This routine enforces the rule (via /// warning) when atomic property has one but not the other user-declared @@ -2692,6 +2824,10 @@ public: void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D); + void DiagnoseMissingDesignatedInitOverrides( + const ObjCImplementationDecl *ImplD, + const ObjCInterfaceDecl *IFD); + void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID); enum MethodMatchStrategy { @@ -2785,12 +2921,6 @@ public: const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel, QualType ObjectType=QualType()); - - /// DiagnoseMismatchedMethodsInGlobalPool - This routine goes through list of - /// methods in global pool and issues diagnostic on identical selectors which - /// have mismathched types. - void DiagnoseMismatchedMethodsInGlobalPool(); - /// LookupImplementedMethodInGlobalPool - Returns the method which has an /// implementation. ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel); @@ -2805,7 +2935,7 @@ public: public: class FullExprArg { public: - FullExprArg(Sema &actions) : E(0) { } + FullExprArg(Sema &actions) : E(nullptr) { } // FIXME: The const_cast here is ugly. RValue references would make this // much nicer (or we could duplicate a bunch of the move semantics @@ -2836,13 +2966,13 @@ public: return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); } FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { - return FullExprArg(ActOnFinishFullExpr(Arg, CC).release()); + return FullExprArg(ActOnFinishFullExpr(Arg, CC).get()); } FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) { ExprResult FE = ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), /*DiscardedValue*/ true); - return FullExprArg(FE.release()); + return FullExprArg(FE.get()); } StmtResult ActOnExprStmt(ExprResult Arg); @@ -2957,15 +3087,23 @@ public: void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams); + typedef std::pair<StringRef, QualType> CapturedParamNameType; + void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, + CapturedRegionKind Kind, + ArrayRef<CapturedParamNameType> Params); StmtResult ActOnCapturedRegionEnd(Stmt *S); void ActOnCapturedRegionError(); RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc, unsigned NumParams); - const VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E, - bool AllowFunctionParameters); - - StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); + VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E, + bool AllowFunctionParameters); + bool isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD, + bool AllowFunctionParameters); + + StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, + Scope *CurScope); + StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, @@ -2978,7 +3116,7 @@ public: ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, - InlineAsmIdentifierInfo &Info, + llvm::InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext); bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc); @@ -3031,14 +3169,12 @@ public: StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ? SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler); - - StmtResult ActOnSEHExceptBlock(SourceLocation Loc, - Expr *FilterExpr, + Stmt *Handler, int HandlerIndex, + int HandlerParentIndex); + StmtResult ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr, Stmt *Block); - - StmtResult ActOnSEHFinallyBlock(SourceLocation Loc, - Stmt *Block); + StmtResult ActOnSEHFinallyBlock(SourceLocation Loc, Stmt *Block); + StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope); void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock); @@ -3083,12 +3219,16 @@ public: void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); - void EmitDeprecationWarning(NamedDecl *D, StringRef Message, - SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty); + enum AvailabilityDiagnostic { AD_Deprecation, AD_Unavailable }; + + void EmitAvailabilityWarning(AvailabilityDiagnostic AD, + NamedDecl *D, StringRef Message, + SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty, + bool ObjCPropertyAccess); - void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); + void HandleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); bool makeUnavailableInSystemHeader(SourceLocation loc, StringRef message); @@ -3098,7 +3238,8 @@ public: bool CanUseDecl(NamedDecl *D); bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass=0); + const ObjCInterfaceDecl *UnknownObjCClass=nullptr, + bool ObjCPropertyAccess=false); void NoteDeletedFunction(FunctionDecl *FD); std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD); bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, @@ -3108,7 +3249,7 @@ public: ArrayRef<Expr *> Args); void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = 0, + Decl *LambdaContextDecl = nullptr, bool IsDecltype = false); enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl }; void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, @@ -3199,7 +3340,7 @@ public: /// emitted; this may also leave the ExprResult invalid. bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, bool ForceComplain = false, - bool (*IsPlausibleResult)(QualType) = 0); + bool (*IsPlausibleResult)(QualType) = nullptr); /// \brief Figure out if an expression could be turned into a call. bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, @@ -3222,7 +3363,7 @@ public: SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC = 0, + CorrectionCandidateCallback *CCC = nullptr, bool IsInlineAsmIdentifier = false); void DecomposeUnqualifiedId(const UnqualifiedId &Id, @@ -3230,10 +3371,11 @@ public: DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *&TemplateArgs); - bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, - CorrectionCandidateCallback &CCC, - TemplateArgumentListInfo *ExplicitTemplateArgs = 0, - ArrayRef<Expr *> Args = None); + bool + DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, + CorrectionCandidateCallback &CCC, + TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, + ArrayRef<Expr *> Args = None); ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, IdentifierInfo *II, @@ -3248,18 +3390,20 @@ public: ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, - const CXXScopeSpec *SS = 0); - ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, - const DeclarationNameInfo &NameInfo, - const CXXScopeSpec *SS = 0, NamedDecl *FoundD = 0, - const TemplateArgumentListInfo *TemplateArgs = 0); + const CXXScopeSpec *SS = nullptr); + ExprResult + BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, + const DeclarationNameInfo &NameInfo, + const CXXScopeSpec *SS = nullptr, + NamedDecl *FoundD = nullptr, + const TemplateArgumentListInfo *TemplateArgs = nullptr); ExprResult BuildAnonymousStructUnionMemberReference( const CXXScopeSpec &SS, SourceLocation nameLoc, IndirectFieldDecl *indirectField, - DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_none), - Expr *baseObjectExpr = 0, + DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none), + Expr *baseObjectExpr = nullptr, SourceLocation opLoc = SourceLocation()); ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, @@ -3275,9 +3419,10 @@ public: const LookupResult &R, bool HasTrailingLParen); - ExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo, - bool IsAddressOfOperand); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, @@ -3288,20 +3433,22 @@ public: bool NeedsADL); ExprResult BuildDeclarationNameExpr( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, - NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0); + NamedDecl *FoundD = nullptr, + const TemplateArgumentListInfo *TemplateArgs = nullptr); ExprResult BuildLiteralOperatorCall(LookupResult &R, - DeclarationNameInfo &SuffixInfo, - ArrayRef<Expr*> Args, - SourceLocation LitEndLoc, - TemplateArgumentListInfo *ExplicitTemplateArgs = 0); + DeclarationNameInfo &SuffixInfo, + ArrayRef<Expr *> Args, + SourceLocation LitEndLoc, + TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); ExprResult BuildPredefinedExpr(SourceLocation Loc, PredefinedExpr::IdentType IT); ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val); - ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = 0); - ExprResult ActOnCharacterConstant(const Token &Tok, Scope *UDLScope = 0); + ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr); + ExprResult ActOnCharacterConstant(const Token &Tok, + Scope *UDLScope = nullptr); ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E); ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R, @@ -3309,8 +3456,8 @@ public: /// ActOnStringLiteral - The specified tokens were lexed as pasted string /// fragments (e.g. "foo" "bar" L"baz"). - ExprResult ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks, - Scope *UDLScope = 0); + ExprResult ActOnStringLiteral(ArrayRef<Token> StringToks, + Scope *UDLScope = nullptr); ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc, SourceLocation DefaultLoc, @@ -3367,14 +3514,6 @@ public: ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc); - ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, - SourceLocation OpLoc, bool IsArrow, - CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierInScope, - 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 @@ -3387,22 +3526,23 @@ public: bool HasTrailingLParen; }; - ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, - SourceLocation OpLoc, bool IsArrow, - const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierInScope, - LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, - bool SuppressQualifierCheck = false, - ActOnMemberAccessExtraArgs *ExtraArgs = 0); + ExprResult BuildMemberReferenceExpr( + Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, + CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, + ActOnMemberAccessExtraArgs *ExtraArgs = nullptr); + + ExprResult + BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, + bool IsArrow, const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, + bool SuppressQualifierCheck = false, + ActOnMemberAccessExtraArgs *ExtraArgs = nullptr); ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow); - ExprResult LookupMemberExpr(LookupResult &R, ExprResult &Base, - bool &IsArrow, SourceLocation OpLoc, - CXXScopeSpec &SS, - Decl *ObjCImpDecl, - bool HasTemplateArgs); bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, const CXXScopeSpec &SS, @@ -3441,12 +3581,13 @@ public: /// locations. ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, - Expr *ExecConfig = 0, bool IsExecConfig = false); + Expr *ExecConfig = nullptr, + bool IsExecConfig = false); ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, ArrayRef<Expr *> Arg, SourceLocation RParenLoc, - Expr *Config = 0, + Expr *Config = nullptr, bool IsExecConfig = false); ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, @@ -3682,12 +3823,13 @@ public: const LookupResult &Previous); bool CheckUsingDeclQualifier(SourceLocation UsingLoc, const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, SourceLocation NameLoc); NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo, + DeclarationNameInfo NameInfo, AttributeList *AttrList, bool IsInstantiation, bool HasTypenameKeyword, @@ -3720,16 +3862,18 @@ public: BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg Exprs, bool HadMultipleCandidates, bool IsListInitialization, + bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange); - // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if + // FIXME: Can we remove this and have the above BuildCXXConstructExpr check if // the constructor can be elidable? ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, bool HadMultipleCandidates, - bool IsListInitialization, bool RequiresZeroInit, + bool IsListInitialization, + bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange); /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating @@ -3801,7 +3945,7 @@ public: /// potential exceptions of the special member function contains "any" EPI.ExceptionSpecType = EST_ComputedNoexcept; EPI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(), - tok::kw_false).take(); + tok::kw_false).get(); } } FunctionProtoType::ExtProtoInfo getEPI() const { @@ -4111,7 +4255,7 @@ public: /// \return returns 'true' if failed, 'false' if success. bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false, bool BuildAndDiagnose = true, - const unsigned *const FunctionScopeIndexToStopAt = 0); + const unsigned *const FunctionScopeIndexToStopAt = nullptr); /// \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 @@ -4208,32 +4352,6 @@ public: ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand, SourceLocation RParen); - /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support - /// pseudo-functions. - ExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT, - SourceLocation KWLoc, - ParsedType Ty, - SourceLocation RParen); - - ExprResult BuildUnaryTypeTrait(UnaryTypeTrait OTT, - SourceLocation KWLoc, - TypeSourceInfo *T, - SourceLocation RParen); - - /// ActOnBinaryTypeTrait - Parsed one of the bianry type trait support - /// pseudo-functions. - ExprResult ActOnBinaryTypeTrait(BinaryTypeTrait OTT, - SourceLocation KWLoc, - ParsedType LhsTy, - ParsedType RhsTy, - SourceLocation RParen); - - ExprResult BuildBinaryTypeTrait(BinaryTypeTrait BTT, - SourceLocation KWLoc, - TypeSourceInfo *LhsT, - TypeSourceInfo *RhsT, - SourceLocation RParen); - /// \brief Parsed one of the type trait support pseudo-functions. ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ArrayRef<ParsedType> Args, @@ -4359,7 +4477,8 @@ public: bool EnteringContext, CXXScopeSpec &SS, NamedDecl *ScopeLookupResult, - bool ErrorRecoveryLookup); + bool ErrorRecoveryLookup, + bool *IsCorrectedToColon = nullptr); /// \brief The parser has parsed a nested-name-specifier 'identifier::'. /// @@ -4382,6 +4501,13 @@ public: /// output parameter (containing the full nested-name-specifier, /// including this new type). /// + /// \param ErrorRecoveryLookup If true, then this method is called to improve + /// error recovery. In this case do not emit error message. + /// + /// \param IsCorrectedToColon If not null, suggestions to replace '::' -> ':' + /// are allowed. The bool value pointed by this parameter is set to 'true' + /// if the identifier is treated as if it was followed by ':', not '::'. + /// /// \returns true if an error occurred, false otherwise. bool ActOnCXXNestedNameSpecifier(Scope *S, IdentifierInfo &Identifier, @@ -4389,7 +4515,9 @@ public: SourceLocation CCLoc, ParsedType ObjectType, bool EnteringContext, - CXXScopeSpec &SS); + CXXScopeSpec &SS, + bool ErrorRecoveryLookup = false, + bool *IsCorrectedToColon = nullptr); ExprResult ActOnDecltypeExpression(Expr *E); @@ -4632,7 +4760,8 @@ public: SourceLocation AtLoc, SourceLocation SelLoc, SourceLocation LParenLoc, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + bool WarnMultipleSelectors); /// ParseObjCProtocolExpression - Build protocol expression for \@protocol ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName, @@ -4647,8 +4776,7 @@ public: // Decl *ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, - SourceLocation LangLoc, - StringRef Lang, + Expr *LangStr, SourceLocation LBraceLoc); Decl *ActOnFinishLinkageSpecification(Scope *S, Decl *LinkageSpec, @@ -4659,21 +4787,24 @@ public: // C++ Classes // bool isCurrentClassName(const IdentifierInfo &II, Scope *S, - const CXXScopeSpec *SS = 0); + const CXXScopeSpec *SS = nullptr); bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS); bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs = 0); + AttributeList *Attrs = nullptr); NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, Expr *BitfieldWidth, const VirtSpecifiers &VS, InClassInitStyle InitStyle); - void ActOnCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc, - Expr *Init); + + void ActOnStartCXXInClassMemberInitializer(); + void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl, + SourceLocation EqualLoc, + Expr *Init); MemInitResult ActOnMemInitializer(Decl *ConstructorD, Scope *S, @@ -4799,8 +4930,8 @@ public: AttributeList *AttrList); void ActOnFinishCXXMemberDecls(); - void ActOnReenterTemplateScope(Scope *S, Decl *Template); - void ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D); + void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param); + unsigned ActOnReenterTemplateScope(Scope *S, Decl *Template); void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record); void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method); void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param); @@ -4879,7 +5010,7 @@ public: bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, - CXXCastPath *BasePath = 0, + CXXCastPath *BasePath = nullptr, bool IgnoreAccess = false); bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, unsigned InaccessibleBaseID, @@ -5067,7 +5198,7 @@ public: void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl); - Decl *ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, + Decl *ActOnTypeParameter(Scope *S, bool Typename, SourceLocation EllipsisLoc, SourceLocation KeyLoc, IdentifierInfo *ParamName, @@ -5118,7 +5249,8 @@ public: TemplateParamListContext TPC); TemplateParameterList *MatchTemplateParametersToScopeSpecifier( SourceLocation DeclStartLoc, SourceLocation DeclLoc, - const CXXScopeSpec &SS, ArrayRef<TemplateParameterList *> ParamLists, + const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId, + ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend, bool &IsExplicitSpecialization, bool &Invalid); DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, @@ -5128,6 +5260,7 @@ public: TemplateParameterList *TemplateParams, AccessSpecifier AS, SourceLocation ModulePrivateLoc, + SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, TemplateParameterList **OuterTemplateParamLists); @@ -5162,7 +5295,7 @@ public: SourceLocation RAngleLoc); DeclResult ActOnVarTemplateSpecialization( - Scope *S, VarTemplateDecl *VarTemplate, Declarator &D, TypeSourceInfo *DI, + Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams, StorageClass SC, bool IsPartialSpecialization); @@ -5200,12 +5333,7 @@ public: ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, SourceLocation ModulePrivateLoc, - CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc, + TemplateIdAnnotation &TemplateId, AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists); @@ -5290,7 +5418,7 @@ public: }; bool CheckTemplateArgument(NamedDecl *Param, - const TemplateArgumentLoc &Arg, + TemplateArgumentLoc &Arg, NamedDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, @@ -5318,21 +5446,15 @@ public: /// \param Converted Will receive the converted, canonicalized template /// arguments. /// - /// - /// \param ExpansionIntoFixedList If non-NULL, will be set true to indicate - /// when the template arguments contain a pack expansion that is being - /// expanded into a fixed parameter list. - /// - /// \returns True if an error occurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl<TemplateArgument> &Converted, - bool *ExpansionIntoFixedList = 0); + SmallVectorImpl<TemplateArgument> &Converted); bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, - const TemplateArgumentLoc &Arg, + TemplateArgumentLoc &Arg, SmallVectorImpl<TemplateArgument> &Converted); bool CheckTemplateArgument(TemplateTypeParmDecl *Param, @@ -5342,7 +5464,7 @@ public: TemplateArgument &Converted, CheckTemplateArgumentKind CTAK = CTAK_Specified); bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, - const TemplateArgumentLoc &Arg, + TemplateArgumentLoc &Arg, unsigned ArgumentPackIndex); ExprResult @@ -5880,7 +6002,7 @@ public: unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, - SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = 0); + SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, @@ -5977,10 +6099,11 @@ public: // C++ Template Instantiation // - MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D, - const TemplateArgumentList *Innermost = 0, - bool RelativeToPrimary = false, - const FunctionDecl *Pattern = 0); + MultiLevelTemplateArgumentList + getTemplateInstantiationArgs(NamedDecl *D, + const TemplateArgumentList *Innermost = nullptr, + bool RelativeToPrimary = false, + const FunctionDecl *Pattern = nullptr); /// \brief A template instantiation that is currently in progress. struct ActiveTemplateInstantiation { @@ -6055,8 +6178,8 @@ public: SourceRange InstantiationRange; ActiveTemplateInstantiation() - : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0), - NumTemplateArgs(0), DeductionInfo(0) {} + : Kind(TemplateInstantiation), Template(nullptr), Entity(nullptr), + TemplateArgs(nullptr), NumTemplateArgs(0), DeductionInfo(nullptr) {} /// \brief Determines whether this template is an actual instantiation /// that should be counted toward the maximum instantiation depth. @@ -6249,13 +6372,15 @@ public: SourceRange InstantiationRange = SourceRange()); /// \brief Note that we are substituting prior template arguments into a - /// non-type or template template parameter. + /// non-type parameter. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template, NonTypeTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange); + /// \brief Note that we are substituting prior template arguments into a + /// template template parameter. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template, TemplateTemplateParmDecl *Param, @@ -6287,6 +6412,15 @@ public: bool CheckInstantiationDepth(SourceLocation PointOfInstantiation, SourceRange InstantiationRange); + // FIXME: Replace this with a constructor once we can use delegating + // constructors in llvm. + void Initialize( + ActiveTemplateInstantiation::InstantiationKind Kind, + SourceLocation PointOfInstantiation, SourceRange InstantiationRange, + Decl *Entity, NamedDecl *Template = nullptr, + ArrayRef<TemplateArgument> TemplateArgs = ArrayRef<TemplateArgument>(), + sema::TemplateDeductionInfo *DeductionInfo = nullptr); + InstantiatingTemplate(const InstantiatingTemplate&) LLVM_DELETED_FUNCTION; InstantiatingTemplate& @@ -6472,7 +6606,7 @@ public: ParmVarDecl **Params, unsigned NumParams, const MultiLevelTemplateArgumentList &TemplateArgs, SmallVectorImpl<QualType> &ParamTypes, - SmallVectorImpl<ParmVarDecl *> *OutParams = 0); + SmallVectorImpl<ParmVarDecl *> *OutParams = nullptr); ExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -6536,8 +6670,8 @@ public: void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Pattern, Decl *Inst, - LateInstantiatedAttrVec *LateAttrs = 0, - LocalInstantiationScope *OuterMostScope = 0); + LateInstantiatedAttrVec *LateAttrs = nullptr, + LocalInstantiationScope *OuterMostScope = nullptr); bool InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation, @@ -6582,8 +6716,8 @@ public: const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl<TemplateArgument> &Converted, SourceLocation PointOfInstantiation, void *InsertPos, - LateInstantiatedAttrVec *LateAttrs = 0, - LocalInstantiationScope *StartingScope = 0); + LateInstantiatedAttrVec *LateAttrs = nullptr, + LocalInstantiationScope *StartingScope = nullptr); VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -6717,8 +6851,8 @@ public: /// \param lexicalDC Container for redeclaredProperty. void ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCContainerDecl *CD, - ObjCPropertyDecl *redeclaredProperty = 0, - ObjCContainerDecl *lexicalDC = 0); + ObjCPropertyDecl *redeclaredProperty = nullptr, + ObjCContainerDecl *lexicalDC = nullptr); void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, @@ -6739,7 +6873,7 @@ public: Selector GetterSel, Selector SetterSel, bool *OverridingProperty, tok::ObjCKeywordKind MethodImplKind, - DeclContext *lexicalDC = 0); + DeclContext *lexicalDC = nullptr); Decl *ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc, @@ -6902,6 +7036,27 @@ public: SourceLocation RParenLoc, Expr *SubExpr); + void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr); + + void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr); + + bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, + CastKind &Kind); + + bool checkObjCBridgeRelatedComponents(SourceLocation Loc, + QualType DestType, QualType SrcType, + ObjCInterfaceDecl *&RelatedClass, + ObjCMethodDecl *&ClassMethod, + ObjCMethodDecl *&InstanceMethod, + TypedefNameDecl *&TDNDecl, + bool CfToNs); + + bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, + QualType DestType, QualType SrcType, + Expr *&SrcExpr); + + bool ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&SrcExpr); + bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); /// \brief Check whether the given new method is a valid override of the @@ -6969,6 +7124,69 @@ public: /// \#pragma comment(kind, "arg"). void ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg); + /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma + /// pointers_to_members(representation method[, general purpose + /// representation]). + void ActOnPragmaMSPointersToMembers( + LangOptions::PragmaMSPointersToMembersKind Kind, + SourceLocation PragmaLoc); + + /// \brief Called on well formed \#pragma vtordisp(). + void ActOnPragmaMSVtorDisp(PragmaVtorDispKind Kind, SourceLocation PragmaLoc, + MSVtorDispAttr::Mode Value); + + enum PragmaSectionKind { + PSK_DataSeg, + PSK_BSSSeg, + PSK_ConstSeg, + PSK_CodeSeg, + }; + + enum PragmaSectionFlag : unsigned { + PSF_None = 0, + PSF_Read = 0x1, + PSF_Write = 0x2, + PSF_Execute = 0x4, + PSF_Implicit = 0x8, + PSF_Invalid = 0x80000000U, + }; + + struct SectionInfo { + DeclaratorDecl *Decl; + SourceLocation PragmaSectionLocation; + int SectionFlags; + SectionInfo() {} + SectionInfo(DeclaratorDecl *Decl, + SourceLocation PragmaSectionLocation, + int SectionFlags) + : Decl(Decl), + PragmaSectionLocation(PragmaSectionLocation), + SectionFlags(SectionFlags) {} + }; + + llvm::StringMap<SectionInfo> SectionInfos; + bool UnifySection(const StringRef &SectionName, + int SectionFlags, + DeclaratorDecl *TheDecl); + bool UnifySection(const StringRef &SectionName, + int SectionFlags, + SourceLocation PragmaSectionLocation); + + /// \brief Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg. + void ActOnPragmaMSSeg(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + llvm::StringRef StackSlotLabel, + StringLiteral *SegmentName, + llvm::StringRef PragmaName); + + /// \brief Called on well formed \#pragma section(). + void ActOnPragmaMSSection(SourceLocation PragmaLocation, + int SectionFlags, StringLiteral *SegmentName); + + /// \brief Called on well-formed \#pragma init_seg(). + void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, + StringLiteral *SegmentName); + /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value); @@ -7040,6 +7258,25 @@ public: /// the appropriate attribute. void AddCFAuditedAttribute(Decl *D); + /// \brief Called on well formed \#pragma clang optimize. + void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc); + + /// \brief Get the location for the currently active "\#pragma clang optimize + /// off". If this location is invalid, then the state of the pragma is "on". + SourceLocation getOptimizeOffPragmaLocation() const { + return OptimizeOffPragmaLocation; + } + + /// \brief Only called on function definitions; if there is a pragma in scope + /// with the effect of a range-based optnone, consider marking the function + /// with attribute optnone. + void AddRangeBasedOptnone(FunctionDecl *FD); + + /// \brief Adds the 'optnone' attribute to the function declaration if there + /// are no conflicts; Loc represents the location causing the 'optnone' + /// attribute to be added (usually because of a pragma). + void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc); + /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, unsigned SpellingListIndex, bool IsPackExpansion); @@ -7052,11 +7289,15 @@ private: /// \brief Initialization of data-sharing attributes stack. void InitDataSharingAttributesStack(); void DestroyDataSharingAttributesStack(); + ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, + OpenMPClauseKind CKind); public: + ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, + Expr *Op); /// \brief Called on start of new data sharing attribute block. void StartOpenMPDSABlock(OpenMPDirectiveKind K, - const DeclarationNameInfo &DirName, - Scope *CurScope); + const DeclarationNameInfo &DirName, Scope *CurScope, + SourceLocation Loc); /// \brief Called on end of data sharing attribute block. void EndOpenMPDSABlock(Stmt *CurDirective); @@ -7070,12 +7311,15 @@ public: DeclGroupPtrTy ActOnOpenMPThreadprivateDirective( SourceLocation Loc, ArrayRef<Expr *> VarList); - // \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness. + /// \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness. OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl( SourceLocation Loc, ArrayRef<Expr *> VarList); + /// \brief Initialization of captured region for OpenMP region. + void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope); StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, + const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, @@ -7086,6 +7330,100 @@ public: Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp simd' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPSimdDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); + /// \brief Called on well-formed '\#pragma omp for' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPForDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); + /// \brief Called on well-formed '\#pragma omp sections' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp section' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp single' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp master' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp critical' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp parallel for' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPParallelForDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); + /// \brief Called on well-formed '\#pragma omp parallel sections' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp task' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp taskyield'. + StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp barrier'. + StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp taskwait'. + StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp flush'. + StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc); + + OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, + Expr *Expr, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'if' clause. + OMPClause *ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'final' clause. + OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'num_threads' clause. + OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'safelen' clause. + OMPClause *ActOnOpenMPSafelenClause(Expr *Length, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'collapse' clause. + OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, @@ -7099,12 +7437,50 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - - OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind, - ArrayRef<Expr *> Vars, - SourceLocation StartLoc, - SourceLocation LParenLoc, + /// \brief Called on well-formed 'proc_bind' clause. + OMPClause *ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + + OMPClause *ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, + unsigned Argument, Expr *Expr, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ArgumentLoc, + SourceLocation CommaLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'schedule' clause. + OMPClause *ActOnOpenMPScheduleClause(OpenMPScheduleClauseKind Kind, + Expr *ChunkSize, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation KindLoc, + SourceLocation CommaLoc, + SourceLocation EndLoc); + + OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'ordered' clause. + OMPClause *ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed 'nowait' clause. + OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'untied' clause. + OMPClause *ActOnOpenMPUntiedClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'mergeable' clause. + OMPClause *ActOnOpenMPMergeableClause(SourceLocation StartLoc, + SourceLocation EndLoc); + + OMPClause * + ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, + Expr *TailExpr, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, + CXXScopeSpec &ReductionIdScopeSpec, + const DeclarationNameInfo &ReductionId); /// \brief Called on well-formed 'private' clause. OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, @@ -7115,11 +7491,52 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// \brief Called on well-formed 'lastprivate' clause. + OMPClause *ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); /// \brief Called on well-formed 'shared' clause. OMPClause *ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// \brief Called on well-formed 'reduction' clause. + OMPClause * + ActOnOpenMPReductionClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, + CXXScopeSpec &ReductionIdScopeSpec, + const DeclarationNameInfo &ReductionId); + /// \brief Called on well-formed 'linear' clause. + OMPClause *ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, + Expr *Step, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'aligned' clause. + OMPClause *ActOnOpenMPAlignedClause(ArrayRef<Expr *> VarList, + Expr *Alignment, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'copyin' clause. + OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'copyprivate' clause. + OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'flush' pseudo clause. + OMPClause *ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); /// \brief The kind of conversion being performed. enum CheckedConversionKind { @@ -7138,7 +7555,7 @@ public: /// If isLvalue, the result of the cast is an lvalue. ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK = VK_RValue, - const CXXCastPath *BasePath = 0, + const CXXCastPath *BasePath = nullptr, CheckedConversionKind CCK = CCK_ImplicitConversion); @@ -7155,6 +7572,10 @@ public: // functions and arrays to their respective pointers (C99 6.3.2.1). ExprResult UsualUnaryConversions(Expr *E); + /// CallExprUnaryConversions - a special case of an unary conversion + /// performed on a function designator of a call expression. + ExprResult CallExprUnaryConversions(Expr *E); + // DefaultFunctionArrayConversion - converts functions and arrays // to their respective pointers (C99 6.3.2.1). ExprResult DefaultFunctionArrayConversion(Expr *E); @@ -7204,13 +7625,14 @@ public: /// function, issuing a diagnostic if not. void checkVariadicArgument(const Expr *E, VariadicCallType CT); + /// Check to see if a given expression could have '.c_str()' called on it. + bool hasCStrMethod(const Expr *E); + /// GatherArgumentsForCall - Collector argument expressions for various /// form of call prototypes. - bool GatherArgumentsForCall(SourceLocation CallLoc, - FunctionDecl *FDecl, + bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, const FunctionProtoType *Proto, - unsigned FirstProtoArg, - ArrayRef<Expr *> Args, + unsigned FirstParam, ArrayRef<Expr *> Args, SmallVectorImpl<Expr *> &AllArgs, VariadicCallType CallType = VariadicDoesNotApply, bool AllowExplicit = false, @@ -7308,7 +7730,7 @@ public: SourceLocation Loc, QualType DstType, QualType SrcType, Expr *SrcExpr, AssignmentAction Action, - bool *Complained = 0); + bool *Complained = nullptr); /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant /// integer not in the range of enum values. @@ -7379,10 +7801,10 @@ public: bool IsCompAssign = false); QualType CheckAdditionOperands( // C99 6.5.6 ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, - QualType* CompLHSTy = 0); + QualType* CompLHSTy = nullptr); QualType CheckSubtractionOperands( // C99 6.5.6 ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - QualType* CompLHSTy = 0); + QualType* CompLHSTy = nullptr); QualType CheckShiftOperands( // C99 6.5.7 ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, bool IsCompAssign = false); @@ -7415,15 +7837,15 @@ public: ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, - bool *NonStandardCompositeType = 0); + bool *NonStandardCompositeType = nullptr); QualType FindCompositePointerType(SourceLocation Loc, ExprResult &E1, ExprResult &E2, - bool *NonStandardCompositeType = 0) { - Expr *E1Tmp = E1.take(), *E2Tmp = E2.take(); + bool *NonStandardCompositeType = nullptr) { + Expr *E1Tmp = E1.get(), *E2Tmp = E2.get(); QualType Composite = FindCompositePointerType(Loc, E1Tmp, E2Tmp, NonStandardCompositeType); - E1 = Owned(E1Tmp); - E2 = Owned(E2Tmp); + E1 = E1Tmp; + E2 = E2Tmp; return Composite; } @@ -7433,6 +7855,10 @@ public: bool DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr, SourceLocation QuestionLoc); + void DiagnoseAlwaysNonNullPointer(Expr *E, + Expr::NullPointerConstantKind NullType, + bool IsEqual, SourceRange Range); + /// type checking for vector binary operators. QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign); @@ -7442,6 +7868,8 @@ public: QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc); + bool isLaxVectorConversion(QualType srcType, QualType destType); + /// type checking declaration initializers (C99 6.7.8) bool CheckForConstantInitializer(Expr *e, QualType t); @@ -7514,7 +7942,9 @@ public: ARCConversionResult CheckObjCARCConversion(SourceRange castRange, QualType castType, Expr *&op, CheckedConversionKind CCK, - bool DiagnoseCFAudited = false); + bool DiagnoseCFAudited = false, + BinaryOperatorKind Opc = BO_PtrMemD + ); Expr *stripARCUnbridgedCast(Expr *e); void diagnoseARCUnbridgedCast(Expr *e); @@ -7622,7 +8052,8 @@ public: ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, unsigned DiagID, bool AllowFold = true); - ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result=0); + ExprResult VerifyIntegerConstantExpression(Expr *E, + llvm::APSInt *Result = nullptr); /// VerifyBitField - verifies that a bit field expression is an ICE and has /// the correct width, and that the field type is valid. @@ -7630,7 +8061,7 @@ public: /// Can optionally return whether the bit-field is of width 0 ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, QualType FieldTy, bool IsMsStruct, - Expr *BitWidth, bool *ZeroWidth = 0); + Expr *BitWidth, bool *ZeroWidth = nullptr); enum CUDAFunctionTarget { CFT_Device, @@ -7754,7 +8185,7 @@ public: void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, ArrayRef<IdentifierInfo *> SelIdents, bool AtArgumentExpression, - ObjCInterfaceDecl *Super = 0); + ObjCInterfaceDecl *Super = nullptr); void CodeCompleteObjCForCollection(Scope *S, DeclGroupPtrTy IterationVar); void CodeCompleteObjCSelector(Scope *S, @@ -7807,7 +8238,7 @@ public: private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, - const ArraySubscriptExpr *ASE=0, + const ArraySubscriptExpr *ASE=nullptr, bool AllowOnePastEnd=true, bool IndexNegated=false); void CheckArrayAccess(const Expr *E); // Used to grab the relevant information from a FormatAttr and a @@ -7833,21 +8264,24 @@ private: SourceLocation Loc); void checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args, - unsigned NumProtoArgs, bool IsMemberFunction, - SourceLocation Loc, SourceRange Range, - VariadicCallType CallType); - + unsigned NumParams, bool IsMemberFunction, SourceLocation Loc, + SourceRange Range, VariadicCallType CallType); bool CheckObjCString(Expr *Arg); ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, + unsigned MaxWidth); + bool CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool SemaBuiltinVAStart(CallExpr *TheCall); + bool SemaBuiltinVAStartARM(CallExpr *Call); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs); @@ -7860,13 +8294,15 @@ public: private: bool SemaBuiltinPrefetch(CallExpr *TheCall); - bool SemaBuiltinObjectSize(CallExpr *TheCall); + bool SemaBuiltinAssume(CallExpr *TheCall); bool SemaBuiltinLongjmp(CallExpr *TheCall); ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult); ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op); bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result); + bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, + int Low, int High); public: enum FormatStringType { @@ -7901,9 +8337,9 @@ private: SourceLocation Loc, SourceRange range, llvm::SmallBitVector &CheckedVarArgs); - void CheckNonNullArguments(const NonNullAttr *NonNull, - const Expr * const *ExprArgs, - SourceLocation CallSiteLoc); + void CheckAbsoluteValueFunction(const CallExpr *Call, + const FunctionDecl *FDecl, + IdentifierInfo *FnInfo); void CheckMemaccessArguments(const CallExpr *Call, unsigned BId, @@ -7915,8 +8351,12 @@ private: void CheckStrncatArguments(const CallExpr *Call, IdentifierInfo *FnName); - void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, - SourceLocation ReturnLoc); + void CheckReturnValExpr(Expr *RetValExp, QualType lhsType, + SourceLocation ReturnLoc, + bool isObjCMethod = false, + const AttrVec *Attrs = nullptr, + const FunctionDecl *FD = nullptr); + void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS); void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); void CheckForIntOverflow(Expr *E); @@ -7930,6 +8370,10 @@ private: void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field, Expr *Init); + /// \brief Check if the given expression contains 'break' or 'continue' + /// statement that produces control flow different from GCC. + void CheckBreakContinueBinding(Expr *E); + public: /// \brief Register a magic integral constant to be used as a type tag. void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind, @@ -7958,7 +8402,7 @@ public: private: /// \brief A map from magic value to type information. - OwningPtr<llvm::DenseMap<TypeTagMagicValue, TypeTagData> > + std::unique_ptr<llvm::DenseMap<TypeTagMagicValue, TypeTagData>> TypeTagForDatatypeMagicValues; /// \brief Peform checks on a call of a function with argument_with_type_tag @@ -7991,6 +8435,10 @@ public: /// template substitution or instantiation. Scope *getCurScope() const { return CurScope; } + void incrementMSLocalManglingNumber() const { + return CurScope->incrementMSLocalManglingNumber(); + } + IdentifierInfo *getSuperIdentifier() const; IdentifierInfo *getFloat128Identifier() const; @@ -8018,7 +8466,7 @@ class EnterExpressionEvaluationContext { public: EnterExpressionEvaluationContext(Sema &Actions, Sema::ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = 0, + Decl *LambdaContextDecl = nullptr, bool IsDecltype = false) : Actions(Actions) { Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h index 01d4cc9..9199b0f 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h @@ -24,44 +24,68 @@ namespace clang { inline PartialDiagnostic Sema::PDiag(unsigned DiagID) { return PartialDiagnostic(DiagID, Context.getDiagAllocator()); } -
-
-// This requires the variable to be non-dependent and the initializer
-// to not be value dependent.
-inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) {
- const VarDecl *DefVD = 0;
- return !isa<ParmVarDecl>(Var) &&
- Var->isUsableInConstantExpressions(Context) &&
- Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();
-}
-
-// Directly mark a variable odr-used. Given a choice, prefer to use
-// MarkVariableReferenced since it does additional checks and then
-// calls MarkVarDeclODRUsed.
-// If the variable must be captured:
-// - if FunctionScopeIndexToStopAt is null, capture it in the CurContext
-// - else capture it in the DeclContext that maps to the
-// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack.
-inline void MarkVarDeclODRUsed(VarDecl *Var,
- SourceLocation Loc, Sema &SemaRef,
- const unsigned *const FunctionScopeIndexToStopAt) {
- // Keep track of used but undefined variables.
- // FIXME: We shouldn't suppress this warning for static data members.
- if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
- !Var->isExternallyVisible() &&
- !(Var->isStaticDataMember() && Var->hasInit())) {
- SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
- if (old.isInvalid()) old = Loc;
- }
- QualType CaptureType, DeclRefType;
- SemaRef.tryCaptureVariable(Var, Loc, Sema::TryCapture_Implicit,
- /*EllipsisLoc*/ SourceLocation(),
- /*BuildAndDiagnose*/ true,
- CaptureType, DeclRefType,
- FunctionScopeIndexToStopAt);
-
- Var->markUsed(SemaRef.Context);
+ +inline bool +FTIHasSingleVoidParameter(const DeclaratorChunk::FunctionTypeInfo &FTI) { + return FTI.NumParams == 1 && !FTI.isVariadic && + FTI.Params[0].Ident == nullptr && FTI.Params[0].Param && + cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType(); +} + +inline bool +FTIHasNonVoidParameters(const DeclaratorChunk::FunctionTypeInfo &FTI) { + // Assume FTI is well-formed. + return FTI.NumParams && !FTIHasSingleVoidParameter(FTI); } + +// This requires the variable to be non-dependent and the initializer +// to not be value dependent. +inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) { + const VarDecl *DefVD = nullptr; + return !isa<ParmVarDecl>(Var) && + Var->isUsableInConstantExpressions(Context) && + Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE(); +} + +// Directly mark a variable odr-used. Given a choice, prefer to use +// MarkVariableReferenced since it does additional checks and then +// calls MarkVarDeclODRUsed. +// If the variable must be captured: +// - if FunctionScopeIndexToStopAt is null, capture it in the CurContext +// - else capture it in the DeclContext that maps to the +// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack. +inline void MarkVarDeclODRUsed(VarDecl *Var, + SourceLocation Loc, Sema &SemaRef, + const unsigned *const FunctionScopeIndexToStopAt) { + // Keep track of used but undefined variables. + // FIXME: We shouldn't suppress this warning for static data members. + if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly && + !Var->isExternallyVisible() && + !(Var->isStaticDataMember() && Var->hasInit())) { + SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()]; + if (old.isInvalid()) old = Loc; + } + QualType CaptureType, DeclRefType; + SemaRef.tryCaptureVariable(Var, Loc, Sema::TryCapture_Implicit, + /*EllipsisLoc*/ SourceLocation(), + /*BuildAndDiagnose*/ true, + CaptureType, DeclRefType, + FunctionScopeIndexToStopAt); + + Var->markUsed(SemaRef.Context); +} + +/// Return a DLL attribute from the declaration. +inline InheritableAttr *getDLLAttr(Decl *D) { + assert(!(D->hasAttr<DLLImportAttr>() && D->hasAttr<DLLExportAttr>()) && + "A declaration cannot be both dllimport and dllexport."); + if (auto *Import = D->getAttr<DLLImportAttr>()) + return Import; + if (auto *Export = D->getAttr<DLLExportAttr>()) + return Export; + return nullptr; +} + } #endif diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h index cf9fff1..f636750 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h @@ -1,39 +1,36 @@ -//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief This file provides some common utility functions for processing
-/// Lambdas.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SEMA_LAMBDA_H
-#define LLVM_CLANG_SEMA_LAMBDA_H
-#include "clang/AST/ASTLambda.h"
-#include "clang/Sema/ScopeInfo.h"
-namespace clang {
-
-// Given a lambda's call operator and a variable (or null for 'this'),
-// compute the nearest enclosing lambda that is capture-ready (i.e
-// the enclosing context is not dependent, and all intervening lambdas can
-// either implicitly or explicitly capture Var)
-//
-// Return the CallOperator of the capturable lambda and set function scope
-// index to the correct index within the function scope stack to correspond
-// to the capturable lambda.
-// If VarDecl *VD is null, we check for 'this' capture.
-CXXMethodDecl*
-GetInnermostEnclosingCapturableLambda(
- ArrayRef<sema::FunctionScopeInfo*> FunctionScopes,
- unsigned &FunctionScopeIndex,
- DeclContext *const CurContext, VarDecl *VD, Sema &S);
-
-} // clang
-
-#endif // LLVM_CLANG_SEMA_LAMBDA_H
+//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file provides some common utility functions for processing +/// Lambdas. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_LAMBDA_H +#define LLVM_CLANG_SEMA_LAMBDA_H +#include "clang/AST/ASTLambda.h" +#include "clang/Sema/ScopeInfo.h" +namespace clang { + + +/// \brief Examines the FunctionScopeInfo stack to determine the nearest +/// enclosing lambda (to the current lambda) that is 'capture-capable' for +/// the variable referenced in the current lambda (i.e. \p VarToCapture). +/// If successful, returns the index into Sema's FunctionScopeInfo stack +/// of the capture-capable lambda's LambdaScopeInfo. +/// See Implementation for more detailed comments. + +Optional<unsigned> getStackIndexOfNearestEnclosingCaptureCapableLambda( + ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes, + VarDecl *VarToCapture, Sema &S); + +} // clang + +#endif // LLVM_CLANG_SEMA_LAMBDA_H diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Template.h b/contrib/llvm/tools/clang/include/clang/Sema/Template.h index 1af61d5..c08a5df 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Template.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Template.h @@ -246,7 +246,7 @@ namespace clang { LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), Exited(false), CombineWithOuterScope(CombineWithOuterScope), - PartiallySubstitutedPack(0) + PartiallySubstitutedPack(nullptr) { SemaRef.CurrentInstantiationScope = this; } @@ -276,7 +276,7 @@ namespace clang { LocalInstantiationScope *newScope = new LocalInstantiationScope(SemaRef, CombineWithOuterScope); - newScope->Outer = 0; + newScope->Outer = nullptr; if (Outer) newScope->Outer = Outer->cloneScopes(Outermost); @@ -319,7 +319,7 @@ namespace clang { /// \param D The declaration whose instantiation we are searching for. /// /// \returns A pointer to the declaration or argument pack of declarations - /// to which the declaration \c D is instantiataed, if found. Otherwise, + /// to which the declaration \c D is instantiated, if found. Otherwise, /// returns NULL. llvm::PointerUnion<Decl *, DeclArgumentPack *> * findInstantiationOf(const Decl *D); @@ -348,17 +348,17 @@ namespace clang { /// interest. void ResetPartiallySubstitutedPack() { assert(PartiallySubstitutedPack && "No partially-substituted pack"); - PartiallySubstitutedPack = 0; - ArgsInPartiallySubstitutedPack = 0; + PartiallySubstitutedPack = nullptr; + ArgsInPartiallySubstitutedPack = nullptr; NumArgsInPartiallySubstitutedPack = 0; } /// \brief Retrieve the partially-substitued template parameter pack. /// /// If there is no partially-substituted parameter pack, returns NULL. - NamedDecl *getPartiallySubstitutedPack( - const TemplateArgument **ExplicitArgs = 0, - unsigned *NumExplicitArgs = 0) const; + NamedDecl * + getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr, + unsigned *NumExplicitArgs = nullptr) const; }; class TemplateDeclInstantiator @@ -391,8 +391,8 @@ namespace clang { const MultiLevelTemplateArgumentList &TemplateArgs) : SemaRef(SemaRef), SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex), - Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0) - { } + Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(nullptr), + StartingScope(nullptr) {} // Define all the decl visitors using DeclNodes.inc #define DECL(DERIVED, BASE) \ @@ -436,8 +436,8 @@ namespace clang { // Disable late instantiation of attributes. void disableLateAttributeInstantiation() { - LateAttrs = 0; - StartingScope = 0; + LateAttrs = nullptr; + StartingScope = nullptr; } LocalInstantiationScope *getStartingScope() const { return StartingScope; } @@ -493,7 +493,7 @@ namespace clang { Decl *VisitVarTemplateSpecializationDecl( VarTemplateDecl *VarTemplate, VarDecl *FromVar, void *InsertPos, const TemplateArgumentListInfo &TemplateArgsInfo, - llvm::ArrayRef<TemplateArgument> Converted); + ArrayRef<TemplateArgument> Converted); Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias); ClassTemplatePartialSpecializationDecl * diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h index 1daa689..2c2c36d 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h @@ -19,6 +19,7 @@ namespace clang { +struct DeducedPack; class TemplateArgumentList; class Sema; @@ -48,7 +49,8 @@ class TemplateDeductionInfo { public: TemplateDeductionInfo(SourceLocation Loc) - : Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false), Expression(0) { } + : Deduced(nullptr), Loc(Loc), HasSFINAEDiagnostic(false), + Expression(nullptr) {} /// \brief Returns the location at which template argument is /// occurring. @@ -59,7 +61,7 @@ public: /// \brief Take ownership of the deduced template argument list. TemplateArgumentList *take() { TemplateArgumentList *Result = Deduced; - Deduced = 0; + Deduced = nullptr; return Result; } @@ -161,6 +163,11 @@ public: /// an overloaded function which could not be resolved to a specific /// function. Expr *Expression; + + /// \brief Information on packs that we're currently expanding. + /// + /// FIXME: This should be kept internal to SemaTemplateDeduction. + SmallVector<DeducedPack *, 8> PendingDeducedPacks; }; } // end namespace sema diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h index f0b7726..6cab59c 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h @@ -39,7 +39,7 @@ public: static const unsigned CallbackDistanceWeight = 150U; TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl, - NestedNameSpecifier *NNS = 0, unsigned CharDistance = 0, + NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0, unsigned QualifierDistance = 0) : CorrectionName(Name), CorrectionNameSpec(NNS), CharDistance(CharDistance), QualifierDistance(QualifierDistance), @@ -49,7 +49,7 @@ public: CorrectionDecls.push_back(NameDecl); } - TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = 0, + TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0) : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS), CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0), @@ -58,14 +58,14 @@ public: CorrectionDecls.push_back(Name); } - TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = 0, + TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0) : CorrectionName(Name), CorrectionNameSpec(NNS), CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0), ForceSpecifierReplacement(false), RequiresImport(false) {} TypoCorrection() - : CorrectionNameSpec(0), CharDistance(0), QualifierDistance(0), + : CorrectionNameSpec(nullptr), CharDistance(0), QualifierDistance(0), CallbackDistance(0), ForceSpecifierReplacement(false), RequiresImport(false) {} @@ -81,7 +81,7 @@ public: } void setCorrectionSpecifier(NestedNameSpecifier* NNS) { CorrectionNameSpec = NNS; - ForceSpecifierReplacement = (NNS != 0); + ForceSpecifierReplacement = (NNS != nullptr); } void WillReplaceSpecifier(bool ForceReplacement) { @@ -130,7 +130,7 @@ public: /// \brief Gets the pointer to the declaration of the typo correction NamedDecl *getCorrectionDecl() const { - return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : 0; + return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr; } template <class DeclClass> DeclClass *getCorrectionDeclAs() const { @@ -172,7 +172,7 @@ public: /// as the only element in the list to mark this TypoCorrection as a keyword. void makeKeyword() { CorrectionDecls.clear(); - CorrectionDecls.push_back(0); + CorrectionDecls.push_back(nullptr); ForceSpecifierReplacement = true; } @@ -180,7 +180,7 @@ public: // item in CorrectionDecls is NULL. bool isKeyword() const { return !CorrectionDecls.empty() && - CorrectionDecls.front() == 0; + CorrectionDecls.front() == nullptr; } // Check if this TypoCorrection is the given keyword. @@ -250,8 +250,8 @@ public: CorrectionCandidateCallback() : WantTypeSpecifiers(true), WantExpressionKeywords(true), WantCXXNamedCasts(true), WantRemainingKeywords(true), - WantObjCSuper(false), - IsObjCIvarLookup(false) {} + WantObjCSuper(false), IsObjCIvarLookup(false), + IsAddressOfOperand(false) {} virtual ~CorrectionCandidateCallback() {} @@ -287,6 +287,7 @@ public: // Temporary hack for the one case where a CorrectTypoContext enum is used // when looking up results. bool IsObjCIvarLookup; + bool IsAddressOfOperand; }; /// @brief Simple template class for restricting typo correction candidates @@ -294,7 +295,7 @@ public: template <class C> class DeclFilterCCC : public CorrectionCandidateCallback { public: - virtual bool ValidateCandidate(const TypoCorrection &candidate) { + bool ValidateCandidate(const TypoCorrection &candidate) override { return candidate.getCorrectionDeclAs<C>(); } }; @@ -305,13 +306,16 @@ public: class FunctionCallFilterCCC : public CorrectionCandidateCallback { public: FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs, - bool HasExplicitTemplateArgs); + bool HasExplicitTemplateArgs, + MemberExpr *ME = nullptr); - virtual bool ValidateCandidate(const TypoCorrection &candidate); + bool ValidateCandidate(const TypoCorrection &candidate) override; private: unsigned NumArgs; bool HasExplicitTemplateArgs; + DeclContext *CurContext; + MemberExpr *MemberFn; }; // @brief Callback class that effectively disabled typo correction @@ -324,7 +328,7 @@ public: WantRemainingKeywords = false; } - virtual bool ValidateCandidate(const TypoCorrection &candidate) { + bool ValidateCandidate(const TypoCorrection &candidate) override { return false; } }; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Weak.h b/contrib/llvm/tools/clang/include/clang/Sema/Weak.h index 6d1b64b..9c7212e 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Weak.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Weak.h @@ -28,7 +28,7 @@ class WeakInfo { bool used; // identifier later declared? public: WeakInfo() - : alias(0), loc(SourceLocation()), used(false) {} + : alias(nullptr), loc(SourceLocation()), used(false) {} WeakInfo(IdentifierInfo *Alias, SourceLocation Loc) : alias(Alias), loc(Loc), used(false) {} inline IdentifierInfo * getAlias() const { return alias; } diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h index 03d9050..7ae1977 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h @@ -213,9 +213,6 @@ namespace clang { /// types and decls used within the AST file. DECLTYPES_BLOCK_ID, - /// \brief The block containing DECL_UPDATES records. - DECL_UPDATES_BLOCK_ID, - /// \brief The block containing the detailed preprocessing record. PREPROCESSOR_DETAIL_BLOCK_ID, @@ -284,7 +281,14 @@ namespace clang { HEADER_SEARCH_OPTIONS = 11, /// \brief Record code for the preprocessor options table. - PREPROCESSOR_OPTIONS = 12 + PREPROCESSOR_OPTIONS = 12, + + /// \brief Record code for the module name. + MODULE_NAME = 13, + + /// \brief Record code for the module map file that was used to build this + /// AST file. + MODULE_MAP_FILE = 14 }; /// \brief Record types that occur within the input-files block @@ -349,15 +353,15 @@ namespace clang { /// IDs). IDENTIFIER_TABLE = 5, - /// \brief Record code for the array of external definitions. + /// \brief Record code for the array of eagerly deserialized decls. /// - /// The AST file contains a list of all of the unnamed external - /// definitions present within the parsed headers, stored as an - /// array of declaration IDs. These external definitions will be + /// The AST file contains a list of all of the declarations that should be + /// eagerly deserialized present within the parsed headers, stored as an + /// array of declaration IDs. These declarations will be /// reported to the AST consumer after the AST file has been /// read, since their presence can affect the semantics of the /// program (e.g., for code generation). - EXTERNAL_DEFINITIONS = 6, + EAGERLY_DESERIALIZED_DECLS = 6, /// \brief Record code for the set of non-builtin, special /// types. @@ -538,7 +542,10 @@ namespace clang { UNDEFINED_BUT_USED = 49, /// \brief Record code for late parsed template functions. - LATE_PARSED_TEMPLATE = 50 + LATE_PARSED_TEMPLATE = 50, + + /// \brief Record code for \#pragma optimize options. + OPTIMIZE_PRAGMA_OPTIONS = 51 }; /// \brief Record types used within a source manager block. @@ -841,7 +848,9 @@ namespace clang { /// \brief An AtomicType record. TYPE_ATOMIC = 40, /// \brief A DecayedType record. - TYPE_DECAYED = 41 + TYPE_DECAYED = 41, + /// \brief An AdjustedType record. + TYPE_ADJUSTED = 42 }; /// \brief The type IDs for special types constructed by semantic @@ -1300,13 +1309,11 @@ namespace clang { EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr - EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr EXPR_OPAQUE_VALUE, // OpaqueValueExpr EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator - EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr EXPR_TYPE_TRAIT, // TypeTraitExpr EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr @@ -1327,12 +1334,27 @@ namespace clang { EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr). EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type). + STMT_SEH_LEAVE, // SEHLeaveStmt STMT_SEH_EXCEPT, // SEHExceptStmt STMT_SEH_FINALLY, // SEHFinallyStmt STMT_SEH_TRY, // SEHTryStmt // OpenMP drectives STMT_OMP_PARALLEL_DIRECTIVE, + STMT_OMP_SIMD_DIRECTIVE, + STMT_OMP_FOR_DIRECTIVE, + STMT_OMP_SECTIONS_DIRECTIVE, + STMT_OMP_SECTION_DIRECTIVE, + STMT_OMP_SINGLE_DIRECTIVE, + STMT_OMP_MASTER_DIRECTIVE, + STMT_OMP_CRITICAL_DIRECTIVE, + STMT_OMP_PARALLEL_FOR_DIRECTIVE, + STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE, + STMT_OMP_TASK_DIRECTIVE, + STMT_OMP_TASKYIELD_DIRECTIVE, + STMT_OMP_BARRIER_DIRECTIVE, + STMT_OMP_TASKWAIT_DIRECTIVE, + STMT_OMP_FLUSH_DIRECTIVE, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h index 0218129..180f554 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H #define LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H +#include "clang/Basic/IdentifierTable.h" #include "clang/Serialization/ASTBitCodes.h" namespace clang { @@ -27,10 +28,8 @@ class MacroInfo; class Module; class ASTDeserializationListener { -protected: - virtual ~ASTDeserializationListener(); - public: + virtual ~ASTDeserializationListener(); /// \brief The ASTReader was initialized. virtual void ReaderInitialized(ASTReader *Reader) { } diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h index d3cca1a..3f44440 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h @@ -34,21 +34,20 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Support/DataTypes.h" #include <deque> #include <map> +#include <memory> #include <string> #include <utility> #include <vector> -#include <sys/stat.h> namespace llvm { class MemoryBuffer; @@ -64,6 +63,7 @@ class ASTUnit; // FIXME: Layering violation and egregious hack. class Attr; class Decl; class DeclContext; +class DefMacroDirective; class DiagnosticOptions; class NestedNameSpecifier; class CXXBaseSpecifier; @@ -108,6 +108,9 @@ public: return FullVersion != getClangFullRepositoryVersion(); } + virtual void ReadModuleName(StringRef ModuleName) {} + virtual void ReadModuleMapFile(StringRef ModuleMapPath) {} + /// \brief Receives the language options. /// /// \returns true to indicate the options are invalid or false otherwise. @@ -129,8 +132,9 @@ public: /// /// \returns true to indicate the diagnostic options are invalid, or false /// otherwise. - virtual bool ReadDiagnosticOptions(const DiagnosticOptions &DiagOpts, - bool Complain) { + virtual bool + ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, + bool Complain) { return false; } @@ -170,15 +174,60 @@ public: virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value) {} + /// This is called for each AST file loaded. + virtual void visitModuleFile(StringRef Filename) {} + /// \brief Returns true if this \c ASTReaderListener wants to receive the /// input files of the AST file via \c visitInputFile, false otherwise. virtual bool needsInputFileVisitation() { return false; } - - /// \brief if \c needsInputFileVisitation returns true, this is called for each - /// input file of the AST file. + /// \brief Returns true if this \c ASTReaderListener wants to receive the + /// system input files of the AST file via \c visitInputFile, false otherwise. + virtual bool needsSystemInputFileVisitation() { return false; } + /// \brief if \c needsInputFileVisitation returns true, this is called for + /// each non-system input file of the AST File. If + /// \c needsSystemInputFileVisitation is true, then it is called for all + /// system input files as well. /// /// \returns true to continue receiving the next input file, false to stop. - virtual bool visitInputFile(StringRef Filename, bool isSystem) { return true;} + virtual bool visitInputFile(StringRef Filename, bool isSystem, + bool isOverridden) { + return true; + } +}; + +/// \brief Simple wrapper class for chaining listeners. +class ChainedASTReaderListener : public ASTReaderListener { + std::unique_ptr<ASTReaderListener> First; + std::unique_ptr<ASTReaderListener> Second; + +public: + /// Takes ownership of \p First and \p Second. + ChainedASTReaderListener(ASTReaderListener *First, ASTReaderListener *Second) + : First(First), Second(Second) { } + + bool ReadFullVersionInformation(StringRef FullVersion) override; + void ReadModuleName(StringRef ModuleName) override; + void ReadModuleMapFile(StringRef ModuleMapPath) override; + bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain) override; + bool ReadTargetOptions(const TargetOptions &TargetOpts, + bool Complain) override; + bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, + bool Complain) override; + bool ReadFileSystemOptions(const FileSystemOptions &FSOpts, + bool Complain) override; + + bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, + bool Complain) override; + bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, + bool Complain, + std::string &SuggestedPredefines) override; + + void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override; + bool needsInputFileVisitation() override; + bool needsSystemInputFileVisitation() override; + void visitModuleFile(StringRef Filename) override; + bool visitInputFile(StringRef Filename, bool isSystem, + bool isOverridden) override; }; /// \brief ASTReaderListener implementation to validate the information of @@ -191,14 +240,15 @@ public: PCHValidator(Preprocessor &PP, ASTReader &Reader) : PP(PP), Reader(Reader) {} - virtual bool ReadLanguageOptions(const LangOptions &LangOpts, - bool Complain); - virtual bool ReadTargetOptions(const TargetOptions &TargetOpts, - bool Complain); - virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, - bool Complain, - std::string &SuggestedPredefines); - virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value); + bool ReadLanguageOptions(const LangOptions &LangOpts, + bool Complain) override; + bool ReadTargetOptions(const TargetOptions &TargetOpts, + bool Complain) override; + bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, + bool Complain) override; + bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, + std::string &SuggestedPredefines) override; + void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override; private: void Error(const char *Msg); @@ -211,7 +261,7 @@ class ReadMethodPoolVisitor; namespace reader { class ASTIdentifierLookupTrait; /// \brief The on-disk hash table used for the DeclContext's Name lookup table. - typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait> + typedef llvm::OnDiskIterableChainedHashTable<ASTDeclContextNameLookupTrait> ASTDeclContextNameLookupTable; } @@ -285,10 +335,11 @@ public: private: /// \brief The receiver of some callbacks invoked by ASTReader. - OwningPtr<ASTReaderListener> Listener; + std::unique_ptr<ASTReaderListener> Listener; /// \brief The receiver of deserialization events. ASTDeserializationListener *DeserializationListener; + bool OwnsDeserializationListener; SourceManager &SourceMgr; FileManager &FileMgr; @@ -315,7 +366,7 @@ private: SourceLocation CurrentImportLoc; /// \brief The global module index, if loaded. - llvm::OwningPtr<GlobalModuleIndex> GlobalIndex; + std::unique_ptr<GlobalModuleIndex> GlobalIndex; /// \brief A map of global bit offsets to the module that stores entities /// at those bit offsets. @@ -366,12 +417,17 @@ private: /// in the chain. DeclUpdateOffsetsMap DeclUpdateOffsets; + /// \brief Declaration updates for already-loaded declarations that we need + /// to apply once we finish processing an import. + llvm::SmallVector<std::pair<serialization::GlobalDeclID, Decl*>, 16> + PendingUpdateRecords; + struct ReplacedDeclInfo { ModuleFile *Mod; uint64_t Offset; unsigned RawLoc; - ReplacedDeclInfo() : Mod(0), Offset(0), RawLoc(0) {} + ReplacedDeclInfo() : Mod(nullptr), Offset(0), RawLoc(0) {} ReplacedDeclInfo(ModuleFile *Mod, uint64_t Offset, unsigned RawLoc) : Mod(Mod), Offset(Offset), RawLoc(RawLoc) {} }; @@ -385,7 +441,7 @@ private: ModuleFile *Mod; ArrayRef<serialization::LocalDeclID> Decls; - FileDeclsInfo() : Mod(0) {} + FileDeclsInfo() : Mod(nullptr) {} FileDeclsInfo(ModuleFile *Mod, ArrayRef<serialization::LocalDeclID> Decls) : Mod(Mod), Decls(Decls) {} }; @@ -471,18 +527,22 @@ private: /// global submodule ID to produce a local ID. GlobalSubmoduleMapType GlobalSubmoduleMap; + /// \brief Information on a macro definition or undefinition that is visible + /// at the end of a submodule. + struct ModuleMacroInfo; + /// \brief An entity that has been hidden. class HiddenName { public: enum NameKind { Declaration, - MacroVisibility + Macro } Kind; private: union { Decl *D; - MacroDirective *MD; + ModuleMacroInfo *MMI; }; IdentifierInfo *Id; @@ -490,8 +550,8 @@ private: public: HiddenName(Decl *D) : Kind(Declaration), D(D), Id() { } - HiddenName(IdentifierInfo *II, MacroDirective *MD) - : Kind(MacroVisibility), MD(MD), Id(II) { } + HiddenName(IdentifierInfo *II, ModuleMacroInfo *MMI) + : Kind(Macro), MMI(MMI), Id(II) { } NameKind getKind() const { return Kind; } @@ -500,15 +560,21 @@ private: return D; } - std::pair<IdentifierInfo *, MacroDirective *> getMacro() const { - assert(getKind() == MacroVisibility && "Hidden name is not a macro!"); - return std::make_pair(Id, MD); + std::pair<IdentifierInfo *, ModuleMacroInfo *> getMacro() const { + assert(getKind() == Macro && "Hidden name is not a macro!"); + return std::make_pair(Id, MMI); } -}; + }; + + typedef llvm::SmallDenseMap<IdentifierInfo*, + ModuleMacroInfo*> HiddenMacrosMap; /// \brief A set of hidden declarations. - typedef SmallVector<HiddenName, 2> HiddenNames; - + struct HiddenNames { + SmallVector<Decl*, 2> HiddenDecls; + HiddenMacrosMap HiddenMacros; + }; + typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType; /// \brief A mapping from each of the hidden submodules to the deserialized @@ -564,8 +630,8 @@ private: ModuleFile *M; struct ModuleMacroDataTy { - serialization::GlobalMacroID GMacID; - unsigned ImportLoc; + uint32_t MacID; + serialization::SubmoduleID *Overrides; }; struct PCHMacroDataTy { uint64_t MacroDirectivesOffset; @@ -577,10 +643,10 @@ private: }; PendingMacroInfo(ModuleFile *M, - serialization::GlobalMacroID GMacID, - SourceLocation ImportLoc) : M(M) { - ModuleMacroData.GMacID = GMacID; - ModuleMacroData.ImportLoc = ImportLoc.getRawEncoding(); + uint32_t MacID, + serialization::SubmoduleID *Overrides) : M(M) { + ModuleMacroData.MacID = MacID; + ModuleMacroData.Overrides = Overrides; } PendingMacroInfo(ModuleFile *M, uint64_t MacroDirectivesOffset) : M(M) { @@ -610,10 +676,10 @@ private: /// \brief The IDs of all declarations that fulfill the criteria of /// "interesting" decls. /// - /// This contains the data loaded from all EXTERNAL_DEFINITIONS blocks in the - /// chain. The referenced declarations are deserialized and passed to the - /// consumer eagerly. - SmallVector<uint64_t, 16> ExternalDefinitions; + /// This contains the data loaded from all EAGERLY_DESERIALIZED_DECLS blocks + /// in the chain. The referenced declarations are deserialized and passed to + /// the consumer eagerly. + SmallVector<uint64_t, 16> EagerlyDeserializedDecls; /// \brief The IDs of all tentative definitions stored in the chain. /// @@ -701,6 +767,9 @@ private: /// \brief The floating point pragma option settings. SmallVector<uint64_t, 1> FPPragmaOptions; + /// \brief The pragma clang optimize location (if the pragma state is "off"). + SourceLocation OptimizeOffPragmaLocation; + /// \brief The OpenCL extension settings. SmallVector<uint64_t, 1> OpenCLExtensions; @@ -714,9 +783,17 @@ private: // \brief A list of late parsed template function data. SmallVector<uint64_t, 1> LateParsedTemplates; + struct ImportedSubmodule { + serialization::SubmoduleID ID; + SourceLocation ImportLoc; + + ImportedSubmodule(serialization::SubmoduleID ID, SourceLocation ImportLoc) + : ID(ID), ImportLoc(ImportLoc) {} + }; + /// \brief A list of modules that were imported by precompiled headers or /// any other non-module AST file. - SmallVector<serialization::SubmoduleID, 2> ImportedModules; + SmallVector<ImportedSubmodule, 2> ImportedModules; //@} /// \brief The directory that the PCH we are reading is stored in. @@ -733,16 +810,19 @@ private: /// \brief Whether to accept an AST file with compiler errors. bool AllowASTWithCompilerErrors; + /// \brief Whether to accept an AST file that has a different configuration + /// from the current compiler instance. + bool AllowConfigurationMismatch; + + /// \brief Whether validate system input files. + bool ValidateSystemInputs; + /// \brief Whether we are allowed to use the global module index. bool UseGlobalIndex; /// \brief Whether we have tried loading the global module index yet. bool TriedLoadingGlobalIndex; - /// \brief The current "generation" of the module file import stack, which - /// 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 /// @@ -860,6 +940,10 @@ private: /// \brief Keeps track of the elements added to PendingDeclChains. llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown; + /// \brief The list of canonical declarations whose redeclaration chains + /// need to be marked as incomplete once we're done deserializing things. + SmallVector<Decl *, 16> PendingIncompleteDeclChains; + /// \brief The Decl IDs for the Sema/Lexical DeclContext of a Decl that has /// been loaded but its DeclContext was not set yet. struct PendingDeclContextInfo { @@ -883,6 +967,13 @@ private: /// once recursing loading has been completed. llvm::SmallVector<NamedDecl *, 16> PendingOdrMergeChecks; + /// \brief Record definitions in which we found an ODR violation. + llvm::SmallDenseMap<CXXRecordDecl *, llvm::TinyPtrVector<CXXRecordDecl *>, 2> + PendingOdrMergeFailures; + + /// \brief DeclContexts in which we have diagnosed an ODR violation. + llvm::SmallPtrSet<DeclContext*, 2> DiagnosedOdrMergeFailures; + /// \brief The set of Objective-C categories that have been deserialized /// since the last time the declaration chains were linked. llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized; @@ -891,7 +982,14 @@ private: /// loaded, for which we will need to check for categories whenever a new /// module is loaded. SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded; - + + /// \brief A mapping from a primary context for a declaration chain to the + /// other declarations of that entity that also have name lookup tables. + /// Used when we merge together two class definitions that have different + /// sets of declared special member functions. + llvm::DenseMap<const DeclContext*, SmallVector<const DeclContext*, 2>> + MergedLookups; + typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> > MergedDeclsMap; @@ -970,6 +1068,18 @@ private: /// \brief Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile &F); + struct InputFileInfo { + std::string Filename; + off_t StoredSize; + time_t StoredTime; + bool Overridden; + }; + + /// \brief Reads the stored information about an input file. + InputFileInfo readInputFileInfo(ModuleFile &F, unsigned ID); + /// \brief A convenience method to read the filename from an input file. + std::string getInputFileName(ModuleFile &F, unsigned ID); + /// \brief Retrieve the file entry and 'overridden' bit for an input /// file in the given module file. serialization::InputFile getInputFile(ModuleFile &F, unsigned ID, @@ -999,13 +1109,15 @@ private: unsigned ClientLoadCapabilities); ASTReadResult ReadControlBlock(ModuleFile &F, SmallVectorImpl<ImportedModule> &Loaded, + const ModuleFile *ImportedBy, unsigned ClientLoadCapabilities); - bool ReadASTBlock(ModuleFile &F); + ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities); bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record); bool ReadSourceManagerBlock(ModuleFile &F); llvm::BitstreamCursor &SLocCursorForID(int ID); SourceLocation getImportLocation(ModuleFile *F); - bool ReadSubmoduleBlock(ModuleFile &F); + ASTReadResult ReadSubmoduleBlock(ModuleFile &F, + unsigned ClientLoadCapabilities); static bool ParseLanguageOptions(const RecordData &Record, bool Complain, ASTReaderListener &Listener); static bool ParseTargetOptions(const RecordData &Record, bool Complain, @@ -1028,9 +1140,14 @@ private: }; QualType readTypeRecord(unsigned Index); + void readExceptionSpec(ModuleFile &ModuleFile, + SmallVectorImpl<QualType> &ExceptionStorage, + FunctionProtoType::ExtProtoInfo &EPI, + const RecordData &Record, unsigned &Index); RecordLocation TypeCursorForIndex(unsigned Index); void LoadedDecl(unsigned Index, Decl *D); Decl *ReadDeclRecord(serialization::DeclID ID); + void markIncompleteDeclChain(Decl *Canon); RecordLocation DeclCursorForID(serialization::DeclID ID, unsigned &RawLocation); void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D); @@ -1041,13 +1158,10 @@ private: RecordLocation getLocalBitOffset(uint64_t GlobalOffset); uint64_t getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset); - /// \brief Returns the first preprocessed entity ID that ends after BLoc. + /// \brief Returns the first preprocessed entity ID that begins or ends after + /// \arg Loc. serialization::PreprocessedEntityID - findBeginPreprocessedEntity(SourceLocation BLoc) const; - - /// \brief Returns the first preprocessed entity ID that begins after ELoc. - serialization::PreprocessedEntityID - findEndPreprocessedEntity(SourceLocation ELoc) const; + findPreprocessedEntity(SourceLocation Loc, bool EndsAfter) const; /// \brief Find the next module that contains entities and return the ID /// of the first entry. @@ -1079,7 +1193,7 @@ private: typedef value_type& reference; typedef value_type* pointer; - ModuleDeclIterator() : Reader(0), Mod(0), Pos(0) { } + ModuleDeclIterator() : Reader(nullptr), Mod(nullptr), Pos(nullptr) { } ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod, const serialization::LocalDeclID *Pos) @@ -1174,11 +1288,20 @@ public: /// AST file the was created out of an AST with compiler errors, /// otherwise it will reject it. /// + /// \param AllowConfigurationMismatch If true, the AST reader will not check + /// for configuration differences between the AST file and the invocation. + /// + /// \param ValidateSystemInputs If true, the AST reader will validate + /// system input files in addition to user input files. This is only + /// meaningful if \p DisableValidation is false. + /// /// \param UseGlobalIndex If true, the AST reader will try to load and use /// the global module index. ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "", bool DisableValidation = false, bool AllowASTWithCompilerErrors = false, + bool AllowConfigurationMismatch = false, + bool ValidateSystemInputs = false, bool UseGlobalIndex = true); ~ASTReader(); @@ -1237,24 +1360,41 @@ public: /// \param ImportLoc The location at which the import occurs. /// /// \param Complain Whether to complain about conflicting module imports. - void makeModuleVisible(Module *Mod, + void makeModuleVisible(Module *Mod, Module::NameVisibilityKind NameVisibility, SourceLocation ImportLoc, bool Complain); - + /// \brief Make the names within this set of hidden names visible. - void makeNamesVisible(const HiddenNames &Names, Module *Owner); - + void makeNamesVisible(const HiddenNames &Names, Module *Owner, + bool FromFinalization); + /// \brief Set the AST callbacks listener. void setListener(ASTReaderListener *listener) { Listener.reset(listener); } + /// \brief Add an AST callbak listener. + /// + /// Takes ownership of \p L. + void addListener(ASTReaderListener *L) { + if (Listener) + L = new ChainedASTReaderListener(L, Listener.release()); + Listener.reset(L); + } + /// \brief Set the AST deserialization listener. - void setDeserializationListener(ASTDeserializationListener *Listener); + void setDeserializationListener(ASTDeserializationListener *Listener, + bool TakeOwnership = false); /// \brief Determine whether this AST reader has a global index. - bool hasGlobalIndex() const { return GlobalIndex.isValid(); } + bool hasGlobalIndex() const { return (bool)GlobalIndex; } + + /// \brief Return global module index. + GlobalModuleIndex *getGlobalIndex() { return GlobalIndex.get(); } + + /// \brief Reset reader for a reload try. + void resetForReload() { TriedLoadingGlobalIndex = false; } /// \brief Attempts to load the global index. /// @@ -1325,20 +1465,20 @@ public: /// /// \returns null if an error occurred that prevented the preprocessed /// entity from being loaded. - virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index); + PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) override; /// \brief Returns a pair of [Begin, End) indices of preallocated /// preprocessed entities that \p Range encompasses. - virtual std::pair<unsigned, unsigned> - findPreprocessedEntitiesInRange(SourceRange Range); + std::pair<unsigned, unsigned> + findPreprocessedEntitiesInRange(SourceRange Range) override; /// \brief Optionally returns true or false if the preallocated preprocessed /// entity with index \p Index came from file \p FID. - virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index, - FileID FID); + Optional<bool> isPreprocessedEntityInFileID(unsigned Index, + FileID FID) override; /// \brief Read the header file information for the given file entry. - virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE); + HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) override; void ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag); @@ -1443,14 +1583,22 @@ public: /// \brief Retrieve the module file that owns the given declaration, or NULL /// if the declaration is not from a module file. ModuleFile *getOwningModuleFile(const Decl *D); - + + /// \brief Get the best name we know for the module that owns the given + /// declaration, or an empty string if the declaration is not from a module. + std::string getOwningModuleNameForDiagnostic(const Decl *D); + /// \brief Returns the source location for the decl \p ID. SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID); /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. Decl *GetDecl(serialization::DeclID ID); - virtual Decl *GetExternalDecl(uint32_t ID); + Decl *GetExternalDecl(uint32_t ID) override; + + /// \brief Resolve a declaration ID into a declaration. Return 0 if it's not + /// been loaded yet. + Decl *GetExistingDecl(serialization::DeclID ID); /// \brief Reads a declaration with the given local ID in the given module. Decl *GetLocalDecl(ModuleFile &F, uint32_t LocalID) { @@ -1497,19 +1645,24 @@ public: return cast_or_null<T>(GetDecl(ReadDeclID(F, R, I))); } + /// \brief If any redeclarations of \p D have been imported since it was + /// last checked, this digs out those redeclarations and adds them to the + /// redeclaration chain for \p D. + void CompleteRedeclChain(const Decl *D) override; + /// \brief Read a CXXBaseSpecifiers ID form the given record and /// return its global bit offset. uint64_t readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record, unsigned &Idx); - virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); + CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override; /// \brief Resolve the offset of a statement into a statement. /// /// This operation will read a new statement from the external /// source each time it is called, and is meant to be used via a /// LazyOffsetPtr (which is used by Decls for the body of functions, etc). - virtual Stmt *GetExternalDeclStmt(uint64_t Offset); + Stmt *GetExternalDeclStmt(uint64_t Offset) override; /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the /// specified cursor. Read the abbreviations that are at the top of the block @@ -1519,9 +1672,8 @@ public: /// \brief Finds all the visible declarations with a given name. /// The current implementation of this method just loads the entire /// lookup table as unmaterialized references. - virtual bool - FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name); + bool FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) override; /// \brief Read all of the declarations lexically stored in a /// declaration context. @@ -1536,49 +1688,49 @@ public: /// /// \returns true if there was an error while reading the /// declarations for this declaration context. - virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, - bool (*isKindWeWant)(Decl::Kind), - SmallVectorImpl<Decl*> &Decls); + ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, + bool (*isKindWeWant)(Decl::Kind), + SmallVectorImpl<Decl*> &Decls) override; /// \brief Get the decls that are contained in a file in the Offset/Length /// range. \p Length can be 0 to indicate a point at \p Offset instead of /// a range. - virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, - SmallVectorImpl<Decl *> &Decls); + void FindFileRegionDecls(FileID File, unsigned Offset, unsigned Length, + SmallVectorImpl<Decl *> &Decls) override; /// \brief Notify ASTReader that we started deserialization of /// a decl or type so until FinishedDeserializing is called there may be /// decls that are initializing. Must be paired with FinishedDeserializing. - virtual void StartedDeserializing() { ++NumCurrentElementsDeserializing; } + void StartedDeserializing() override { ++NumCurrentElementsDeserializing; } /// \brief Notify ASTReader that we finished the deserialization of /// a decl or type. Must be paired with StartedDeserializing. - virtual void FinishedDeserializing(); + void FinishedDeserializing() override; /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. /// /// This function will provide all of the external definitions to /// the ASTConsumer. - virtual void StartTranslationUnit(ASTConsumer *Consumer); + void StartTranslationUnit(ASTConsumer *Consumer) override; /// \brief Print some statistics about AST usage. - virtual void PrintStats(); + void PrintStats() override; /// \brief Dump information about the AST reader to standard error. void dump(); /// Return the amount of memory used by memory buffers, breaking down /// by heap-backed versus mmap'ed memory. - virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; + void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override; /// \brief Initialize the semantic source with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. - virtual void InitializeSema(Sema &S); + void InitializeSema(Sema &S) override; /// \brief Inform the semantic consumer that Sema is no longer available. - virtual void ForgetSema() { SemaObj = 0; } + void ForgetSema() override { SemaObj = nullptr; } /// \brief Retrieve the IdentifierInfo for the named identifier. /// @@ -1587,56 +1739,57 @@ public: /// declarations will be deserialized and introduced into the declaration /// chain of the identifier. virtual IdentifierInfo *get(const char *NameStart, const char *NameEnd); - IdentifierInfo *get(StringRef Name) { + IdentifierInfo *get(StringRef Name) override { return get(Name.begin(), Name.end()); } /// \brief Retrieve an iterator into the set of all identifiers /// in all loaded AST files. - virtual IdentifierIterator *getIdentifiers(); + IdentifierIterator *getIdentifiers() override; /// \brief Load the contents of the global method pool for a given /// selector. - virtual void ReadMethodPool(Selector Sel); + void ReadMethodPool(Selector Sel) override; /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. - virtual void ReadKnownNamespaces( - SmallVectorImpl<NamespaceDecl *> &Namespaces); + void ReadKnownNamespaces( + SmallVectorImpl<NamespaceDecl *> &Namespaces) override; - virtual void ReadUndefinedButUsed( - llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined); + void ReadUndefinedButUsed( + llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) override; - virtual void ReadTentativeDefinitions( - SmallVectorImpl<VarDecl *> &TentativeDefs); + void ReadTentativeDefinitions( + SmallVectorImpl<VarDecl *> &TentativeDefs) override; - virtual void ReadUnusedFileScopedDecls( - SmallVectorImpl<const DeclaratorDecl *> &Decls); + void ReadUnusedFileScopedDecls( + SmallVectorImpl<const DeclaratorDecl *> &Decls) override; - virtual void ReadDelegatingConstructors( - SmallVectorImpl<CXXConstructorDecl *> &Decls); + void ReadDelegatingConstructors( + SmallVectorImpl<CXXConstructorDecl *> &Decls) override; - virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls); + void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) override; - virtual void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls); + void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) override; - virtual void ReadLocallyScopedExternCDecls( - SmallVectorImpl<NamedDecl *> &Decls); + void ReadLocallyScopedExternCDecls( + SmallVectorImpl<NamedDecl *> &Decls) override; - virtual void ReadReferencedSelectors( - SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels); + void ReadReferencedSelectors( + SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) override; - virtual void ReadWeakUndeclaredIdentifiers( - SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI); + void ReadWeakUndeclaredIdentifiers( + SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) override; - virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables); + void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override; - virtual void ReadPendingInstantiations( + void ReadPendingInstantiations( SmallVectorImpl<std::pair<ValueDecl *, - SourceLocation> > &Pending); + SourceLocation> > &Pending) override; - virtual void ReadLateParsedTemplates( - llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap); + void ReadLateParsedTemplates( + llvm::DenseMap<const FunctionDecl *, + LateParsedTemplate *> &LPTMap) override; /// \brief Load a selector from disk, registering its ID if it exists. void LoadSelector(Selector Sel); @@ -1644,7 +1797,7 @@ public: void SetIdentifierInfo(unsigned ID, IdentifierInfo *II); void SetGloballyVisibleDecls(IdentifierInfo *II, const SmallVectorImpl<uint32_t> &DeclIDs, - SmallVectorImpl<Decl *> *Decls = 0); + SmallVectorImpl<Decl *> *Decls = nullptr); /// \brief Report a diagnostic. DiagnosticBuilder Diag(unsigned DiagID); @@ -1659,7 +1812,7 @@ public: return DecodeIdentifierInfo(getGlobalIdentifierID(M, Record[Idx++])); } - virtual IdentifierInfo *GetIdentifier(serialization::IdentifierID ID) { + IdentifierInfo *GetIdentifier(serialization::IdentifierID ID) override { // Note that we are loading an identifier. Deserializing AnIdentifier(this); @@ -1671,13 +1824,26 @@ public: serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M, unsigned LocalID); + ModuleMacroInfo *getModuleMacro(const PendingMacroInfo &PMInfo); + void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo); void installPCHMacroDirectives(IdentifierInfo *II, ModuleFile &M, uint64_t Offset); - void installImportedMacro(IdentifierInfo *II, MacroDirective *MD, - Module *Owner); + void installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI, + Module *Owner, bool FromFinalization); + + typedef llvm::TinyPtrVector<DefMacroDirective *> AmbiguousMacros; + llvm::DenseMap<IdentifierInfo*, AmbiguousMacros> AmbiguousMacroDefs; + + void + removeOverriddenMacros(IdentifierInfo *II, AmbiguousMacros &Ambig, + ArrayRef<serialization::SubmoduleID> Overrides); + + AmbiguousMacros * + removeOverriddenMacros(IdentifierInfo *II, + ArrayRef<serialization::SubmoduleID> Overrides); /// \brief Retrieve the macro with the given ID. MacroInfo *getMacro(serialization::MacroID ID); @@ -1687,11 +1853,11 @@ public: serialization::MacroID getGlobalMacroID(ModuleFile &M, unsigned LocalID); /// \brief Read the source location entry with index ID. - virtual bool ReadSLocEntry(int ID); + bool ReadSLocEntry(int ID) override; /// \brief Retrieve the module import location and module name for the /// given source manager entry ID. - virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID); + std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) override; /// \brief Retrieve the global submodule ID given a module and its local ID /// number. @@ -1705,7 +1871,7 @@ public: /// \brief Retrieve the module that corresponds to the given module ID. /// /// Note: overrides method in ExternalASTSource - virtual Module *getModule(unsigned ID); + Module *getModule(unsigned ID) override; /// \brief Retrieve a selector from the given module with its local ID /// number. @@ -1713,8 +1879,8 @@ public: Selector DecodeSelector(serialization::SelectorID Idx); - virtual Selector GetExternalSelector(serialization::SelectorID ID); - uint32_t GetNumExternalSelectors(); + Selector GetExternalSelector(serialization::SelectorID ID) override; + uint32_t GetNumExternalSelectors() override; Selector ReadSelector(ModuleFile &M, const RecordData &Record, unsigned &Idx) { return getLocalSelector(M, Record[Idx++]); @@ -1832,7 +1998,7 @@ public: "Should be called only during statement reading!"); // Subexpressions are stored from last to first, so the next Stmt we need // is at the back of the stack. - assert(!StmtStack.empty() && "Read too many sub statements!"); + assert(!StmtStack.empty() && "Read too many sub-statements!"); return StmtStack.pop_back_val(); } @@ -1855,11 +2021,10 @@ public: /// \param II The name of the macro. /// \param M The module file. /// \param GMacID The global macro ID that is associated with this identifier. - /// \param ImportLoc The location where the module is imported. void addPendingMacroFromModule(IdentifierInfo *II, ModuleFile *M, serialization::GlobalMacroID GMacID, - SourceLocation ImportLoc); + ArrayRef<serialization::SubmoduleID>); /// \brief Add a macro to deserialize its macro directive history from a PCH. /// @@ -1871,16 +2036,16 @@ public: ModuleFile *M, uint64_t MacroDirectivesOffset); /// \brief Read the set of macros defined by this external macro source. - virtual void ReadDefinedMacros(); + void ReadDefinedMacros() override; /// \brief Update an out-of-date identifier. - virtual void updateOutOfDateIdentifier(IdentifierInfo &II); + void updateOutOfDateIdentifier(IdentifierInfo &II) override; /// \brief Note that this identifier is up-to-date. void markIdentifierUpToDate(IdentifierInfo *II); /// \brief Load all external visible decls in the given DeclContext. - void completeVisibleDeclsMap(const DeclContext *DC); + void completeVisibleDeclsMap(const DeclContext *DC) override; /// \brief Retrieve the AST context that this AST reader supplements. ASTContext &getContext() { return Context; } @@ -1911,8 +2076,8 @@ public: SmallVector<std::pair<llvm::BitstreamCursor, serialization::ModuleFile *>, 8> CommentsCursors; - /// \brief Loads comments ranges. - void ReadComments(); + //RIDErief Loads comments ranges. + void ReadComments() override; }; /// \brief Helper class that saves the current stream position and diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h index 07fdd06..ad6ecdd 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h @@ -246,10 +246,10 @@ private: /// @name FlushStmt Caches /// @{ - /// \brief Set of parent Stmts for the currently serializing sub stmt. + /// \brief Set of parent Stmts for the currently serializing sub-stmt. llvm::DenseSet<Stmt *> ParentStmts; - /// \brief Offsets of sub stmts already serialized. The offset points + /// \brief Offsets of sub-stmts already serialized. The offset points /// just after the stmt record. llvm::DenseMap<Stmt *, uint64_t> SubStmtEntries; @@ -283,7 +283,37 @@ private: llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID> MacroDefinitions; - typedef SmallVector<uint64_t, 2> UpdateRecord; + /// An update to a Decl. + class DeclUpdate { + /// A DeclUpdateKind. + unsigned Kind; + union { + const Decl *Dcl; + void *Type; + unsigned Loc; + unsigned Val; + }; + + public: + DeclUpdate(unsigned Kind) : Kind(Kind), Dcl(nullptr) {} + DeclUpdate(unsigned Kind, const Decl *Dcl) : Kind(Kind), Dcl(Dcl) {} + DeclUpdate(unsigned Kind, QualType Type) + : Kind(Kind), Type(Type.getAsOpaquePtr()) {} + DeclUpdate(unsigned Kind, SourceLocation Loc) + : Kind(Kind), Loc(Loc.getRawEncoding()) {} + DeclUpdate(unsigned Kind, unsigned Val) + : Kind(Kind), Val(Val) {} + + unsigned getKind() const { return Kind; } + const Decl *getDecl() const { return Dcl; } + QualType getType() const { return QualType::getFromOpaquePtr(Type); } + SourceLocation getLoc() const { + return SourceLocation::getFromRawEncoding(Loc); + } + unsigned getNumber() const { return Val; } + }; + + typedef SmallVector<DeclUpdate, 1> UpdateRecord; typedef llvm::DenseMap<const Decl *, UpdateRecord> DeclUpdateMap; /// \brief Mapping from declarations that came from a chained PCH to the /// record containing modifications to them. @@ -297,16 +327,15 @@ private: /// \brief Declarations encountered that might be external /// definitions. /// - /// We keep track of external definitions (as well as tentative - /// definitions) as we are emitting declarations to the AST - /// file. The AST file contains a separate record for these external - /// definitions, which are provided to the AST consumer by the AST - /// reader. This is behavior is required to properly cope with, + /// We keep track of external definitions and other 'interesting' declarations + /// as we are emitting declarations to the AST file. The AST file contains a + /// separate record for these declarations, which are provided to the AST + /// consumer by the AST reader. This is behavior is required to properly cope with, /// e.g., tentative variable definitions that occur within /// headers. The declarations themselves are stored as declaration - /// IDs, since they will be written out to an EXTERNAL_DEFINITIONS + /// IDs, since they will be written out to an EAGERLY_DESERIALIZED_DECLS /// record. - SmallVector<uint64_t, 16> ExternalDefinitions; + SmallVector<uint64_t, 16> EagerlyDeserializedDecls; /// \brief DeclContexts that have received extensions since their serialized /// form. @@ -438,6 +467,8 @@ private: bool isModule); void WriteCXXBaseSpecifiersOffsets(); void WriteType(QualType T); + uint32_t GenerateNameLookupTable(const DeclContext *DC, + llvm::SmallVectorImpl<char> &LookupTable); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); void WriteTypeDeclOffsets(); @@ -448,8 +479,7 @@ private: void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule); void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record); - void ResolveDeclUpdatesBlocks(); - void WriteDeclUpdatesBlocks(); + void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord); void WriteDeclReplacementsBlock(); void WriteDeclContextVisibleUpdate(const DeclContext *DC); void WriteFPPragmaOptions(const FPOptions &Opts); @@ -458,6 +488,7 @@ private: void WriteRedeclarations(); void WriteMergedDecls(); void WriteLateParsedTemplates(Sema &SemaRef); + void WriteOptimizePragmaOptions(Sema &SemaRef); unsigned DeclParmVarAbbrev; unsigned DeclContextLexicalAbbrev; @@ -475,6 +506,7 @@ private: void WriteDeclsBlockAbbrevs(); void WriteDecl(ASTContext &Context, Decl *D); + void AddFunctionDefinition(const FunctionDecl *FD, RecordData &Record); void WriteASTCore(Sema &SemaRef, StringRef isysroot, const std::string &OutputFile, @@ -645,9 +677,7 @@ public: void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record); /// \brief Mark a declaration context as needing an update. - void AddUpdatedDeclContext(const DeclContext *DC) { - UpdatedDeclContexts.insert(DC); - } + void AddUpdatedDeclContext(const DeclContext *DC); void RewriteDecl(const Decl *D) { DeclsToRewrite.insert(D); @@ -715,35 +745,36 @@ public: bool hasChain() const { return Chain; } // ASTDeserializationListener implementation - void ReaderInitialized(ASTReader *Reader); - void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II); - void MacroRead(serialization::MacroID ID, MacroInfo *MI); - void TypeRead(serialization::TypeIdx Idx, QualType T); - void SelectorRead(serialization::SelectorID ID, Selector Sel); + void ReaderInitialized(ASTReader *Reader) override; + void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) override; + void MacroRead(serialization::MacroID ID, MacroInfo *MI) override; + void TypeRead(serialization::TypeIdx Idx, QualType T) override; + void SelectorRead(serialization::SelectorID ID, Selector Sel) override; void MacroDefinitionRead(serialization::PreprocessedEntityID ID, - MacroDefinition *MD); - void ModuleRead(serialization::SubmoduleID ID, Module *Mod); + MacroDefinition *MD) override; + void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override; // ASTMutationListener implementation. - virtual void CompletedTagDefinition(const TagDecl *D); - virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D); - virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D); - virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, - const ClassTemplateSpecializationDecl *D); - virtual void - AddedCXXTemplateSpecialization(const VarTemplateDecl *TD, - const VarTemplateSpecializationDecl *D); - virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, - const FunctionDecl *D); - virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType); - virtual void CompletedImplicitDefinition(const FunctionDecl *D); - virtual void StaticDataMemberInstantiated(const VarDecl *D); - virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, - const ObjCInterfaceDecl *IFD); - virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, - const ObjCPropertyDecl *OrigProp, - const ObjCCategoryDecl *ClassExt); - void DeclarationMarkedUsed(const Decl *D) LLVM_OVERRIDE; + void CompletedTagDefinition(const TagDecl *D) override; + void AddedVisibleDecl(const DeclContext *DC, const Decl *D) override; + void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) override; + void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, + const ClassTemplateSpecializationDecl *D) override; + void AddedCXXTemplateSpecialization(const VarTemplateDecl *TD, + const VarTemplateSpecializationDecl *D) override; + void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D) override; + void ResolvedExceptionSpec(const FunctionDecl *FD) override; + void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override; + void CompletedImplicitDefinition(const FunctionDecl *D) override; + void StaticDataMemberInstantiated(const VarDecl *D) override; + void FunctionDefinitionInstantiated(const FunctionDecl *D) override; + void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, + const ObjCInterfaceDecl *IFD) override; + void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, + const ObjCPropertyDecl *OrigProp, + const ObjCCategoryDecl *ClassExt) override; + void DeclarationMarkedUsed(const Decl *D) override; }; /// \brief AST and semantic-analysis consumer that generates a @@ -771,10 +802,10 @@ public: StringRef isysroot, raw_ostream *Out, bool AllowASTWithErrors = false); ~PCHGenerator(); - virtual void InitializeSema(Sema &S) { SemaPtr = &S; } - virtual void HandleTranslationUnit(ASTContext &Ctx); - virtual ASTMutationListener *GetASTMutationListener(); - virtual ASTDeserializationListener *GetASTDeserializationListener(); + void InitializeSema(Sema &S) override { SemaPtr = &S; } + void HandleTranslationUnit(ASTContext &Ctx) override; + ASTMutationListener *GetASTMutationListener() override; + ASTDeserializationListener *GetASTDeserializationListener() override; bool hasEmittedPCH() const { return HasEmittedPCH; } }; diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h b/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h index 76414ba..1f0d752 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h @@ -17,11 +17,11 @@ #define LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include <memory> #include <utility> namespace llvm { @@ -59,7 +59,7 @@ using serialization::ModuleFile; class GlobalModuleIndex { /// \brief Buffer containing the index file, which is lazily accessed so long /// as the global module index is live. - llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + std::unique_ptr<llvm::MemoryBuffer> Buffer; /// \brief The hash table. /// @@ -186,6 +186,9 @@ public: /// \brief Print statistics to standard error. void printStats(); + /// \brief Print debugging view to standard error. + void dump(); + /// \brief Write a global index into the given /// /// \param FileMgr The file manager to use to load module files. diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/Module.h b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h index 89c604f..4952039 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/Module.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h @@ -18,17 +18,21 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ContinuousRangeMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SetVector.h" #include "llvm/Bitcode/BitstreamReader.h" +#include <memory> #include <string> +namespace llvm { +template <typename Info> class OnDiskChainedHashTable; +template <typename Info> class OnDiskIterableChainedHashTable; +} + namespace clang { class FileEntry; class DeclContext; class Module; -template<typename Info> class OnDiskChainedHashTable; namespace serialization { @@ -49,7 +53,7 @@ struct DeclContextInfo { DeclContextInfo() : NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {} - OnDiskChainedHashTable<reader::ASTDeclContextNameLookupTrait> + llvm::OnDiskIterableChainedHashTable<reader::ASTDeclContextNameLookupTrait> *NameLookupTableData; // an ASTDeclContextNameLookupTable. const KindDeclIDPair *LexicalDecls; unsigned NumLexicalDecls; @@ -57,11 +61,12 @@ struct DeclContextInfo { /// \brief The input file that has been loaded from this AST file, along with /// bools indicating whether this was an overridden buffer or if it was -/// out-of-date. +/// out-of-date or not-found. class InputFile { enum { Overridden = 1, - OutOfDate = 2 + OutOfDate = 2, + NotFound = 3 }; llvm::PointerIntPair<const FileEntry *, 2, unsigned> Val; @@ -79,9 +84,16 @@ public: Val.setPointerAndInt(File, intVal); } + static InputFile getNotFound() { + InputFile File; + File.Val.setInt(NotFound); + return File; + } + const FileEntry *getFile() const { return Val.getPointer(); } bool isOverridden() const { return Val.getInt() == Overridden; } bool isOutOfDate() const { return Val.getInt() == OutOfDate; } + bool isNotFound() const { return Val.getInt() == NotFound; } }; /// \brief Information about a module that has been loaded by the ASTReader. @@ -107,6 +119,13 @@ public: /// \brief The file name of the module file. std::string FileName; + /// \brief The name of the module. + std::string ModuleName; + + std::string getTimestampFilename() const { + return FileName + ".timestamp"; + } + /// \brief The original source file name that was used to build the /// primary AST file, which may have been modified for /// relocatable-pch support. @@ -124,6 +143,8 @@ public: /// allow resolving headers even after headers+PCH was moved to a new path. std::string OriginalDir; + std::string ModuleMapPath; + /// \brief Whether this precompiled header is a relocatable PCH file. bool RelocatablePCH; @@ -139,7 +160,7 @@ public: /// \brief The memory buffer that stores the data associated with /// this AST file. - OwningPtr<llvm::MemoryBuffer> Buffer; + std::unique_ptr<llvm::MemoryBuffer> Buffer; /// \brief The size of this file, in bits. uint64_t SizeInBits; @@ -159,6 +180,9 @@ public: /// If module A depends on and imports module B, both modules will have the /// same DirectImportLoc, but different ImportLoc (B's ImportLoc will be a /// source location inside module A). + /// + /// WARNING: This is largely useless. It doesn't tell you when a module was + /// made visible, just when the first submodule of that module was imported. SourceLocation DirectImportLoc; /// \brief The source location where this module was first imported. @@ -177,6 +201,12 @@ public: /// \brief The input files that have been loaded from this AST file. std::vector<InputFile> InputFilesLoaded; + /// \brief If non-zero, specifies the time when we last validated input + /// files. Zero means we never validated them. + /// + /// The time is specified in seconds since the start of the Epoch. + uint64_t InputFilesValidationTimestamp; + // === Source Locations === /// \brief Cursor used to read source location entries. diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h index ca643ba..3259902 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h @@ -18,6 +18,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Serialization/Module.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" namespace clang { @@ -65,7 +66,7 @@ class ModuleManager { /// calls to visit(). struct VisitState { explicit VisitState(unsigned N) - : VisitNumber(N, 0), NextVisitNumber(1), NextState(0) + : VisitNumber(N, 0), NextVisitNumber(1), NextState(nullptr) { Stack.reserve(N); } @@ -194,6 +195,7 @@ public: /// \brief Remove the given set of modules. void removeModules(ModuleIterator first, ModuleIterator last, + llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully, ModuleMap *modMap); /// \brief Add an in-memory buffer the list of known buffers @@ -230,7 +232,7 @@ public: /// Any module that is known to both the global module index and the module /// manager that is *not* in this set can be skipped. void visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData, - llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit = 0); + llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit = nullptr); /// \brief Visit each of the modules with a depth-first traversal. /// diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h index 5978299..26335bf 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h @@ -114,8 +114,6 @@ public: /// Indicates that the object is not owned and controlled by the /// Garbage collector. GCNotOwnedSymbol, - /// Indicates that the object is not owned and controlled by ARC. - ARCNotOwnedSymbol, /// Indicates that the return value is an owned object when the /// receiver is also a tracked object. OwnedWhenTrackedReceiver, @@ -154,7 +152,7 @@ public: } bool notOwned() const { - return K == NotOwnedSymbol || K == ARCNotOwnedSymbol; + return K == NotOwnedSymbol; } bool operator==(const RetEffect &Other) const { @@ -174,9 +172,6 @@ public: static RetEffect MakeGCNotOwned() { return RetEffect(GCNotOwnedSymbol, ObjC); } - static RetEffect MakeARCNotOwned() { - return RetEffect(ARCNotOwnedSymbol, ObjC); - } static RetEffect MakeNoRet() { return RetEffect(NoRet); } @@ -202,7 +197,7 @@ class CallEffects { public: /// Returns the argument effects for a call. - llvm::ArrayRef<ArgEffect> getArgs() const { return Args; } + ArrayRef<ArgEffect> getArgs() const { return Args; } /// Returns the effects on the receiver. ArgEffect getReceiver() const { return Receiver; } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 618782e..978c3e2 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -54,6 +54,7 @@ NumConstraints enum AnalysisDiagClients { #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME, #include "clang/StaticAnalyzer/Core/Analyses.def" +PD_NONE, NUM_ANALYSIS_DIAG_CLIENTS }; @@ -140,7 +141,7 @@ public: unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; - + /// \brief The flag regulates if we should eagerly assume evaluations of /// conditionals, thus, bifurcating the path. /// @@ -198,8 +199,11 @@ private: /// \sa mayInlineTemplateFunctions Optional<bool> InlineTemplateFunctions; - /// \sa mayInlineCXXContainerCtorsAndDtors - Optional<bool> InlineCXXContainerCtorsAndDtors; + /// \sa mayInlineCXXAllocator + Optional<bool> InlineCXXAllocator; + + /// \sa mayInlineCXXContainerMethods + Optional<bool> InlineCXXContainerMethods; /// \sa mayInlineCXXSharedPtrDtor Optional<bool> InlineCXXSharedPtrDtor; @@ -229,6 +233,9 @@ private: /// \sa reportIssuesInMainSourceFile Optional<bool> ReportIssuesInMainSourceFile; + /// \sa StableReportFilename + Optional<bool> StableReportFilename; + /// \sa getGraphTrimInterval Optional<unsigned> GraphTrimInterval; @@ -290,12 +297,18 @@ public: /// accepts the values "true" and "false". bool mayInlineTemplateFunctions(); - /// Returns whether or not constructors and destructors of C++ container - /// objects may be considered for inlining. + /// Returns whether or not allocator call may be considered for inlining. + /// + /// This is controlled by the 'c++-allocator-inlining' config option, which + /// accepts the values "true" and "false". + bool mayInlineCXXAllocator(); + + /// Returns whether or not methods of C++ container objects may be considered + /// for inlining. /// /// This is controlled by the 'c++-container-inlining' config option, which /// accepts the values "true" and "false". - bool mayInlineCXXContainerCtorsAndDtors(); + bool mayInlineCXXContainerMethods(); /// Returns whether or not the destructor of C++ 'shared_ptr' may be /// considered for inlining. @@ -349,6 +362,12 @@ public: /// which accepts the values "true" and "false". bool shouldReportIssuesInMainSourceFile(); + /// Returns whether or not the report filename should be random or not. + /// + /// This is controlled by the 'stable-report-filename' config option, + /// which accepts the values "true" and "false". Default = false + bool shouldWriteStableReportFilename(); + /// Returns whether irrelevant parts of a bug report path should be pruned /// out of the final output. /// diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 9584b8b..5371231 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -19,6 +19,7 @@ #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" @@ -143,19 +144,18 @@ private: public: BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) - : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode), + : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode), 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), + : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc), + Description(desc), 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), - DoNotPrunePath(false) {} + BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l) + : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l), + ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {} /// \brief Create a BugReport with a custom uniqueing location. /// @@ -166,7 +166,7 @@ public: /// the allocation site, rather then the location where the bug is reported. BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique) - : BT(bt), DeclWithIssue(0), Description(desc), + : BT(bt), DeclWithIssue(nullptr), Description(desc), UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique), ErrorNode(errornode), ConfigurationChangeToken(0), @@ -463,7 +463,12 @@ public: /// reports. void emitReport(BugReport *R); - void EmitBasicReport(const Decl *DeclWithIssue, + void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, + StringRef BugName, StringRef BugCategory, + StringRef BugStr, PathDiagnosticLocation Loc, + ArrayRef<SourceRange> Ranges = None); + + void EmitBasicReport(const Decl *DeclWithIssue, CheckName CheckName, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef<SourceRange> Ranges = None); @@ -473,7 +478,8 @@ private: /// \brief Returns a BugType that is associated with the given name and /// category. - BugType *getBugTypeForName(StringRef name, StringRef category); + BugType *getBugTypeForName(CheckName CheckName, StringRef name, + StringRef category); }; // FIXME: Get rid of GRBugReporter. It's the wrong abstraction. @@ -505,9 +511,8 @@ public: /// /// \return True if the report was valid and a path was generated, /// false if the reports should be considered invalid. - virtual bool generatePathDiagnostic(PathDiagnostic &PD, - PathDiagnosticConsumer &PC, - ArrayRef<BugReport*> &bugReports); + bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC, + ArrayRef<BugReport*> &bugReports) override; /// classof - Used by isa<>, cast<>, and dyn_cast<>. static bool classof(const BugReporter* R) { diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index 2e67180..f352f80 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -89,7 +89,7 @@ public: /// will have to provide your own implementation.) template <class DERIVED> class BugReporterVisitorImpl : public BugReporterVisitor { - virtual BugReporterVisitor *clone() const { + BugReporterVisitor *clone() const override { return new DERIVED(*static_cast<const DERIVED *>(this)); } }; @@ -118,12 +118,12 @@ public: Satisfied(false), EnableNullFPSuppression(InEnableNullFPSuppression) {} - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; }; class TrackConstraintBRVisitor @@ -144,7 +144,7 @@ public: IsZeroCheck(!Assumption && Constraint.getAs<Loc>()), IsTrackingTurnedOn(false) {} - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; /// Return the tag associated with this visitor. This tag will be used /// to make all PathDiagnosticPieces created by this visitor. @@ -153,7 +153,7 @@ public: PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; private: /// Checks if the constraint is valid in the current state. @@ -166,8 +166,8 @@ private: class NilReceiverBRVisitor : public BugReporterVisitorImpl<NilReceiverBRVisitor> { public: - - void Profile(llvm::FoldingSetNodeID &ID) const { + + void Profile(llvm::FoldingSetNodeID &ID) const override { static int x = 0; ID.AddPointer(&x); } @@ -175,7 +175,7 @@ public: PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; /// If the statement is a message send expression with nil receiver, returns /// the receiver expression. Returns NULL otherwise. @@ -185,7 +185,7 @@ public: /// Visitor that tries to report interesting diagnostics from conditions. class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> { public: - void Profile(llvm::FoldingSetNodeID &ID) const { + void Profile(llvm::FoldingSetNodeID &ID) const override { static int x = 0; ID.AddPointer(&x); } @@ -193,11 +193,11 @@ public: /// Return the tag associated with this visitor. This tag will be used /// to make all PathDiagnosticPieces created by this visitor. static const char *getTag(); - - virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, - const ExplodedNode *Prev, - BugReporterContext &BRC, - BugReport &BR); + + PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *Prev, + BugReporterContext &BRC, + BugReport &BR) override; PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N, const ExplodedNode *Prev, @@ -257,20 +257,20 @@ public: return static_cast<void *>(&Tag); } - void Profile(llvm::FoldingSetNodeID &ID) const { + void Profile(llvm::FoldingSetNodeID &ID) const override { ID.AddPointer(getTag()); } - virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, - const ExplodedNode *Prev, - BugReporterContext &BRC, - BugReport &BR) { - return 0; + PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *Prev, + BugReporterContext &BRC, + BugReport &BR) override { + return nullptr; } - virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR); + PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR) override; }; /// \brief When a region containing undefined value or '0' value is passed @@ -287,7 +287,7 @@ class UndefOrNullArgVisitor public: UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {} - virtual void Profile(llvm::FoldingSetNodeID &ID) const { + void Profile(llvm::FoldingSetNodeID &ID) const override { static int Tag = 0; ID.AddPointer(&Tag); ID.AddPointer(R); @@ -296,7 +296,7 @@ public: PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; }; class SuppressInlineDefensiveChecksVisitor @@ -319,7 +319,7 @@ class SuppressInlineDefensiveChecksVisitor public: SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N); - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; /// Return the tag associated with this visitor. This tag will be used /// to make all PathDiagnosticPieces created by this visitor. @@ -328,7 +328,7 @@ public: PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; }; namespace bugreporter { diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index 49f9c83..24c7785 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -14,8 +14,9 @@ #ifndef LLVM_CLANG_ANALYSIS_BUGTYPE #define LLVM_CLANG_ANALYSIS_BUGTYPE -#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "llvm/ADT/FoldingSet.h" #include <string> @@ -29,20 +30,25 @@ class ExprEngine; class BugType { private: + const CheckName Check; const std::string Name; const std::string Category; bool SuppressonSink; virtual void anchor(); public: - BugType(StringRef name, StringRef cat) - : Name(name), Category(cat), SuppressonSink(false) {} + BugType(class CheckName check, StringRef name, StringRef cat) + : Check(check), Name(name), Category(cat), SuppressonSink(false) {} + BugType(const CheckerBase *checker, StringRef name, StringRef cat) + : Check(checker->getCheckName()), Name(name), Category(cat), + SuppressonSink(false) {} virtual ~BugType() {} // FIXME: Should these be made strings as well? StringRef getName() const { return Name; } StringRef getCategory() const { return Category; } - + StringRef getCheckName() const { return Check.getName(); } + /// isSuppressOnSink - Returns true if bug reports associated with this bug /// type should be suppressed if the end node of the report is post-dominated /// by a sink node. @@ -54,14 +60,18 @@ public: class BuiltinBug : public BugType { const std::string desc; - virtual void anchor(); + void anchor() override; public: - BuiltinBug(const char *name, const char *description) - : BugType(name, categories::LogicError), desc(description) {} - - BuiltinBug(const char *name) - : BugType(name, categories::LogicError), desc(name) {} - + BuiltinBug(class CheckName check, const char *name, const char *description) + : BugType(check, name, categories::LogicError), desc(description) {} + + BuiltinBug(const CheckerBase *checker, const char *name, + const char *description) + : BugType(checker, name, categories::LogicError), desc(description) {} + + BuiltinBug(const CheckerBase *checker, const char *name) + : BugType(checker, name, categories::LogicError), desc(name) {} + StringRef getDescription() const { return desc; } }; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index b0670da..5a578d0 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -21,13 +21,13 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" #include <deque> -#include <list> #include <iterator> +#include <list> #include <string> #include <vector> namespace clang { - +class ConditionalOperator; class AnalysisDeclContext; class BinaryOperator; class CompoundStmt; @@ -72,7 +72,9 @@ public: struct FilesMade : public llvm::FoldingSet<PDFileEntry> { llvm::BumpPtrAllocator Alloc; - + + ~FilesMade(); + void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName); @@ -136,29 +138,29 @@ private: PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, Kind kind) - : K(kind), S(0), D(0), SM(&sm), + : K(kind), S(nullptr), D(nullptr), SM(&sm), Loc(genLocation(L)), Range(genRange()) { } - FullSourceLoc - genLocation(SourceLocation L = SourceLocation(), - LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const; + FullSourceLoc genLocation( + SourceLocation L = SourceLocation(), + LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const; - PathDiagnosticRange - genRange(LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const; + PathDiagnosticRange genRange( + LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const; public: /// Create an invalid location. PathDiagnosticLocation() - : K(SingleLocK), S(0), D(0), SM(0) {} + : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {} /// Create a location corresponding to the given statement. PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac) : K(s->getLocStart().isValid() ? StmtK : SingleLocK), - S(K == StmtK ? s : 0), - D(0), SM(&sm), + S(K == StmtK ? s : nullptr), + D(nullptr), SM(&sm), Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) { assert(K == SingleLocK || S); @@ -168,7 +170,7 @@ public: /// Create a location corresponding to the given declaration. PathDiagnosticLocation(const Decl *d, const SourceManager &sm) - : K(DeclK), S(0), D(d), SM(&sm), + : K(DeclK), S(nullptr), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) { assert(D); assert(Loc.isValid()); @@ -179,7 +181,8 @@ public: /// /// 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()) { + : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm), + Range(genRange()) { assert(Loc.isValid()); assert(Range.isValid()); } @@ -211,6 +214,9 @@ public: /// Assumes the statement has a valid location. static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM); + static PathDiagnosticLocation createConditionalColonLoc( + const ConditionalOperator *CO, + const SourceManager &SM); /// For member expressions, return the location of the '.' or '->'. /// Assumes the statement has a valid location. @@ -259,7 +265,7 @@ public: } bool isValid() const { - return SM != 0; + return SM != nullptr; } FullSourceLoc asLocation() const { @@ -420,7 +426,7 @@ public: return Result; } - LLVM_ATTRIBUTE_USED void dump() const; + void dump() const; }; class PathDiagnosticSpotPiece : public PathDiagnosticPiece { @@ -437,10 +443,10 @@ public: if (addPosRange && Pos.hasRange()) addRange(Pos.asRange()); } - PathDiagnosticLocation getLocation() const { return Pos; } - virtual void flattenLocations() { Pos.flatten(); } + PathDiagnosticLocation getLocation() const override { return Pos; } + void flattenLocations() override { Pos.flatten(); } - virtual void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event || P->getKind() == Macro; @@ -476,7 +482,7 @@ public: /// \brief Search the call expression for the symbol Sym and dispatch the /// 'getMessageForX()' methods to construct a specific message. - virtual std::string getMessage(const ExplodedNode *N); + std::string getMessage(const ExplodedNode *N) override; /// Produces the message of the following form: /// 'Msg via Nth parameter' @@ -496,12 +502,12 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { /// supply a message that will be used to construct an extra hint on the /// returns from all the calls on the stack from this event to the final /// diagnostic. - OwningPtr<StackHintGenerator> CallStackHint; + std::unique_ptr<StackHintGenerator> CallStackHint; public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange = true, - StackHintGenerator *stackHint = 0) + StackHintGenerator *stackHint = nullptr) : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), CallStackHint(stackHint) {} @@ -520,10 +526,8 @@ public: bool isPrunable() const { return IsPrunable.hasValue() ? IsPrunable.getValue() : false; } - - bool hasCallStackHint() { - return CallStackHint.isValid(); - } + + bool hasCallStackHint() { return (bool)CallStackHint; } /// Produce the hint for the given node. The node contains /// information about the call for which the diagnostic can be generated. @@ -533,7 +537,7 @@ public: return ""; } - virtual void dump() const; + void dump() const override; static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event; @@ -543,11 +547,11 @@ public: class PathDiagnosticCallPiece : public PathDiagnosticPiece { PathDiagnosticCallPiece(const Decl *callerD, const PathDiagnosticLocation &callReturnPos) - : PathDiagnosticPiece(Call), Caller(callerD), Callee(0), + : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr), NoExit(false), callReturn(callReturnPos) {} PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller) - : PathDiagnosticPiece(Call), Caller(caller), Callee(0), + : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr), NoExit(true), path(oldPath) {} const Decl *Caller; @@ -579,7 +583,7 @@ public: CallStackMessage = st; } - virtual PathDiagnosticLocation getLocation() const { + PathDiagnosticLocation getLocation() const override { return callEnter; } @@ -588,7 +592,7 @@ public: getCallEnterWithinCallerEvent() const; IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const; - virtual void flattenLocations() { + void flattenLocations() override { callEnter.flatten(); callReturn.flatten(); for (PathPieces::iterator I = path.begin(), @@ -601,10 +605,10 @@ public: static PathDiagnosticCallPiece *construct(PathPieces &pieces, const Decl *caller); - - virtual void dump() const; - virtual void Profile(llvm::FoldingSetNodeID &ID) const; + void dump() const override; + + void Profile(llvm::FoldingSetNodeID &ID) const override; static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Call; @@ -651,7 +655,7 @@ public: void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); } - virtual PathDiagnosticLocation getLocation() const { + PathDiagnosticLocation getLocation() const override { return getStartLocation(); } @@ -659,7 +663,7 @@ public: iterator begin() { return LPairs.begin(); } iterator end() { return LPairs.end(); } - virtual void flattenLocations() { + void flattenLocations() override { for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten(); } @@ -672,9 +676,9 @@ public: return P->getKind() == ControlFlow; } - virtual void dump() const; + void dump() const override; - virtual void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; }; class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece { @@ -688,7 +692,7 @@ public: bool containsEvent() const; - virtual void flattenLocations() { + void flattenLocations() override { PathDiagnosticSpotPiece::flattenLocations(); for (PathPieces::iterator I = subPieces.begin(), E = subPieces.end(); I != E; ++I) (*I)->flattenLocations(); @@ -698,15 +702,16 @@ public: return P->getKind() == Macro; } - virtual void dump() const; + void dump() const override; - virtual void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; }; /// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces, /// each which represent the pieces of the path. class PathDiagnostic : public llvm::FoldingSetNode { + std::string CheckName; const Decl *DeclWithIssue; std::string BugType; std::string VerboseDesc; @@ -727,8 +732,8 @@ class PathDiagnostic : public llvm::FoldingSetNode { PathDiagnostic() LLVM_DELETED_FUNCTION; public: - PathDiagnostic(const Decl *DeclWithIssue, StringRef bugtype, - StringRef verboseDesc, StringRef shortDesc, + PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue, + StringRef bugtype, StringRef verboseDesc, StringRef shortDesc, StringRef category, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique); @@ -785,6 +790,7 @@ public: StringRef getShortDescription() const { return ShortDesc.empty() ? VerboseDesc : ShortDesc; } + StringRef getCheckName() const { return CheckName; } StringRef getBugType() const { return BugType; } StringRef getCategory() const { return Category; } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h index cf7cf05..b9a5b8a 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h @@ -453,14 +453,29 @@ public: } // end eval namespace class CheckerBase : public ProgramPointTag { + CheckName Name; + friend class ::clang::ento::CheckerManager; + public: - StringRef getTagDescription() const; + StringRef getTagDescription() const override; + CheckName getCheckName() const; /// See CheckerManager::runCheckersForPrintState. virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const { } }; - + +/// Dump checker name to stream. +raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); + +/// Tag that can use a checker name as a message provider +/// (see SimpleProgramPointTag). +class CheckerProgramPointTag : public SimpleProgramPointTag { +public: + CheckerProgramPointTag(StringRef CheckerName, StringRef Msg); + CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg); +}; + template <typename CHECK1, typename CHECK2=check::_VoidCheck, typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, @@ -511,7 +526,7 @@ template <typename EVENT> class EventDispatcher { CheckerManager *Mgr; public: - EventDispatcher() : Mgr(0) { } + EventDispatcher() : Mgr(nullptr) { } template <typename CHECKER> static void _register(CHECKER *checker, CheckerManager &mgr) { diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h index 8ad67c1..b364115 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -16,8 +16,8 @@ #include "clang/Analysis/ProgramPoint.h" #include "clang/Basic/LangOptions.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include <vector> @@ -29,11 +29,11 @@ namespace clang { namespace ento { class CheckerBase; + class CheckerRegistry; class ExprEngine; class AnalysisManager; class BugReporter; class CheckerContext; - class SimpleCall; class ObjCMethodCall; class SVal; class ExplodedNode; @@ -132,9 +132,26 @@ enum PointerEscapeKind { PSK_EscapeOther }; +// This wrapper is used to ensure that only StringRefs originating from the +// CheckerRegistry are used as check names. We want to make sure all check +// name strings have a lifetime that keeps them alive at least until the path +// diagnostics have been processed. +class CheckName { + StringRef Name; + friend class ::clang::ento::CheckerRegistry; + explicit CheckName(StringRef Name) : Name(Name) {} + +public: + CheckName() {} + CheckName(const CheckName &Other) : Name(Other.Name) {} + StringRef getName() const { return Name; } +}; + class CheckerManager { const LangOptions LangOpts; AnalyzerOptionsRef AOptions; + CheckName CurrentCheckName; + public: CheckerManager(const LangOptions &langOpts, AnalyzerOptionsRef AOptions) @@ -143,6 +160,9 @@ public: ~CheckerManager(); + void setCurrentCheckName(CheckName name) { CurrentCheckName = name; } + CheckName getCurrentCheckName() const { return CurrentCheckName; } + bool hasPathSensitiveCheckers() const; void finishedCheckerRegistration(); @@ -169,6 +189,7 @@ public: return static_cast<CHECKER *>(ref); // already registered. CHECKER *checker = new CHECKER(); + checker->Name = CurrentCheckName; CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); CHECKER::_register(checker, *this); ref = checker; @@ -183,6 +204,7 @@ public: return static_cast<CHECKER *>(ref); // already registered. CHECKER *checker = new CHECKER(AOpts); + checker->Name = CurrentCheckName; CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); CHECKER::_register(checker, *this); ref = checker; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h index 9502900..37be69a 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_SA_CORE_APSINTTYPE_H #include "llvm/ADT/APSInt.h" +#include <tuple> namespace clang { namespace ento { @@ -97,13 +98,8 @@ public: /// 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; + return std::tie(BitWidth, IsUnsigned) < + std::tie(Other.BitWidth, Other.IsUnsigned); } }; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index d7d83ce..1a398b8 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -65,8 +65,8 @@ public: StoreManagerCreator getStoreManagerCreator() { return CreateStoreMgr; } - - AnalyzerOptions& getAnalyzerOptions() { + + AnalyzerOptions& getAnalyzerOptions() override { return options; } @@ -76,15 +76,15 @@ public: CheckerManager *getCheckerManager() const { return CheckerMgr; } - virtual ASTContext &getASTContext() { + ASTContext &getASTContext() override { return Ctx; } - virtual SourceManager &getSourceManager() { + SourceManager &getSourceManager() override { return getASTContext().getSourceManager(); } - virtual DiagnosticsEngine &getDiagnostic() { + DiagnosticsEngine &getDiagnostic() override { return Diags; } @@ -92,7 +92,7 @@ public: return LangOpts; } - ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() { + ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() override { return PathConsumers; } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 2c799c0..08905fd 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -79,9 +79,9 @@ class BasicValueFactory { const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); public: - BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator& Alloc) - : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0), - SValListFactory(Alloc) {} + BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc) + : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr), + PersistentSValPairs(nullptr), SValListFactory(Alloc) {} ~BasicValueFactory(); diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h index 2483a79..0408070 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h @@ -16,9 +16,7 @@ #ifndef LLVM_CLANG_GR_BLOCKCOUNTER #define LLVM_CLANG_GR_BLOCKCOUNTER -namespace llvm { - class BumpPtrAllocator; -} +#include "llvm/Support/Allocator.h" namespace clang { @@ -35,7 +33,7 @@ class BlockCounter { BlockCounter(void *D) : Data(D) {} public: - BlockCounter() : Data(0) {} + BlockCounter() : Data(nullptr) {} unsigned getNumVisited(const StackFrameContext *CallSite, unsigned BlockID) const; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index cfaf085..4a5426b 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -33,9 +33,6 @@ 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, @@ -45,6 +42,7 @@ enum CallEventKind { CE_CXXAllocator, CE_BEG_FUNCTION_CALLS = CE_Function, CE_END_FUNCTION_CALLS = CE_CXXAllocator, + CE_Block, CE_ObjCMessage }; @@ -58,14 +56,14 @@ public: CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr<const T>(Orig) {} CallEventRef<T> cloneWithState(ProgramStateRef State) const { - return this->getPtr()->template cloneWithState<T>(State); + return this->get()->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(); + return this->get(); } }; @@ -88,15 +86,15 @@ class RuntimeDefinition { const MemRegion *R; public: - RuntimeDefinition(): D(0), R(0) {} - RuntimeDefinition(const Decl *InD): D(InD), R(0) {} + RuntimeDefinition(): D(nullptr), R(nullptr) {} + RuntimeDefinition(const Decl *InD): D(InD), R(nullptr) {} RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {} const Decl *getDecl() { return D; } /// \brief Check if the definition we have is precise. /// If not, it is possible that the call dispatches to another definition at /// execution time. - bool mayHaveOtherDefinitions() { return R != 0; } + bool mayHaveOtherDefinitions() { return R != nullptr; } /// When other definitions are possible, returns the region whose runtime type /// determines the method definition. @@ -239,7 +237,7 @@ public: /// \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; } + virtual const Expr *getArgExpr(unsigned Index) const { return nullptr; } /// \brief Returns the source range for errors associated with this argument. /// @@ -295,20 +293,20 @@ public: const IdentifierInfo *getCalleeIdentifier() const { const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDecl()); if (!ND) - return 0; + return nullptr; return ND->getIdentifier(); } /// \brief Returns an appropriate ProgramPoint for this call. ProgramPoint getProgramPoint(bool IsPreVisit = false, - const ProgramPointTag *Tag = 0) const; + const ProgramPointTag *Tag = nullptr) 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; + ProgramStateRef Orig = nullptr) const; typedef std::pair<Loc, SVal> FrameBindingTy; typedef SmallVectorImpl<FrameBindingTy> BindingsTy; @@ -344,23 +342,16 @@ public: // 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. +public: + /// Return call's formal parameters. /// /// 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, \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; + virtual ArrayRef<ParmVarDecl*> parameters() const = 0; - typedef llvm::mapped_iterator<param_iterator, get_type_fun> + typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, get_type_fun> param_type_iterator; /// Returns an iterator over the types of the call's formal parameters. @@ -369,17 +360,18 @@ public: /// 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(), + return llvm::map_iterator(parameters().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)); + return llvm::map_iterator(parameters().end(), + get_type_fun(&ParmVarDecl::getType)); } // For debugging purposes only void dump(raw_ostream &Out) const; - LLVM_ATTRIBUTE_USED void dump() const; + void dump() const; }; @@ -398,11 +390,11 @@ protected: public: // This function is overridden by subclasses, but they must return // a FunctionDecl. - virtual const FunctionDecl *getDecl() const { + const FunctionDecl *getDecl() const override { return cast<FunctionDecl>(CallEvent::getDecl()); } - virtual RuntimeDefinition getRuntimeDefinition() const { + RuntimeDefinition getRuntimeDefinition() const override { const FunctionDecl *FD = getDecl(); // Note that the AnalysisDeclContext will have the FunctionDecl with // the definition (if one exists). @@ -417,13 +409,12 @@ public: return RuntimeDefinition(); } - virtual bool argumentsMayEscape() const; + bool argumentsMayEscape() const override; - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const; + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; - virtual param_iterator param_begin() const; - virtual param_iterator param_end() const; + ArrayRef<ParmVarDecl *> parameters() const override; static bool classof(const CallEvent *CA) { return CA->getKind() >= CE_BEG_FUNCTION_CALLS && @@ -431,49 +422,36 @@ public: } }; -/// \brief Represents a call to a non-C++ function, written as a CallExpr. -class SimpleCall : public AnyFunctionCall { +/// \brief Represents a C function or static C++ member function call. +/// +/// Example: \c fun() +class SimpleFunctionCall : public AnyFunctionCall { + friend class CallEventManager; + protected: - SimpleCall(const CallExpr *CE, ProgramStateRef St, - const LocationContext *LCtx) + SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx) : AnyFunctionCall(CE, St, LCtx) {} - SimpleCall(const SimpleCall &Other) : AnyFunctionCall(Other) {} + SimpleFunctionCall(const SimpleFunctionCall &Other) + : AnyFunctionCall(Other) {} + void cloneTo(void *Dest) const override { + new (Dest) SimpleFunctionCall(*this); + } public: virtual const CallExpr *getOriginExpr() const { return cast<CallExpr>(AnyFunctionCall::getOriginExpr()); } - virtual const FunctionDecl *getDecl() const; + const FunctionDecl *getDecl() const override; - virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); } + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { 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; } + Kind getKind() const override { return CE_Function; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_Function; @@ -483,47 +461,56 @@ public: /// \brief Represents a call to a block. /// /// Example: <tt>^{ /* ... */ }()</tt> -class BlockCall : public SimpleCall { +class BlockCall : public CallEvent { friend class CallEventManager; protected: BlockCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) - : SimpleCall(CE, St, LCtx) {} + : CallEvent(CE, St, LCtx) {} - BlockCall(const BlockCall &Other) : SimpleCall(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) BlockCall(*this); } + BlockCall(const BlockCall &Other) : CallEvent(Other) {} + void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); } - virtual void getExtraInvalidatedValues(ValueList &Values) const; + void getExtraInvalidatedValues(ValueList &Values) const override; public: + virtual const CallExpr *getOriginExpr() const { + return cast<CallExpr>(CallEvent::getOriginExpr()); + } + + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } + + const Expr *getArgExpr(unsigned Index) const override { + return getOriginExpr()->getArg(Index); + } + /// \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 BlockDecl *getDecl() const override { const BlockDataRegion *BR = getBlockRegion(); if (!BR) - return 0; + return nullptr; return BR->getDecl(); } - virtual RuntimeDefinition getRuntimeDefinition() const { - return RuntimeDefinition(getBlockDecl()); + RuntimeDefinition getRuntimeDefinition() const override { + return RuntimeDefinition(getDecl()); } - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const; + bool argumentsMayEscape() const override { + return true; + } - virtual param_iterator param_begin() const; - virtual param_iterator param_end() const; + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; - virtual Kind getKind() const { return CE_Block; } + ArrayRef<ParmVarDecl*> parameters() const override; + + Kind getKind() const override { return CE_Block; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_Block; @@ -534,7 +521,7 @@ public: /// it is written. class CXXInstanceCall : public AnyFunctionCall { protected: - virtual void getExtraInvalidatedValues(ValueList &Values) const; + void getExtraInvalidatedValues(ValueList &Values) const override; CXXInstanceCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) @@ -548,17 +535,17 @@ protected: public: /// \brief Returns the expression representing the implicit 'this' object. - virtual const Expr *getCXXThisExpr() const { return 0; } + virtual const Expr *getCXXThisExpr() const { return nullptr; } /// \brief Returns the value of the implicit 'this' object. virtual SVal getCXXThisVal() const; - virtual const FunctionDecl *getDecl() const; + const FunctionDecl *getDecl() const override; - virtual RuntimeDefinition getRuntimeDefinition() const; + RuntimeDefinition getRuntimeDefinition() const override; - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const; + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; static bool classof(const CallEvent *CA) { return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS && @@ -578,28 +565,28 @@ protected: : CXXInstanceCall(CE, St, LCtx) {} CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) CXXMemberCall(*this); } + void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); } public: virtual const CXXMemberCallExpr *getOriginExpr() const { return cast<CXXMemberCallExpr>(CXXInstanceCall::getOriginExpr()); } - virtual unsigned getNumArgs() const { + unsigned getNumArgs() const override { if (const CallExpr *CE = getOriginExpr()) return CE->getNumArgs(); return 0; } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index); } - virtual const Expr *getCXXThisExpr() const; - - virtual RuntimeDefinition getRuntimeDefinition() const; + const Expr *getCXXThisExpr() const override; - virtual Kind getKind() const { return CE_CXXMember; } + RuntimeDefinition getRuntimeDefinition() const override; + + Kind getKind() const override { return CE_CXXMember; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_CXXMember; @@ -620,7 +607,7 @@ protected: CXXMemberOperatorCall(const CXXMemberOperatorCall &Other) : CXXInstanceCall(Other) {} - virtual void cloneTo(void *Dest) const { + void cloneTo(void *Dest) const override { new (Dest) CXXMemberOperatorCall(*this); } @@ -629,16 +616,16 @@ public: return cast<CXXOperatorCallExpr>(CXXInstanceCall::getOriginExpr()); } - virtual unsigned getNumArgs() const { + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs() - 1; } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index + 1); } - virtual const Expr *getCXXThisExpr() const; + const Expr *getCXXThisExpr() const override; - virtual Kind getKind() const { return CE_CXXMemberOperator; } + Kind getKind() const override { return CE_CXXMemberOperator; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_CXXMemberOperator; @@ -671,23 +658,23 @@ protected: } CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) CXXDestructorCall(*this); } + void cloneTo(void *Dest) const override {new (Dest) CXXDestructorCall(*this);} public: - virtual SourceRange getSourceRange() const { return Location; } - virtual unsigned getNumArgs() const { return 0; } + SourceRange getSourceRange() const override { return Location; } + unsigned getNumArgs() const override { return 0; } - virtual RuntimeDefinition getRuntimeDefinition() const; + RuntimeDefinition getRuntimeDefinition() const override; /// \brief Returns the value of the implicit 'this' object. - virtual SVal getCXXThisVal() const; + SVal getCXXThisVal() const override; /// Returns true if this is a call to a base class destructor. bool isBaseDestructor() const { return DtorDataTy::getFromOpaqueValue(Data).getInt(); } - virtual Kind getKind() const { return CE_CXXDestructor; } + Kind getKind() const override { return CE_CXXDestructor; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_CXXDestructor; @@ -715,32 +702,32 @@ protected: } CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){} - virtual void cloneTo(void *Dest) const { new (Dest) CXXConstructorCall(*this); } + void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); } - virtual void getExtraInvalidatedValues(ValueList &Values) const; + void getExtraInvalidatedValues(ValueList &Values) const override; public: virtual const CXXConstructExpr *getOriginExpr() const { return cast<CXXConstructExpr>(AnyFunctionCall::getOriginExpr()); } - virtual const CXXConstructorDecl *getDecl() const { + const CXXConstructorDecl *getDecl() const override { return getOriginExpr()->getConstructor(); } - virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); } + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { 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; + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; - virtual Kind getKind() const { return CE_CXXConstructor; } + Kind getKind() const override { return CE_CXXConstructor; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_CXXConstructor; @@ -759,29 +746,29 @@ protected: : AnyFunctionCall(E, St, LCtx) {} CXXAllocatorCall(const CXXAllocatorCall &Other) : AnyFunctionCall(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) CXXAllocatorCall(*this); } + void cloneTo(void *Dest) const override { new (Dest) CXXAllocatorCall(*this); } public: virtual const CXXNewExpr *getOriginExpr() const { return cast<CXXNewExpr>(AnyFunctionCall::getOriginExpr()); } - virtual const FunctionDecl *getDecl() const { + const FunctionDecl *getDecl() const override { return getOriginExpr()->getOperatorNew(); } - virtual unsigned getNumArgs() const { + unsigned getNumArgs() const override { return getOriginExpr()->getNumPlacementArgs() + 1; } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { // The first argument of an allocator call is the size of the allocation. if (Index == 0) - return 0; + return nullptr; return getOriginExpr()->getPlacementArg(Index - 1); } - virtual Kind getKind() const { return CE_CXXAllocator; } + Kind getKind() const override { return CE_CXXAllocator; } static bool classof(const CallEvent *CE) { return CE->getKind() == CE_CXXAllocator; @@ -810,13 +797,13 @@ protected: ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St, const LocationContext *LCtx) : CallEvent(Msg, St, LCtx) { - Data = 0; + Data = nullptr; } ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) ObjCMethodCall(*this); } + void cloneTo(void *Dest) const override { new (Dest) ObjCMethodCall(*this); } - virtual void getExtraInvalidatedValues(ValueList &Values) const; + void getExtraInvalidatedValues(ValueList &Values) const override; /// Check if the selector may have multiple definitions (may have overrides). virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl, @@ -826,13 +813,13 @@ public: virtual const ObjCMessageExpr *getOriginExpr() const { return cast<ObjCMessageExpr>(CallEvent::getOriginExpr()); } - virtual const ObjCMethodDecl *getDecl() const { + const ObjCMethodDecl *getDecl() const override { return getOriginExpr()->getMethodDecl(); } - virtual unsigned getNumArgs() const { + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index); } @@ -846,7 +833,7 @@ public: return getOriginExpr()->getSelector(); } - virtual SourceRange getSourceRange() const; + SourceRange getSourceRange() const override; /// \brief Returns the value of the receiver at the time of this call. SVal getReceiverSVal() const; @@ -883,15 +870,16 @@ public: llvm_unreachable("Unknown message kind"); } - virtual RuntimeDefinition getRuntimeDefinition() const; + RuntimeDefinition getRuntimeDefinition() const override; - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const; + bool argumentsMayEscape() const override; + + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; - virtual param_iterator param_begin() const; - virtual param_iterator param_end() const; + ArrayRef<ParmVarDecl*> parameters() const override; - virtual Kind getKind() const { return CE_ObjCMessage; } + Kind getKind() const override { return CE_ObjCMessage; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_ObjCMessage; @@ -911,6 +899,7 @@ class CallEventManager { llvm::BumpPtrAllocator &Alloc; SmallVector<void *, 8> Cache; + typedef SimpleFunctionCall CallEventTemplateTy; void reclaim(const void *Memory) { Cache.push_back(const_cast<void *>(Memory)); @@ -919,24 +908,30 @@ class CallEventManager { /// Returns memory that can be initialized as a CallEvent. void *allocate() { if (Cache.empty()) - return Alloc.Allocate<FunctionCall>(); + return Alloc.Allocate<CallEventTemplateTy>(); else return Cache.pop_back_val(); } template <typename T, typename Arg> T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { + static_assert(sizeof(T) == sizeof(CallEventTemplateTy), + "CallEvent subclasses are not all the same size"); 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) { + static_assert(sizeof(T) == sizeof(CallEventTemplateTy), + "CallEvent subclasses are not all the same size"); 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) { + static_assert(sizeof(T) == sizeof(CallEventTemplateTy), + "CallEvent subclasses are not all the same size"); return new (allocate()) T(A1, A2, A3, St, LCtx); } @@ -944,6 +939,8 @@ class CallEventManager { typename Arg4> T *create(Arg1 A1, Arg2 A2, Arg3 A3, Arg4 A4, ProgramStateRef St, const LocationContext *LCtx) { + static_assert(sizeof(T) == sizeof(CallEventTemplateTy), + "CallEvent subclasses are not all the same size"); return new (allocate()) T(A1, A2, A3, A4, St, LCtx); } @@ -989,7 +986,8 @@ public: 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"); + static_assert(sizeof(T) == sizeof(CallEvent), + "Subclasses may not add fields"); if (NewState == State) return cast<T>(this); @@ -1026,7 +1024,7 @@ namespace llvm { static SimpleType getSimplifiedValue(clang::ento::CallEventRef<T> Val) { - return Val.getPtr(); + return Val.get(); } }; } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 0b9762a..5a33bdf 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -174,8 +174,13 @@ public: return Pred->getLocationContext()->getAnalysisDeclContext(); } - /// \brief If the given node corresponds to a PostStore program point, retrieve - /// the location region as it was uttered in the code. + /// \brief Get the blockID. + unsigned getBlockID() const { + return NB.getContext().getBlock()->getBlockID(); + } + + /// \brief If the given node corresponds to a PostStore program point, + /// retrieve the location region as it was uttered in the code. /// /// This utility can be useful for generating extensive diagnostics, for /// example, for finding variables that the given symbol was assigned to. @@ -183,7 +188,7 @@ public: ProgramPoint L = N->getLocation(); if (Optional<PostStore> PSL = L.getAs<PostStore>()) return reinterpret_cast<const MemRegion*>(PSL->getLocationValue()); - return 0; + return nullptr; } /// \brief Get the value of arbitrary expressions at this point in the path. @@ -200,9 +205,9 @@ public: /// tag is specified, a default tag, unique to the given checker, /// will be used. Tags are used to prevent states generated at /// different sites from caching out. - ExplodedNode *addTransition(ProgramStateRef State = 0, - const ProgramPointTag *Tag = 0) { - return addTransitionImpl(State ? State : getState(), false, 0, Tag); + ExplodedNode *addTransition(ProgramStateRef State = nullptr, + const ProgramPointTag *Tag = nullptr) { + return addTransitionImpl(State ? State : getState(), false, nullptr, Tag); } /// \brief Generates a new transition with the given predecessor. @@ -214,15 +219,15 @@ public: /// @param Tag The tag to uniquely identify the creation site. ExplodedNode *addTransition(ProgramStateRef State, ExplodedNode *Pred, - const ProgramPointTag *Tag = 0) { + const ProgramPointTag *Tag = nullptr) { return addTransitionImpl(State, false, Pred, Tag); } /// \brief Generate a sink node. Generating a sink stops exploration of the /// given path. - ExplodedNode *generateSink(ProgramStateRef State = 0, - ExplodedNode *Pred = 0, - const ProgramPointTag *Tag = 0) { + ExplodedNode *generateSink(ProgramStateRef State = nullptr, + ExplodedNode *Pred = nullptr, + const ProgramPointTag *Tag = nullptr) { return addTransitionImpl(State ? State : getState(), true, Pred, Tag); } @@ -244,7 +249,7 @@ public: if (FunDecl) return FunDecl->getIdentifier(); else - return 0; + return nullptr; } /// \brief Get the name of the called function (path-sensitive). @@ -280,8 +285,8 @@ public: private: ExplodedNode *addTransitionImpl(ProgramStateRef State, bool MarkAsSink, - ExplodedNode *P = 0, - const ProgramPointTag *Tag = 0) { + ExplodedNode *P = nullptr, + const ProgramPointTag *Tag = nullptr) { if (!State || (State == Pred->getState() && !Tag && !MarkAsSink)) return Pred; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index 1e76ea6..51bb89b 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -85,7 +85,7 @@ public: // does not. Is there a good equivalent there? assert(assume(State, Cond, false) && "System is over constrained."); #endif - return ProgramStatePair((ProgramStateRef)NULL, State); + return ProgramStatePair((ProgramStateRef)nullptr, State); } ProgramStateRef StFalse = assume(State, Cond, false); @@ -93,7 +93,7 @@ public: // We are careful to return the original state, /not/ StTrue, // because we want to avoid having callers generate a new node // in the ExplodedGraph. - return ProgramStatePair(State, (ProgramStateRef)NULL); + return ProgramStatePair(State, (ProgramStateRef)nullptr); } return ProgramStatePair(StTrue, StFalse); @@ -106,7 +106,7 @@ public: /// value for a symbol, even if it is perfectly constrained. virtual const llvm::APSInt* getSymVal(ProgramStateRef state, SymbolRef sym) const { - return 0; + return nullptr; } virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index a2e211e..76ace6d 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -21,7 +21,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" -#include "llvm/ADT/OwningPtr.h" +#include <memory> namespace clang { @@ -60,12 +60,12 @@ private: SubEngine& SubEng; /// G - The simulation graph. Each node is a (location,state) pair. - OwningPtr<ExplodedGraph> G; + std::unique_ptr<ExplodedGraph> G; /// 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. - OwningPtr<WorkList> WList; + std::unique_ptr<WorkList> WList; /// BCounterFactory - A factory object for created BlockCounter objects. /// These are used to record for key nodes in the ExplodedGraph the @@ -120,7 +120,7 @@ public: /// takeGraph - Returns the exploded graph. Ownership of the graph is /// transferred to the caller. - ExplodedGraph* takeGraph() { return G.take(); } + ExplodedGraph *takeGraph() { return G.release(); } /// ExecuteWorkList - Run the worklist algorithm for a maximum number of /// steps. Returns true if there is still simulation state on the worklist. @@ -312,7 +312,7 @@ public: /// \class NodeBuilderWithSinks /// \brief This node builder keeps track of the generated sink nodes. class NodeBuilderWithSinks: public NodeBuilder { - virtual void anchor(); + void anchor() override; protected: SmallVector<ExplodedNode*, 2> sinksGenerated; ProgramPoint &Location; @@ -324,13 +324,13 @@ public: ExplodedNode *generateNode(ProgramStateRef State, ExplodedNode *Pred, - const ProgramPointTag *Tag = 0) { + const ProgramPointTag *Tag = nullptr) { const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location); return NodeBuilder::generateNode(LocalLoc, State, Pred); } ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred, - const ProgramPointTag *Tag = 0) { + const ProgramPointTag *Tag = nullptr) { const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location); ExplodedNode *N = NodeBuilder::generateSink(LocalLoc, State, Pred); if (N && N->isSink()) @@ -355,14 +355,16 @@ public: /// nodes currently owned by another builder(with larger scope), use /// Enclosing builder to transfer ownership. StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, - const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = 0) + const NodeBuilderContext &Ctx, + NodeBuilder *Enclosing = nullptr) : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) { if (EnclosingBldr) EnclosingBldr->takeNodes(SrcNode); } StmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, - const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = 0) + const NodeBuilderContext &Ctx, + NodeBuilder *Enclosing = nullptr) : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) { if (EnclosingBldr) for (ExplodedNodeSet::iterator I = SrcSet.begin(), @@ -378,7 +380,7 @@ public: ExplodedNode *generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, - const ProgramPointTag *tag = 0, + const ProgramPointTag *tag = nullptr, ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, Pred->getLocationContext(), tag); @@ -388,7 +390,7 @@ public: ExplodedNode *generateSink(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, - const ProgramPointTag *tag = 0, + const ProgramPointTag *tag = nullptr, ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, Pred->getLocationContext(), tag); @@ -399,7 +401,7 @@ public: /// \brief BranchNodeBuilder is responsible for constructing the nodes /// corresponding to the two branches of the if statement - true and false. class BranchNodeBuilder: public NodeBuilder { - virtual void anchor(); + void anchor() override; const CFGBlock *DstT; const CFGBlock *DstF; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index bf17cd8..98092ef 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -27,11 +27,11 @@ #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include <memory> #include <vector> namespace clang { @@ -164,7 +164,7 @@ public: const ProgramStateRef &state, bool IsSink) { ID.Add(Loc); - ID.AddPointer(state.getPtr()); + ID.AddPointer(state.get()); ID.AddBoolean(IsSink); } @@ -189,7 +189,7 @@ public: } ExplodedNode *getFirstPred() { - return pred_empty() ? NULL : *(pred_begin()); + return pred_empty() ? nullptr : *(pred_begin()); } const ExplodedNode *getFirstPred() const { @@ -197,7 +197,7 @@ public: } const ExplodedNode *getFirstSucc() const { - return succ_empty() ? NULL : *(succ_begin()); + return succ_empty() ? nullptr : *(succ_begin()); } // Iterators over successor and predecessor vertices. @@ -295,7 +295,7 @@ public: /// the node was freshly created. ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink = false, - bool* IsNew = 0); + bool* IsNew = nullptr); ExplodedGraph* MakeEmptyGraph() const { return new ExplodedGraph(); @@ -373,8 +373,8 @@ public: /// nodes in this graph. /// \returns The trimmed graph ExplodedGraph *trim(ArrayRef<const NodeTy *> Nodes, - InterExplodedGraphMap *ForwardMap = 0, - InterExplodedGraphMap *InverseMap = 0) const; + InterExplodedGraphMap *ForwardMap = nullptr, + InterExplodedGraphMap *InverseMap = nullptr) const; /// Enable tracking of recently allocated nodes for potential reclamation /// when calling reclaimRecentlyAllocatedNodes(). diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index d89dffe..0fb4a24 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -43,7 +43,6 @@ namespace ento { class AnalysisManager; class CallEvent; -class SimpleCall; class CXXConstructorCall; class ExprEngine : public SubEngine { @@ -107,7 +106,7 @@ public: /// Returns true if there is still simulation state on the worklist. bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { - return Engine.ExecuteWorkList(L, Steps, 0); + return Engine.ExecuteWorkList(L, Steps, nullptr); } /// Execute the work list with an initial state. Nodes that reaches the exit @@ -123,7 +122,7 @@ public: /// getContext - Return the ASTContext associated with this analysis. ASTContext &getContext() const { return AMgr.getASTContext(); } - virtual AnalysisManager &getAnalysisManager() { return AMgr; } + AnalysisManager &getAnalysisManager() override { return AMgr; } CheckerManager &getCheckerManager() const { return *AMgr.getCheckerManager(); @@ -155,7 +154,7 @@ public: /// getInitialState - Return the initial state used for the root vertex /// in the ExplodedGraph. - ProgramStateRef getInitialState(const LocationContext *InitLoc); + ProgramStateRef getInitialState(const LocationContext *InitLoc) override; ExplodedGraph& getGraph() { return G; } const ExplodedGraph& getGraph() const { return G; } @@ -187,13 +186,13 @@ public: /// and \p ReferenceStmt must be valid (non-null). void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const LocationContext *LC, - const Stmt *DiagnosticStmt = 0, + const Stmt *DiagnosticStmt = nullptr, 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, - unsigned StmtIdx, NodeBuilderContext *Ctx); + unsigned StmtIdx, NodeBuilderContext *Ctx) override; void ProcessStmt(const CFGStmt S, ExplodedNode *Pred); @@ -201,7 +200,9 @@ public: void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred); - void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, + void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred); + + void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst); void ProcessDeleteDtor(const CFGDeleteDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -213,10 +214,10 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst); /// Called by CoreEngine when processing the entrance of a CFGBlock. - virtual void processCFGBlockEntrance(const BlockEdge &L, - NodeBuilderWithSinks &nodeBuilder, - ExplodedNode *Pred); - + void processCFGBlockEntrance(const BlockEdge &L, + NodeBuilderWithSinks &nodeBuilder, + ExplodedNode *Pred) override; + /// ProcessBranch - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. void processBranch(const Stmt *Condition, const Stmt *Term, @@ -224,7 +225,7 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, - const CFGBlock *DstF); + const CFGBlock *DstF) override; /// Called by CoreEngine. Used to processing branching behavior /// at static initalizers. @@ -233,20 +234,20 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, - const CFGBlock *DstF); + const CFGBlock *DstF) override; /// processIndirectGoto - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a computed goto jump. - void processIndirectGoto(IndirectGotoNodeBuilder& builder); + void processIndirectGoto(IndirectGotoNodeBuilder& builder) override; /// ProcessSwitch - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a switch statement. - void processSwitch(SwitchNodeBuilder& builder); + void processSwitch(SwitchNodeBuilder& builder) override; /// Called by CoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. void processEndOfFunction(NodeBuilderContext& BC, - ExplodedNode *Pred); + ExplodedNode *Pred) override; /// Remove dead bindings/symbols before exiting a function. void removeDeadOnEndOfFunction(NodeBuilderContext& BC, @@ -254,22 +255,23 @@ public: ExplodedNodeSet &Dst); /// Generate the entry node of the callee. - void processCallEnter(CallEnter CE, ExplodedNode *Pred); + void processCallEnter(CallEnter CE, ExplodedNode *Pred) override; /// Generate the sequence of nodes that simulate the call exit and the post /// visit for CallExpr. - void processCallExit(ExplodedNode *Pred); + void processCallExit(ExplodedNode *Pred) override; /// Called by CoreEngine when the analysis worklist has terminated. - void processEndWorklist(bool hasWorkRemaining); + void processEndWorklist(bool hasWorkRemaining) override; /// evalAssume - Callback function invoked by the ConstraintManager when /// making assumptions about state values. - ProgramStateRef processAssume(ProgramStateRef state, SVal cond,bool assumption); + ProgramStateRef processAssume(ProgramStateRef state, SVal cond, + bool assumption) override; /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a /// region change should trigger a processRegionChanges update. - bool wantsRegionChangeUpdate(ProgramStateRef state); + bool wantsRegionChangeUpdate(ProgramStateRef state) override; /// processRegionChanges - Called by ProgramStateManager whenever a change is made /// to the store. Used to update checkers that track region values. @@ -278,13 +280,13 @@ public: const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, - const CallEvent *Call); + const CallEvent *Call) override; /// printState - Called by ProgramStateManager to print checker-specific data. void printState(raw_ostream &Out, ProgramStateRef State, - const char *NL, const char *Sep); + const char *NL, const char *Sep) override; - virtual ProgramStateManager& getStateManager() { return StateMgr; } + ProgramStateManager& getStateManager() override { return StateMgr; } StoreManager& getStoreManager() { return StateMgr.getStoreManager(); } @@ -420,6 +422,10 @@ public: const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst); + void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, + ExplodedNode *Pred, + ExplodedNodeSet &Dst); + void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -471,21 +477,21 @@ protected: /// This method is used by evalStore, VisitDeclStmt, and others. void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred, SVal location, SVal Val, bool atDeclInit = false, - const ProgramPoint *PP = 0); + const ProgramPoint *PP = nullptr); /// Call PointerEscape callback when a value escapes as a result of bind. ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, - SVal Loc, SVal Val); + SVal Loc, SVal Val) override; /// Call PointerEscape callback when a value escapes as a result of /// region invalidation. /// \param[in] ITraits Specifies invalidation traits for regions/symbols. ProgramStateRef notifyCheckersOfPointerEscape( - ProgramStateRef State, - const InvalidatedSymbols *Invalidated, - ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions, - const CallEvent *Call, - RegionAndSymbolInvalidationTraits &ITraits); + ProgramStateRef State, + const InvalidatedSymbols *Invalidated, + ArrayRef<const MemRegion *> ExplicitRegions, + ArrayRef<const MemRegion *> Regions, + const CallEvent *Call, + RegionAndSymbolInvalidationTraits &ITraits) override; public: // FIXME: 'tag' should be removed, and a LocationContext should be used @@ -500,14 +506,14 @@ public: ExplodedNode *Pred, ProgramStateRef St, SVal location, - const ProgramPointTag *tag = 0, + const ProgramPointTag *tag = nullptr, QualType LoadTy = QualType()); // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, - const ProgramPointTag *tag = 0); + const ProgramPointTag *tag = nullptr); /// \brief Create a new state in which the call return value is binded to the /// call origin expression. @@ -580,7 +586,7 @@ private: ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State, const LocationContext *LC, const Expr *E, - const Expr *ResultE = 0); + const Expr *ResultE = nullptr); }; /// Traits for storing the call processing policy inside GDM. diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index cc790c1..92b082d 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -23,13 +23,10 @@ #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/ErrorHandling.h" #include <string> -namespace llvm { -class BumpPtrAllocator; -} - namespace clang { class LocationContext; @@ -57,7 +54,7 @@ public: // Visual Studio will only create enumerations of size int, not long long. static const int64_t Symbolic = INT64_MAX; - RegionOffset() : R(0) {} + RegionOffset() : R(nullptr) {} RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {} const MemRegion *getRegion() const { return R; } @@ -204,12 +201,12 @@ protected: assert(classof(this)); } - MemRegionManager* getMemRegionManager() const { return Mgr; } + MemRegionManager* getMemRegionManager() const override { return Mgr; } public: - bool isBoundable() const { return false; } - - void Profile(llvm::FoldingSetNodeID &ID) const; + bool isBoundable() const override { return false; } + + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const MemRegion *R) { Kind k = R->getKind(); @@ -243,9 +240,9 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion { : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {} public: - void Profile(llvm::FoldingSetNodeID &ID) const; - - void dumpToStream(raw_ostream &os) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; + + void dumpToStream(raw_ostream &os) const override; const CodeTextRegion *getCodeRegion() const { return CR; } @@ -286,7 +283,7 @@ class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion { public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == GlobalSystemSpaceRegionKind; @@ -306,7 +303,7 @@ class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion { public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == GlobalImmutableSpaceRegionKind; @@ -324,7 +321,7 @@ class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion { public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == GlobalInternalSpaceRegionKind; @@ -339,7 +336,7 @@ class HeapSpaceRegion : public MemSpaceRegion { : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == HeapSpaceRegionKind; @@ -353,7 +350,7 @@ class UnknownSpaceRegion : public MemSpaceRegion { : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == UnknownSpaceRegionKind; @@ -373,7 +370,7 @@ protected: public: const StackFrameContext *getStackFrame() const { return SFC; } - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const MemRegion *R) { Kind k = R->getKind(); @@ -389,7 +386,7 @@ class StackLocalsSpaceRegion : public StackSpaceRegion { : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == StackLocalsSpaceRegionKind; @@ -404,7 +401,7 @@ private: : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == StackArgumentsSpaceRegionKind; @@ -430,9 +427,9 @@ public: return UnknownVal(); } - MemRegionManager* getMemRegionManager() const; + MemRegionManager* getMemRegionManager() const override; - virtual bool isSubRegionOf(const MemRegion* R) const; + bool isSubRegionOf(const MemRegion* R) const override; static bool classof(const MemRegion* R) { return R->getKind() > END_MEMSPACES; @@ -459,16 +456,16 @@ public: const Expr *getExpr() const { return Ex; } - bool isBoundable() const { return true; } + bool isBoundable() const override { return true; } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex, unsigned Cnt, const MemRegion *superRegion); - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == AllocaRegionKind; @@ -478,7 +475,7 @@ public: /// TypedRegion - An abstract class representing regions that are typed. class TypedRegion : public SubRegion { public: - virtual void anchor(); + void anchor() override; protected: TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {} @@ -489,7 +486,7 @@ public: return getLocationType().getDesugaredType(Context); } - bool isBoundable() const { return true; } + bool isBoundable() const override { return true; } static bool classof(const MemRegion* R) { unsigned k = R->getKind(); @@ -500,14 +497,14 @@ public: /// TypedValueRegion - An abstract class representing regions having a typed value. class TypedValueRegion : public TypedRegion { public: - virtual void anchor(); + void anchor() override; protected: TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {} public: virtual QualType getValueType() const = 0; - virtual QualType getLocationType() const { + QualType getLocationType() const override { // FIXME: We can possibly optimize this later to cache this value. QualType T = getValueType(); ASTContext &ctx = getContext(); @@ -521,7 +518,7 @@ public: return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T; } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; static bool classof(const MemRegion* R) { unsigned k = R->getKind(); @@ -532,12 +529,12 @@ public: class CodeTextRegion : public TypedRegion { public: - virtual void anchor(); + void anchor() override; protected: CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} public: - bool isBoundable() const { return false; } - + bool isBoundable() const override { return false; } + static bool classof(const MemRegion* R) { Kind k = R->getKind(); return k >= FunctionTextRegionKind && k <= BlockTextRegionKind; @@ -552,8 +549,8 @@ public: : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) { assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd)); } - - QualType getLocationType() const { + + QualType getLocationType() const override { const ASTContext &Ctx = getContext(); if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) { return Ctx.getPointerType(D->getType()); @@ -570,11 +567,11 @@ public: const NamedDecl *getDecl() const { return FD; } - - virtual void dumpToStream(raw_ostream &os) const; - - void Profile(llvm::FoldingSetNodeID& ID) const; - + + void dumpToStream(raw_ostream &os) const override; + + void Profile(llvm::FoldingSetNodeID& ID) const override; + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD, const MemRegion*); @@ -602,7 +599,7 @@ class BlockTextRegion : public CodeTextRegion { : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} public: - QualType getLocationType() const { + QualType getLocationType() const override { return locTy; } @@ -611,11 +608,11 @@ public: } AnalysisDeclContext *getAnalysisDeclContext() const { return AC; } - - virtual void dumpToStream(raw_ostream &os) const; - - void Profile(llvm::FoldingSetNodeID& ID) const; - + + virtual void dumpToStream(raw_ostream &os) const override; + + void Profile(llvm::FoldingSetNodeID& ID) const override; + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, CanQualType, const AnalysisDeclContext*, const MemRegion*); @@ -643,15 +640,15 @@ class BlockDataRegion : public TypedRegion { unsigned count, const MemRegion *sreg) : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), BlockCount(count), - ReferencedVars(0), OriginalVars(0) {} + ReferencedVars(nullptr), OriginalVars(nullptr) {} public: const BlockTextRegion *getCodeRegion() const { return BC; } const BlockDecl *getDecl() const { return BC->getDecl(); } - QualType getLocationType() const { return BC->getLocationType(); } - + QualType getLocationType() const override { return BC->getLocationType(); } + class referenced_vars_iterator { const MemRegion * const *R; const MemRegion * const *OriginalR; @@ -668,11 +665,11 @@ public: } bool operator==(const referenced_vars_iterator &I) const { - assert((R == 0) == (I.R == 0)); + assert((R == nullptr) == (I.R == nullptr)); return I.R == R; } bool operator!=(const referenced_vars_iterator &I) const { - assert((R == 0) == (I.R == 0)); + assert((R == nullptr) == (I.R == nullptr)); return I.R != R; } referenced_vars_iterator &operator++() { @@ -688,11 +685,11 @@ public: referenced_vars_iterator referenced_vars_begin() const; referenced_vars_iterator referenced_vars_end() const; - - virtual void dumpToStream(raw_ostream &os) const; - - void Profile(llvm::FoldingSetNodeID& ID) const; - + + void dumpToStream(raw_ostream &os) const override; + + void Profile(llvm::FoldingSetNodeID& ID) const override; + static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *, const LocationContext *, unsigned, const MemRegion *); @@ -723,17 +720,17 @@ public: return sym; } - bool isBoundable() const { return true; } + bool isBoundable() const override { return true; } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; static void ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, const MemRegion* superRegion); - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == SymbolicRegionKind; @@ -757,19 +754,19 @@ public: const StringLiteral* getStringLiteral() const { return Str; } - QualType getValueType() const { + QualType getValueType() const override { return Str->getType(); } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; - bool isBoundable() const { return false; } + bool isBoundable() const override { return false; } - void Profile(llvm::FoldingSetNodeID& ID) const { + void Profile(llvm::FoldingSetNodeID& ID) const override { ProfileRegion(ID, Str, superRegion); } - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == StringRegionKind; @@ -792,19 +789,19 @@ protected: public: const ObjCStringLiteral* getObjCStringLiteral() const { return Str; } - - QualType getValueType() const { + + QualType getValueType() const override { return Str->getType(); } - - bool isBoundable() const { return false; } - - void Profile(llvm::FoldingSetNodeID& ID) const { + + bool isBoundable() const override { return false; } + + void Profile(llvm::FoldingSetNodeID& ID) const override { ProfileRegion(ID, Str, superRegion); } - - void dumpToStream(raw_ostream &os) const; - + + void dumpToStream(raw_ostream &os) const override; + static bool classof(const MemRegion* R) { return R->getKind() == ObjCStringRegionKind; } @@ -825,15 +822,15 @@ private: const CompoundLiteralExpr *CL, const MemRegion* superRegion); public: - QualType getValueType() const { + QualType getValueType() const override { return CL->getType(); } - bool isBoundable() const { return !CL->isFileScope(); } + bool isBoundable() const override { return !CL->isFileScope(); } - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; const CompoundLiteralExpr *getLiteralExpr() const { return CL; } @@ -854,7 +851,7 @@ protected: public: const Decl *getDecl() const { return D; } - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; static bool classof(const MemRegion* R) { unsigned k = R->getKind(); @@ -874,27 +871,27 @@ class VarRegion : public DeclRegion { DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); } - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; public: const VarDecl *getDecl() const { return cast<VarDecl>(D); } const StackFrameContext *getStackFrame() const; - - QualType getValueType() const { + + QualType getValueType() const override { // FIXME: We can cache this if needed. return getDecl()->getType(); } - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == VarRegionKind; } - bool canPrintPrettyAsExpr() const; + bool canPrintPrettyAsExpr() const override; - void printPrettyAsExpr(raw_ostream &os) const; + void printPrettyAsExpr(raw_ostream &os) const override; }; /// CXXThisRegion - Represents the region for the implicit 'this' parameter @@ -910,15 +907,15 @@ class CXXThisRegion : public TypedValueRegion { const PointerType *PT, const MemRegion *sReg); - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; -public: - QualType getValueType() const { +public: + QualType getValueType() const override { return QualType(ThisPointerTy, 0); } - void dumpToStream(raw_ostream &os) const; - + void dumpToStream(raw_ostream &os) const override; + static bool classof(const MemRegion* R) { return R->getKind() == CXXThisRegionKind; } @@ -936,12 +933,12 @@ class FieldRegion : public DeclRegion { public: const FieldDecl *getDecl() const { return cast<FieldDecl>(D); } - QualType getValueType() const { + QualType getValueType() const override { // FIXME: We can cache this if needed. return getDecl()->getType(); } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD, const MemRegion* superRegion) { @@ -952,12 +949,12 @@ public: return R->getKind() == FieldRegionKind; } - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - bool canPrintPretty() const; - void printPretty(raw_ostream &os) const; - bool canPrintPrettyAsExpr() const; - void printPrettyAsExpr(raw_ostream &os) const; + bool canPrintPretty() const override; + void printPretty(raw_ostream &os) const override; + bool canPrintPrettyAsExpr() const override; + void printPrettyAsExpr(raw_ostream &os) const override; }; class ObjCIvarRegion : public DeclRegion { @@ -971,12 +968,12 @@ class ObjCIvarRegion : public DeclRegion { public: const ObjCIvarDecl *getDecl() const; - QualType getValueType() const; + QualType getValueType() const override; - bool canPrintPrettyAsExpr() const; - void printPrettyAsExpr(raw_ostream &os) const; + bool canPrintPrettyAsExpr() const override; + void printPrettyAsExpr(raw_ostream &os) const override; - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == ObjCIvarRegionKind; @@ -1029,7 +1026,7 @@ public: NonLoc getIndex() const { return Index; } - QualType getValueType() const { + QualType getValueType() const override { return ElementType; } @@ -1039,9 +1036,9 @@ public: /// Compute the offset within the array. The array might also be a subobject. RegionRawOffset getAsArrayOffset() const; - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; static bool classof(const MemRegion* R) { return R->getKind() == ElementRegionKind; @@ -1063,13 +1060,13 @@ class CXXTempObjectRegion : public TypedValueRegion { public: const Expr *getExpr() const { return Ex; } - QualType getValueType() const { + QualType getValueType() const override { return Ex->getType(); } - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const MemRegion* R) { return R->getKind() == CXXTempObjectRegionKind; @@ -1094,19 +1091,19 @@ public: const CXXRecordDecl *getDecl() const { return Data.getPointer(); } bool isVirtual() const { return Data.getInt(); } - QualType getValueType() const; + QualType getValueType() const override; - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const MemRegion *region) { return region->getKind() == CXXBaseObjectRegionKind; } - bool canPrintPrettyAsExpr() const; - - void printPrettyAsExpr(raw_ostream &os) const; + bool canPrintPrettyAsExpr() const override; + + void printPrettyAsExpr(raw_ostream &os) const override; }; template<typename RegionTy> @@ -1114,7 +1111,7 @@ const RegionTy* MemRegion::getAs() const { if (const RegionTy* RT = dyn_cast<RegionTy>(this)) return RT; - return NULL; + return nullptr; } //===----------------------------------------------------------------------===// @@ -1143,9 +1140,10 @@ class MemRegionManager { MemSpaceRegion *code; public: - MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) - : C(c), A(a), InternalGlobals(0), SystemGlobals(0), ImmutableGlobals(0), - heap(0), unknown(0), code(0) {} + MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) + : C(c), A(a), InternalGlobals(nullptr), SystemGlobals(nullptr), + ImmutableGlobals(nullptr), heap(nullptr), unknown(nullptr), + code(nullptr) {} ~MemRegionManager(); @@ -1167,7 +1165,7 @@ public: /// global variables. const GlobalsSpaceRegion *getGlobalsRegion( MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind, - const CodeTextRegion *R = 0); + const CodeTextRegion *R = nullptr); /// getHeapRegion - Retrieve the memory region associated with the /// generic "heap". diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 03739ed..4902ef5 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -25,10 +25,10 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Allocator.h" namespace llvm { class APSInt; -class BumpPtrAllocator; } namespace clang { @@ -237,16 +237,16 @@ public: ProgramStateRef invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E, unsigned BlockCount, const LocationContext *LCtx, - bool CausesPointerEscape, InvalidatedSymbols *IS = 0, - const CallEvent *Call = 0, - RegionAndSymbolInvalidationTraits *ITraits = 0) const; + bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, + const CallEvent *Call = nullptr, + RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; ProgramStateRef invalidateRegions(ArrayRef<SVal> Regions, const Expr *E, unsigned BlockCount, const LocationContext *LCtx, - bool CausesPointerEscape, InvalidatedSymbols *IS = 0, - const CallEvent *Call = 0, - RegionAndSymbolInvalidationTraits *ITraits = 0) const; + bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, + const CallEvent *Call = nullptr, + RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; /// enterStackFrame - Returns the state for entry to the given stack frame, /// preserving the current state. @@ -441,8 +441,8 @@ private: SubEngine *Eng; /* Can be null. */ EnvironmentManager EnvMgr; - OwningPtr<StoreManager> StoreMgr; - OwningPtr<ConstraintManager> ConstraintMgr; + std::unique_ptr<StoreManager> StoreMgr; + std::unique_ptr<ConstraintManager> ConstraintMgr; ProgramState::GenericDataMap::Factory GDMFactory; @@ -454,10 +454,10 @@ private: llvm::FoldingSet<ProgramState> StateSet; /// Object that manages the data for all created SVals. - OwningPtr<SValBuilder> svalBuilder; + std::unique_ptr<SValBuilder> svalBuilder; /// Manages memory for created CallEvents. - OwningPtr<CallEventManager> CallEventMgr; + std::unique_ptr<CallEventManager> CallEventMgr; /// A BumpPtrAllocator to allocate states. llvm::BumpPtrAllocator &Alloc; @@ -676,10 +676,8 @@ inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const { 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); + for (const auto *I : D->chain()) { + Base = SM.getLValueField(cast<FieldDecl>(I), Base); } return Base; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index eb52ae4..823bde7 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -18,10 +18,10 @@ #ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H #define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H +#include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" namespace llvm { - class BumpPtrAllocator; template <typename K, typename D, typename I> class ImmutableMap; template <typename K, typename I> class ImmutableSet; template <typename T> class ImmutableList; @@ -64,7 +64,8 @@ namespace ento { typedef const value_type* lookup_type; static inline data_type MakeData(void *const* p) { - return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); + return p ? data_type((typename data_type::TreeTy*) *p) + : data_type(nullptr); } static inline void *MakeVoidPtr(data_type B) { return B.getRoot(); @@ -112,7 +113,8 @@ namespace ento { typedef Key key_type; static inline data_type MakeData(void *const* p) { - return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); + return p ? data_type((typename data_type::TreeTy*) *p) + : data_type(nullptr); } static inline void *MakeVoidPtr(data_type B) { @@ -163,7 +165,7 @@ namespace ento { static inline data_type MakeData(void *const* p) { return p ? data_type((const llvm::ImmutableListImpl<T>*) *p) - : data_type(0); + : data_type(nullptr); } static inline void *MakeVoidPtr(data_type D) { diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index c5d0a92..29fb413 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -88,7 +88,7 @@ public: virtual SVal evalComplement(NonLoc val) = 0; - /// Create a new value which represents a binary expression with two non + /// Create a new value which represents a binary expression with two non- /// location operands. virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy) = 0; @@ -99,7 +99,7 @@ public: Loc lhs, Loc rhs, QualType resultTy) = 0; /// Create a new value which represents a binary expression with a memory - /// location and non location operands. For example, this would be used to + /// location and non-location operands. For example, this would be used to /// evaluate a pointer arithmetic operation. virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy) = 0; @@ -146,14 +146,14 @@ public: const LocationContext *LCtx, QualType type, unsigned visitCount, - const void *symbolTag = 0) { + const void *symbolTag = nullptr) { return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag); } const SymbolConjured* conjureSymbol(const Expr *expr, const LocationContext *LCtx, unsigned visitCount, - const void *symbolTag = 0) { + const void *symbolTag = nullptr) { return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag); } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 5a426ef..d50c3be 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -63,11 +63,11 @@ protected: explicit SVal(const void *d, bool isLoc, unsigned ValKind) : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {} - explicit SVal(BaseKind k, const void *D = NULL) + explicit SVal(BaseKind k, const void *D = nullptr) : Data(D), Kind(k) {} public: - explicit SVal() : Data(0), Kind(0) {} + explicit SVal() : Data(nullptr), Kind(0) {} /// \brief Convert to the specified SVal type, asserting that this SVal is of /// the desired type. @@ -211,7 +211,7 @@ protected: explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind) : SVal(d, isLoc, ValKind) {} - explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL) + explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {} private: diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 530dae5..84c3166 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -220,10 +220,11 @@ public: bool First; public: - FindUniqueBinding(SymbolRef sym) : Sym(sym), Binding(0), First(true) {} + FindUniqueBinding(SymbolRef sym) + : Sym(sym), Binding(nullptr), First(true) {} bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, - SVal val); + SVal val) override; LLVM_EXPLICIT operator bool() { return First && Binding; } const MemRegion *getRegion() { return Binding; } }; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index f653c70..3482e8d 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -122,7 +122,7 @@ public: inline ProgramStateRef processRegionChange(ProgramStateRef state, const MemRegion* MR) { - return processRegionChanges(state, 0, MR, MR, 0); + return processRegionChanges(state, nullptr, MR, MR, nullptr); } virtual ProgramStateRef diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 914b2be..2b5cc18 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -23,12 +23,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" -namespace llvm { -class BumpPtrAllocator; -} - namespace clang { class ASTContext; class StackFrameContext; @@ -105,7 +102,7 @@ typedef unsigned SymbolID; /// \brief A symbol representing data which can be stored in a memory location /// (region). class SymbolData : public SymExpr { - virtual void anchor(); + void anchor() override; const SymbolID Sym; protected: @@ -138,13 +135,13 @@ public: profile.AddPointer(R); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, R); } - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - QualType getType() const; + QualType getType() const override; // Implement isa<T> support. static inline bool classof(const SymExpr *SE) { @@ -173,9 +170,9 @@ public: unsigned getCount() const { return Count; } const void *getTag() const { return SymbolTag; } - QualType getType() const; + QualType getType() const override; - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S, QualType T, unsigned Count, const LocationContext *LCtx, @@ -188,7 +185,7 @@ public: profile.AddPointer(SymbolTag); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, S, T, Count, LCtx, SymbolTag); } @@ -211,9 +208,9 @@ public: SymbolRef getParentSymbol() const { return parentSymbol; } const TypedValueRegion *getRegion() const { return R; } - QualType getType() const; + QualType getType() const override; - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent, const TypedValueRegion *r) { @@ -222,7 +219,7 @@ public: profile.AddPointer(parent); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, parentSymbol, R); } @@ -244,16 +241,16 @@ public: const SubRegion *getRegion() const { return R; } - QualType getType() const; + QualType getType() const override; - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) { profile.AddInteger((unsigned) ExtentKind); profile.AddPointer(R); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, R); } @@ -283,9 +280,9 @@ public: unsigned getCount() const { return Count; } const void *getTag() const { return Tag; } - QualType getType() const; + QualType getType() const override; - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R, const Stmt *S, QualType T, unsigned Count, @@ -298,7 +295,7 @@ public: profile.AddPointer(Tag); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, R, S, T, Count, Tag); } @@ -320,11 +317,11 @@ public: SymbolCast(const SymExpr *In, QualType From, QualType To) : SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { } - QualType getType() const { return ToTy; } + QualType getType() const override { return ToTy; } const SymExpr *getOperand() const { return Operand; } - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *In, QualType From, QualType To) { @@ -334,7 +331,7 @@ public: ID.Add(To); } - void Profile(llvm::FoldingSetNodeID& ID) { + void Profile(llvm::FoldingSetNodeID& ID) override { Profile(ID, Operand, FromTy, ToTy); } @@ -356,7 +353,7 @@ protected: public: // FIXME: We probably need to make this out-of-line to avoid redundant // generation of virtual functions. - QualType getType() const { return T; } + QualType getType() const override { return T; } BinaryOperator::Opcode getOpcode() const { return Op; } @@ -377,7 +374,7 @@ public: const llvm::APSInt& rhs, QualType t) : BinarySymExpr(SymIntKind, op, t), LHS(lhs), RHS(rhs) {} - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; const SymExpr *getLHS() const { return LHS; } const llvm::APSInt &getRHS() const { return RHS; } @@ -392,7 +389,7 @@ public: ID.Add(t); } - void Profile(llvm::FoldingSetNodeID& ID) { + void Profile(llvm::FoldingSetNodeID& ID) override { Profile(ID, LHS, getOpcode(), RHS, getType()); } @@ -412,7 +409,7 @@ public: const SymExpr *rhs, QualType t) : BinarySymExpr(IntSymKind, op, t), LHS(lhs), RHS(rhs) {} - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; const SymExpr *getRHS() const { return RHS; } const llvm::APSInt &getLHS() const { return LHS; } @@ -427,7 +424,7 @@ public: ID.Add(t); } - void Profile(llvm::FoldingSetNodeID& ID) { + void Profile(llvm::FoldingSetNodeID& ID) override { Profile(ID, LHS, getOpcode(), RHS, getType()); } @@ -450,7 +447,7 @@ public: const SymExpr *getLHS() const { return LHS; } const SymExpr *getRHS() const { return RHS; } - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { @@ -461,7 +458,7 @@ public: ID.Add(t); } - void Profile(llvm::FoldingSetNodeID& ID) { + void Profile(llvm::FoldingSetNodeID& ID) override { Profile(ID, LHS, getOpcode(), RHS, getType()); } @@ -501,12 +498,12 @@ public: const LocationContext *LCtx, QualType T, unsigned VisitCount, - const void *SymbolTag = 0); + const void *SymbolTag = nullptr); const SymbolConjured* conjureSymbol(const Expr *E, const LocationContext *LCtx, unsigned VisitCount, - const void *SymbolTag = 0) { + const void *SymbolTag = nullptr) { return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag); } @@ -519,9 +516,9 @@ public: /// /// VisitCount can be used to differentiate regions corresponding to /// different loop iterations, thus, making the symbol path-dependent. - const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt *S, + const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S, QualType T, unsigned VisitCount, - const void *SymbolTag = 0); + const void *SymbolTag = nullptr); const SymbolCast* getCastSymbol(const SymExpr *Operand, QualType From, QualType To); @@ -590,7 +587,7 @@ public: SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr, StoreManager &storeMgr) : LCtx(Ctx), Loc(s), SymMgr(symmgr), - reapedStore(0, storeMgr) {} + reapedStore(nullptr, storeMgr) {} ~SymbolReaper() {} diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h index d12a151..3ed145d 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h @@ -42,7 +42,7 @@ public: explicit WorkListUnit(ExplodedNode *N, BlockCounter C) : node(N), counter(C), - block(NULL), + block(nullptr), blockIdx(0) {} /// Returns the node associated with the worklist unit. diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h new file mode 100644 index 0000000..30e5d3d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h @@ -0,0 +1,49 @@ +//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains the functions necessary for a front-end to run various +// analyses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_GR_ANALYSISCONSUMER_H +#define LLVM_CLANG_GR_ANALYSISCONSUMER_H + +#include "clang/AST/ASTConsumer.h" +#include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" +#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" +#include <string> + +namespace clang { + +class Preprocessor; +class DiagnosticsEngine; + +namespace ento { +class CheckerManager; + +class AnalysisASTConsumer : public ASTConsumer { +public: + virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0; +}; + +/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code +/// analysis passes. (The set of analyses run is controlled by command-line +/// options.) +AnalysisASTConsumer *CreateAnalysisConsumer(const Preprocessor &pp, + const std::string &output, + AnalyzerOptionsRef opts, + ArrayRef<std::string> plugins); + +} // end GR namespace + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index 838ac92..21ecfc2 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h @@ -22,8 +22,8 @@ namespace ento { class AnalysisAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins); diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h b/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h index 71acef8..765e7d2 100644 --- a/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h +++ b/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h @@ -49,13 +49,13 @@ public: /// 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); + CommandLineArguments Adjust(const CommandLineArguments &Args) override; }; /// \brief An argument adjuster which removes output-related command line /// arguments. class ClangStripOutputAdjuster : public ArgumentsAdjuster { - virtual CommandLineArguments Adjust(const CommandLineArguments &Args); + CommandLineArguments Adjust(const CommandLineArguments &Args) override; }; } // end namespace tooling diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h index eaffe43..815ede8 100644 --- a/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h +++ b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h @@ -28,6 +28,7 @@ #define LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMONOPTIONSPARSER_H #include "clang/Tooling/CompilationDatabase.h" +#include "llvm/Support/CommandLine.h" namespace clang { namespace tooling { @@ -46,13 +47,14 @@ namespace tooling { /// using namespace clang::tooling; /// using namespace llvm; /// +/// static cl::OptionCategory MyToolCategory("My tool options"); /// static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); /// static cl::extrahelp MoreHelp("\nMore help text..."); -/// static cl:opt<bool> YourOwnOption(...); +/// static cl::opt<bool> YourOwnOption(...); /// ... /// /// int main(int argc, const char **argv) { -/// CommonOptionsParser OptionsParser(argc, argv); +/// CommonOptionsParser OptionsParser(argc, argv, MyToolCategory); /// ClangTool Tool(OptionsParser.getCompilations(), /// OptionsParser.getSourcePathListi()); /// return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>()); @@ -61,10 +63,16 @@ namespace tooling { class CommonOptionsParser { public: /// \brief Parses command-line, initializes a compilation database. + /// /// This constructor can change argc and argv contents, e.g. consume /// command-line options used for creating FixedCompilationDatabase. + /// + /// All options not belonging to \p Category become hidden. + /// /// This constructor exits program in case of error. - CommonOptionsParser(int &argc, const char **argv, const char *Overview = 0); + CommonOptionsParser(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + const char *Overview = nullptr); /// Returns a reference to the loaded compilations database. CompilationDatabase &getCompilations() { @@ -79,7 +87,7 @@ public: static const char *const HelpMessage; private: - OwningPtr<CompilationDatabase> Compilations; + std::unique_ptr<CompilationDatabase> Compilations; std::vector<std::string> SourcePathList; }; diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h index 8cca329..d1e729a 100644 --- a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h +++ b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h @@ -30,9 +30,9 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include <memory> #include <string> #include <vector> @@ -42,8 +42,8 @@ namespace tooling { /// \brief Specifies the working directory and command of a compilation. struct CompileCommand { CompileCommand() {} - CompileCommand(Twine Directory, ArrayRef<std::string> CommandLine) - : Directory(Directory.str()), CommandLine(CommandLine) {} + CompileCommand(Twine Directory, std::vector<std::string> CommandLine) + : Directory(Directory.str()), CommandLine(std::move(CommandLine)) {} /// \brief The working directory the command was executed from. std::string Directory; @@ -166,7 +166,7 @@ public: /// The argument list is meant to be compatible with normal llvm command line /// parsing in main methods. /// int main(int argc, char **argv) { - /// OwningPtr<FixedCompilationDatabase> Compilations( + /// std::unique_ptr<FixedCompilationDatabase> Compilations( /// FixedCompilationDatabase::loadFromCommandLine(argc, argv)); /// cl::ParseCommandLineOptions(argc, argv); /// ... @@ -190,19 +190,19 @@ public: /// Will always return a vector with one entry that contains the directory /// and command line specified at construction with "clang-tool" as argv[0] /// and 'FilePath' as positional argument. - virtual std::vector<CompileCommand> getCompileCommands( - StringRef FilePath) const; + std::vector<CompileCommand> + getCompileCommands(StringRef FilePath) const override; /// \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; + std::vector<std::string> getAllFiles() const override; /// \brief Returns all compile commands for all the files in the compilation /// database. /// /// Note: This is always an empty list for the fixed compilation database. - virtual std::vector<CompileCommand> getAllCompileCommands() const; + std::vector<CompileCommand> getAllCompileCommands() const override; private: /// This is built up to contain a single entry vector to be returned from diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h b/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h index e531854..be37baf 100644 --- a/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h +++ b/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h @@ -16,8 +16,8 @@ #define LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H #include "clang/Basic/LLVM.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" +#include <memory> #include <string> #include <vector> @@ -79,7 +79,7 @@ public: raw_ostream &Error) const; private: FileMatchTrieNode *Root; - OwningPtr<PathComparator> Comparator; + std::unique_ptr<PathComparator> Comparator; }; diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h index e3f149b..1b33359 100644 --- a/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h +++ b/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h @@ -18,12 +18,12 @@ #include "clang/Basic/LLVM.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Tooling/FileMatchTrie.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" +#include <memory> #include <string> #include <vector> @@ -67,17 +67,17 @@ public: /// /// FIXME: Currently FilePath must be an absolute path inside the /// source directory which does not have symlinks resolved. - virtual std::vector<CompileCommand> getCompileCommands( - StringRef FilePath) const; + std::vector<CompileCommand> + getCompileCommands(StringRef FilePath) const override; /// \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; + std::vector<std::string> getAllFiles() const override; /// \brief Returns all compile commands for all the files in the compilation /// database. - virtual std::vector<CompileCommand> getAllCompileCommands() const; + std::vector<CompileCommand> getAllCompileCommands() const override; private: /// \brief Constructs a JSON compilation database on a memory buffer. @@ -104,7 +104,7 @@ private: FileMatchTrie MatchTrie; - OwningPtr<llvm::MemoryBuffer> Database; + std::unique_ptr<llvm::MemoryBuffer> Database; llvm::SourceMgr SM; llvm::yaml::Stream YAMLStream; }; diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h index 43ec9ac..cd2fb9f 100644 --- a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h +++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h @@ -83,16 +83,16 @@ public: /// \brief Creates a Replacement of the range [Start, Start+Length) with /// ReplacementText. - Replacement(SourceManager &Sources, SourceLocation Start, unsigned Length, + Replacement(const SourceManager &Sources, SourceLocation Start, unsigned Length, StringRef ReplacementText); /// \brief Creates a Replacement of the given range with ReplacementText. - Replacement(SourceManager &Sources, const CharSourceRange &Range, + Replacement(const SourceManager &Sources, const CharSourceRange &Range, StringRef ReplacementText); /// \brief Creates a Replacement of the node with ReplacementText. template <typename Node> - Replacement(SourceManager &Sources, const Node &NodeToReplace, + Replacement(const SourceManager &Sources, const Node &NodeToReplace, StringRef ReplacementText); /// \brief Returns whether this replacement can be applied to a file. @@ -115,9 +115,10 @@ public: std::string toString() const; private: - void setFromSourceLocation(SourceManager &Sources, SourceLocation Start, + void setFromSourceLocation(const SourceManager &Sources, SourceLocation Start, unsigned Length, StringRef ReplacementText); - void setFromSourceRange(SourceManager &Sources, const CharSourceRange &Range, + void setFromSourceRange(const SourceManager &Sources, + const CharSourceRange &Range, StringRef ReplacementText); std::string FilePath; @@ -230,8 +231,8 @@ private: }; template <typename Node> -Replacement::Replacement(SourceManager &Sources, const Node &NodeToReplace, - StringRef ReplacementText) { +Replacement::Replacement(const SourceManager &Sources, + const Node &NodeToReplace, StringRef ReplacementText) { const CharSourceRange Range = CharSourceRange::getTokenRange(NodeToReplace->getSourceRange()); setFromSourceRange(Sources, Range, ReplacementText); diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h b/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h index c500f35..19f2774 100644 --- a/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h +++ b/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h @@ -52,7 +52,7 @@ protected: class ReplaceStmtWithText : public RefactoringCallback { public: ReplaceStmtWithText(StringRef FromId, StringRef ToText); - virtual void run(const ast_matchers::MatchFinder::MatchResult &Result); + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; private: std::string FromId; @@ -64,7 +64,7 @@ private: class ReplaceStmtWithStmt : public RefactoringCallback { public: ReplaceStmtWithStmt(StringRef FromId, StringRef ToId); - virtual void run(const ast_matchers::MatchFinder::MatchResult &Result); + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; private: std::string FromId; @@ -77,7 +77,7 @@ private: class ReplaceIfStmtWithItsBody : public RefactoringCallback { public: ReplaceIfStmtWithItsBody(StringRef Id, bool PickTrueBranch); - virtual void run(const ast_matchers::MatchFinder::MatchResult &Result); + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; private: std::string Id; diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h b/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h index 18d3259..ac9f469 100644 --- a/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h +++ b/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h @@ -18,26 +18,14 @@ #include "clang/Tooling/Refactoring.h" #include "llvm/Support/YAMLTraits.h" -#include <vector> #include <string> +#include <vector> LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Replacement) namespace llvm { namespace yaml { -/// \brief ScalarTraits to read/write std::string objects. -template <> struct ScalarTraits<std::string> { - static void output(const std::string &Val, void *, llvm::raw_ostream &Out) { - Out << Val; - } - - static StringRef input(StringRef Scalar, void *, std::string &Val) { - Val = Scalar; - return StringRef(); - } -}; - /// \brief Specialized MappingTraits to describe how a Replacement is /// (de)serialized. template <> struct MappingTraits<clang::tooling::Replacement> { diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h index de507a7..769acd3 100644 --- a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h +++ b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h @@ -39,6 +39,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" +#include <memory> #include <string> #include <vector> @@ -80,7 +81,7 @@ public: /// \brief Invokes the compiler with a FrontendAction created by create(). bool runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files, - DiagnosticConsumer *DiagConsumer); + DiagnosticConsumer *DiagConsumer) override; /// \brief Returns a new clang::FrontendAction. /// @@ -96,7 +97,7 @@ public: /// FrontendActionFactory *Factory = /// newFrontendActionFactory<clang::SyntaxOnlyAction>(); template <typename T> -FrontendActionFactory *newFrontendActionFactory(); +std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(); /// \brief Callbacks called before and after each source file processed by a /// FrontendAction created by the FrontedActionFactory returned by \c @@ -125,11 +126,11 @@ public: /// struct ProvidesASTConsumers { /// clang::ASTConsumer *newASTConsumer(); /// } Factory; -/// FrontendActionFactory *FactoryAdapter = -/// newFrontendActionFactory(&Factory); +/// std::unique_ptr<FrontendActionFactory> FactoryAdapter( +/// newFrontendActionFactory(&Factory)); template <typename FactoryT> -inline FrontendActionFactory *newFrontendActionFactory( - FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = NULL); +inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( + FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr); /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag. /// @@ -160,8 +161,8 @@ bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code, /// \param FileName The file name which 'Code' will be mapped as. /// /// \return The resulting AST or null if an error occurred. -ASTUnit *buildASTFromCode(const Twine &Code, - const Twine &FileName = "input.cc"); +std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code, + const Twine &FileName = "input.cc"); /// \brief Builds an AST for 'Code' with additional flags. /// @@ -170,9 +171,10 @@ ASTUnit *buildASTFromCode(const Twine &Code, /// \param FileName The file name which 'Code' will be mapped as. /// /// \return The resulting AST or null if an error occurred. -ASTUnit *buildASTFromCodeWithArgs(const Twine &Code, - const std::vector<std::string> &Args, - const Twine &FileName = "input.cc"); +std::unique_ptr<ASTUnit> +buildASTFromCodeWithArgs(const Twine &Code, + const std::vector<std::string> &Args, + const Twine &FileName = "input.cc"); /// \brief Utility to run a FrontendAction in a single clang invocation. class ToolInvocation { @@ -186,7 +188,7 @@ class ToolInvocation { /// \param FAction The action to be executed. Class takes ownership. /// \param Files The FileManager used for the execution. Class does not take /// ownership. - ToolInvocation(ArrayRef<std::string> CommandLine, FrontendAction *FAction, + ToolInvocation(std::vector<std::string> CommandLine, FrontendAction *FAction, FileManager *Files); /// \brief Create a tool invocation. @@ -194,7 +196,7 @@ class ToolInvocation { /// \param CommandLine The command line arguments to clang. /// \param Action The action to be executed. /// \param Files The FileManager used for the execution. - ToolInvocation(ArrayRef<std::string> CommandLine, ToolAction *Action, + ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action, FileManager *Files); ~ToolInvocation(); @@ -282,7 +284,7 @@ class ClangTool { /// \brief Create an AST for each file specified in the command line and /// append them to ASTs. - int buildASTs(std::vector<ASTUnit *> &ASTs); + int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs); /// \brief Returns the file manager used in the tool. /// @@ -303,17 +305,18 @@ class ClangTool { }; template <typename T> -FrontendActionFactory *newFrontendActionFactory() { +std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() { class SimpleFrontendActionFactory : public FrontendActionFactory { public: - virtual clang::FrontendAction *create() { return new T; } + clang::FrontendAction *create() override { return new T; } }; - return new SimpleFrontendActionFactory; + return std::unique_ptr<FrontendActionFactory>( + new SimpleFrontendActionFactory); } template <typename FactoryT> -inline FrontendActionFactory *newFrontendActionFactory( +inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) { class FrontendActionFactoryAdapter : public FrontendActionFactory { public: @@ -321,7 +324,7 @@ inline FrontendActionFactory *newFrontendActionFactory( SourceFileCallbacks *Callbacks) : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} - virtual clang::FrontendAction *create() { + clang::FrontendAction *create() override { return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks); } @@ -333,21 +336,21 @@ inline FrontendActionFactory *newFrontendActionFactory( : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &, - StringRef) { + StringRef) override { return ConsumerFactory->newASTConsumer(); } protected: - virtual bool BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename) LLVM_OVERRIDE { + bool BeginSourceFileAction(CompilerInstance &CI, + StringRef Filename) override { if (!clang::ASTFrontendAction::BeginSourceFileAction(CI, Filename)) return false; - if (Callbacks != NULL) + if (Callbacks) return Callbacks->handleBeginSource(CI, Filename); return true; } - virtual void EndSourceFileAction() LLVM_OVERRIDE { - if (Callbacks != NULL) + void EndSourceFileAction() override { + if (Callbacks) Callbacks->handleEndSource(); clang::ASTFrontendAction::EndSourceFileAction(); } @@ -360,7 +363,8 @@ inline FrontendActionFactory *newFrontendActionFactory( SourceFileCallbacks *Callbacks; }; - return new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks); + return std::unique_ptr<FrontendActionFactory>( + new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks)); } /// \brief Returns the absolute path of \c File, by prepending it with diff --git a/contrib/llvm/tools/clang/include/clang/module.modulemap b/contrib/llvm/tools/clang/include/clang/module.modulemap new file mode 100644 index 0000000..0380601 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/module.modulemap @@ -0,0 +1,110 @@ +module Clang_Analysis { + requires cplusplus + umbrella "Analysis" + + // This file is intended for repeated textual inclusion. + exclude header "Analysis/Analyses/ThreadSafetyOps.def" + + module * { export * } +} + +module Clang_AST { + requires cplusplus + umbrella "AST" + + // These files are intended for repeated textual inclusion. + exclude header "AST/BuiltinTypes.def" + exclude header "AST/TypeLocNodes.def" + exclude header "AST/TypeNodes.def" + + module * { export * } +} + +module Clang_ASTMatchers { requires cplusplus umbrella "ASTMatchers" module * { export * } } + +module Clang_Basic { + requires cplusplus + umbrella "Basic" + + // These files are intended for repeated textual inclusion. + exclude header "Basic/BuiltinsAArch64.def" + exclude header "Basic/BuiltinsARM64.def" + exclude header "Basic/BuiltinsARM.def" + exclude header "Basic/Builtins.def" + exclude header "Basic/BuiltinsHexagon.def" + exclude header "Basic/BuiltinsMips.def" + exclude header "Basic/BuiltinsNEON.def" + exclude header "Basic/BuiltinsNVPTX.def" + exclude header "Basic/BuiltinsPPC.def" + exclude header "Basic/BuiltinsR600.def" + exclude header "Basic/BuiltinsX86.def" + exclude header "Basic/BuiltinsXCore.def" + exclude header "Basic/DiagnosticOptions.def" + exclude header "Basic/LangOptions.def" + exclude header "Basic/OpenCLExtensions.def" + exclude header "Basic/OpenMPKinds.def" + exclude header "Basic/OperatorKinds.def" + exclude header "Basic/Sanitizers.def" + exclude header "Basic/TokenKinds.def" + + // This file is one big layering violation. + exclude header "Basic/AllDiagnostics.h" + + // This file includes a header from Lex. + exclude header "Basic/PlistSupport.h" + + // FIXME: This is logically a part of Basic, but has been put in the wrong place. + header "StaticAnalyzer/Core/AnalyzerOptions.h" + + module * { export * } +} + +module Clang_CodeGen { requires cplusplus umbrella "CodeGen" module * { export * } } +module Clang_Config { requires cplusplus umbrella "Config" module * { export * } } + +module Clang_Driver { + requires cplusplus + umbrella "Driver" + + // This file is intended for repeated textual inclusion. + exclude header "Driver/Types.def" + + module * { export * } +} + +module Clang_Edit { requires cplusplus umbrella "Edit" module * { export * } } +module Clang_Format { requires cplusplus umbrella "Format" module * { export * } } + +module Clang_Frontend { + requires cplusplus + umbrella "Frontend" + + // These files are intended for repeated textual inclusion. + exclude header "Frontend/CodeGenOptions.def" + exclude header "Frontend/LangStandards.def" + + module * { export * } +} + +module Clang_FrontendTool { requires cplusplus umbrella "FrontendTool" module * { export * } } +module Clang_Index { requires cplusplus umbrella "Index" module * { export * } } +module Clang_Lex { requires cplusplus umbrella "Lex" module * { export * } } +module Clang_Parse { requires cplusplus umbrella "Parse" module * { export * } } +module Clang_Rewrite { requires cplusplus umbrella "Rewrite" module * { export * } } +module Clang_Sema { requires cplusplus umbrella "Sema" module * { export * } } +module Clang_Serialization { requires cplusplus umbrella "Serialization" module * { export * } } + +module Clang_StaticAnalyzer { + requires cplusplus + umbrella "StaticAnalyzer" + + // This file is intended for repeated textual inclusion. + exclude header "StaticAnalyzer/Core/Analyses.def" + + // FIXME: This is logically a part of Basic, but has been put in the wrong place. + exclude header "StaticAnalyzer/Core/AnalyzerOptions.h" + + module * { export * } +} + +module Clang_Tooling { requires cplusplus umbrella "Tooling" module * { export * } } |