Update clang to trunk r256633.
This commit is contained in:
commit
0623d7483d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/clang380-import/; revision=292942
@ -125,6 +125,12 @@ clang_CompileCommands_getCommand(CXCompileCommands, unsigned I);
|
||||
CINDEX_LINKAGE CXString
|
||||
clang_CompileCommand_getDirectory(CXCompileCommand);
|
||||
|
||||
/**
|
||||
* \brief Get the filename associated with the CompileCommand.
|
||||
*/
|
||||
CINDEX_LINKAGE CXString
|
||||
clang_CompileCommand_getFilename(CXCompileCommand);
|
||||
|
||||
/**
|
||||
* \brief Get the number of arguments in the compiler invocation.
|
||||
*
|
||||
|
@ -40,6 +40,11 @@ typedef struct {
|
||||
unsigned private_flags;
|
||||
} CXString;
|
||||
|
||||
typedef struct {
|
||||
CXString *Strings;
|
||||
unsigned Count;
|
||||
} CXStringSet;
|
||||
|
||||
/**
|
||||
* \brief Retrieve the character data associated with the given string.
|
||||
*/
|
||||
@ -50,6 +55,11 @@ CINDEX_LINKAGE const char *clang_getCString(CXString string);
|
||||
*/
|
||||
CINDEX_LINKAGE void clang_disposeString(CXString string);
|
||||
|
||||
/**
|
||||
* \brief Free the given string set.
|
||||
*/
|
||||
CINDEX_LINKAGE void clang_disposeStringSet(CXStringSet *set);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -32,7 +32,7 @@
|
||||
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
|
||||
*/
|
||||
#define CINDEX_VERSION_MAJOR 0
|
||||
#define CINDEX_VERSION_MINOR 30
|
||||
#define CINDEX_VERSION_MINOR 32
|
||||
|
||||
#define CINDEX_VERSION_ENCODE(major, minor) ( \
|
||||
((major) * 10000) \
|
||||
@ -285,7 +285,6 @@ CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex);
|
||||
*/
|
||||
typedef void *CXFile;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Retrieve the complete file and path name of the given file.
|
||||
*/
|
||||
@ -705,7 +704,6 @@ CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
|
||||
CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
|
||||
unsigned Index);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Describes the kind of error that occurred (if any) in a call to
|
||||
* \c clang_loadDiagnostics.
|
||||
@ -1202,7 +1200,15 @@ enum CXTranslationUnit_Flags {
|
||||
* included into the set of code completions returned from this translation
|
||||
* unit.
|
||||
*/
|
||||
CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 0x80
|
||||
CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 0x80,
|
||||
|
||||
/**
|
||||
* \brief Used to indicate that the precompiled preamble should be created on
|
||||
* the first parse. Otherwise it will be created on the first reparse. This
|
||||
* trades runtime on the first parse (serializing the preamble takes time) for
|
||||
* reduced runtime on the second parse (can now reuse the preamble).
|
||||
*/
|
||||
CXTranslationUnit_CreatePreambleOnFirstParse = 0x100
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1288,6 +1294,17 @@ clang_parseTranslationUnit2(CXIndex CIdx,
|
||||
unsigned options,
|
||||
CXTranslationUnit *out_TU);
|
||||
|
||||
/**
|
||||
* \brief Same as clang_parseTranslationUnit2 but requires a full command line
|
||||
* for \c command_line_args including argv[0]. This is useful if the standard
|
||||
* library paths are relative to the binary.
|
||||
*/
|
||||
CINDEX_LINKAGE enum CXErrorCode clang_parseTranslationUnit2FullArgv(
|
||||
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.
|
||||
*
|
||||
@ -1573,7 +1590,7 @@ enum CXCursorKind {
|
||||
CXCursor_ObjCImplementationDecl = 18,
|
||||
/** \brief An Objective-C \@implementation for a category. */
|
||||
CXCursor_ObjCCategoryImplDecl = 19,
|
||||
/** \brief A typedef */
|
||||
/** \brief A typedef. */
|
||||
CXCursor_TypedefDecl = 20,
|
||||
/** \brief A C++ class method. */
|
||||
CXCursor_CXXMethod = 21,
|
||||
@ -1982,7 +1999,11 @@ enum CXCursorKind {
|
||||
*/
|
||||
CXCursor_ObjCSelfExpr = 146,
|
||||
|
||||
CXCursor_LastExpr = CXCursor_ObjCSelfExpr,
|
||||
/** \brief OpenMP 4.0 [2.4, Array Section].
|
||||
*/
|
||||
CXCursor_OMPArraySectionExpr = 147,
|
||||
|
||||
CXCursor_LastExpr = CXCursor_OMPArraySectionExpr,
|
||||
|
||||
/* Statements */
|
||||
CXCursor_FirstStmt = 200,
|
||||
@ -2227,17 +2248,33 @@ enum CXCursorKind {
|
||||
|
||||
/** \brief OpenMP taskgroup directive.
|
||||
*/
|
||||
CXCursor_OMPTaskgroupDirective = 254,
|
||||
CXCursor_OMPTaskgroupDirective = 254,
|
||||
|
||||
/** \brief OpenMP cancellation point directive.
|
||||
*/
|
||||
CXCursor_OMPCancellationPointDirective = 255,
|
||||
CXCursor_OMPCancellationPointDirective = 255,
|
||||
|
||||
/** \brief OpenMP cancel directive.
|
||||
*/
|
||||
CXCursor_OMPCancelDirective = 256,
|
||||
CXCursor_OMPCancelDirective = 256,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OMPCancelDirective,
|
||||
/** \brief OpenMP target data directive.
|
||||
*/
|
||||
CXCursor_OMPTargetDataDirective = 257,
|
||||
|
||||
/** \brief OpenMP taskloop directive.
|
||||
*/
|
||||
CXCursor_OMPTaskLoopDirective = 258,
|
||||
|
||||
/** \brief OpenMP taskloop simd directive.
|
||||
*/
|
||||
CXCursor_OMPTaskLoopSimdDirective = 259,
|
||||
|
||||
/** \brief OpenMP distribute directive.
|
||||
*/
|
||||
CXCursor_OMPDistributeDirective = 260,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OMPDistributeDirective,
|
||||
|
||||
/**
|
||||
* \brief Cursor that represents the translation unit itself.
|
||||
@ -2271,7 +2308,10 @@ enum CXCursorKind {
|
||||
CXCursor_CUDAGlobalAttr = 414,
|
||||
CXCursor_CUDAHostAttr = 415,
|
||||
CXCursor_CUDASharedAttr = 416,
|
||||
CXCursor_LastAttr = CXCursor_CUDASharedAttr,
|
||||
CXCursor_VisibilityAttr = 417,
|
||||
CXCursor_DLLExport = 418,
|
||||
CXCursor_DLLImport = 419,
|
||||
CXCursor_LastAttr = CXCursor_DLLImport,
|
||||
|
||||
/* Preprocessing */
|
||||
CXCursor_PreprocessingDirective = 500,
|
||||
@ -2287,8 +2327,9 @@ enum CXCursorKind {
|
||||
* \brief A module import declaration.
|
||||
*/
|
||||
CXCursor_ModuleImportDecl = 600,
|
||||
CXCursor_TypeAliasTemplateDecl = 601,
|
||||
CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
|
||||
CXCursor_LastExtraDecl = CXCursor_ModuleImportDecl,
|
||||
CXCursor_LastExtraDecl = CXCursor_TypeAliasTemplateDecl,
|
||||
|
||||
/**
|
||||
* \brief A code completion overload candidate.
|
||||
@ -2439,6 +2480,32 @@ enum CXLinkageKind {
|
||||
*/
|
||||
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
|
||||
|
||||
enum CXVisibilityKind {
|
||||
/** \brief This value indicates that no visibility information is available
|
||||
* for a provided CXCursor. */
|
||||
CXVisibility_Invalid,
|
||||
|
||||
/** \brief Symbol not seen by the linker. */
|
||||
CXVisibility_Hidden,
|
||||
/** \brief Symbol seen by the linker but resolves to a symbol inside this object. */
|
||||
CXVisibility_Protected,
|
||||
/** \brief Symbol seen by the linker and acts like a normal symbol. */
|
||||
CXVisibility_Default
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Describe the visibility of the entity referred to by a cursor.
|
||||
*
|
||||
* This returns the default visibility if not explicitly specified by
|
||||
* a visibility attribute. The default visibility may be changed by
|
||||
* commandline arguments.
|
||||
*
|
||||
* \param cursor The cursor to query.
|
||||
*
|
||||
* \returns The visibility of the cursor.
|
||||
*/
|
||||
CINDEX_LINKAGE enum CXVisibilityKind clang_getCursorVisibility(CXCursor cursor);
|
||||
|
||||
/**
|
||||
* \brief Determine the availability of the entity that this cursor refers to,
|
||||
* taking the current target platform into account.
|
||||
@ -2558,7 +2625,6 @@ CINDEX_LINKAGE enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor);
|
||||
*/
|
||||
CINDEX_LINKAGE CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor);
|
||||
|
||||
|
||||
/**
|
||||
* \brief A fast container representing a set of CXCursors.
|
||||
*/
|
||||
@ -2851,7 +2917,8 @@ enum CXTypeKind {
|
||||
CXType_IncompleteArray = 114,
|
||||
CXType_VariableArray = 115,
|
||||
CXType_DependentSizedArray = 116,
|
||||
CXType_MemberPointer = 117
|
||||
CXType_MemberPointer = 117,
|
||||
CXType_Auto = 118
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2876,7 +2943,6 @@ enum CXCallingConv {
|
||||
CXCallingConv_Unexposed = 200
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief The type of an element in the abstract syntax tree.
|
||||
*
|
||||
@ -3314,7 +3380,6 @@ CINDEX_LINKAGE long long clang_Cursor_getOffsetOfField(CXCursor C);
|
||||
*/
|
||||
CINDEX_LINKAGE unsigned clang_Cursor_isAnonymous(CXCursor C);
|
||||
|
||||
|
||||
enum CXRefQualifierKind {
|
||||
/** \brief No ref-qualifier was provided. */
|
||||
CXRefQualifier_None = 0,
|
||||
@ -3443,7 +3508,6 @@ CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor,
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \brief For cursors representing an iboutletcollection attribute,
|
||||
* this function returns the collection element type.
|
||||
@ -3597,7 +3661,6 @@ CINDEX_LINKAGE CXString
|
||||
CINDEX_LINKAGE CXString
|
||||
clang_constructUSR_ObjCProtocol(const char *protocol_name);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Construct a USR for a specified Objective-C instance variable and
|
||||
* the USR for its containing class.
|
||||
@ -3723,7 +3786,6 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
|
||||
*/
|
||||
CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor);
|
||||
|
||||
|
||||
/**
|
||||
* \brief If the cursor points to a selector identifier in an Objective-C
|
||||
* method or message expression, this returns the selector index.
|
||||
@ -3853,6 +3915,12 @@ CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
|
||||
*/
|
||||
CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor);
|
||||
|
||||
/**
|
||||
* \brief Retrieve the CXStrings representing the mangled symbols of the C++
|
||||
* constructor or destructor at the cursor.
|
||||
*/
|
||||
CINDEX_LINKAGE CXStringSet *clang_Cursor_getCXXManglings(CXCursor);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@ -3947,6 +4015,11 @@ CXFile clang_Module_getTopLevelHeader(CXTranslationUnit,
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Determine if a C++ field is declared 'mutable'.
|
||||
*/
|
||||
CINDEX_LINKAGE unsigned clang_CXXField_isMutable(CXCursor C);
|
||||
|
||||
/**
|
||||
* \brief Determine if a C++ member function or member function template is
|
||||
* pure virtual.
|
||||
@ -4939,8 +5012,7 @@ enum CXCursorKind clang_codeCompleteGetContainerKind(
|
||||
*/
|
||||
CINDEX_LINKAGE
|
||||
CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns the currently-entered selector for an Objective-C message
|
||||
* send, formatted like "initWithFoo:bar:". Only guaranteed to return a
|
||||
@ -4959,7 +5031,6 @@ CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \defgroup CINDEX_MISC Miscellaneous utility functions
|
||||
*
|
||||
@ -4972,7 +5043,6 @@ CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
|
||||
*/
|
||||
CINDEX_LINKAGE CXString clang_getClangVersion(void);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Enable/disable crash recovery.
|
||||
*
|
||||
@ -5658,6 +5728,18 @@ CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction,
|
||||
CXTranslationUnit *out_TU,
|
||||
unsigned TU_options);
|
||||
|
||||
/**
|
||||
* \brief Same as clang_indexSourceFile but requires a full command line
|
||||
* for \c command_line_args including argv[0]. This is useful if the standard
|
||||
* library paths are relative to the binary.
|
||||
*/
|
||||
CINDEX_LINKAGE int clang_indexSourceFileFullArgv(
|
||||
CXIndexAction, CXClientData client_data, IndexerCallbacks *index_callbacks,
|
||||
unsigned index_callbacks_size, unsigned index_options,
|
||||
const char *source_filename, const char *const *command_line_args,
|
||||
int num_command_line_args, struct CXUnsavedFile *unsaved_files,
|
||||
unsigned num_unsaved_files, CXTranslationUnit *out_TU, unsigned TU_options);
|
||||
|
||||
/**
|
||||
* \brief Index the given translation unit via callbacks implemented through
|
||||
* #IndexerCallbacks.
|
||||
@ -5739,7 +5821,6 @@ CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T,
|
||||
CXFieldVisitor visitor,
|
||||
CXClientData client_data);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@ -5752,4 +5833,3 @@ CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T,
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "clang/Basic/AddressSpaces.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
#include "clang/Basic/PartialDiagnostic.h"
|
||||
#include "clang/Basic/SanitizerBlacklist.h"
|
||||
@ -70,6 +71,7 @@ namespace clang {
|
||||
class VTableContextBase;
|
||||
|
||||
namespace Builtin { class Context; }
|
||||
enum BuiltinTemplateKind : int;
|
||||
|
||||
namespace comments {
|
||||
class FullComment;
|
||||
@ -176,8 +178,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
ClassScopeSpecializationPattern;
|
||||
|
||||
/// \brief Mapping from materialized temporaries with static storage duration
|
||||
/// that appear in constant initializers to their evaluated values.
|
||||
llvm::DenseMap<const MaterializeTemporaryExpr*, APValue>
|
||||
/// that appear in constant initializers to their evaluated values. These are
|
||||
/// allocated in a std::map because their address must be stable.
|
||||
llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *>
|
||||
MaterializedTemporaryValues;
|
||||
|
||||
/// \brief Representation of a "canonical" template template parameter that
|
||||
@ -215,6 +218,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// __builtin_va_list type.
|
||||
mutable TypedefDecl *BuiltinVaListDecl;
|
||||
|
||||
/// The typedef for the predefined \c __builtin_ms_va_list type.
|
||||
mutable TypedefDecl *BuiltinMSVaListDecl;
|
||||
|
||||
/// \brief The typedef for the predefined \c id type.
|
||||
mutable TypedefDecl *ObjCIdDecl;
|
||||
|
||||
@ -242,6 +248,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// The identifier 'NSCopying'.
|
||||
IdentifierInfo *NSCopyingName = nullptr;
|
||||
|
||||
/// The identifier '__make_integer_seq'.
|
||||
mutable IdentifierInfo *MakeIntegerSeqName = nullptr;
|
||||
|
||||
QualType ObjCConstantStringType;
|
||||
mutable RecordDecl *CFConstantStringTypeDecl;
|
||||
|
||||
@ -395,6 +404,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
TranslationUnitDecl *TUDecl;
|
||||
mutable ExternCContextDecl *ExternCContext;
|
||||
mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;
|
||||
|
||||
/// \brief The associated SourceManager object.a
|
||||
SourceManager &SourceMgr;
|
||||
@ -433,6 +443,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
friend class CXXRecordDecl;
|
||||
|
||||
const TargetInfo *Target;
|
||||
const TargetInfo *AuxTarget;
|
||||
clang::PrintingPolicy PrintingPolicy;
|
||||
|
||||
public:
|
||||
@ -446,10 +457,59 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// \brief Contains parents of a node.
|
||||
typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector;
|
||||
|
||||
/// \brief Maps from a node to its parents.
|
||||
/// \brief Maps from a node to its parents. This is used for nodes that have
|
||||
/// pointer identity only, which are more common and we can save space by
|
||||
/// only storing a unique pointer to them.
|
||||
typedef llvm::DenseMap<const void *,
|
||||
llvm::PointerUnion<ast_type_traits::DynTypedNode *,
|
||||
ParentVector *>> ParentMap;
|
||||
llvm::PointerUnion4<const Decl *, const Stmt *,
|
||||
ast_type_traits::DynTypedNode *,
|
||||
ParentVector *>> ParentMapPointers;
|
||||
|
||||
/// Parent map for nodes without pointer identity. We store a full
|
||||
/// DynTypedNode for all keys.
|
||||
typedef llvm::DenseMap<
|
||||
ast_type_traits::DynTypedNode,
|
||||
llvm::PointerUnion4<const Decl *, const Stmt *,
|
||||
ast_type_traits::DynTypedNode *, ParentVector *>>
|
||||
ParentMapOtherNodes;
|
||||
|
||||
/// Container for either a single DynTypedNode or for an ArrayRef to
|
||||
/// DynTypedNode. For use with ParentMap.
|
||||
class DynTypedNodeList {
|
||||
typedef ast_type_traits::DynTypedNode DynTypedNode;
|
||||
llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode,
|
||||
ArrayRef<DynTypedNode>> Storage;
|
||||
bool IsSingleNode;
|
||||
|
||||
public:
|
||||
DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
|
||||
new (Storage.buffer) DynTypedNode(N);
|
||||
}
|
||||
DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
|
||||
new (Storage.buffer) ArrayRef<DynTypedNode>(A);
|
||||
}
|
||||
|
||||
const ast_type_traits::DynTypedNode *begin() const {
|
||||
if (!IsSingleNode)
|
||||
return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
|
||||
->begin();
|
||||
return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
|
||||
}
|
||||
|
||||
const ast_type_traits::DynTypedNode *end() const {
|
||||
if (!IsSingleNode)
|
||||
return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
|
||||
->end();
|
||||
return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1;
|
||||
}
|
||||
|
||||
size_t size() const { return end() - begin(); }
|
||||
bool empty() const { return begin() == end(); }
|
||||
const DynTypedNode &operator[](size_t N) const {
|
||||
assert(N < size() && "Out of bounds!");
|
||||
return *(begin() + N);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Returns the parents of the given node.
|
||||
///
|
||||
@ -475,13 +535,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
///
|
||||
/// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
|
||||
/// NestedNameSpecifier or NestedNameSpecifierLoc.
|
||||
template <typename NodeT>
|
||||
ArrayRef<ast_type_traits::DynTypedNode> getParents(const NodeT &Node) {
|
||||
template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node) {
|
||||
return getParents(ast_type_traits::DynTypedNode::create(Node));
|
||||
}
|
||||
|
||||
ArrayRef<ast_type_traits::DynTypedNode>
|
||||
getParents(const ast_type_traits::DynTypedNode &Node);
|
||||
DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node);
|
||||
|
||||
const clang::PrintingPolicy &getPrintingPolicy() const {
|
||||
return PrintingPolicy;
|
||||
@ -501,6 +559,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
void *Allocate(size_t Size, unsigned Align = 8) const {
|
||||
return BumpAlloc.Allocate(Size, Align);
|
||||
}
|
||||
template <typename T> T *Allocate(size_t Num = 1) const {
|
||||
return static_cast<T *>(Allocate(Num * sizeof(T), llvm::alignOf<T>()));
|
||||
}
|
||||
void Deallocate(void *Ptr) const { }
|
||||
|
||||
/// Return the total amount of physical memory allocated for representing
|
||||
@ -516,7 +577,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
}
|
||||
|
||||
const TargetInfo &getTargetInfo() const { return *Target; }
|
||||
|
||||
const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
|
||||
|
||||
/// getIntTypeForBitwidth -
|
||||
/// sets integer QualTy according to specified details:
|
||||
/// bitwidth, signed/unsigned.
|
||||
@ -812,6 +874,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
|
||||
|
||||
ExternCContextDecl *getExternCContextDecl() const;
|
||||
BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
|
||||
|
||||
// Builtin Types.
|
||||
CanQualType VoidTy;
|
||||
@ -835,17 +898,21 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
|
||||
CanQualType ObjCBuiltinBoolTy;
|
||||
CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy;
|
||||
CanQualType OCLImage2dTy, OCLImage2dArrayTy;
|
||||
CanQualType OCLImage2dTy, OCLImage2dArrayTy, OCLImage2dDepthTy;
|
||||
CanQualType OCLImage2dArrayDepthTy, OCLImage2dMSAATy, OCLImage2dArrayMSAATy;
|
||||
CanQualType OCLImage2dMSAADepthTy, OCLImage2dArrayMSAADepthTy;
|
||||
CanQualType OCLImage3dTy;
|
||||
CanQualType OCLSamplerTy, OCLEventTy;
|
||||
CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
|
||||
CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy;
|
||||
CanQualType OMPArraySectionTy;
|
||||
|
||||
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
|
||||
mutable QualType AutoDeductTy; // Deduction against 'auto'.
|
||||
mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'.
|
||||
|
||||
// Type used to help define __builtin_va_list for some targets.
|
||||
// The type is built when constructing 'BuiltinVaListDecl'.
|
||||
mutable QualType VaListTagTy;
|
||||
// Decl used to help define __builtin_va_list for some targets.
|
||||
// The decl is built when constructing 'BuiltinVaListDecl'.
|
||||
mutable Decl *VaListTagDecl;
|
||||
|
||||
ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
|
||||
SelectorTable &sels, Builtin::Context &builtins);
|
||||
@ -881,6 +948,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
void PrintStats() const;
|
||||
const SmallVectorImpl<Type *>& getTypes() const { return Types; }
|
||||
|
||||
BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
|
||||
const IdentifierInfo *II) const;
|
||||
|
||||
/// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl
|
||||
/// declaration.
|
||||
RecordDecl *buildImplicitRecord(StringRef Name,
|
||||
@ -955,6 +1025,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
const FunctionType *adjustFunctionType(const FunctionType *Fn,
|
||||
FunctionType::ExtInfo EInfo);
|
||||
|
||||
/// Adjust the given function result type.
|
||||
CanQualType getCanonicalFunctionResultType(QualType ResultType) const;
|
||||
|
||||
/// \brief Change the result type of a function type once it is deduced.
|
||||
void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
|
||||
|
||||
@ -1227,7 +1300,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
UnaryTransformType::UTTKind UKind) const;
|
||||
|
||||
/// \brief C++11 deduced auto type.
|
||||
QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,
|
||||
QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
|
||||
bool IsDependent) const;
|
||||
|
||||
/// \brief C++11 deduction pattern for 'auto' type.
|
||||
@ -1381,6 +1454,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
return NSCopyingName;
|
||||
}
|
||||
|
||||
IdentifierInfo *getMakeIntegerSeqName() const {
|
||||
if (!MakeIntegerSeqName)
|
||||
MakeIntegerSeqName = &Idents.get("__make_integer_seq");
|
||||
return MakeIntegerSeqName;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the Objective-C "instancetype" type, if already known;
|
||||
/// otherwise, returns a NULL type;
|
||||
QualType getObjCInstanceType() {
|
||||
@ -1569,7 +1648,16 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// \brief Retrieve the C type declaration corresponding to the predefined
|
||||
/// \c __va_list_tag type used to help define the \c __builtin_va_list type
|
||||
/// for some targets.
|
||||
QualType getVaListTagType() const;
|
||||
Decl *getVaListTagDecl() const;
|
||||
|
||||
/// Retrieve the C type declaration corresponding to the predefined
|
||||
/// \c __builtin_ms_va_list type.
|
||||
TypedefDecl *getBuiltinMSVaListDecl() const;
|
||||
|
||||
/// Retrieve the type of the \c __builtin_ms_va_list type.
|
||||
QualType getBuiltinMSVaListType() const {
|
||||
return getTypeDeclType(getBuiltinMSVaListDecl());
|
||||
}
|
||||
|
||||
/// \brief Return a type with additional \c const, \c volatile, or
|
||||
/// \c restrict qualifiers.
|
||||
@ -1774,7 +1862,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// record (struct/union/class) \p D, which indicates its size and field
|
||||
/// position information.
|
||||
const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
|
||||
const ASTRecordLayout *BuildMicrosoftASTRecordLayout(const RecordDecl *D) const;
|
||||
|
||||
/// \brief Get or compute information about the layout of the specified
|
||||
/// Objective-C interface.
|
||||
@ -2170,9 +2257,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
const FunctionProtoType *FromFunctionType,
|
||||
const FunctionProtoType *ToFunctionType);
|
||||
|
||||
void ResetObjCLayout(const ObjCContainerDecl *CD) {
|
||||
ObjCLayouts[CD] = nullptr;
|
||||
}
|
||||
void ResetObjCLayout(const ObjCContainerDecl *CD);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Integer Predicates
|
||||
@ -2187,16 +2272,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
// corresponding unsigned integer type.
|
||||
QualType getCorrespondingUnsignedType(QualType T) const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Iterators.
|
||||
//===--------------------------------------------------------------------===//
|
||||
typedef llvm::iterator_range<SmallVectorImpl<Type *>::const_iterator>
|
||||
type_const_range;
|
||||
|
||||
type_const_range types() const {
|
||||
return type_const_range(Types.begin(), Types.end());
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Integer Values
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -2233,16 +2308,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief Get the duplicate declaration of a ObjCMethod in the same
|
||||
/// interface, or null if none exists.
|
||||
const ObjCMethodDecl *getObjCMethodRedeclaration(
|
||||
const ObjCMethodDecl *MD) const {
|
||||
return ObjCMethodRedecls.lookup(MD);
|
||||
}
|
||||
const ObjCMethodDecl *
|
||||
getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const;
|
||||
|
||||
void setObjCMethodRedeclaration(const ObjCMethodDecl *MD,
|
||||
const ObjCMethodDecl *Redecl) {
|
||||
assert(!getObjCMethodRedeclaration(MD) && "MD already has a redeclaration");
|
||||
ObjCMethodRedecls[MD] = Redecl;
|
||||
}
|
||||
const ObjCMethodDecl *Redecl);
|
||||
|
||||
/// \brief Returns the Objective-C interface that \p ND belongs to if it is
|
||||
/// an Objective-C method/property/ivar etc. that is part of an interface,
|
||||
@ -2307,6 +2377,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
|
||||
unsigned ParmIdx);
|
||||
|
||||
void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *TND);
|
||||
|
||||
TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD);
|
||||
|
||||
void addDeclaratorForUnnamedTagDecl(TagDecl *TD, DeclaratorDecl *DD);
|
||||
|
||||
DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD);
|
||||
|
||||
void setManglingNumber(const NamedDecl *ND, unsigned Number);
|
||||
unsigned getManglingNumber(const NamedDecl *ND) const;
|
||||
|
||||
@ -2388,9 +2466,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// This routine may only be invoked once for a given ASTContext object.
|
||||
/// It is normally invoked after ASTContext construction.
|
||||
///
|
||||
/// \param Target The target
|
||||
void InitBuiltinTypes(const TargetInfo &Target);
|
||||
|
||||
/// \param Target The target
|
||||
void InitBuiltinTypes(const TargetInfo &Target,
|
||||
const TargetInfo *AuxTarget = nullptr);
|
||||
|
||||
private:
|
||||
void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);
|
||||
|
||||
@ -2429,9 +2508,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief A set of deallocations that should be performed when the
|
||||
/// ASTContext is destroyed.
|
||||
typedef llvm::SmallDenseMap<void(*)(void*), llvm::SmallVector<void*, 16> >
|
||||
DeallocationMap;
|
||||
DeallocationMap Deallocations;
|
||||
// FIXME: We really should have a better mechanism in the ASTContext to
|
||||
// manage running destructors for types which do variable sized allocation
|
||||
// within the AST. In some places we thread the AST bump pointer allocator
|
||||
// into the datastructures which avoids this mess during deallocation but is
|
||||
// wasteful of memory, and here we require a lot of error prone book keeping
|
||||
// in order to track and run destructors while we're tearing things down.
|
||||
typedef llvm::SmallVector<std::pair<void (*)(void *), void *>, 16>
|
||||
DeallocationFunctionsAndArguments;
|
||||
DeallocationFunctionsAndArguments Deallocations;
|
||||
|
||||
// FIXME: This currently contains the set of StoredDeclMaps used
|
||||
// by DeclContext objects. This probably should not be in ASTContext,
|
||||
@ -2443,7 +2528,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
void ReleaseDeclContextMaps();
|
||||
void ReleaseParentMapEntries();
|
||||
|
||||
std::unique_ptr<ParentMap> AllParents;
|
||||
std::unique_ptr<ParentMapPointers> PointerParents;
|
||||
std::unique_ptr<ParentMapOtherNodes> OtherParents;
|
||||
|
||||
std::unique_ptr<VTableContextBase> VTContext;
|
||||
|
||||
|
@ -92,18 +92,6 @@ class ASTMutationListener {
|
||||
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
|
||||
const ObjCInterfaceDecl *IFD) {}
|
||||
|
||||
/// \brief A objc class extension redeclared or introduced a property.
|
||||
///
|
||||
/// \param Prop the property in the class extension
|
||||
///
|
||||
/// \param OrigProp the property from the original interface that was declared
|
||||
/// or null if the property was introduced.
|
||||
///
|
||||
/// \param ClassExt the class extension.
|
||||
virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
|
||||
const ObjCPropertyDecl *OrigProp,
|
||||
const ObjCCategoryDecl *ClassExt) {}
|
||||
|
||||
/// \brief A declaration is marked used which was not previously marked used.
|
||||
///
|
||||
/// \param D the declaration marked used
|
||||
|
@ -106,18 +106,25 @@ class ASTNodeKind {
|
||||
}
|
||||
};
|
||||
|
||||
/// Check if the given ASTNodeKind identifies a type that offers pointer
|
||||
/// identity. This is useful for the fast path in DynTypedNode.
|
||||
bool hasPointerIdentity() const {
|
||||
return KindId > NKI_LastKindWithoutPointerIdentity;
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief Kind ids.
|
||||
///
|
||||
/// Includes all possible base and derived kinds.
|
||||
enum NodeKindId {
|
||||
NKI_None,
|
||||
NKI_CXXCtorInitializer,
|
||||
NKI_TemplateArgument,
|
||||
NKI_NestedNameSpecifier,
|
||||
NKI_NestedNameSpecifierLoc,
|
||||
NKI_QualType,
|
||||
NKI_TypeLoc,
|
||||
NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
|
||||
NKI_CXXCtorInitializer,
|
||||
NKI_NestedNameSpecifier,
|
||||
NKI_Decl,
|
||||
#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
|
||||
#include "clang/AST/DeclNodes.inc"
|
||||
@ -238,7 +245,11 @@ class DynTypedNode {
|
||||
/// Note that this is not supported by all AST nodes. For AST nodes
|
||||
/// that don't have a pointer-defined identity inside the AST, this
|
||||
/// method returns NULL.
|
||||
const void *getMemoizationData() const { return MemoizationData; }
|
||||
const void *getMemoizationData() const {
|
||||
return NodeKind.hasPointerIdentity()
|
||||
? *reinterpret_cast<void *const *>(Storage.buffer)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/// \brief Prints the node to the given output stream.
|
||||
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
|
||||
@ -257,6 +268,32 @@ class DynTypedNode {
|
||||
/// FIXME: Implement comparsion for other node types (currently
|
||||
/// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
|
||||
bool operator<(const DynTypedNode &Other) const {
|
||||
if (!NodeKind.isSame(Other.NodeKind))
|
||||
return NodeKind < Other.NodeKind;
|
||||
|
||||
if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
|
||||
return getUnchecked<QualType>().getAsOpaquePtr() <
|
||||
Other.getUnchecked<QualType>().getAsOpaquePtr();
|
||||
|
||||
if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) {
|
||||
auto TLA = getUnchecked<TypeLoc>();
|
||||
auto TLB = Other.getUnchecked<TypeLoc>();
|
||||
return std::make_pair(TLA.getType().getAsOpaquePtr(),
|
||||
TLA.getOpaqueData()) <
|
||||
std::make_pair(TLB.getType().getAsOpaquePtr(),
|
||||
TLB.getOpaqueData());
|
||||
}
|
||||
|
||||
if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
|
||||
NodeKind)) {
|
||||
auto NNSLA = getUnchecked<NestedNameSpecifierLoc>();
|
||||
auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>();
|
||||
return std::make_pair(NNSLA.getNestedNameSpecifier(),
|
||||
NNSLA.getOpaqueData()) <
|
||||
std::make_pair(NNSLB.getNestedNameSpecifier(),
|
||||
NNSLB.getOpaqueData());
|
||||
}
|
||||
|
||||
assert(getMemoizationData() && Other.getMemoizationData());
|
||||
return getMemoizationData() < Other.getMemoizationData();
|
||||
}
|
||||
@ -270,6 +307,13 @@ class DynTypedNode {
|
||||
if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
|
||||
return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
|
||||
|
||||
if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind))
|
||||
return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>();
|
||||
|
||||
if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind))
|
||||
return getUnchecked<NestedNameSpecifierLoc>() ==
|
||||
Other.getUnchecked<NestedNameSpecifierLoc>();
|
||||
|
||||
assert(getMemoizationData() && Other.getMemoizationData());
|
||||
return getMemoizationData() == Other.getMemoizationData();
|
||||
}
|
||||
@ -278,6 +322,47 @@ class DynTypedNode {
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// \brief Hooks for using DynTypedNode as a key in a DenseMap.
|
||||
struct DenseMapInfo {
|
||||
static inline DynTypedNode getEmptyKey() {
|
||||
DynTypedNode Node;
|
||||
Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey();
|
||||
return Node;
|
||||
}
|
||||
static inline DynTypedNode getTombstoneKey() {
|
||||
DynTypedNode Node;
|
||||
Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey();
|
||||
return Node;
|
||||
}
|
||||
static unsigned getHashValue(const DynTypedNode &Val) {
|
||||
// FIXME: Add hashing support for the remaining types.
|
||||
if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) {
|
||||
auto TL = Val.getUnchecked<TypeLoc>();
|
||||
return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
|
||||
TL.getOpaqueData());
|
||||
}
|
||||
|
||||
if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
|
||||
Val.NodeKind)) {
|
||||
auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>();
|
||||
return llvm::hash_combine(NNSL.getNestedNameSpecifier(),
|
||||
NNSL.getOpaqueData());
|
||||
}
|
||||
|
||||
assert(Val.getMemoizationData());
|
||||
return llvm::hash_value(Val.getMemoizationData());
|
||||
}
|
||||
static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) {
|
||||
auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey();
|
||||
auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey();
|
||||
return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) &&
|
||||
ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) ||
|
||||
(ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) &&
|
||||
ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) ||
|
||||
LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
/// \brief Takes care of converting from and to \c T.
|
||||
template <typename T, typename EnablerT = void> struct BaseConverter;
|
||||
@ -286,18 +371,18 @@ class DynTypedNode {
|
||||
template <typename T, typename BaseT> struct DynCastPtrConverter {
|
||||
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
|
||||
if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
|
||||
return cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
|
||||
return &getUnchecked(NodeKind, Storage);
|
||||
return nullptr;
|
||||
}
|
||||
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
|
||||
assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
|
||||
return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
|
||||
return *cast<T>(static_cast<const BaseT *>(
|
||||
*reinterpret_cast<const void *const *>(Storage)));
|
||||
}
|
||||
static DynTypedNode create(const BaseT &Node) {
|
||||
DynTypedNode Result;
|
||||
Result.NodeKind = ASTNodeKind::getFromNode(Node);
|
||||
Result.MemoizationData = &Node;
|
||||
new (Result.Storage.buffer) const BaseT * (&Node);
|
||||
new (Result.Storage.buffer) const void *(&Node);
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
@ -306,18 +391,18 @@ class DynTypedNode {
|
||||
template <typename T> struct PtrConverter {
|
||||
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
|
||||
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
|
||||
return *reinterpret_cast<T *const *>(Storage);
|
||||
return &getUnchecked(NodeKind, Storage);
|
||||
return nullptr;
|
||||
}
|
||||
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
|
||||
assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
|
||||
return **reinterpret_cast<T *const *>(Storage);
|
||||
return *static_cast<const T *>(
|
||||
*reinterpret_cast<const void *const *>(Storage));
|
||||
}
|
||||
static DynTypedNode create(const T &Node) {
|
||||
DynTypedNode Result;
|
||||
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
|
||||
Result.MemoizationData = &Node;
|
||||
new (Result.Storage.buffer) const T * (&Node);
|
||||
new (Result.Storage.buffer) const void *(&Node);
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
@ -336,14 +421,12 @@ class DynTypedNode {
|
||||
static DynTypedNode create(const T &Node) {
|
||||
DynTypedNode Result;
|
||||
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
|
||||
Result.MemoizationData = nullptr;
|
||||
new (Result.Storage.buffer) T(Node);
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
|
||||
ASTNodeKind NodeKind;
|
||||
const void *MemoizationData;
|
||||
|
||||
/// \brief Stores the data of the node.
|
||||
///
|
||||
@ -353,12 +436,9 @@ class DynTypedNode {
|
||||
/// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
|
||||
/// \c TemplateArguments on the other hand do not have storage or unique
|
||||
/// pointers and thus need to be stored by value.
|
||||
typedef llvm::AlignedCharArrayUnion<
|
||||
Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *>
|
||||
KindsByPointer;
|
||||
llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument,
|
||||
NestedNameSpecifierLoc, QualType, TypeLoc>
|
||||
Storage;
|
||||
llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
|
||||
NestedNameSpecifierLoc, QualType,
|
||||
TypeLoc> Storage;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -420,6 +500,10 @@ template <>
|
||||
struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind>
|
||||
: clang::ast_type_traits::ASTNodeKind::DenseMapInfo {};
|
||||
|
||||
template <>
|
||||
struct DenseMapInfo<clang::ast_type_traits::DynTypedNode>
|
||||
: clang::ast_type_traits::DynTypedNode::DenseMapInfo {};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -56,21 +56,21 @@ class Attr {
|
||||
bool IsLateParsed : 1;
|
||||
bool DuplicatesAllowed : 1;
|
||||
|
||||
void* operator new(size_t bytes) throw() {
|
||||
void *operator new(size_t bytes) LLVM_NOEXCEPT {
|
||||
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
|
||||
}
|
||||
void operator delete(void* data) throw() {
|
||||
void operator delete(void *data) LLVM_NOEXCEPT {
|
||||
llvm_unreachable("Attrs cannot be released with regular 'delete'.");
|
||||
}
|
||||
|
||||
public:
|
||||
// Forward so that the regular new and delete do not hide global ones.
|
||||
void* operator new(size_t Bytes, ASTContext &C,
|
||||
size_t Alignment = 8) throw() {
|
||||
void *operator new(size_t Bytes, ASTContext &C,
|
||||
size_t Alignment = 8) LLVM_NOEXCEPT {
|
||||
return ::operator new(Bytes, C, Alignment);
|
||||
}
|
||||
void operator delete(void *Ptr, ASTContext &C,
|
||||
size_t Alignment) throw() {
|
||||
size_t Alignment) LLVM_NOEXCEPT {
|
||||
return ::operator delete(Ptr, C, Alignment);
|
||||
}
|
||||
|
||||
|
@ -160,6 +160,12 @@ BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy)
|
||||
BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy)
|
||||
BUILTIN_TYPE(OCLImage2d, OCLImage2dTy)
|
||||
BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy)
|
||||
BUILTIN_TYPE(OCLImage2dDepth, OCLImage2dDepthTy)
|
||||
BUILTIN_TYPE(OCLImage2dArrayDepth, OCLImage2dArrayDepthTy)
|
||||
BUILTIN_TYPE(OCLImage2dMSAA, OCLImage2dMSAATy)
|
||||
BUILTIN_TYPE(OCLImage2dArrayMSAA, OCLImage2dArrayMSAATy)
|
||||
BUILTIN_TYPE(OCLImage2dMSAADepth, OCLImage2dMSAADepthTy)
|
||||
BUILTIN_TYPE(OCLImage2dArrayMSAADepth, OCLImage2dArrayMSAADepthTy)
|
||||
BUILTIN_TYPE(OCLImage3d, OCLImage3dTy)
|
||||
|
||||
// OpenCL sampler_t.
|
||||
@ -168,6 +174,18 @@ BUILTIN_TYPE(OCLSampler, OCLSamplerTy)
|
||||
// OpenCL event_t.
|
||||
BUILTIN_TYPE(OCLEvent, OCLEventTy)
|
||||
|
||||
// OpenCL clk_event_t.
|
||||
BUILTIN_TYPE(OCLClkEvent, OCLClkEventTy)
|
||||
|
||||
// OpenCL queue_t.
|
||||
BUILTIN_TYPE(OCLQueue, OCLQueueTy)
|
||||
|
||||
// OpenCL ndrange_t.
|
||||
BUILTIN_TYPE(OCLNDRange, OCLNDRangeTy)
|
||||
|
||||
// OpenCL reserve_id_t.
|
||||
BUILTIN_TYPE(OCLReserveID, OCLReserveIDTy)
|
||||
|
||||
// This represents the type of an expression whose type is
|
||||
// totally unknown, e.g. 'T::foo'. It is permitted for this to
|
||||
// appear in situations where the structure of the type is
|
||||
@ -227,8 +245,11 @@ PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
|
||||
// context.
|
||||
PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
|
||||
|
||||
// A placeholder type for OpenMP array sections.
|
||||
PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)
|
||||
|
||||
#ifdef LAST_BUILTIN_TYPE
|
||||
LAST_BUILTIN_TYPE(ARCUnbridgedCast)
|
||||
LAST_BUILTIN_TYPE(OMPArraySection)
|
||||
#undef LAST_BUILTIN_TYPE
|
||||
#endif
|
||||
|
||||
|
@ -155,17 +155,16 @@ class CXXBasePaths {
|
||||
/// \brief Array of the declarations that have been found. This
|
||||
/// array is constructed only if needed, e.g., to iterate over the
|
||||
/// results within LookupResult.
|
||||
NamedDecl **DeclsFound;
|
||||
std::unique_ptr<NamedDecl *[]> DeclsFound;
|
||||
unsigned NumDeclsFound;
|
||||
|
||||
friend class CXXRecordDecl;
|
||||
|
||||
void ComputeDeclsFound();
|
||||
|
||||
bool lookupInBases(ASTContext &Context,
|
||||
const CXXRecordDecl *Record,
|
||||
CXXRecordDecl::BaseMatchesCallback *BaseMatches,
|
||||
void *UserData);
|
||||
bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record,
|
||||
CXXRecordDecl::BaseMatchesCallback BaseMatches);
|
||||
|
||||
public:
|
||||
typedef std::list<CXXBasePath>::iterator paths_iterator;
|
||||
typedef std::list<CXXBasePath>::const_iterator const_paths_iterator;
|
||||
@ -173,15 +172,12 @@ class CXXBasePaths {
|
||||
|
||||
/// BasePaths - Construct a new BasePaths structure to record the
|
||||
/// paths for a derived-to-base search.
|
||||
explicit CXXBasePaths(bool FindAmbiguities = true,
|
||||
bool RecordPaths = true,
|
||||
explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true,
|
||||
bool DetectVirtual = true)
|
||||
: FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
|
||||
DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
|
||||
DeclsFound(nullptr), NumDeclsFound(0) { }
|
||||
|
||||
~CXXBasePaths() { delete [] DeclsFound; }
|
||||
|
||||
: FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
|
||||
DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
|
||||
NumDeclsFound(0) {}
|
||||
|
||||
paths_iterator begin() { return Paths.begin(); }
|
||||
paths_iterator end() { return Paths.end(); }
|
||||
const_paths_iterator begin() const { return Paths.begin(); }
|
||||
|
@ -130,6 +130,14 @@ namespace clang {
|
||||
return (Quantity & -Quantity) == Quantity;
|
||||
}
|
||||
|
||||
/// Test whether this is a multiple of the other value.
|
||||
///
|
||||
/// Among other things, this promises that
|
||||
/// self.RoundUpToAlignment(N) will just return self.
|
||||
bool isMultipleOf(CharUnits N) const {
|
||||
return (*this % N) == 0;
|
||||
}
|
||||
|
||||
// Arithmetic operators.
|
||||
CharUnits operator* (QuantityType N) const {
|
||||
return CharUnits(Quantity * N);
|
||||
@ -172,10 +180,20 @@ namespace clang {
|
||||
|
||||
/// Given that this is a non-zero alignment value, what is the
|
||||
/// alignment at the given offset?
|
||||
CharUnits alignmentAtOffset(CharUnits offset) {
|
||||
CharUnits alignmentAtOffset(CharUnits offset) const {
|
||||
assert(Quantity != 0 && "offsetting from unknown alignment?");
|
||||
return CharUnits(llvm::MinAlign(Quantity, offset.Quantity));
|
||||
}
|
||||
|
||||
/// Given that this is the alignment of the first element of an
|
||||
/// array, return the minimum alignment of any element in the array.
|
||||
CharUnits alignmentOfArrayElement(CharUnits elementSize) const {
|
||||
// Since we don't track offsetted alignments, the alignment of
|
||||
// the second element (or any odd element) will be minimally
|
||||
// aligned.
|
||||
return alignmentAtOffset(elementSize);
|
||||
}
|
||||
|
||||
|
||||
}; // class CharUnit
|
||||
} // namespace clang
|
||||
|
@ -79,12 +79,8 @@ class Sema {
|
||||
/// Returns a copy of array, owned by Sema's allocator.
|
||||
template<typename T>
|
||||
ArrayRef<T> copyArray(ArrayRef<T> Source) {
|
||||
size_t Size = Source.size();
|
||||
if (Size != 0) {
|
||||
T *Mem = Allocator.Allocate<T>(Size);
|
||||
std::uninitialized_copy(Source.begin(), Source.end(), Mem);
|
||||
return llvm::makeArrayRef(Mem, Size);
|
||||
}
|
||||
if (!Source.empty())
|
||||
return Source.copy(Allocator);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,11 +21,13 @@
|
||||
#include "clang/AST/Redeclarable.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/Linkage.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/TrailingObjects.h"
|
||||
|
||||
namespace clang {
|
||||
struct ASTTemplateArgumentListInfo;
|
||||
@ -37,7 +39,6 @@ class FunctionTemplateDecl;
|
||||
class FunctionTemplateSpecializationInfo;
|
||||
class LabelStmt;
|
||||
class MemberSpecializationInfo;
|
||||
class Module;
|
||||
class NestedNameSpecifier;
|
||||
class ParmVarDecl;
|
||||
class Stmt;
|
||||
@ -318,7 +319,8 @@ class NamedDecl : public Decl {
|
||||
NamedDecl *getUnderlyingDecl() {
|
||||
// Fast-path the common case.
|
||||
if (this->getKind() != UsingShadow &&
|
||||
this->getKind() != ObjCCompatibleAlias)
|
||||
this->getKind() != ObjCCompatibleAlias &&
|
||||
this->getKind() != NamespaceAlias)
|
||||
return this;
|
||||
|
||||
return getUnderlyingDeclImpl();
|
||||
@ -462,25 +464,15 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
|
||||
}
|
||||
|
||||
/// \brief Get the original (first) namespace declaration.
|
||||
NamespaceDecl *getOriginalNamespace() {
|
||||
if (isFirstDecl())
|
||||
return this;
|
||||
|
||||
return AnonOrFirstNamespaceAndInline.getPointer();
|
||||
}
|
||||
NamespaceDecl *getOriginalNamespace();
|
||||
|
||||
/// \brief Get the original (first) namespace declaration.
|
||||
const NamespaceDecl *getOriginalNamespace() const {
|
||||
if (isFirstDecl())
|
||||
return this;
|
||||
|
||||
return AnonOrFirstNamespaceAndInline.getPointer();
|
||||
}
|
||||
const NamespaceDecl *getOriginalNamespace() const;
|
||||
|
||||
/// \brief Return true if this declaration is an original (first) declaration
|
||||
/// of the namespace. This is false for non-original (subsequent) namespace
|
||||
/// declarations and anonymous namespaces.
|
||||
bool isOriginalNamespace() const { return isFirstDecl(); }
|
||||
bool isOriginalNamespace() const;
|
||||
|
||||
/// \brief Retrieve the anonymous namespace nested inside this namespace,
|
||||
/// if any.
|
||||
@ -572,8 +564,7 @@ struct QualifierInfo {
|
||||
/// setTemplateParameterListsInfo - Sets info about "outer" template
|
||||
/// parameter lists.
|
||||
void setTemplateParameterListsInfo(ASTContext &Context,
|
||||
unsigned NumTPLists,
|
||||
TemplateParameterList **TPLists);
|
||||
ArrayRef<TemplateParameterList *> TPLists);
|
||||
|
||||
private:
|
||||
// Copy constructor and copy assignment are disabled.
|
||||
@ -658,8 +649,8 @@ class DeclaratorDecl : public ValueDecl {
|
||||
assert(index < getNumTemplateParameterLists());
|
||||
return getExtInfo()->TemplParamLists[index];
|
||||
}
|
||||
void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
|
||||
TemplateParameterList **TPLists);
|
||||
void setTemplateParameterListsInfo(ASTContext &Context,
|
||||
ArrayRef<TemplateParameterList *> TPLists);
|
||||
|
||||
SourceLocation getTypeSpecStartLoc() const;
|
||||
|
||||
@ -728,17 +719,14 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
};
|
||||
|
||||
protected:
|
||||
/// \brief Placeholder type used in Init to denote an unparsed C++ default
|
||||
/// argument.
|
||||
struct UnparsedDefaultArgument;
|
||||
|
||||
/// \brief Placeholder type used in Init to denote an uninstantiated C++
|
||||
/// default argument.
|
||||
struct UninstantiatedDefaultArgument;
|
||||
|
||||
typedef llvm::PointerUnion4<Stmt *, EvaluatedStmt *,
|
||||
UnparsedDefaultArgument *,
|
||||
UninstantiatedDefaultArgument *> InitType;
|
||||
// A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we
|
||||
// have allocated the auxilliary struct of information there.
|
||||
//
|
||||
// TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for
|
||||
// this as *many* VarDecls are ParmVarDecls that don't have default
|
||||
// arguments. We could save some space by moving this pointer union to be
|
||||
// allocated in trailing space when necessary.
|
||||
typedef llvm::PointerUnion<Stmt *, EvaluatedStmt *> InitType;
|
||||
|
||||
/// \brief The initializer for this variable or, for a ParmVarDecl, the
|
||||
/// C++ default argument.
|
||||
@ -762,6 +750,13 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
protected:
|
||||
enum { NumParameterIndexBits = 8 };
|
||||
|
||||
enum DefaultArgKind {
|
||||
DAK_None,
|
||||
DAK_Unparsed,
|
||||
DAK_Uninstantiated,
|
||||
DAK_Normal
|
||||
};
|
||||
|
||||
class ParmVarDeclBitfields {
|
||||
friend class ParmVarDecl;
|
||||
friend class ASTDeclReader;
|
||||
@ -772,6 +767,12 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
/// prior declaration.
|
||||
unsigned HasInheritedDefaultArg : 1;
|
||||
|
||||
/// Describes the kind of default argument for this parameter. By default
|
||||
/// this is none. If this is normal, then the default argument is stored in
|
||||
/// the \c VarDecl initalizer expression unless we were unble to parse
|
||||
/// (even an invalid) expression for the default argument.
|
||||
unsigned DefaultArgKind : 2;
|
||||
|
||||
/// Whether this parameter undergoes K&R argument promotion.
|
||||
unsigned IsKNRPromoted : 1;
|
||||
|
||||
@ -815,6 +816,9 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
/// \brief Whether this variable is (C++0x) constexpr.
|
||||
unsigned IsConstexpr : 1;
|
||||
|
||||
/// \brief Whether this variable is a (C++ Concepts TS) concept.
|
||||
unsigned IsConcept : 1;
|
||||
|
||||
/// \brief Whether this variable is the implicit variable for a lambda
|
||||
/// init-capture.
|
||||
unsigned IsInitCapture : 1;
|
||||
@ -1062,47 +1066,14 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
/// declaration it is attached to. Also get that declaration.
|
||||
const Expr *getAnyInitializer(const VarDecl *&D) const;
|
||||
|
||||
bool hasInit() const {
|
||||
return !Init.isNull() && (Init.is<Stmt *>() || Init.is<EvaluatedStmt *>());
|
||||
}
|
||||
bool hasInit() const;
|
||||
const Expr *getInit() const {
|
||||
if (Init.isNull())
|
||||
return nullptr;
|
||||
|
||||
const Stmt *S = Init.dyn_cast<Stmt *>();
|
||||
if (!S) {
|
||||
if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
|
||||
S = ES->Value;
|
||||
}
|
||||
return (const Expr*) S;
|
||||
}
|
||||
Expr *getInit() {
|
||||
if (Init.isNull())
|
||||
return nullptr;
|
||||
|
||||
Stmt *S = Init.dyn_cast<Stmt *>();
|
||||
if (!S) {
|
||||
if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
|
||||
S = ES->Value;
|
||||
}
|
||||
|
||||
return (Expr*) S;
|
||||
return const_cast<VarDecl *>(this)->getInit();
|
||||
}
|
||||
Expr *getInit();
|
||||
|
||||
/// \brief Retrieve the address of the initializer expression.
|
||||
Stmt **getInitAddress() {
|
||||
if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
|
||||
return &ES->Value;
|
||||
|
||||
// This union hack tip-toes around strict-aliasing rules.
|
||||
union {
|
||||
InitType *InitPtr;
|
||||
Stmt **StmtPtr;
|
||||
};
|
||||
|
||||
InitPtr = &Init;
|
||||
return StmtPtr;
|
||||
}
|
||||
Stmt **getInitAddress();
|
||||
|
||||
void setInit(Expr *I);
|
||||
|
||||
@ -1124,33 +1095,18 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
/// \brief Return the already-evaluated value of this variable's
|
||||
/// initializer, or NULL if the value is not yet known. Returns pointer
|
||||
/// to untyped APValue if the value could not be evaluated.
|
||||
APValue *getEvaluatedValue() const {
|
||||
if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
|
||||
if (Eval->WasEvaluated)
|
||||
return &Eval->Evaluated;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
APValue *getEvaluatedValue() const;
|
||||
|
||||
/// \brief Determines whether it is already known whether the
|
||||
/// initializer is an integral constant expression or not.
|
||||
bool isInitKnownICE() const {
|
||||
if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
|
||||
return Eval->CheckedICE;
|
||||
|
||||
return false;
|
||||
}
|
||||
bool isInitKnownICE() const;
|
||||
|
||||
/// \brief Determines whether the initializer is an integral constant
|
||||
/// expression, or in C++11, whether the initializer is a constant
|
||||
/// expression.
|
||||
///
|
||||
/// \pre isInitKnownICE()
|
||||
bool isInitICE() const {
|
||||
assert(isInitKnownICE() &&
|
||||
"Check whether we already know that the initializer is an ICE");
|
||||
return Init.get<EvaluatedStmt *>()->IsICE;
|
||||
}
|
||||
bool isInitICE() const;
|
||||
|
||||
/// \brief Determine whether the value of the initializer attached to this
|
||||
/// declaration is an integral constant expression.
|
||||
@ -1238,6 +1194,15 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
NonParmVarDeclBits.IsConstexpr = IC;
|
||||
}
|
||||
|
||||
/// Whether this variable is (C++ Concepts TS) concept.
|
||||
bool isConcept() const {
|
||||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConcept;
|
||||
}
|
||||
void setConcept(bool IC) {
|
||||
assert(!isa<ParmVarDecl>(this));
|
||||
NonParmVarDeclBits.IsConcept = IC;
|
||||
}
|
||||
|
||||
/// Whether this variable is the implicit variable for a lambda init-capture.
|
||||
bool isInitCapture() const {
|
||||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture;
|
||||
@ -1342,6 +1307,7 @@ class ParmVarDecl : public VarDecl {
|
||||
TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
|
||||
: VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) {
|
||||
assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
|
||||
assert(ParmVarDeclBits.DefaultArgKind == DAK_None);
|
||||
assert(ParmVarDeclBits.IsKNRPromoted == false);
|
||||
assert(ParmVarDeclBits.IsObjCMethodParam == false);
|
||||
setDefaultArg(DefArg);
|
||||
@ -1416,29 +1382,20 @@ class ParmVarDecl : public VarDecl {
|
||||
return const_cast<ParmVarDecl *>(this)->getDefaultArg();
|
||||
}
|
||||
|
||||
void setDefaultArg(Expr *defarg) {
|
||||
Init = reinterpret_cast<Stmt *>(defarg);
|
||||
}
|
||||
void setDefaultArg(Expr *defarg);
|
||||
|
||||
/// \brief Retrieve the source range that covers the entire default
|
||||
/// argument.
|
||||
SourceRange getDefaultArgRange() const;
|
||||
void setUninstantiatedDefaultArg(Expr *arg) {
|
||||
Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg);
|
||||
}
|
||||
Expr *getUninstantiatedDefaultArg() {
|
||||
return (Expr *)Init.get<UninstantiatedDefaultArgument *>();
|
||||
}
|
||||
void setUninstantiatedDefaultArg(Expr *arg);
|
||||
Expr *getUninstantiatedDefaultArg();
|
||||
const Expr *getUninstantiatedDefaultArg() const {
|
||||
return (const Expr *)Init.get<UninstantiatedDefaultArgument *>();
|
||||
return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg();
|
||||
}
|
||||
|
||||
/// hasDefaultArg - Determines whether this parameter has a default argument,
|
||||
/// either parsed or not.
|
||||
bool hasDefaultArg() const {
|
||||
return getInit() || hasUnparsedDefaultArg() ||
|
||||
hasUninstantiatedDefaultArg();
|
||||
}
|
||||
bool hasDefaultArg() const;
|
||||
|
||||
/// hasUnparsedDefaultArg - Determines whether this parameter has a
|
||||
/// default argument that has not yet been parsed. This will occur
|
||||
@ -1451,11 +1408,11 @@ class ParmVarDecl : public VarDecl {
|
||||
/// }; // x has a regular default argument now
|
||||
/// @endcode
|
||||
bool hasUnparsedDefaultArg() const {
|
||||
return Init.is<UnparsedDefaultArgument*>();
|
||||
return ParmVarDeclBits.DefaultArgKind == DAK_Unparsed;
|
||||
}
|
||||
|
||||
bool hasUninstantiatedDefaultArg() const {
|
||||
return Init.is<UninstantiatedDefaultArgument*>();
|
||||
return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated;
|
||||
}
|
||||
|
||||
/// setUnparsedDefaultArg - Specify that this parameter has an
|
||||
@ -1463,7 +1420,9 @@ class ParmVarDecl : public VarDecl {
|
||||
/// real default argument via setDefaultArg when the class
|
||||
/// definition enclosing the function declaration that owns this
|
||||
/// default argument is completed.
|
||||
void setUnparsedDefaultArg() { Init = (UnparsedDefaultArgument *)nullptr; }
|
||||
void setUnparsedDefaultArg() {
|
||||
ParmVarDeclBits.DefaultArgKind = DAK_Unparsed;
|
||||
}
|
||||
|
||||
bool hasInheritedDefaultArg() const {
|
||||
return ParmVarDeclBits.HasInheritedDefaultArg;
|
||||
@ -1546,25 +1505,25 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
|
||||
LazyDeclStmtPtr Body;
|
||||
|
||||
// FIXME: This can be packed into the bitfields in Decl.
|
||||
// NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
|
||||
// FIXME: This can be packed into the bitfields in DeclContext.
|
||||
// NOTE: VC++ packs bitfields poorly if the types differ.
|
||||
unsigned SClass : 2;
|
||||
bool IsInline : 1;
|
||||
bool IsInlineSpecified : 1;
|
||||
bool IsVirtualAsWritten : 1;
|
||||
bool IsPure : 1;
|
||||
bool HasInheritedPrototype : 1;
|
||||
bool HasWrittenPrototype : 1;
|
||||
bool IsDeleted : 1;
|
||||
bool IsTrivial : 1; // sunk from CXXMethodDecl
|
||||
bool IsDefaulted : 1; // sunk from CXXMethoDecl
|
||||
bool IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
|
||||
bool HasImplicitReturnZero : 1;
|
||||
bool IsLateTemplateParsed : 1;
|
||||
bool IsConstexpr : 1;
|
||||
unsigned IsInline : 1;
|
||||
unsigned IsInlineSpecified : 1;
|
||||
unsigned IsVirtualAsWritten : 1;
|
||||
unsigned IsPure : 1;
|
||||
unsigned HasInheritedPrototype : 1;
|
||||
unsigned HasWrittenPrototype : 1;
|
||||
unsigned IsDeleted : 1;
|
||||
unsigned IsTrivial : 1; // sunk from CXXMethodDecl
|
||||
unsigned IsDefaulted : 1; // sunk from CXXMethoDecl
|
||||
unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
|
||||
unsigned HasImplicitReturnZero : 1;
|
||||
unsigned IsLateTemplateParsed : 1;
|
||||
unsigned IsConstexpr : 1;
|
||||
|
||||
/// \brief Indicates if the function uses __try.
|
||||
bool UsesSEHTry : 1;
|
||||
unsigned UsesSEHTry : 1;
|
||||
|
||||
/// \brief Indicates if the function was a definition but its body was
|
||||
/// skipped.
|
||||
@ -1835,7 +1794,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
bool isConstexpr() const { return IsConstexpr; }
|
||||
void setConstexpr(bool IC) { IsConstexpr = IC; }
|
||||
|
||||
/// Whether this is a (C++11) constexpr function or constexpr constructor.
|
||||
/// \brief Indicates the function uses __try.
|
||||
bool usesSEHTry() const { return UsesSEHTry; }
|
||||
void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
|
||||
|
||||
@ -2084,9 +2043,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
/// \brief If this function is an instantiation of a member function of a
|
||||
/// class template specialization, retrieves the member specialization
|
||||
/// information.
|
||||
MemberSpecializationInfo *getMemberSpecializationInfo() const {
|
||||
return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
|
||||
}
|
||||
MemberSpecializationInfo *getMemberSpecializationInfo() const;
|
||||
|
||||
/// \brief Specify that this record is an instantiation of the
|
||||
/// member function FD.
|
||||
@ -2107,13 +2064,9 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
/// FunctionDecl that describes the function template,
|
||||
/// getDescribedFunctionTemplate() retrieves the
|
||||
/// FunctionTemplateDecl from a FunctionDecl.
|
||||
FunctionTemplateDecl *getDescribedFunctionTemplate() const {
|
||||
return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl*>();
|
||||
}
|
||||
FunctionTemplateDecl *getDescribedFunctionTemplate() const;
|
||||
|
||||
void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
|
||||
TemplateOrSpecialization = Template;
|
||||
}
|
||||
void setDescribedFunctionTemplate(FunctionTemplateDecl *Template);
|
||||
|
||||
/// \brief Determine whether this function is a function template
|
||||
/// specialization.
|
||||
@ -2128,10 +2081,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
/// \brief If this function is actually a function template specialization,
|
||||
/// retrieve information about this function template specialization.
|
||||
/// Otherwise, returns NULL.
|
||||
FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const {
|
||||
return TemplateOrSpecialization.
|
||||
dyn_cast<FunctionTemplateSpecializationInfo*>();
|
||||
}
|
||||
FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const;
|
||||
|
||||
/// \brief Determines whether this function is a function template
|
||||
/// specialization or a member of a class template specialization that can
|
||||
@ -2208,10 +2158,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
const TemplateArgumentListInfo &TemplateArgs);
|
||||
|
||||
DependentFunctionTemplateSpecializationInfo *
|
||||
getDependentSpecializationInfo() const {
|
||||
return TemplateOrSpecialization.
|
||||
dyn_cast<DependentFunctionTemplateSpecializationInfo*>();
|
||||
}
|
||||
getDependentSpecializationInfo() const;
|
||||
|
||||
/// \brief Determine what kind of template instantiation this function
|
||||
/// represents.
|
||||
@ -2487,7 +2434,8 @@ class EnumConstantDecl : public ValueDecl, public Mergeable<EnumConstantDecl> {
|
||||
/// IndirectFieldDecl - An instance of this class is created to represent a
|
||||
/// field injected from an anonymous union/struct into the parent scope.
|
||||
/// IndirectFieldDecl are always implicit.
|
||||
class IndirectFieldDecl : public ValueDecl {
|
||||
class IndirectFieldDecl : public ValueDecl,
|
||||
public Mergeable<IndirectFieldDecl> {
|
||||
void anchor() override;
|
||||
NamedDecl **Chaining;
|
||||
unsigned ChainingSize;
|
||||
@ -2525,6 +2473,9 @@ class IndirectFieldDecl : public ValueDecl {
|
||||
return dyn_cast<VarDecl>(*chain_begin());
|
||||
}
|
||||
|
||||
IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
|
||||
const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == IndirectField; }
|
||||
@ -2762,12 +2713,12 @@ class TagDecl
|
||||
/// declaration specifier for variables, it points to the first VarDecl (used
|
||||
/// for mangling);
|
||||
/// otherwise, it is a null (TypedefNameDecl) pointer.
|
||||
llvm::PointerUnion<NamedDecl *, ExtInfo *> NamedDeclOrQualifier;
|
||||
llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier;
|
||||
|
||||
bool hasExtInfo() const { return NamedDeclOrQualifier.is<ExtInfo *>(); }
|
||||
ExtInfo *getExtInfo() { return NamedDeclOrQualifier.get<ExtInfo *>(); }
|
||||
bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); }
|
||||
ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); }
|
||||
const ExtInfo *getExtInfo() const {
|
||||
return NamedDeclOrQualifier.get<ExtInfo *>();
|
||||
return TypedefNameDeclOrQualifier.get<ExtInfo *>();
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -2778,7 +2729,7 @@ class TagDecl
|
||||
TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false),
|
||||
IsEmbeddedInDeclarator(false), IsFreeStanding(false),
|
||||
IsCompleteDefinitionRequired(false),
|
||||
NamedDeclOrQualifier((NamedDecl *)nullptr) {
|
||||
TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
|
||||
assert((DK != Enum || TK == TTK_Enum) &&
|
||||
"EnumDecl not matched with TTK_Enum");
|
||||
setPreviousDecl(PrevDecl);
|
||||
@ -2925,22 +2876,11 @@ class TagDecl
|
||||
return (getDeclName() || getTypedefNameForAnonDecl());
|
||||
}
|
||||
|
||||
bool hasDeclaratorForAnonDecl() const {
|
||||
return dyn_cast_or_null<DeclaratorDecl>(
|
||||
NamedDeclOrQualifier.get<NamedDecl *>());
|
||||
}
|
||||
DeclaratorDecl *getDeclaratorForAnonDecl() const {
|
||||
return hasExtInfo() ? nullptr : dyn_cast_or_null<DeclaratorDecl>(
|
||||
NamedDeclOrQualifier.get<NamedDecl *>());
|
||||
}
|
||||
|
||||
TypedefNameDecl *getTypedefNameForAnonDecl() const {
|
||||
return hasExtInfo() ? nullptr : dyn_cast_or_null<TypedefNameDecl>(
|
||||
NamedDeclOrQualifier.get<NamedDecl *>());
|
||||
return hasExtInfo() ? nullptr
|
||||
: TypedefNameDeclOrQualifier.get<TypedefNameDecl *>();
|
||||
}
|
||||
|
||||
void setDeclaratorForAnonDecl(DeclaratorDecl *DD) { NamedDeclOrQualifier = DD; }
|
||||
|
||||
void setTypedefNameForAnonDecl(TypedefNameDecl *TDD);
|
||||
|
||||
/// \brief Retrieve the nested-name-specifier that qualifies the name of this
|
||||
@ -2967,8 +2907,8 @@ class TagDecl
|
||||
assert(i < getNumTemplateParameterLists());
|
||||
return getExtInfo()->TemplParamLists[i];
|
||||
}
|
||||
void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
|
||||
TemplateParameterList **TPLists);
|
||||
void setTemplateParameterListsInfo(ASTContext &Context,
|
||||
ArrayRef<TemplateParameterList *> TPLists);
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
@ -3301,7 +3241,14 @@ class RecordDecl : public TagDecl {
|
||||
|
||||
bool hasVolatileMember() const { return HasVolatileMember; }
|
||||
void setHasVolatileMember (bool val) { HasVolatileMember = val; }
|
||||
|
||||
|
||||
bool hasLoadedFieldsFromExternalStorage() const {
|
||||
return LoadedFieldsFromExternalStorage;
|
||||
}
|
||||
void setHasLoadedFieldsFromExternalStorage(bool val) {
|
||||
LoadedFieldsFromExternalStorage = val;
|
||||
}
|
||||
|
||||
/// \brief Determines whether this declaration represents the
|
||||
/// injected class name.
|
||||
///
|
||||
@ -3475,7 +3422,7 @@ class BlockDecl : public Decl, public DeclContext {
|
||||
Stmt *Body;
|
||||
TypeSourceInfo *SignatureAsWritten;
|
||||
|
||||
Capture *Captures;
|
||||
const Capture *Captures;
|
||||
unsigned NumCaptures;
|
||||
|
||||
unsigned ManglingNumber;
|
||||
@ -3581,10 +3528,8 @@ class BlockDecl : public Decl, public DeclContext {
|
||||
|
||||
bool capturesVariable(const VarDecl *var) const;
|
||||
|
||||
void setCaptures(ASTContext &Context,
|
||||
const Capture *begin,
|
||||
const Capture *end,
|
||||
bool capturesCXXThis);
|
||||
void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
|
||||
bool CapturesCXXThis);
|
||||
|
||||
unsigned getBlockManglingNumber() const {
|
||||
return ManglingNumber;
|
||||
@ -3613,7 +3558,15 @@ class BlockDecl : public Decl, public DeclContext {
|
||||
|
||||
/// \brief This represents the body of a CapturedStmt, and serves as its
|
||||
/// DeclContext.
|
||||
class CapturedDecl : public Decl, public DeclContext {
|
||||
class CapturedDecl final
|
||||
: public Decl,
|
||||
public DeclContext,
|
||||
private llvm::TrailingObjects<CapturedDecl, ImplicitParamDecl *> {
|
||||
protected:
|
||||
size_t numTrailingObjects(OverloadToken<ImplicitParamDecl>) {
|
||||
return NumParams;
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief The number of parameters to the outlined function.
|
||||
unsigned NumParams;
|
||||
@ -3622,13 +3575,14 @@ class CapturedDecl : public Decl, public DeclContext {
|
||||
/// \brief The body of the outlined function.
|
||||
llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow;
|
||||
|
||||
explicit CapturedDecl(DeclContext *DC, unsigned NumParams)
|
||||
: Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
|
||||
NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) { }
|
||||
explicit CapturedDecl(DeclContext *DC, unsigned NumParams);
|
||||
|
||||
ImplicitParamDecl **getParams() const {
|
||||
return reinterpret_cast<ImplicitParamDecl **>(
|
||||
const_cast<CapturedDecl *>(this) + 1);
|
||||
ImplicitParamDecl *const *getParams() const {
|
||||
return getTrailingObjects<ImplicitParamDecl *>();
|
||||
}
|
||||
|
||||
ImplicitParamDecl **getParams() {
|
||||
return getTrailingObjects<ImplicitParamDecl *>();
|
||||
}
|
||||
|
||||
public:
|
||||
@ -3637,11 +3591,11 @@ class CapturedDecl : public Decl, public DeclContext {
|
||||
static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
unsigned NumParams);
|
||||
|
||||
Stmt *getBody() const override { return BodyAndNothrow.getPointer(); }
|
||||
void setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }
|
||||
Stmt *getBody() const override;
|
||||
void setBody(Stmt *B);
|
||||
|
||||
bool isNothrow() const { return BodyAndNothrow.getInt(); }
|
||||
void setNothrow(bool Nothrow = true) { BodyAndNothrow.setInt(Nothrow); }
|
||||
bool isNothrow() const;
|
||||
void setNothrow(bool Nothrow = true);
|
||||
|
||||
unsigned getNumParams() const { return NumParams; }
|
||||
|
||||
@ -3666,7 +3620,7 @@ class CapturedDecl : public Decl, public DeclContext {
|
||||
}
|
||||
unsigned getContextParamPosition() const { return ContextParam; }
|
||||
|
||||
typedef ImplicitParamDecl **param_iterator;
|
||||
typedef ImplicitParamDecl *const *param_iterator;
|
||||
typedef llvm::iterator_range<param_iterator> param_range;
|
||||
|
||||
/// \brief Retrieve an iterator pointing to the first parameter decl.
|
||||
@ -3689,6 +3643,7 @@ class CapturedDecl : public Decl, public DeclContext {
|
||||
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
friend TrailingObjects;
|
||||
};
|
||||
|
||||
/// \brief Describes a module import declaration, which makes the contents
|
||||
@ -3701,7 +3656,8 @@ class CapturedDecl : public Decl, public DeclContext {
|
||||
///
|
||||
/// Import declarations can also be implicitly generated from
|
||||
/// \#include/\#import directives.
|
||||
class ImportDecl : public Decl {
|
||||
class ImportDecl final : public Decl,
|
||||
llvm::TrailingObjects<ImportDecl, SourceLocation> {
|
||||
/// \brief The imported module, along with a bit that indicates whether
|
||||
/// we have source-location information for each identifier in the module
|
||||
/// name.
|
||||
@ -3717,7 +3673,8 @@ class ImportDecl : public Decl {
|
||||
friend class ASTReader;
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTContext;
|
||||
|
||||
friend TrailingObjects;
|
||||
|
||||
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
|
||||
ArrayRef<SourceLocation> IdentifierLocs);
|
||||
|
||||
|
@ -70,8 +70,15 @@ namespace clang {
|
||||
/// Decl - This represents one declaration (or definition), e.g. a variable,
|
||||
/// typedef, function, struct, etc.
|
||||
///
|
||||
/// Note: There are objects tacked on before the *beginning* of Decl
|
||||
/// (and its subclasses) in its Decl::operator new(). Proper alignment
|
||||
/// of all subclasses (not requiring more than DeclObjAlignment) is
|
||||
/// asserted in DeclBase.cpp.
|
||||
class Decl {
|
||||
public:
|
||||
/// \brief Alignment guaranteed when allocating Decl and any subtypes.
|
||||
enum { DeclObjAlignment = llvm::AlignOf<uint64_t>::Alignment };
|
||||
|
||||
/// \brief Lists the kind of concrete classes of Decl.
|
||||
enum Kind {
|
||||
#define DECL(DERIVED, BASE) DERIVED,
|
||||
@ -468,8 +475,7 @@ class Decl {
|
||||
|
||||
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>());
|
||||
return llvm::make_range(specific_attr_begin<T>(), specific_attr_end<T>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -721,6 +727,15 @@ class Decl {
|
||||
return getParentFunctionOrMethod() == nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this declaration lexically is inside a function.
|
||||
/// It recognizes non-defining declarations as well as members of local
|
||||
/// classes:
|
||||
/// \code
|
||||
/// void foo() { void bar(); }
|
||||
/// void foo2() { class ABC { void bar(); }; }
|
||||
/// \endcode
|
||||
bool isLexicallyWithinFunctionOrMethod() const;
|
||||
|
||||
/// \brief If this decl is defined inside a function/method/block it returns
|
||||
/// the corresponding DeclContext, otherwise it returns null.
|
||||
const DeclContext *getParentFunctionOrMethod() const;
|
||||
@ -1126,6 +1141,11 @@ class DeclContext {
|
||||
/// that are missing from the lookup table.
|
||||
mutable bool HasLazyExternalLexicalLookups : 1;
|
||||
|
||||
/// \brief If \c true, lookups should only return identifier from
|
||||
/// DeclContext scope (for example TranslationUnit). Used in
|
||||
/// LookupQualifiedName()
|
||||
mutable bool UseQualifiedLookup : 1;
|
||||
|
||||
/// \brief Pointer to the data structure used to lookup declarations
|
||||
/// within this context (or a DependentStoredDeclsMap if this is a
|
||||
/// dependent context). We maintain the invariant that, if the map
|
||||
@ -1160,6 +1180,7 @@ class DeclContext {
|
||||
ExternalVisibleStorage(false),
|
||||
NeedToReconcileExternalVisibleStorage(false),
|
||||
HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false),
|
||||
UseQualifiedLookup(false),
|
||||
LookupPtr(nullptr), FirstDecl(nullptr), LastDecl(nullptr) {}
|
||||
|
||||
public:
|
||||
@ -1740,6 +1761,16 @@ class DeclContext {
|
||||
D == LastDecl);
|
||||
}
|
||||
|
||||
bool setUseQualifiedLookup(bool use = true) {
|
||||
bool old_value = UseQualifiedLookup;
|
||||
UseQualifiedLookup = use;
|
||||
return old_value;
|
||||
}
|
||||
|
||||
bool shouldUseQualifiedLookup() const {
|
||||
return UseQualifiedLookup;
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D);
|
||||
static bool classof(const DeclContext *D) { return true; }
|
||||
|
||||
|
@ -1344,9 +1344,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief If this class is an instantiation of a member class of a
|
||||
/// class template specialization, retrieves the member specialization
|
||||
/// information.
|
||||
MemberSpecializationInfo *getMemberSpecializationInfo() const {
|
||||
return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
|
||||
}
|
||||
MemberSpecializationInfo *getMemberSpecializationInfo() const;
|
||||
|
||||
/// \brief Specify that this record is an instantiation of the
|
||||
/// member class \p RD.
|
||||
@ -1364,13 +1362,9 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// CXXRecordDecl that from a ClassTemplateDecl, while
|
||||
/// getDescribedClassTemplate() retrieves the ClassTemplateDecl from
|
||||
/// a CXXRecordDecl.
|
||||
ClassTemplateDecl *getDescribedClassTemplate() const {
|
||||
return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl*>();
|
||||
}
|
||||
ClassTemplateDecl *getDescribedClassTemplate() const;
|
||||
|
||||
void setDescribedClassTemplate(ClassTemplateDecl *Template) {
|
||||
TemplateOrInstantiation = Template;
|
||||
}
|
||||
void setDescribedClassTemplate(ClassTemplateDecl *Template);
|
||||
|
||||
/// \brief Determine whether this particular class is a specialization or
|
||||
/// instantiation of a class template or member class of a class template,
|
||||
@ -1468,8 +1462,8 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \param BaseDefinition the definition of the base class
|
||||
///
|
||||
/// \returns true if this base matched the search criteria
|
||||
typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition,
|
||||
void *UserData);
|
||||
typedef llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>
|
||||
ForallBasesCallback;
|
||||
|
||||
/// \brief Determines if the given callback holds for all the direct
|
||||
/// or indirect base classes of this type.
|
||||
@ -1481,13 +1475,10 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// class of this type, or if \p AllowShortCircuit is true then until a call
|
||||
/// returns false.
|
||||
///
|
||||
/// \param UserData Passed as the second argument of every call to
|
||||
/// \p BaseMatches.
|
||||
///
|
||||
/// \param AllowShortCircuit if false, forces the callback to be called
|
||||
/// for every base class, even if a dependent or non-matching base was
|
||||
/// found.
|
||||
bool forallBases(ForallBasesCallback *BaseMatches, void *UserData,
|
||||
bool forallBases(ForallBasesCallback BaseMatches,
|
||||
bool AllowShortCircuit = true) const;
|
||||
|
||||
/// \brief Function type used by lookupInBases() to determine whether a
|
||||
@ -1499,13 +1490,9 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \param Path the current path, from the most-derived class down to the
|
||||
/// base named by the \p Specifier.
|
||||
///
|
||||
/// \param UserData a single pointer to user-specified data, provided to
|
||||
/// lookupInBases().
|
||||
///
|
||||
/// \returns true if this base matched the search criteria, false otherwise.
|
||||
typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path,
|
||||
void *UserData);
|
||||
typedef llvm::function_ref<bool(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path)> BaseMatchesCallback;
|
||||
|
||||
/// \brief Look for entities within the base classes of this C++ class,
|
||||
/// transitively searching all base class subobjects.
|
||||
@ -1520,14 +1507,12 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \param BaseMatches callback function used to determine whether a given
|
||||
/// base matches the user-defined search criteria.
|
||||
///
|
||||
/// \param UserData user data pointer that will be provided to \p BaseMatches.
|
||||
///
|
||||
/// \param Paths used to record the paths from this class to its base class
|
||||
/// subobjects that match the search criteria.
|
||||
///
|
||||
/// \returns true if there exists any path from this class to a base class
|
||||
/// subobject that matches the search criteria.
|
||||
bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData,
|
||||
bool lookupInBases(BaseMatchesCallback BaseMatches,
|
||||
CXXBasePaths &Paths) const;
|
||||
|
||||
/// \brief Base-class lookup callback that determines whether the given
|
||||
@ -1535,10 +1520,10 @@ class CXXRecordDecl : public RecordDecl {
|
||||
///
|
||||
/// This callback can be used with \c lookupInBases() to determine whether
|
||||
/// a given derived class has is a base class subobject of a particular type.
|
||||
/// The user data pointer should refer to the canonical CXXRecordDecl of the
|
||||
/// The base record pointer should refer to the canonical CXXRecordDecl of the
|
||||
/// base class that we are searching for.
|
||||
static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path, void *BaseRecord);
|
||||
CXXBasePath &Path, const CXXRecordDecl *BaseRecord);
|
||||
|
||||
/// \brief Base-class lookup callback that determines whether the
|
||||
/// given base class specifier refers to a specific class
|
||||
@ -1546,39 +1531,38 @@ class CXXRecordDecl : public RecordDecl {
|
||||
///
|
||||
/// This callback can be used with \c lookupInBases() to determine
|
||||
/// whether a given derived class has is a virtual base class
|
||||
/// subobject of a particular type. The user data pointer should
|
||||
/// subobject of a particular type. The base record pointer should
|
||||
/// refer to the canonical CXXRecordDecl of the base class that we
|
||||
/// are searching for.
|
||||
static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path, void *BaseRecord);
|
||||
CXXBasePath &Path,
|
||||
const CXXRecordDecl *BaseRecord);
|
||||
|
||||
/// \brief Base-class lookup callback that determines whether there exists
|
||||
/// a tag with the given name.
|
||||
///
|
||||
/// This callback can be used with \c lookupInBases() to find tag members
|
||||
/// of the given name within a C++ class hierarchy. The user data pointer
|
||||
/// is an opaque \c DeclarationName pointer.
|
||||
/// of the given name within a C++ class hierarchy.
|
||||
static bool FindTagMember(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path, void *Name);
|
||||
CXXBasePath &Path, DeclarationName Name);
|
||||
|
||||
/// \brief Base-class lookup callback that determines whether there exists
|
||||
/// a member with the given name.
|
||||
///
|
||||
/// This callback can be used with \c lookupInBases() to find members
|
||||
/// of the given name within a C++ class hierarchy. The user data pointer
|
||||
/// is an opaque \c DeclarationName pointer.
|
||||
/// of the given name within a C++ class hierarchy.
|
||||
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path, void *Name);
|
||||
CXXBasePath &Path, DeclarationName Name);
|
||||
|
||||
/// \brief Base-class lookup callback that determines whether there exists
|
||||
/// a member with the given name that can be used in a nested-name-specifier.
|
||||
///
|
||||
/// This callback can be used with \c lookupInBases() to find membes of
|
||||
/// This callback can be used with \c lookupInBases() to find members of
|
||||
/// the given name within a C++ class hierarchy that can occur within
|
||||
/// nested-name-specifiers.
|
||||
static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path,
|
||||
void *UserData);
|
||||
DeclarationName Name);
|
||||
|
||||
/// \brief Retrieve the final overriders for each virtual member
|
||||
/// function in the class hierarchy where this class is the
|
||||
@ -1898,7 +1882,8 @@ class CXXMethodDecl : public FunctionDecl {
|
||||
/// B(A& a) : A(a), f(3.14159) { }
|
||||
/// };
|
||||
/// \endcode
|
||||
class CXXCtorInitializer {
|
||||
class CXXCtorInitializer final
|
||||
: private llvm::TrailingObjects<CXXCtorInitializer, VarDecl *> {
|
||||
/// \brief Either the base class name/delegating constructor type (stored as
|
||||
/// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field
|
||||
/// (IndirectFieldDecl*) being initialized.
|
||||
@ -2114,24 +2099,26 @@ class CXXCtorInitializer {
|
||||
/// describe an array member initialization.
|
||||
VarDecl *getArrayIndex(unsigned I) {
|
||||
assert(I < getNumArrayIndices() && "Out of bounds member array index");
|
||||
return reinterpret_cast<VarDecl **>(this + 1)[I];
|
||||
return getTrailingObjects<VarDecl *>()[I];
|
||||
}
|
||||
const VarDecl *getArrayIndex(unsigned I) const {
|
||||
assert(I < getNumArrayIndices() && "Out of bounds member array index");
|
||||
return reinterpret_cast<const VarDecl * const *>(this + 1)[I];
|
||||
return getTrailingObjects<VarDecl *>()[I];
|
||||
}
|
||||
void setArrayIndex(unsigned I, VarDecl *Index) {
|
||||
assert(I < getNumArrayIndices() && "Out of bounds member array index");
|
||||
reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
|
||||
getTrailingObjects<VarDecl *>()[I] = Index;
|
||||
}
|
||||
ArrayRef<VarDecl *> getArrayIndexes() {
|
||||
assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init");
|
||||
return llvm::makeArrayRef(reinterpret_cast<VarDecl **>(this + 1),
|
||||
return llvm::makeArrayRef(getTrailingObjects<VarDecl *>(),
|
||||
getNumArrayIndices());
|
||||
}
|
||||
|
||||
/// \brief Get the initializer.
|
||||
Expr *getInit() const { return static_cast<Expr*>(Init); }
|
||||
|
||||
friend TrailingObjects;
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ constructor within a class.
|
||||
@ -2289,14 +2276,14 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
}
|
||||
|
||||
/// \brief Determine whether this constructor is a move constructor
|
||||
/// (C++0x [class.copy]p3), which can be used to move values of the class.
|
||||
/// (C++11 [class.copy]p3), which can be used to move values of the class.
|
||||
///
|
||||
/// \param TypeQuals If this constructor is a move constructor, will be set
|
||||
/// to the type qualifiers on the referent of the first parameter's type.
|
||||
bool isMoveConstructor(unsigned &TypeQuals) const;
|
||||
|
||||
/// \brief Determine whether this constructor is a move constructor
|
||||
/// (C++0x [class.copy]p3), which can be used to move values of the class.
|
||||
/// (C++11 [class.copy]p3), which can be used to move values of the class.
|
||||
bool isMoveConstructor() const {
|
||||
unsigned TypeQuals = 0;
|
||||
return isMoveConstructor(TypeQuals);
|
||||
@ -2406,7 +2393,7 @@ class CXXConversionDecl : public CXXMethodDecl {
|
||||
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.
|
||||
/// explicitly wrote a cast. This is a C++11 feature.
|
||||
bool IsExplicitSpecified : 1;
|
||||
|
||||
CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
|
@ -37,7 +37,9 @@ namespace clang {
|
||||
/// @endcode
|
||||
///
|
||||
/// The semantic context of a friend decl is its declaring class.
|
||||
class FriendDecl : public Decl {
|
||||
class FriendDecl final
|
||||
: public Decl,
|
||||
private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
|
||||
virtual void anchor();
|
||||
public:
|
||||
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
|
||||
@ -62,14 +64,6 @@ class FriendDecl : public Decl {
|
||||
// template <class T> friend class A<T>::B;
|
||||
unsigned NumTPLists : 31;
|
||||
|
||||
// The tail-allocated friend type template parameter lists (if any).
|
||||
TemplateParameterList* const *getTPLists() const {
|
||||
return reinterpret_cast<TemplateParameterList* const *>(this + 1);
|
||||
}
|
||||
TemplateParameterList **getTPLists() {
|
||||
return reinterpret_cast<TemplateParameterList**>(this + 1);
|
||||
}
|
||||
|
||||
friend class CXXRecordDecl::friend_iterator;
|
||||
friend class CXXRecordDecl;
|
||||
|
||||
@ -83,7 +77,7 @@ class FriendDecl : public Decl {
|
||||
UnsupportedFriend(false),
|
||||
NumTPLists(FriendTypeTPLists.size()) {
|
||||
for (unsigned i = 0; i < NumTPLists; ++i)
|
||||
getTPLists()[i] = FriendTypeTPLists[i];
|
||||
getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i];
|
||||
}
|
||||
|
||||
FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
|
||||
@ -118,7 +112,7 @@ class FriendDecl : public Decl {
|
||||
}
|
||||
TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
|
||||
assert(N < NumTPLists);
|
||||
return getTPLists()[N];
|
||||
return getTrailingObjects<TemplateParameterList *>()[N];
|
||||
}
|
||||
|
||||
/// If this friend declaration doesn't name a type, return the inner
|
||||
@ -148,9 +142,10 @@ class FriendDecl : public Decl {
|
||||
return SourceRange(getFriendLoc(), ND->getLocEnd());
|
||||
}
|
||||
else if (TypeSourceInfo *TInfo = getFriendType()) {
|
||||
SourceLocation StartL = (NumTPLists == 0)
|
||||
? getFriendLoc()
|
||||
: getTPLists()[0]->getTemplateLoc();
|
||||
SourceLocation StartL =
|
||||
(NumTPLists == 0) ? getFriendLoc()
|
||||
: getTrailingObjects<TemplateParameterList *>()[0]
|
||||
->getTemplateLoc();
|
||||
return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc());
|
||||
}
|
||||
else
|
||||
@ -171,6 +166,7 @@ class FriendDecl : public Decl {
|
||||
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
friend TrailingObjects;
|
||||
};
|
||||
|
||||
/// An iterator over the friend declarations of a class.
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define LLVM_CLANG_AST_DECLGROUP_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/TrailingObjects.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace clang {
|
||||
@ -24,13 +25,9 @@ class Decl;
|
||||
class DeclGroup;
|
||||
class DeclGroupIterator;
|
||||
|
||||
class DeclGroup {
|
||||
class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> {
|
||||
// FIXME: Include a TypeSpecifier object.
|
||||
union {
|
||||
unsigned NumDecls;
|
||||
|
||||
Decl *Aligner;
|
||||
};
|
||||
unsigned NumDecls;
|
||||
|
||||
private:
|
||||
DeclGroup() : NumDecls(0) {}
|
||||
@ -43,13 +40,15 @@ class DeclGroup {
|
||||
|
||||
Decl*& operator[](unsigned i) {
|
||||
assert (i < NumDecls && "Out-of-bounds access.");
|
||||
return ((Decl**) (this+1))[i];
|
||||
return getTrailingObjects<Decl *>()[i];
|
||||
}
|
||||
|
||||
Decl* const& operator[](unsigned i) const {
|
||||
assert (i < NumDecls && "Out-of-bounds access.");
|
||||
return ((Decl* const*) (this+1))[i];
|
||||
return getTrailingObjects<Decl *>()[i];
|
||||
}
|
||||
|
||||
friend TrailingObjects;
|
||||
};
|
||||
|
||||
class DeclGroupRef {
|
||||
|
@ -612,7 +612,8 @@ class ObjCTypeParamDecl : public TypedefNameDecl {
|
||||
/// @interface NSArray<T> // stores the <T>
|
||||
/// @end
|
||||
/// \endcode
|
||||
class ObjCTypeParamList {
|
||||
class ObjCTypeParamList final
|
||||
: private llvm::TrailingObjects<ObjCTypeParamList, ObjCTypeParamDecl *> {
|
||||
/// Stores the components of a SourceRange as a POD.
|
||||
struct PODSourceRange {
|
||||
unsigned Begin;
|
||||
@ -644,7 +645,7 @@ class ObjCTypeParamList {
|
||||
/// Iterate through the type parameters in the list.
|
||||
typedef ObjCTypeParamDecl **iterator;
|
||||
|
||||
iterator begin() { return reinterpret_cast<ObjCTypeParamDecl **>(this + 1); }
|
||||
iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); }
|
||||
|
||||
iterator end() { return begin() + size(); }
|
||||
|
||||
@ -655,7 +656,7 @@ class ObjCTypeParamList {
|
||||
typedef ObjCTypeParamDecl * const *const_iterator;
|
||||
|
||||
const_iterator begin() const {
|
||||
return reinterpret_cast<ObjCTypeParamDecl * const *>(this + 1);
|
||||
return getTrailingObjects<ObjCTypeParamDecl *>();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
@ -685,6 +686,7 @@ class ObjCTypeParamList {
|
||||
/// Gather the default set of type arguments to be substituted for
|
||||
/// these type parameters when dealing with an unspecialized type.
|
||||
void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
|
||||
friend TrailingObjects;
|
||||
};
|
||||
|
||||
/// ObjCContainerDecl - Represents a container for method declarations.
|
||||
@ -1202,13 +1204,8 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
||||
// might bring in a definition.
|
||||
// Note: a null value indicates that we don't have a definition and that
|
||||
// modules are enabled.
|
||||
if (!Data.getOpaqueValue()) {
|
||||
if (IdentifierInfo *II = getIdentifier()) {
|
||||
if (II->isOutOfDate()) {
|
||||
updateOutOfDate(*II);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!Data.getOpaqueValue())
|
||||
getMostRecentDecl();
|
||||
|
||||
return Data.getPointer();
|
||||
}
|
||||
@ -1851,13 +1848,8 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
|
||||
// might bring in a definition.
|
||||
// Note: a null value indicates that we don't have a definition and that
|
||||
// modules are enabled.
|
||||
if (!Data.getOpaqueValue()) {
|
||||
if (IdentifierInfo *II = getIdentifier()) {
|
||||
if (II->isOutOfDate()) {
|
||||
updateOutOfDate(*II);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!Data.getOpaqueValue())
|
||||
getMostRecentDecl();
|
||||
|
||||
return Data.getPointer();
|
||||
}
|
||||
@ -2519,26 +2511,18 @@ class ObjCPropertyDecl : public NamedDecl {
|
||||
void setPropertyAttributes(PropertyAttributeKind PRVal) {
|
||||
PropertyAttributes |= PRVal;
|
||||
}
|
||||
void overwritePropertyAttributes(unsigned PRVal) {
|
||||
PropertyAttributes = PRVal;
|
||||
}
|
||||
|
||||
PropertyAttributeKind getPropertyAttributesAsWritten() const {
|
||||
return PropertyAttributeKind(PropertyAttributesAsWritten);
|
||||
}
|
||||
|
||||
bool hasWrittenStorageAttribute() const {
|
||||
return PropertyAttributesAsWritten & (OBJC_PR_assign | OBJC_PR_copy |
|
||||
OBJC_PR_unsafe_unretained | OBJC_PR_retain | OBJC_PR_strong |
|
||||
OBJC_PR_weak);
|
||||
}
|
||||
|
||||
void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
|
||||
PropertyAttributesAsWritten = PRVal;
|
||||
}
|
||||
|
||||
void makeitReadWriteAttribute() {
|
||||
PropertyAttributes &= ~OBJC_PR_readonly;
|
||||
PropertyAttributes |= OBJC_PR_readwrite;
|
||||
}
|
||||
|
||||
// Helper methods for accessing attributes.
|
||||
|
||||
/// isReadOnly - Return true iff the property has a setter.
|
||||
|
@ -33,8 +33,12 @@ class Expr;
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
class OMPThreadPrivateDecl : public Decl {
|
||||
class OMPThreadPrivateDecl final
|
||||
: public Decl,
|
||||
private llvm::TrailingObjects<OMPThreadPrivateDecl, Expr *> {
|
||||
friend class ASTDeclReader;
|
||||
friend TrailingObjects;
|
||||
|
||||
unsigned NumVars;
|
||||
|
||||
virtual void anchor();
|
||||
@ -43,14 +47,11 @@ class OMPThreadPrivateDecl : public Decl {
|
||||
Decl(DK, DC, L), NumVars(0) { }
|
||||
|
||||
ArrayRef<const Expr *> getVars() const {
|
||||
return llvm::makeArrayRef(reinterpret_cast<const Expr * const *>(this + 1),
|
||||
NumVars);
|
||||
return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
|
||||
}
|
||||
|
||||
MutableArrayRef<Expr *> getVars() {
|
||||
return MutableArrayRef<Expr *>(
|
||||
reinterpret_cast<Expr **>(this + 1),
|
||||
NumVars);
|
||||
return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
|
||||
}
|
||||
|
||||
void setVars(ArrayRef<Expr *> VL);
|
||||
|
@ -20,10 +20,12 @@
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/TrailingObjects.h"
|
||||
#include <limits>
|
||||
|
||||
namespace clang {
|
||||
|
||||
enum BuiltinTemplateKind : int;
|
||||
class TemplateParameterList;
|
||||
class TemplateDecl;
|
||||
class RedeclarableTemplateDecl;
|
||||
@ -43,7 +45,9 @@ typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
|
||||
|
||||
/// \brief Stores a list of template parameters for a TemplateDecl and its
|
||||
/// derived classes.
|
||||
class TemplateParameterList {
|
||||
class TemplateParameterList final
|
||||
: private llvm::TrailingObjects<TemplateParameterList, NamedDecl *> {
|
||||
|
||||
/// The location of the 'template' keyword.
|
||||
SourceLocation TemplateLoc;
|
||||
|
||||
@ -59,16 +63,18 @@ class TemplateParameterList {
|
||||
unsigned ContainsUnexpandedParameterPack : 1;
|
||||
|
||||
protected:
|
||||
size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
|
||||
return NumParams;
|
||||
}
|
||||
|
||||
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
|
||||
NamedDecl **Params, unsigned NumParams,
|
||||
SourceLocation RAngleLoc);
|
||||
ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc);
|
||||
|
||||
public:
|
||||
static TemplateParameterList *Create(const ASTContext &C,
|
||||
SourceLocation TemplateLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
NamedDecl **Params,
|
||||
unsigned NumParams,
|
||||
ArrayRef<NamedDecl *> Params,
|
||||
SourceLocation RAngleLoc);
|
||||
|
||||
/// \brief Iterates through the template parameters in this list.
|
||||
@ -77,10 +83,8 @@ class TemplateParameterList {
|
||||
/// \brief Iterates through the template parameters in this list.
|
||||
typedef NamedDecl* const* const_iterator;
|
||||
|
||||
iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); }
|
||||
const_iterator begin() const {
|
||||
return reinterpret_cast<NamedDecl * const *>(this + 1);
|
||||
}
|
||||
iterator begin() { return getTrailingObjects<NamedDecl *>(); }
|
||||
const_iterator begin() const { return getTrailingObjects<NamedDecl *>(); }
|
||||
iterator end() { return begin() + NumParams; }
|
||||
const_iterator end() const { return begin() + NumParams; }
|
||||
|
||||
@ -130,29 +134,45 @@ class TemplateParameterList {
|
||||
SourceRange getSourceRange() const LLVM_READONLY {
|
||||
return SourceRange(TemplateLoc, RAngleLoc);
|
||||
}
|
||||
|
||||
friend TrailingObjects;
|
||||
template <size_t N> friend class FixedSizeTemplateParameterListStorage;
|
||||
};
|
||||
|
||||
/// \brief Stores a list of template parameters for a TemplateDecl and its
|
||||
/// derived classes. Suitable for creating on the stack.
|
||||
template<size_t N>
|
||||
class FixedSizeTemplateParameterList : public TemplateParameterList {
|
||||
template <size_t N> class FixedSizeTemplateParameterListStorage {
|
||||
// This is kinda ugly: TemplateParameterList usually gets allocated
|
||||
// in a block of memory with NamedDecls appended to it. Here, to get
|
||||
// it stack allocated, we include the params as a separate
|
||||
// variable. After allocation, the TemplateParameterList object
|
||||
// treats them as part of itself.
|
||||
TemplateParameterList List;
|
||||
NamedDecl *Params[N];
|
||||
|
||||
public:
|
||||
FixedSizeTemplateParameterList(SourceLocation TemplateLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
NamedDecl **Params, SourceLocation RAngleLoc) :
|
||||
TemplateParameterList(TemplateLoc, LAngleLoc, Params, N, RAngleLoc) {
|
||||
FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ArrayRef<NamedDecl *> Params,
|
||||
SourceLocation RAngleLoc)
|
||||
: List(TemplateLoc, LAngleLoc, Params, RAngleLoc) {
|
||||
// Because we're doing an evil layout hack above, have some
|
||||
// asserts, just to double-check everything is laid out like
|
||||
// expected.
|
||||
assert(sizeof(*this) ==
|
||||
TemplateParameterList::totalSizeToAlloc<NamedDecl *>(N) &&
|
||||
"Object layout not as expected");
|
||||
assert(this->Params == List.getTrailingObjects<NamedDecl *>() &&
|
||||
"Object layout not as expected");
|
||||
}
|
||||
TemplateParameterList *get() { return &List; }
|
||||
};
|
||||
|
||||
/// \brief A template argument list.
|
||||
class TemplateArgumentList {
|
||||
class TemplateArgumentList final
|
||||
: private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> {
|
||||
/// \brief The template argument list.
|
||||
///
|
||||
/// The integer value will be non-zero to indicate that this
|
||||
/// template argument list does own the pointer.
|
||||
llvm::PointerIntPair<const TemplateArgument *, 1> Arguments;
|
||||
const TemplateArgument *Arguments;
|
||||
|
||||
/// \brief The number of template arguments in this template
|
||||
/// argument list.
|
||||
@ -161,9 +181,9 @@ class TemplateArgumentList {
|
||||
TemplateArgumentList(const TemplateArgumentList &Other) = delete;
|
||||
void operator=(const TemplateArgumentList &Other) = delete;
|
||||
|
||||
TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs,
|
||||
bool Owned)
|
||||
: Arguments(Args, Owned), NumArguments(NumArgs) { }
|
||||
// Constructs an instance with an internal Argument list, containing
|
||||
// a copy of the Args array. (Called by CreateCopy)
|
||||
TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs);
|
||||
|
||||
public:
|
||||
/// \brief Type used to indicate that the template argument list itself is a
|
||||
@ -180,9 +200,9 @@ class TemplateArgumentList {
|
||||
///
|
||||
/// The template argument list does not own the template arguments
|
||||
/// provided.
|
||||
explicit TemplateArgumentList(OnStackType,
|
||||
const TemplateArgument *Args, unsigned NumArgs)
|
||||
: Arguments(Args, false), NumArguments(NumArgs) { }
|
||||
explicit TemplateArgumentList(OnStackType, const TemplateArgument *Args,
|
||||
unsigned NumArgs)
|
||||
: Arguments(Args), NumArguments(NumArgs) {}
|
||||
|
||||
/// \brief Produces a shallow copy of the given template argument list.
|
||||
///
|
||||
@ -191,7 +211,7 @@ class TemplateArgumentList {
|
||||
/// constructor, since this really really isn't safe to use that
|
||||
/// way.
|
||||
explicit TemplateArgumentList(const TemplateArgumentList *Other)
|
||||
: Arguments(Other->data(), false), NumArguments(Other->size()) { }
|
||||
: Arguments(Other->data()), NumArguments(Other->size()) {}
|
||||
|
||||
/// \brief Retrieve the template argument at a given index.
|
||||
const TemplateArgument &get(unsigned Idx) const {
|
||||
@ -212,9 +232,9 @@ class TemplateArgumentList {
|
||||
unsigned size() const { return NumArguments; }
|
||||
|
||||
/// \brief Retrieve a pointer to the template argument list.
|
||||
const TemplateArgument *data() const {
|
||||
return Arguments.getPointer();
|
||||
}
|
||||
const TemplateArgument *data() const { return Arguments; }
|
||||
|
||||
friend TrailingObjects;
|
||||
};
|
||||
|
||||
void *allocateDefaultArgStorageChain(const ASTContext &C);
|
||||
@ -426,17 +446,8 @@ class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
|
||||
/// explicit instantiation declaration, or explicit instantiation
|
||||
/// definition.
|
||||
bool isExplicitInstantiationOrSpecialization() const {
|
||||
switch (getTemplateSpecializationKind()) {
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return true;
|
||||
|
||||
case TSK_Undeclared:
|
||||
case TSK_ImplicitInstantiation:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("bad template specialization kind");
|
||||
return isTemplateExplicitInstantiationOrSpecialization(
|
||||
getTemplateSpecializationKind());
|
||||
}
|
||||
|
||||
/// \brief Set the template specialization kind.
|
||||
@ -542,56 +553,52 @@ class MemberSpecializationInfo {
|
||||
/// friend void foo<>(T);
|
||||
/// };
|
||||
/// \endcode
|
||||
class DependentFunctionTemplateSpecializationInfo {
|
||||
struct CA {
|
||||
/// The number of potential template candidates.
|
||||
unsigned NumTemplates;
|
||||
class DependentFunctionTemplateSpecializationInfo final
|
||||
: private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo,
|
||||
TemplateArgumentLoc,
|
||||
FunctionTemplateDecl *> {
|
||||
/// The number of potential template candidates.
|
||||
unsigned NumTemplates;
|
||||
|
||||
/// The number of template arguments.
|
||||
unsigned NumArgs;
|
||||
};
|
||||
|
||||
union {
|
||||
// Force sizeof to be a multiple of sizeof(void*) so that the
|
||||
// trailing data is aligned.
|
||||
void *Aligner;
|
||||
struct CA d;
|
||||
};
|
||||
/// The number of template arguments.
|
||||
unsigned NumArgs;
|
||||
|
||||
/// The locations of the left and right angle brackets.
|
||||
SourceRange AngleLocs;
|
||||
|
||||
FunctionTemplateDecl * const *getTemplates() const {
|
||||
return reinterpret_cast<FunctionTemplateDecl*const*>(this+1);
|
||||
size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
|
||||
return NumArgs;
|
||||
}
|
||||
size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const {
|
||||
return NumTemplates;
|
||||
}
|
||||
|
||||
public:
|
||||
DependentFunctionTemplateSpecializationInfo(
|
||||
const UnresolvedSetImpl &Templates,
|
||||
const TemplateArgumentListInfo &TemplateArgs);
|
||||
|
||||
public:
|
||||
static DependentFunctionTemplateSpecializationInfo *
|
||||
Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
|
||||
const TemplateArgumentListInfo &TemplateArgs);
|
||||
|
||||
/// \brief Returns the number of function templates that this might
|
||||
/// be a specialization of.
|
||||
unsigned getNumTemplates() const {
|
||||
return d.NumTemplates;
|
||||
}
|
||||
unsigned getNumTemplates() const { return NumTemplates; }
|
||||
|
||||
/// \brief Returns the i'th template candidate.
|
||||
FunctionTemplateDecl *getTemplate(unsigned I) const {
|
||||
assert(I < getNumTemplates() && "template index out of range");
|
||||
return getTemplates()[I];
|
||||
return getTrailingObjects<FunctionTemplateDecl *>()[I];
|
||||
}
|
||||
|
||||
/// \brief Returns the explicit template arguments that were given.
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
return reinterpret_cast<const TemplateArgumentLoc*>(
|
||||
&getTemplates()[getNumTemplates()]);
|
||||
return getTrailingObjects<TemplateArgumentLoc>();
|
||||
}
|
||||
|
||||
/// \brief Returns the number of explicit template arguments that were given.
|
||||
unsigned getNumTemplateArgs() const {
|
||||
return d.NumArgs;
|
||||
}
|
||||
unsigned getNumTemplateArgs() const { return NumArgs; }
|
||||
|
||||
/// \brief Returns the nth template argument.
|
||||
const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
|
||||
@ -606,6 +613,8 @@ class DependentFunctionTemplateSpecializationInfo {
|
||||
SourceLocation getRAngleLoc() const {
|
||||
return AngleLocs.getEnd();
|
||||
}
|
||||
|
||||
friend TrailingObjects;
|
||||
};
|
||||
|
||||
/// Declaration of a redeclarable template.
|
||||
@ -926,7 +935,7 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
|
||||
return const_cast<FunctionTemplateDecl*>(this)->getMostRecentDecl();
|
||||
}
|
||||
|
||||
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() const {
|
||||
return cast_or_null<FunctionTemplateDecl>(
|
||||
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
|
||||
}
|
||||
@ -1120,8 +1129,11 @@ class TemplateTypeParmDecl : public TypeDecl {
|
||||
/// @code
|
||||
/// template<int Size> class array { };
|
||||
/// @endcode
|
||||
class NonTypeTemplateParmDecl
|
||||
: public DeclaratorDecl, protected TemplateParmPosition {
|
||||
class NonTypeTemplateParmDecl final
|
||||
: public DeclaratorDecl,
|
||||
protected TemplateParmPosition,
|
||||
private llvm::TrailingObjects<NonTypeTemplateParmDecl,
|
||||
std::pair<QualType, TypeSourceInfo *>> {
|
||||
/// \brief The default template argument, if any, and whether or not
|
||||
/// it was inherited.
|
||||
typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage;
|
||||
@ -1141,6 +1153,11 @@ class NonTypeTemplateParmDecl
|
||||
/// \brief The number of types in an expanded parameter pack.
|
||||
unsigned NumExpandedTypes;
|
||||
|
||||
size_t numTrailingObjects(
|
||||
OverloadToken<std::pair<QualType, TypeSourceInfo *>>) const {
|
||||
return NumExpandedTypes;
|
||||
}
|
||||
|
||||
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, unsigned D, unsigned P,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
@ -1159,6 +1176,7 @@ class NonTypeTemplateParmDecl
|
||||
TypeSourceInfo **ExpandedTInfos);
|
||||
|
||||
friend class ASTDeclReader;
|
||||
friend TrailingObjects;
|
||||
|
||||
public:
|
||||
static NonTypeTemplateParmDecl *
|
||||
@ -1274,16 +1292,18 @@ class NonTypeTemplateParmDecl
|
||||
/// pack.
|
||||
QualType getExpansionType(unsigned I) const {
|
||||
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
|
||||
void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
|
||||
return QualType::getFromOpaquePtr(TypesAndInfos[2*I]);
|
||||
auto TypesAndInfos =
|
||||
getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
|
||||
return TypesAndInfos[I].first;
|
||||
}
|
||||
|
||||
/// \brief Retrieve a particular expansion type source info within an
|
||||
/// expanded parameter pack.
|
||||
TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const {
|
||||
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
|
||||
void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
|
||||
return static_cast<TypeSourceInfo *>(TypesAndInfos[2*I+1]);
|
||||
auto TypesAndInfos =
|
||||
getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
|
||||
return TypesAndInfos[I].second;
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
@ -1298,9 +1318,11 @@ class NonTypeTemplateParmDecl
|
||||
/// @endcode
|
||||
/// A template template parameter is a TemplateDecl because it defines the
|
||||
/// name of a template and the template parameters allowable for substitution.
|
||||
class TemplateTemplateParmDecl : public TemplateDecl,
|
||||
protected TemplateParmPosition
|
||||
{
|
||||
class TemplateTemplateParmDecl final
|
||||
: public TemplateDecl,
|
||||
protected TemplateParmPosition,
|
||||
private llvm::TrailingObjects<TemplateTemplateParmDecl,
|
||||
TemplateParameterList *> {
|
||||
void anchor() override;
|
||||
|
||||
/// \brief The default template argument, if any.
|
||||
@ -1404,7 +1426,7 @@ class TemplateTemplateParmDecl : public TemplateDecl,
|
||||
/// pack.
|
||||
TemplateParameterList *getExpansionTemplateParameters(unsigned I) const {
|
||||
assert(I < NumExpandedParams && "Out-of-range expansion type index");
|
||||
return reinterpret_cast<TemplateParameterList *const *>(this + 1)[I];
|
||||
return getTrailingObjects<TemplateParameterList *>()[I];
|
||||
}
|
||||
|
||||
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
|
||||
@ -1454,6 +1476,36 @@ class TemplateTemplateParmDecl : public TemplateDecl,
|
||||
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
friend TrailingObjects;
|
||||
};
|
||||
|
||||
/// \brief Represents the builtin template declaration which is used to
|
||||
/// implement __make_integer_seq. It serves no real purpose beyond existing as
|
||||
/// a place to hold template parameters.
|
||||
class BuiltinTemplateDecl : public TemplateDecl {
|
||||
void anchor() override;
|
||||
|
||||
BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
|
||||
DeclarationName Name, BuiltinTemplateKind BTK);
|
||||
|
||||
BuiltinTemplateKind BTK;
|
||||
|
||||
public:
|
||||
// Implement isa/cast/dyncast support
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == BuiltinTemplate; }
|
||||
|
||||
static BuiltinTemplateDecl *Create(const ASTContext &C, DeclContext *DC,
|
||||
DeclarationName Name,
|
||||
BuiltinTemplateKind BTK) {
|
||||
return new (C, DC) BuiltinTemplateDecl(C, DC, Name, BTK);
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
return SourceRange();
|
||||
}
|
||||
|
||||
BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
|
||||
};
|
||||
|
||||
/// \brief Represents a class template specialization, which refers to
|
||||
@ -1580,17 +1632,8 @@ class ClassTemplateSpecializationDecl
|
||||
/// explicit instantiation declaration, or explicit instantiation
|
||||
/// definition.
|
||||
bool isExplicitInstantiationOrSpecialization() const {
|
||||
switch (getTemplateSpecializationKind()) {
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return true;
|
||||
|
||||
case TSK_Undeclared:
|
||||
case TSK_ImplicitInstantiation:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("bad template specialization kind");
|
||||
return isTemplateExplicitInstantiationOrSpecialization(
|
||||
getTemplateSpecializationKind());
|
||||
}
|
||||
|
||||
void setSpecializationKind(TemplateSpecializationKind TSK) {
|
||||
@ -1819,8 +1862,8 @@ class ClassTemplatePartialSpecializationDecl
|
||||
/// template partial specialization \c Outer<T>::Inner<U*>. Given
|
||||
/// \c Outer<float>::Inner<U*>, this function would return
|
||||
/// \c Outer<T>::Inner<U*>.
|
||||
ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
|
||||
ClassTemplatePartialSpecializationDecl *First =
|
||||
ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
|
||||
const ClassTemplatePartialSpecializationDecl *First =
|
||||
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
|
||||
return First->InstantiatedFromMember.getPointer();
|
||||
}
|
||||
@ -2000,7 +2043,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
|
||||
return const_cast<ClassTemplateDecl*>(this)->getMostRecentDecl();
|
||||
}
|
||||
|
||||
ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||
ClassTemplateDecl *getInstantiatedFromMemberTemplate() const {
|
||||
return cast_or_null<ClassTemplateDecl>(
|
||||
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
|
||||
}
|
||||
@ -2230,7 +2273,7 @@ class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
|
||||
this)->getPreviousDecl());
|
||||
}
|
||||
|
||||
TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||
TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() const {
|
||||
return cast_or_null<TypeAliasTemplateDecl>(
|
||||
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
|
||||
}
|
||||
@ -2435,17 +2478,8 @@ class VarTemplateSpecializationDecl : public VarDecl,
|
||||
/// explicit instantiation declaration, or explicit instantiation
|
||||
/// definition.
|
||||
bool isExplicitInstantiationOrSpecialization() const {
|
||||
switch (getTemplateSpecializationKind()) {
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return true;
|
||||
|
||||
case TSK_Undeclared:
|
||||
case TSK_ImplicitInstantiation:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("bad template specialization kind");
|
||||
return isTemplateExplicitInstantiationOrSpecialization(
|
||||
getTemplateSpecializationKind());
|
||||
}
|
||||
|
||||
void setSpecializationKind(TemplateSpecializationKind TSK) {
|
||||
@ -2668,8 +2702,8 @@ class VarTemplatePartialSpecializationDecl
|
||||
/// variable template partial specialization \c Outer<T>::Inner<U*>. Given
|
||||
/// \c Outer<float>::Inner<U*>, this function would return
|
||||
/// \c Outer<T>::Inner<U*>.
|
||||
VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
|
||||
VarTemplatePartialSpecializationDecl *First =
|
||||
VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
|
||||
const VarTemplatePartialSpecializationDecl *First =
|
||||
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
|
||||
return First->InstantiatedFromMember.getPointer();
|
||||
}
|
||||
@ -2833,7 +2867,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
|
||||
return const_cast<VarTemplateDecl *>(this)->getMostRecentDecl();
|
||||
}
|
||||
|
||||
VarTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||
VarTemplateDecl *getInstantiatedFromMemberTemplate() const {
|
||||
return cast_or_null<VarTemplateDecl>(
|
||||
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
|
||||
}
|
||||
|
@ -88,8 +88,8 @@ class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> {
|
||||
|
||||
void VisitLambdaExpr(PTR(LambdaExpr) LE) {
|
||||
// Only visit the capture initializers, and not the body.
|
||||
for (LambdaExpr::capture_init_iterator I = LE->capture_init_begin(),
|
||||
E = LE->capture_init_end();
|
||||
for (LambdaExpr::const_capture_init_iterator I = LE->capture_init_begin(),
|
||||
E = LE->capture_init_end();
|
||||
I != E; ++I)
|
||||
if (*I)
|
||||
this->Visit(*I);
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -82,7 +82,9 @@ class ObjCBoolLiteralExpr : public Expr {
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// ObjCBoxedExpr - used for generalized expression boxing.
|
||||
@ -341,6 +343,8 @@ class ObjCDictionaryLiteral : public Expr {
|
||||
child_range children() {
|
||||
// Note: we're taking advantage of the layout of the KeyValuePair struct
|
||||
// here. If that struct changes, this code will need to change as well.
|
||||
static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2,
|
||||
"KeyValuePair is expected size");
|
||||
return child_range(reinterpret_cast<Stmt **>(this + 1),
|
||||
reinterpret_cast<Stmt **>(this + 1) + NumElements * 2);
|
||||
}
|
||||
@ -389,7 +393,9 @@ class ObjCEncodeExpr : public Expr {
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// ObjCSelectorExpr used for \@selector in Objective-C.
|
||||
@ -424,7 +430,9 @@ class ObjCSelectorExpr : public Expr {
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// ObjCProtocolExpr used for protocol expression in Objective-C.
|
||||
@ -464,7 +472,9 @@ class ObjCProtocolExpr : public Expr {
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
@ -713,7 +723,7 @@ class ObjCPropertyRefExpr : public Expr {
|
||||
Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
|
||||
return child_range(begin, begin+1);
|
||||
}
|
||||
return child_range();
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1350,6 +1360,14 @@ class ObjCMessageExpr : public Expr {
|
||||
typedef ExprIterator arg_iterator;
|
||||
typedef ConstExprIterator const_arg_iterator;
|
||||
|
||||
llvm::iterator_range<arg_iterator> arguments() {
|
||||
return llvm::make_range(arg_begin(), arg_end());
|
||||
}
|
||||
|
||||
llvm::iterator_range<const_arg_iterator> arguments() const {
|
||||
return llvm::make_range(arg_begin(), arg_end());
|
||||
}
|
||||
|
||||
arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
|
||||
arg_iterator arg_end() {
|
||||
return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
|
||||
@ -1503,11 +1521,15 @@ class ObjCIndirectCopyRestoreExpr : public Expr {
|
||||
/// \code
|
||||
/// NSString *str = (__bridge_transfer NSString *)CFCreateString();
|
||||
/// \endcode
|
||||
class ObjCBridgedCastExpr : public ExplicitCastExpr {
|
||||
class ObjCBridgedCastExpr final
|
||||
: public ExplicitCastExpr,
|
||||
private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
|
||||
SourceLocation LParenLoc;
|
||||
SourceLocation BridgeKeywordLoc;
|
||||
unsigned Kind : 2;
|
||||
|
||||
|
||||
friend TrailingObjects;
|
||||
friend class CastExpr;
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
|
||||
|
129
contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h
Normal file
129
contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h
Normal file
@ -0,0 +1,129 @@
|
||||
//===--- ExprOpenMP.h - Classes for representing expressions ----*- 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 Expr interface and subclasses.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_EXPROPENMP_H
|
||||
#define LLVM_CLANG_AST_EXPROPENMP_H
|
||||
|
||||
#include "clang/AST/Expr.h"
|
||||
|
||||
namespace clang {
|
||||
/// \brief OpenMP 4.0 [2.4, Array Sections].
|
||||
/// To specify an array section in an OpenMP construct, array subscript
|
||||
/// expressions are extended with the following syntax:
|
||||
/// \code
|
||||
/// [ lower-bound : length ]
|
||||
/// [ lower-bound : ]
|
||||
/// [ : length ]
|
||||
/// [ : ]
|
||||
/// \endcode
|
||||
/// The array section must be a subset of the original array.
|
||||
/// Array sections are allowed on multidimensional arrays. Base language array
|
||||
/// subscript expressions can be used to specify length-one dimensions of
|
||||
/// multidimensional array sections.
|
||||
/// The lower-bound and length are integral type expressions. When evaluated
|
||||
/// they represent a set of integer values as follows:
|
||||
/// \code
|
||||
/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length -
|
||||
/// 1 }
|
||||
/// \endcode
|
||||
/// The lower-bound and length must evaluate to non-negative integers.
|
||||
/// When the size of the array dimension is not known, the length must be
|
||||
/// specified explicitly.
|
||||
/// When the length is absent, it defaults to the size of the array dimension
|
||||
/// minus the lower-bound.
|
||||
/// When the lower-bound is absent it defaults to 0.
|
||||
class OMPArraySectionExpr : public Expr {
|
||||
enum { BASE, LOWER_BOUND, LENGTH, END_EXPR };
|
||||
Stmt *SubExprs[END_EXPR];
|
||||
SourceLocation ColonLoc;
|
||||
SourceLocation RBracketLoc;
|
||||
|
||||
public:
|
||||
OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
|
||||
ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation ColonLoc, SourceLocation RBracketLoc)
|
||||
: Expr(
|
||||
OMPArraySectionExprClass, Type, VK, OK,
|
||||
Base->isTypeDependent() ||
|
||||
(LowerBound && LowerBound->isTypeDependent()) ||
|
||||
(Length && Length->isTypeDependent()),
|
||||
Base->isValueDependent() ||
|
||||
(LowerBound && LowerBound->isValueDependent()) ||
|
||||
(Length && Length->isValueDependent()),
|
||||
Base->isInstantiationDependent() ||
|
||||
(LowerBound && LowerBound->isInstantiationDependent()) ||
|
||||
(Length && Length->isInstantiationDependent()),
|
||||
Base->containsUnexpandedParameterPack() ||
|
||||
(LowerBound && LowerBound->containsUnexpandedParameterPack()) ||
|
||||
(Length && Length->containsUnexpandedParameterPack())),
|
||||
ColonLoc(ColonLoc), RBracketLoc(RBracketLoc) {
|
||||
SubExprs[BASE] = Base;
|
||||
SubExprs[LOWER_BOUND] = LowerBound;
|
||||
SubExprs[LENGTH] = Length;
|
||||
}
|
||||
|
||||
/// \brief Create an empty array section expression.
|
||||
explicit OMPArraySectionExpr(EmptyShell Shell)
|
||||
: Expr(OMPArraySectionExprClass, Shell) {}
|
||||
|
||||
/// An array section can be written only as Base[LowerBound:Length].
|
||||
|
||||
/// \brief Get base of the array section.
|
||||
Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
|
||||
const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
|
||||
/// \brief Set base of the array section.
|
||||
void setBase(Expr *E) { SubExprs[BASE] = E; }
|
||||
|
||||
/// \brief Return original type of the base expression for array section.
|
||||
static QualType getBaseOriginalType(Expr *Base);
|
||||
|
||||
/// \brief Get lower bound of array section.
|
||||
Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
|
||||
const Expr *getLowerBound() const {
|
||||
return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
|
||||
}
|
||||
/// \brief Set lower bound of the array section.
|
||||
void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
|
||||
|
||||
/// \brief Get length of array section.
|
||||
Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
|
||||
const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
|
||||
/// \brief Set length of the array section.
|
||||
void setLength(Expr *E) { SubExprs[LENGTH] = E; }
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY {
|
||||
return getBase()->getLocStart();
|
||||
}
|
||||
SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
|
||||
|
||||
SourceLocation getColonLoc() const { return ColonLoc; }
|
||||
void setColonLoc(SourceLocation L) { ColonLoc = L; }
|
||||
|
||||
SourceLocation getRBracketLoc() const { return RBracketLoc; }
|
||||
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
|
||||
|
||||
SourceLocation getExprLoc() const LLVM_READONLY {
|
||||
return getBase()->getExprLoc();
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPArraySectionExprClass;
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
|
||||
}
|
||||
};
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
@ -33,20 +33,6 @@ class Selector;
|
||||
class Stmt;
|
||||
class TagDecl;
|
||||
|
||||
/// \brief Enumeration describing the result of loading information from
|
||||
/// an external source.
|
||||
enum ExternalLoadResult {
|
||||
/// \brief Loading the external information has succeeded.
|
||||
ELR_Success,
|
||||
|
||||
/// \brief Loading the external information has failed.
|
||||
ELR_Failure,
|
||||
|
||||
/// \brief The external information has already been loaded, and therefore
|
||||
/// 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
|
||||
@ -156,47 +142,50 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
|
||||
/// \brief Retrieve the module that corresponds to the given module ID.
|
||||
virtual Module *getModule(unsigned ID) { return nullptr; }
|
||||
|
||||
/// \brief Holds everything needed to generate debug info for an
|
||||
/// imported module or precompiled header file.
|
||||
struct ASTSourceDescriptor {
|
||||
std::string ModuleName;
|
||||
std::string Path;
|
||||
std::string ASTFile;
|
||||
uint64_t Signature;
|
||||
/// Abstracts clang modules and precompiled header files and holds
|
||||
/// everything needed to generate debug info for an imported module
|
||||
/// or PCH.
|
||||
class ASTSourceDescriptor {
|
||||
StringRef PCHModuleName;
|
||||
StringRef Path;
|
||||
StringRef ASTFile;
|
||||
uint64_t Signature = 0;
|
||||
const Module *ClangModule = nullptr;
|
||||
|
||||
public:
|
||||
ASTSourceDescriptor(){};
|
||||
ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
|
||||
uint64_t Signature)
|
||||
: PCHModuleName(std::move(Name)), Path(std::move(Path)),
|
||||
ASTFile(std::move(ASTFile)), Signature(Signature){};
|
||||
ASTSourceDescriptor(const Module &M);
|
||||
std::string getModuleName() const;
|
||||
StringRef getPath() const { return Path; }
|
||||
StringRef getASTFile() const { return ASTFile; }
|
||||
uint64_t getSignature() const { return Signature; }
|
||||
const Module *getModuleOrNull() const { return ClangModule; }
|
||||
};
|
||||
|
||||
/// \brief Return a descriptor for the corresponding module, if one exists.
|
||||
/// Return a descriptor for the corresponding module, if one exists.
|
||||
virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
|
||||
/// \brief Return a descriptor for the module.
|
||||
virtual ASTSourceDescriptor getSourceDescriptor(const Module &M);
|
||||
|
||||
/// \brief Finds all declarations lexically contained within the given
|
||||
/// DeclContext, after applying an optional filter predicate.
|
||||
///
|
||||
/// \param isKindWeWant a predicate function that returns true if the passed
|
||||
/// declaration kind is one we are looking for. If NULL, all declarations
|
||||
/// are returned.
|
||||
///
|
||||
/// \return an indication of whether the load succeeded or failed.
|
||||
/// \param IsKindWeWant a predicate function that returns true if the passed
|
||||
/// declaration kind is one we are looking for.
|
||||
///
|
||||
/// The default implementation of this method is a no-op.
|
||||
virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
|
||||
bool (*isKindWeWant)(Decl::Kind),
|
||||
SmallVectorImpl<Decl*> &Result);
|
||||
virtual void
|
||||
FindExternalLexicalDecls(const DeclContext *DC,
|
||||
llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
|
||||
SmallVectorImpl<Decl *> &Result);
|
||||
|
||||
/// \brief Finds all declarations lexically contained within the given
|
||||
/// DeclContext.
|
||||
///
|
||||
/// \return true if an error occurred
|
||||
ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
|
||||
SmallVectorImpl<Decl*> &Result) {
|
||||
return FindExternalLexicalDecls(DC, nullptr, Result);
|
||||
}
|
||||
|
||||
template <typename DeclTy>
|
||||
ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
|
||||
SmallVectorImpl<Decl*> &Result) {
|
||||
return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
|
||||
void FindExternalLexicalDecls(const DeclContext *DC,
|
||||
SmallVectorImpl<Decl *> &Result) {
|
||||
FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result);
|
||||
}
|
||||
|
||||
/// \brief Get the decls that are contained in a file in the Offset/Length
|
||||
|
@ -144,9 +144,6 @@ class MangleContext {
|
||||
/// across translation units so it can be used with LTO.
|
||||
virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
|
||||
|
||||
virtual void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
|
||||
raw_ostream &) = 0;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
|
@ -217,7 +217,8 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
|
||||
|
||||
/// \brief Dump the nested name specifier to standard output to aid
|
||||
/// in debugging.
|
||||
void dump(const LangOptions &LO);
|
||||
void dump(const LangOptions &LO) const;
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
/// \brief A C++ nested-name-specifier augmented with source location
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -334,7 +334,8 @@ enum UnaryOperatorKind {
|
||||
UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic
|
||||
UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic
|
||||
UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension.
|
||||
UO_Extension // __extension__ marker.
|
||||
UO_Extension, // __extension__ marker.
|
||||
UO_Coawait // [C++ Coroutines] co_await operator
|
||||
};
|
||||
|
||||
/// \brief The kind of bridging performed by the Objective-C bridge cast.
|
||||
|
@ -42,7 +42,7 @@ struct PrintingPolicy {
|
||||
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
|
||||
Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
|
||||
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
|
||||
IncludeNewlines(true) { }
|
||||
IncludeNewlines(true), MSVCFormatting(false) { }
|
||||
|
||||
/// \brief What language we're printing.
|
||||
LangOptions LangOpts;
|
||||
@ -109,7 +109,7 @@ struct PrintingPolicy {
|
||||
/// \brief Whether we should print the sizes of constant array expressions
|
||||
/// as written in the sources.
|
||||
///
|
||||
/// This flag is determines whether arrays types declared as
|
||||
/// This flag determines whether array types declared as
|
||||
///
|
||||
/// \code
|
||||
/// int a[4+10*10];
|
||||
@ -163,6 +163,11 @@ struct PrintingPolicy {
|
||||
|
||||
/// \brief When true, include newlines after statements like "break", etc.
|
||||
unsigned IncludeNewlines : 1;
|
||||
|
||||
/// \brief Use whitespace and punctuation like MSVC does. In particular, this
|
||||
/// prints anonymous namespaces as `anonymous namespace' and does not insert
|
||||
/// spaces after template arguments.
|
||||
bool MSVCFormatting : 1;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -14,6 +14,8 @@
|
||||
#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
|
||||
#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
@ -24,6 +26,7 @@
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/ExprOpenMP.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
@ -42,7 +45,7 @@
|
||||
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)
|
||||
OPERATOR(Extension) OPERATOR(Coawait)
|
||||
|
||||
// All binary operators (excluding compound assign operators).
|
||||
#define BINOP_LIST() \
|
||||
@ -132,6 +135,12 @@ namespace clang {
|
||||
/// from which they were produced.
|
||||
template <typename Derived> class RecursiveASTVisitor {
|
||||
public:
|
||||
/// A queue used for performing data recursion over statements.
|
||||
/// Parameters involving this type are used to implement data
|
||||
/// recursion over Stmts and Exprs within this class, and should
|
||||
/// typically not be explicitly specified by derived classes.
|
||||
typedef SmallVectorImpl<Stmt *> DataRecursionQueue;
|
||||
|
||||
/// \brief Return a reference to the derived class.
|
||||
Derived &getDerived() { return *static_cast<Derived *>(this); }
|
||||
|
||||
@ -147,19 +156,12 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
/// code, e.g., implicit constructors and destructors.
|
||||
bool shouldVisitImplicitCode() const { return false; }
|
||||
|
||||
/// \brief Return whether \param S should be traversed using data recursion
|
||||
/// to avoid a stack overflow with extreme cases.
|
||||
bool shouldUseDataRecursionFor(Stmt *S) const {
|
||||
return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) ||
|
||||
isa<CaseStmt>(S) || isa<CXXOperatorCallExpr>(S);
|
||||
}
|
||||
|
||||
/// \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);
|
||||
/// otherwise (including when the argument is nullptr).
|
||||
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr);
|
||||
|
||||
/// \brief Recursively visit a type, by dispatching to
|
||||
/// Traverse*Type() based on the argument's getTypeClass() property.
|
||||
@ -252,7 +254,14 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
/// \c LE->getBody().
|
||||
///
|
||||
/// \returns false if the visitation was terminated early, true otherwise.
|
||||
bool TraverseLambdaBody(LambdaExpr *LE);
|
||||
bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr);
|
||||
|
||||
/// \brief Recursively visit the syntactic or semantic form of an
|
||||
/// initialization list.
|
||||
///
|
||||
/// \returns false if the visitation was terminated early, true otherwise.
|
||||
bool TraverseSynOrSemInitListExpr(InitListExpr *S,
|
||||
DataRecursionQueue *Queue = nullptr);
|
||||
|
||||
// ---- Methods on Attrs ----
|
||||
|
||||
@ -266,9 +275,44 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
|
||||
// ---- Methods on Stmts ----
|
||||
|
||||
private:
|
||||
template<typename T, typename U>
|
||||
struct has_same_member_pointer_type : std::false_type {};
|
||||
template<typename T, typename U, typename R, typename... P>
|
||||
struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)>
|
||||
: std::true_type {};
|
||||
|
||||
// Traverse the given statement. If the most-derived traverse function takes a
|
||||
// data recursion queue, pass it on; otherwise, discard it. Note that the
|
||||
// first branch of this conditional must compile whether or not the derived
|
||||
// class can take a queue, so if we're taking the second arm, make the first
|
||||
// arm call our function rather than the derived class version.
|
||||
#define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \
|
||||
(has_same_member_pointer_type<decltype( \
|
||||
&RecursiveASTVisitor::Traverse##NAME), \
|
||||
decltype(&Derived::Traverse##NAME)>::value \
|
||||
? static_cast<typename std::conditional< \
|
||||
has_same_member_pointer_type< \
|
||||
decltype(&RecursiveASTVisitor::Traverse##NAME), \
|
||||
decltype(&Derived::Traverse##NAME)>::value, \
|
||||
Derived &, RecursiveASTVisitor &>::type>(*this) \
|
||||
.Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \
|
||||
: getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)))
|
||||
|
||||
// Try to traverse the given statement, or enqueue it if we're performing data
|
||||
// recursion in the middle of traversing another statement. Can only be called
|
||||
// from within a DEF_TRAVERSE_STMT body or similar context.
|
||||
#define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \
|
||||
do { \
|
||||
if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \
|
||||
return false; \
|
||||
} while (0)
|
||||
|
||||
public:
|
||||
// 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, DataRecursionQueue *Queue = nullptr);
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
// The above header #undefs ABSTRACT_STMT and STMT upon exit.
|
||||
|
||||
@ -288,9 +332,10 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
// 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) { \
|
||||
bool TraverseUnary##NAME(UnaryOperator *S, \
|
||||
DataRecursionQueue *Queue = nullptr) { \
|
||||
TRY_TO(WalkUpFromUnary##NAME(S)); \
|
||||
TRY_TO(TraverseStmt(S->getSubExpr())); \
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \
|
||||
return true; \
|
||||
} \
|
||||
bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
|
||||
@ -307,10 +352,10 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
// 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) { \
|
||||
bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \
|
||||
TRY_TO(WalkUpFromBin##NAME(S)); \
|
||||
TRY_TO(TraverseStmt(S->getLHS())); \
|
||||
TRY_TO(TraverseStmt(S->getRHS())); \
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \
|
||||
return true; \
|
||||
} \
|
||||
bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
|
||||
@ -436,129 +481,14 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
/// \brief Process clauses with list of variables.
|
||||
template <typename T> bool VisitOMPClauseList(T *Node);
|
||||
|
||||
struct EnqueueJob {
|
||||
Stmt *S;
|
||||
Stmt::child_iterator StmtIt;
|
||||
|
||||
EnqueueJob(Stmt *S) : S(S), StmtIt() {}
|
||||
};
|
||||
bool dataTraverse(Stmt *S);
|
||||
bool dataTraverseNode(Stmt *S, bool &EnqueueChildren);
|
||||
bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue);
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
|
||||
|
||||
SmallVector<EnqueueJob, 16> Queue;
|
||||
Queue.push_back(S);
|
||||
|
||||
while (!Queue.empty()) {
|
||||
EnqueueJob &job = Queue.back();
|
||||
Stmt *CurrS = job.S;
|
||||
if (!CurrS) {
|
||||
Queue.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (getDerived().shouldUseDataRecursionFor(CurrS)) {
|
||||
if (job.StmtIt == Stmt::child_iterator()) {
|
||||
bool EnqueueChildren = true;
|
||||
if (!dataTraverseNode(CurrS, EnqueueChildren))
|
||||
return false;
|
||||
if (!EnqueueChildren) {
|
||||
Queue.pop_back();
|
||||
continue;
|
||||
}
|
||||
job.StmtIt = CurrS->child_begin();
|
||||
} else {
|
||||
++job.StmtIt;
|
||||
}
|
||||
|
||||
if (job.StmtIt != CurrS->child_end())
|
||||
Queue.push_back(*job.StmtIt);
|
||||
else
|
||||
Queue.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
Queue.pop_back();
|
||||
TRY_TO(TraverseStmt(CurrS));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
|
||||
switch (BinOp->getOpcode()) {
|
||||
#define OPERATOR(NAME) \
|
||||
case BO_##NAME: \
|
||||
DISPATCH_WALK(Bin##NAME, BinaryOperator, S);
|
||||
|
||||
BINOP_LIST()
|
||||
#undef OPERATOR
|
||||
|
||||
#define OPERATOR(NAME) \
|
||||
case BO_##NAME##Assign: \
|
||||
DISPATCH_WALK(Bin##NAME##Assign, CompoundAssignOperator, S);
|
||||
|
||||
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);
|
||||
|
||||
UNARYOP_LIST()
|
||||
#undef OPERATOR
|
||||
}
|
||||
}
|
||||
|
||||
// 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_WALK(CLASS, CLASS, S);
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
}
|
||||
|
||||
#undef DISPATCH_WALK
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
#define DISPATCH_STMT(NAME, CLASS, VAR) DISPATCH(NAME, CLASS, VAR)
|
||||
|
||||
if (getDerived().shouldUseDataRecursionFor(S))
|
||||
return dataTraverse(S);
|
||||
DataRecursionQueue *Queue) {
|
||||
#define DISPATCH_STMT(NAME, CLASS, VAR) \
|
||||
return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue);
|
||||
|
||||
// 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
|
||||
@ -609,6 +539,35 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
|
||||
|
||||
#undef DISPATCH_STMT
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S,
|
||||
DataRecursionQueue *Queue) {
|
||||
if (!S)
|
||||
return true;
|
||||
|
||||
if (Queue) {
|
||||
Queue->push_back(S);
|
||||
return true;
|
||||
}
|
||||
|
||||
SmallVector<Stmt *, 8> LocalQueue;
|
||||
LocalQueue.push_back(S);
|
||||
|
||||
while (!LocalQueue.empty()) {
|
||||
Stmt *CurrS = LocalQueue.pop_back_val();
|
||||
|
||||
size_t N = LocalQueue.size();
|
||||
TRY_TO(dataTraverseNode(CurrS, &LocalQueue));
|
||||
// Process new children in the order they were added.
|
||||
std::reverse(LocalQueue.begin() + N, LocalQueue.end());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DISPATCH(NAME, CLASS, VAR) \
|
||||
return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
|
||||
if (T.isNull())
|
||||
@ -863,8 +822,9 @@ RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
|
||||
TRY_TO(TraverseStmt(LE->getBody()));
|
||||
bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(
|
||||
LambdaExpr *LE, DataRecursionQueue *Queue) {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(LE->getBody());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1364,6 +1324,8 @@ DEF_TRAVERSE_DECL(
|
||||
DEF_TRAVERSE_DECL(ExternCContextDecl, {})
|
||||
|
||||
DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
|
||||
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
|
||||
|
||||
// We shouldn't traverse an aliased namespace, since it will be
|
||||
// defined (and, therefore, traversed) somewhere else.
|
||||
//
|
||||
@ -1596,6 +1558,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
|
||||
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(BuiltinTemplateDecl, {
|
||||
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
|
||||
// D is the "T" in something like "template<typename T> class vector;"
|
||||
if (D->getTypeForDecl())
|
||||
@ -1906,25 +1872,26 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
|
||||
// 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) { \
|
||||
bool RecursiveASTVisitor<Derived>::Traverse##STMT( \
|
||||
STMT *S, DataRecursionQueue *Queue) { \
|
||||
TRY_TO(WalkUpFrom##STMT(S)); \
|
||||
{ CODE; } \
|
||||
for (Stmt *SubStmt : S->children()) { \
|
||||
TRY_TO(TraverseStmt(SubStmt)); \
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
|
||||
DEF_TRAVERSE_STMT(GCCAsmStmt, {
|
||||
TRY_TO(TraverseStmt(S->getAsmString()));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString());
|
||||
for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
|
||||
TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I)));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I));
|
||||
}
|
||||
for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
|
||||
TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I)));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I));
|
||||
}
|
||||
for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
|
||||
TRY_TO(TraverseStmt(S->getClobberStringLiteral(I)));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I));
|
||||
}
|
||||
// children() iterates over inputExpr and outputExpr.
|
||||
})
|
||||
@ -1977,9 +1944,9 @@ DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {})
|
||||
DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {})
|
||||
DEF_TRAVERSE_STMT(CXXForRangeStmt, {
|
||||
if (!getDerived().shouldVisitImplicitCode()) {
|
||||
TRY_TO(TraverseStmt(S->getLoopVarStmt()));
|
||||
TRY_TO(TraverseStmt(S->getRangeInit()));
|
||||
TRY_TO(TraverseStmt(S->getBody()));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt());
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit());
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
|
||||
// Visit everything else only if shouldVisitImplicitCode().
|
||||
return true;
|
||||
}
|
||||
@ -2012,9 +1979,8 @@ 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(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
|
||||
S->getNumTemplateArgs()));
|
||||
}
|
||||
})
|
||||
|
||||
@ -2055,64 +2021,60 @@ 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) {
|
||||
InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
|
||||
if (Syn) {
|
||||
TRY_TO(WalkUpFromInitListExpr(Syn));
|
||||
bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
|
||||
InitListExpr *S, DataRecursionQueue *Queue) {
|
||||
if (S) {
|
||||
TRY_TO(WalkUpFromInitListExpr(S));
|
||||
// All we need are the default actions. FIXME: use a helper function.
|
||||
for (Stmt *SubStmt : Syn->children()) {
|
||||
TRY_TO(TraverseStmt(SubStmt));
|
||||
}
|
||||
}
|
||||
InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
|
||||
if (Sem) {
|
||||
TRY_TO(WalkUpFromInitListExpr(Sem));
|
||||
for (Stmt *SubStmt : Sem->children()) {
|
||||
TRY_TO(TraverseStmt(SubStmt));
|
||||
for (Stmt *SubStmt : S->children()) {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// This method is called once for each pair of syntactic and semantic
|
||||
// InitListExpr, and it traverses the subtrees defined by the two forms. This
|
||||
// may cause some of the children to be visited twice, if they appear both in
|
||||
// the syntactic and the semantic form.
|
||||
//
|
||||
// There is no guarantee about which form \p S takes when this method is called.
|
||||
DEF_TRAVERSE_STMT(InitListExpr, {
|
||||
TRY_TO(TraverseSynOrSemInitListExpr(
|
||||
S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
|
||||
TRY_TO(TraverseSynOrSemInitListExpr(
|
||||
S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
|
||||
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));
|
||||
DEF_TRAVERSE_STMT(GenericSelectionExpr, {
|
||||
TRY_TO(TraverseStmt(S->getControllingExpr()));
|
||||
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
|
||||
if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
|
||||
TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
|
||||
TRY_TO(TraverseStmt(S->getAssocExpr(i)));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
// PseudoObjectExpr is a special case because of the wierdness with
|
||||
// PseudoObjectExpr is a special case because of the weirdness with
|
||||
// syntactic expressions and opaque values.
|
||||
template <typename Derived>
|
||||
bool
|
||||
RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) {
|
||||
TRY_TO(WalkUpFromPseudoObjectExpr(S));
|
||||
TRY_TO(TraverseStmt(S->getSyntacticForm()));
|
||||
DEF_TRAVERSE_STMT(PseudoObjectExpr, {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(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();
|
||||
TRY_TO(TraverseStmt(sub));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
|
||||
// This is called for code like 'return T()' where T is a built-in
|
||||
@ -2151,6 +2113,8 @@ DEF_TRAVERSE_STMT(MSPropertyRefExpr, {
|
||||
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(MSPropertySubscriptExpr, {})
|
||||
|
||||
DEF_TRAVERSE_STMT(CXXUuidofExpr, {
|
||||
// The child-iterator will pick up the arg if it's an expression,
|
||||
// but not if it's a type.
|
||||
@ -2168,7 +2132,7 @@ DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(ExpressionTraitExpr,
|
||||
{ TRY_TO(TraverseStmt(S->getQueriedExpression())); })
|
||||
{ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getQueriedExpression()); })
|
||||
|
||||
DEF_TRAVERSE_STMT(VAArgExpr, {
|
||||
// The child-iterator will pick up the expression argument.
|
||||
@ -2181,10 +2145,7 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
|
||||
})
|
||||
|
||||
// Walk only the visible parts of lambda expressions.
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
|
||||
TRY_TO(WalkUpFromLambdaExpr(S));
|
||||
|
||||
DEF_TRAVERSE_STMT(LambdaExpr, {
|
||||
for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
|
||||
CEnd = S->explicit_capture_end();
|
||||
C != CEnd; ++C) {
|
||||
@ -2213,12 +2174,11 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
|
||||
}
|
||||
|
||||
if (Expr *NE = T->getNoexceptExpr())
|
||||
TRY_TO(TraverseStmt(NE));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE);
|
||||
}
|
||||
|
||||
TRY_TO(TraverseLambdaBody(S));
|
||||
return true;
|
||||
}
|
||||
return TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue);
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
|
||||
// This is called for code like 'T()', where T is a template argument.
|
||||
@ -2235,6 +2195,7 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
|
||||
// over the children.
|
||||
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
|
||||
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
|
||||
DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})
|
||||
DEF_TRAVERSE_STMT(BlockExpr, {
|
||||
TRY_TO(TraverseDecl(S->getBlockDecl()));
|
||||
return true; // no child statements to loop through.
|
||||
@ -2336,6 +2297,34 @@ DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
|
||||
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
|
||||
DEF_TRAVERSE_STMT(AtomicExpr, {})
|
||||
|
||||
// For coroutines expressions, traverse either the operand
|
||||
// as written or the implied calls, depending on what the
|
||||
// derived class requests.
|
||||
DEF_TRAVERSE_STMT(CoroutineBodyStmt, {
|
||||
if (!getDerived().shouldVisitImplicitCode()) {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
|
||||
return true;
|
||||
}
|
||||
})
|
||||
DEF_TRAVERSE_STMT(CoreturnStmt, {
|
||||
if (!getDerived().shouldVisitImplicitCode()) {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
|
||||
return true;
|
||||
}
|
||||
})
|
||||
DEF_TRAVERSE_STMT(CoawaitExpr, {
|
||||
if (!getDerived().shouldVisitImplicitCode()) {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
|
||||
return true;
|
||||
}
|
||||
})
|
||||
DEF_TRAVERSE_STMT(CoyieldExpr, {
|
||||
if (!getDerived().shouldVisitImplicitCode()) {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
// These literals (all of them) do not need any action.
|
||||
DEF_TRAVERSE_STMT(IntegerLiteral, {})
|
||||
DEF_TRAVERSE_STMT(CharacterLiteral, {})
|
||||
@ -2437,9 +2426,21 @@ DEF_TRAVERSE_STMT(OMPAtomicDirective,
|
||||
DEF_TRAVERSE_STMT(OMPTargetDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPTargetDataDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPTeamsDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPTaskLoopDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPDistributeDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
// OpenMP clauses.
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
||||
@ -2483,6 +2484,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getSimdlen()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool
|
||||
RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) {
|
||||
@ -2509,7 +2516,8 @@ RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) {
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getNumForLoops()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2554,6 +2562,21 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPSIMDClause(OMPSIMDClause *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
template <typename T>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
|
||||
@ -2615,6 +2638,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getStep()));
|
||||
TRY_TO(TraverseStmt(C->getCalcStep()));
|
||||
TRY_TO(VisitOMPClauseList(C));
|
||||
for (auto *E : C->privates()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
for (auto *E : C->inits()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
@ -2671,6 +2697,9 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
|
||||
TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
|
||||
TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
|
||||
TRY_TO(VisitOMPClauseList(C));
|
||||
for (auto *E : C->privates()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
for (auto *E : C->lhs_exprs()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
@ -2695,6 +2724,59 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getDevice()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) {
|
||||
TRY_TO(VisitOMPClauseList(C));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause(
|
||||
OMPNumTeamsClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getNumTeams()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause(
|
||||
OMPThreadLimitClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getThreadLimit()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause(
|
||||
OMPPriorityClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getPriority()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause(
|
||||
OMPGrainsizeClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getGrainsize()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause(
|
||||
OMPNumTasksClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getNumTasks()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getHint()));
|
||||
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
|
||||
@ -2713,6 +2795,8 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
|
||||
// Every class that has getQualifier.
|
||||
|
||||
#undef DEF_TRAVERSE_STMT
|
||||
#undef TRAVERSE_STMT
|
||||
#undef TRAVERSE_STMT_BASE
|
||||
|
||||
#undef TRY_TO
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <iterator>
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
|
||||
/// \brief Provides common interface for the Decls that can be redeclared.
|
||||
template<typename decl_type>
|
||||
@ -32,7 +33,11 @@ class Redeclarable {
|
||||
&ExternalASTSource::CompleteRedeclChain>
|
||||
KnownLatest;
|
||||
|
||||
typedef const ASTContext *UninitializedLatest;
|
||||
/// We store a pointer to the ASTContext in the UninitializedLatest
|
||||
/// pointer, but to avoid circular type dependencies when we steal the low
|
||||
/// bits of this pointer, we use a raw void* here.
|
||||
typedef const void *UninitializedLatest;
|
||||
|
||||
typedef Decl *Previous;
|
||||
|
||||
/// A pointer to either an uninitialized latest declaration (where either
|
||||
@ -47,7 +52,7 @@ class Redeclarable {
|
||||
enum LatestTag { LatestLink };
|
||||
|
||||
DeclLink(LatestTag, const ASTContext &Ctx)
|
||||
: Next(NotKnownLatest(&Ctx)) {}
|
||||
: Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {}
|
||||
DeclLink(PreviousTag, decl_type *D)
|
||||
: Next(NotKnownLatest(Previous(D))) {}
|
||||
|
||||
@ -67,7 +72,8 @@ class Redeclarable {
|
||||
return static_cast<decl_type*>(NKL.get<Previous>());
|
||||
|
||||
// Allocate the generational 'most recent' cache now, if needed.
|
||||
Next = KnownLatest(*NKL.get<UninitializedLatest>(),
|
||||
Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
|
||||
NKL.get<UninitializedLatest>()),
|
||||
const_cast<decl_type *>(D));
|
||||
}
|
||||
|
||||
@ -83,7 +89,9 @@ class Redeclarable {
|
||||
assert(NextIsLatest() && "decl became canonical unexpectedly");
|
||||
if (Next.is<NotKnownLatest>()) {
|
||||
NotKnownLatest NKL = Next.get<NotKnownLatest>();
|
||||
Next = KnownLatest(*NKL.get<UninitializedLatest>(), D);
|
||||
Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
|
||||
NKL.get<UninitializedLatest>()),
|
||||
D);
|
||||
} else {
|
||||
auto Latest = Next.get<KnownLatest>();
|
||||
Latest.set(D);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <string>
|
||||
@ -49,57 +50,6 @@ namespace clang {
|
||||
class Token;
|
||||
class VarDecl;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// ExprIterator - Iterators for iterating over Stmt* arrays that contain
|
||||
// only Expr*. This is needed because AST nodes use Stmt* arrays to store
|
||||
// references to children (to be compatible with StmtIterator).
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
class Stmt;
|
||||
class Expr;
|
||||
|
||||
class ExprIterator : public std::iterator<std::forward_iterator_tag,
|
||||
Expr *&, ptrdiff_t,
|
||||
Expr *&, Expr *&> {
|
||||
Stmt** I;
|
||||
public:
|
||||
ExprIterator(Stmt** i) : I(i) {}
|
||||
ExprIterator() : I(nullptr) {}
|
||||
ExprIterator& operator++() { ++I; return *this; }
|
||||
ExprIterator operator-(size_t i) { return I-i; }
|
||||
ExprIterator operator+(size_t i) { return I+i; }
|
||||
Expr* operator[](size_t idx);
|
||||
// FIXME: Verify that this will correctly return a signed distance.
|
||||
signed operator-(const ExprIterator& R) const { return I - R.I; }
|
||||
Expr* operator*() const;
|
||||
Expr* operator->() const;
|
||||
bool operator==(const ExprIterator& R) const { return I == R.I; }
|
||||
bool operator!=(const ExprIterator& R) const { return I != R.I; }
|
||||
bool operator>(const ExprIterator& R) const { return I > R.I; }
|
||||
bool operator>=(const ExprIterator& R) const { return I >= R.I; }
|
||||
};
|
||||
|
||||
class ConstExprIterator : public std::iterator<std::forward_iterator_tag,
|
||||
const Expr *&, ptrdiff_t,
|
||||
const Expr *&,
|
||||
const Expr *&> {
|
||||
const Stmt * const *I;
|
||||
public:
|
||||
ConstExprIterator(const Stmt * const *i) : I(i) {}
|
||||
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; }
|
||||
const Expr * operator[](size_t idx) const;
|
||||
signed operator-(const ConstExprIterator& R) const { return I - R.I; }
|
||||
const Expr * operator*() const;
|
||||
const Expr * operator->() const;
|
||||
bool operator==(const ConstExprIterator& R) const { return I == R.I; }
|
||||
bool operator!=(const ConstExprIterator& R) const { return I != R.I; }
|
||||
bool operator>(const ConstExprIterator& R) const { return I > R.I; }
|
||||
bool operator>=(const ConstExprIterator& R) const { return I >= R.I; }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AST classes for statements.
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -121,10 +71,10 @@ class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt {
|
||||
|
||||
// Make vanilla 'new' and 'delete' illegal for Stmts.
|
||||
protected:
|
||||
void* operator new(size_t bytes) throw() {
|
||||
void *operator new(size_t bytes) LLVM_NOEXCEPT {
|
||||
llvm_unreachable("Stmts cannot be allocated with regular 'new'.");
|
||||
}
|
||||
void operator delete(void* data) throw() {
|
||||
void operator delete(void *data) LLVM_NOEXCEPT {
|
||||
llvm_unreachable("Stmts cannot be released with regular 'delete'.");
|
||||
}
|
||||
|
||||
@ -322,14 +272,12 @@ class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt {
|
||||
return operator new(bytes, *C, alignment);
|
||||
}
|
||||
|
||||
void* operator new(size_t bytes, void* mem) throw() {
|
||||
return mem;
|
||||
}
|
||||
void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; }
|
||||
|
||||
void operator delete(void*, const ASTContext&, unsigned) throw() { }
|
||||
void operator delete(void*, const ASTContext*, unsigned) throw() { }
|
||||
void operator delete(void*, size_t) throw() { }
|
||||
void operator delete(void*, void*) throw() { }
|
||||
void operator delete(void *, const ASTContext &, unsigned) LLVM_NOEXCEPT {}
|
||||
void operator delete(void *, const ASTContext *, unsigned) LLVM_NOEXCEPT {}
|
||||
void operator delete(void *, size_t) LLVM_NOEXCEPT {}
|
||||
void operator delete(void *, void *) LLVM_NOEXCEPT {}
|
||||
|
||||
public:
|
||||
/// \brief A placeholder type used to construct an empty shell of a
|
||||
@ -337,6 +285,39 @@ class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt {
|
||||
/// de-serialization).
|
||||
struct EmptyShell { };
|
||||
|
||||
protected:
|
||||
/// Iterator for iterating over Stmt * arrays that contain only Expr *
|
||||
///
|
||||
/// This is needed because AST nodes use Stmt* arrays to store
|
||||
/// references to children (to be compatible with StmtIterator).
|
||||
struct ExprIterator
|
||||
: llvm::iterator_adaptor_base<ExprIterator, Stmt **,
|
||||
std::random_access_iterator_tag, Expr *> {
|
||||
ExprIterator() : iterator_adaptor_base(nullptr) {}
|
||||
ExprIterator(Stmt **I) : iterator_adaptor_base(I) {}
|
||||
|
||||
reference operator*() const {
|
||||
assert((*I)->getStmtClass() >= firstExprConstant &&
|
||||
(*I)->getStmtClass() <= lastExprConstant);
|
||||
return *reinterpret_cast<Expr **>(I);
|
||||
}
|
||||
};
|
||||
|
||||
/// Const iterator for iterating over Stmt * arrays that contain only Expr *
|
||||
struct ConstExprIterator
|
||||
: llvm::iterator_adaptor_base<ConstExprIterator, const Stmt *const *,
|
||||
std::random_access_iterator_tag,
|
||||
const Expr *const> {
|
||||
ConstExprIterator() : iterator_adaptor_base(nullptr) {}
|
||||
ConstExprIterator(const Stmt *const *I) : iterator_adaptor_base(I) {}
|
||||
|
||||
reference operator*() const {
|
||||
assert((*I)->getStmtClass() >= firstExprConstant &&
|
||||
(*I)->getStmtClass() <= lastExprConstant);
|
||||
return *reinterpret_cast<const Expr *const *>(I);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
/// \brief Whether statistic collection is enabled.
|
||||
static bool StatisticsEnabled;
|
||||
@ -411,19 +392,20 @@ class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt {
|
||||
typedef StmtIterator child_iterator;
|
||||
typedef ConstStmtIterator const_child_iterator;
|
||||
|
||||
typedef StmtRange child_range;
|
||||
typedef ConstStmtRange const_child_range;
|
||||
typedef llvm::iterator_range<child_iterator> child_range;
|
||||
typedef llvm::iterator_range<const_child_iterator> const_child_range;
|
||||
|
||||
child_range children();
|
||||
const_child_range children() const {
|
||||
return const_cast<Stmt*>(this)->children();
|
||||
auto Children = const_cast<Stmt *>(this)->children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
child_iterator child_begin() { return children().first; }
|
||||
child_iterator child_end() { return children().second; }
|
||||
child_iterator child_begin() { return children().begin(); }
|
||||
child_iterator child_end() { return children().end(); }
|
||||
|
||||
const_child_iterator child_begin() const { return children().first; }
|
||||
const_child_iterator child_end() const { return children().second; }
|
||||
const_child_iterator child_begin() const { return children().begin(); }
|
||||
const_child_iterator child_end() const { return children().end(); }
|
||||
|
||||
/// \brief Produce a unique representation of the given statement.
|
||||
///
|
||||
@ -544,7 +526,9 @@ class NullStmt : public Stmt {
|
||||
return T->getStmtClass() == NullStmtClass;
|
||||
}
|
||||
|
||||
child_range children() { return child_range(); }
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
@ -574,7 +558,7 @@ class CompoundStmt : public Stmt {
|
||||
CompoundStmtBits.NumStmts = 0;
|
||||
}
|
||||
|
||||
void setStmts(const ASTContext &C, Stmt **Stmts, unsigned NumStmts);
|
||||
void setStmts(const ASTContext &C, ArrayRef<Stmt *> Stmts);
|
||||
|
||||
bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
|
||||
unsigned size() const { return CompoundStmtBits.NumStmts; }
|
||||
@ -643,7 +627,8 @@ class CompoundStmt : public Stmt {
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return child_range(Body, Body + CompoundStmtBits.NumStmts);
|
||||
return const_child_range(child_iterator(Body),
|
||||
child_iterator(Body + CompoundStmtBits.NumStmts));
|
||||
}
|
||||
};
|
||||
|
||||
@ -840,18 +825,20 @@ class AttributedStmt : public Stmt {
|
||||
AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
|
||||
: Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
|
||||
NumAttrs(Attrs.size()) {
|
||||
memcpy(getAttrArrayPtr(), Attrs.data(), Attrs.size() * sizeof(Attr *));
|
||||
std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr());
|
||||
}
|
||||
|
||||
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
|
||||
: Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
|
||||
memset(getAttrArrayPtr(), 0, NumAttrs * sizeof(Attr *));
|
||||
std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr);
|
||||
}
|
||||
|
||||
Attr *const *getAttrArrayPtr() const {
|
||||
return reinterpret_cast<Attr *const *>(this + 1);
|
||||
const Attr *const *getAttrArrayPtr() const {
|
||||
return reinterpret_cast<const Attr *const *>(this + 1);
|
||||
}
|
||||
const Attr **getAttrArrayPtr() {
|
||||
return reinterpret_cast<const Attr **>(this + 1);
|
||||
}
|
||||
Attr **getAttrArrayPtr() { return reinterpret_cast<Attr **>(this + 1); }
|
||||
|
||||
public:
|
||||
static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
|
||||
@ -1239,7 +1226,9 @@ class GotoStmt : public Stmt {
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// IndirectGotoStmt - This represents an indirect goto.
|
||||
@ -1307,7 +1296,9 @@ class ContinueStmt : public Stmt {
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// BreakStmt - This represents a break.
|
||||
@ -1335,7 +1326,9 @@ class BreakStmt : public Stmt {
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1390,7 +1383,7 @@ class ReturnStmt : public Stmt {
|
||||
// Iterators
|
||||
child_range children() {
|
||||
if (RetExpr) return child_range(&RetExpr, &RetExpr+1);
|
||||
return child_range();
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
@ -1974,7 +1967,9 @@ class SEHLeaveStmt : public Stmt {
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief This captures a statement into a function. For example, the following
|
||||
@ -1993,6 +1988,7 @@ class CapturedStmt : public Stmt {
|
||||
enum VariableCaptureKind {
|
||||
VCK_This,
|
||||
VCK_ByRef,
|
||||
VCK_ByCopy,
|
||||
VCK_VLAType,
|
||||
};
|
||||
|
||||
@ -2012,24 +2008,10 @@ class CapturedStmt : public Stmt {
|
||||
/// \param Var The variable being captured, or null if capturing this.
|
||||
///
|
||||
Capture(SourceLocation Loc, VariableCaptureKind Kind,
|
||||
VarDecl *Var = nullptr)
|
||||
: VarAndKind(Var, Kind), Loc(Loc) {
|
||||
switch (Kind) {
|
||||
case VCK_This:
|
||||
assert(!Var && "'this' capture cannot have a variable!");
|
||||
break;
|
||||
case VCK_ByRef:
|
||||
assert(Var && "capturing by reference must have a variable!");
|
||||
break;
|
||||
case VCK_VLAType:
|
||||
assert(!Var &&
|
||||
"Variable-length array type capture cannot have a variable!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
VarDecl *Var = nullptr);
|
||||
|
||||
/// \brief Determine the kind of capture.
|
||||
VariableCaptureKind getCaptureKind() const { return VarAndKind.getInt(); }
|
||||
VariableCaptureKind getCaptureKind() const;
|
||||
|
||||
/// \brief Retrieve the source location at which the variable or 'this' was
|
||||
/// first used.
|
||||
@ -2038,9 +2020,14 @@ class CapturedStmt : public Stmt {
|
||||
/// \brief Determine whether this capture handles the C++ 'this' pointer.
|
||||
bool capturesThis() const { return getCaptureKind() == VCK_This; }
|
||||
|
||||
/// \brief Determine whether this capture handles a variable.
|
||||
/// \brief Determine whether this capture handles a variable (by reference).
|
||||
bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; }
|
||||
|
||||
/// \brief Determine whether this capture handles a variable by copy.
|
||||
bool capturesVariableByCopy() const {
|
||||
return getCaptureKind() == VCK_ByCopy;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this capture handles a variable-length array
|
||||
/// type.
|
||||
bool capturesVariableArrayType() const {
|
||||
@ -2050,11 +2037,8 @@ class CapturedStmt : public Stmt {
|
||||
/// \brief Retrieve the declaration of the variable being captured.
|
||||
///
|
||||
/// This operation is only valid if this capture captures a variable.
|
||||
VarDecl *getCapturedVar() const {
|
||||
assert(capturesVariable() &&
|
||||
"No variable available for 'this' or VAT capture");
|
||||
return VarAndKind.getPointer();
|
||||
}
|
||||
VarDecl *getCapturedVar() const;
|
||||
|
||||
friend class ASTStmtReader;
|
||||
};
|
||||
|
||||
@ -2076,8 +2060,10 @@ class CapturedStmt : public Stmt {
|
||||
/// \brief Construct an empty captured statement.
|
||||
CapturedStmt(EmptyShell Empty, unsigned NumCaptures);
|
||||
|
||||
Stmt **getStoredStmts() const {
|
||||
return reinterpret_cast<Stmt **>(const_cast<CapturedStmt *>(this) + 1);
|
||||
Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); }
|
||||
|
||||
Stmt *const *getStoredStmts() const {
|
||||
return reinterpret_cast<Stmt *const *>(this + 1);
|
||||
}
|
||||
|
||||
Capture *getStoredCaptures() const;
|
||||
@ -2096,31 +2082,20 @@ class CapturedStmt : public Stmt {
|
||||
|
||||
/// \brief Retrieve the statement being captured.
|
||||
Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; }
|
||||
const Stmt *getCapturedStmt() const {
|
||||
return const_cast<CapturedStmt *>(this)->getCapturedStmt();
|
||||
}
|
||||
const Stmt *getCapturedStmt() const { return getStoredStmts()[NumCaptures]; }
|
||||
|
||||
/// \brief Retrieve the outlined function declaration.
|
||||
CapturedDecl *getCapturedDecl() { return CapDeclAndKind.getPointer(); }
|
||||
const CapturedDecl *getCapturedDecl() const {
|
||||
return const_cast<CapturedStmt *>(this)->getCapturedDecl();
|
||||
}
|
||||
CapturedDecl *getCapturedDecl();
|
||||
const CapturedDecl *getCapturedDecl() const;
|
||||
|
||||
/// \brief Set the outlined function declaration.
|
||||
void setCapturedDecl(CapturedDecl *D) {
|
||||
assert(D && "null CapturedDecl");
|
||||
CapDeclAndKind.setPointer(D);
|
||||
}
|
||||
void setCapturedDecl(CapturedDecl *D);
|
||||
|
||||
/// \brief Retrieve the captured region kind.
|
||||
CapturedRegionKind getCapturedRegionKind() const {
|
||||
return CapDeclAndKind.getInt();
|
||||
}
|
||||
CapturedRegionKind getCapturedRegionKind() const;
|
||||
|
||||
/// \brief Set the captured region kind.
|
||||
void setCapturedRegionKind(CapturedRegionKind Kind) {
|
||||
CapDeclAndKind.setInt(Kind);
|
||||
}
|
||||
void setCapturedRegionKind(CapturedRegionKind Kind);
|
||||
|
||||
/// \brief Retrieve the record declaration for captured variables.
|
||||
const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; }
|
||||
@ -2164,18 +2139,36 @@ class CapturedStmt : public Stmt {
|
||||
typedef Expr **capture_init_iterator;
|
||||
typedef llvm::iterator_range<capture_init_iterator> capture_init_range;
|
||||
|
||||
capture_init_range capture_inits() const {
|
||||
/// \brief Const iterator that walks over the capture initialization
|
||||
/// arguments.
|
||||
typedef Expr *const *const_capture_init_iterator;
|
||||
typedef llvm::iterator_range<const_capture_init_iterator>
|
||||
const_capture_init_range;
|
||||
|
||||
capture_init_range capture_inits() {
|
||||
return capture_init_range(capture_init_begin(), capture_init_end());
|
||||
}
|
||||
|
||||
const_capture_init_range capture_inits() const {
|
||||
return const_capture_init_range(capture_init_begin(), capture_init_end());
|
||||
}
|
||||
|
||||
/// \brief Retrieve the first initialization argument.
|
||||
capture_init_iterator capture_init_begin() const {
|
||||
capture_init_iterator capture_init_begin() {
|
||||
return reinterpret_cast<Expr **>(getStoredStmts());
|
||||
}
|
||||
|
||||
const_capture_init_iterator capture_init_begin() const {
|
||||
return reinterpret_cast<Expr *const *>(getStoredStmts());
|
||||
}
|
||||
|
||||
/// \brief Retrieve the iterator pointing one past the last initialization
|
||||
/// argument.
|
||||
capture_init_iterator capture_init_end() const {
|
||||
capture_init_iterator capture_init_end() {
|
||||
return capture_init_begin() + NumCaptures;
|
||||
}
|
||||
|
||||
const_capture_init_iterator capture_init_end() const {
|
||||
return capture_init_begin() + NumCaptures;
|
||||
}
|
||||
|
||||
|
@ -131,12 +131,16 @@ class CXXForRangeStmt : public Stmt {
|
||||
// SubExprs[RANGE] is an expression or declstmt.
|
||||
// SubExprs[COND] and SubExprs[INC] are expressions.
|
||||
Stmt *SubExprs[END];
|
||||
SourceLocation CoawaitLoc;
|
||||
SourceLocation ColonLoc;
|
||||
SourceLocation RParenLoc;
|
||||
|
||||
friend class ASTStmtReader;
|
||||
public:
|
||||
CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd,
|
||||
Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body,
|
||||
SourceLocation FL, SourceLocation CL, SourceLocation RPL);
|
||||
SourceLocation FL, SourceLocation CAL, SourceLocation CL,
|
||||
SourceLocation RPL);
|
||||
CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
|
||||
|
||||
|
||||
@ -181,13 +185,10 @@ class CXXForRangeStmt : public Stmt {
|
||||
void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; }
|
||||
void setBody(Stmt *S) { SubExprs[BODY] = S; }
|
||||
|
||||
|
||||
SourceLocation getForLoc() const { return ForLoc; }
|
||||
void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
|
||||
SourceLocation getCoawaitLoc() const { return CoawaitLoc; }
|
||||
SourceLocation getColonLoc() const { return ColonLoc; }
|
||||
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
|
||||
SourceLocation getRParenLoc() const { return RParenLoc; }
|
||||
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
|
||||
SourceLocation getLocEnd() const LLVM_READONLY {
|
||||
@ -287,6 +288,130 @@ class MSDependentExistsStmt : public Stmt {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents the body of a coroutine. This wraps the normal function
|
||||
/// body and holds the additional semantic context required to set up and tear
|
||||
/// down the coroutine frame.
|
||||
class CoroutineBodyStmt : public Stmt {
|
||||
enum SubStmt {
|
||||
Body, ///< The body of the coroutine.
|
||||
Promise, ///< The promise statement.
|
||||
InitSuspend, ///< The initial suspend statement, run before the body.
|
||||
FinalSuspend, ///< The final suspend statement, run after the body.
|
||||
OnException, ///< Handler for exceptions thrown in the body.
|
||||
OnFallthrough, ///< Handler for control flow falling off the body.
|
||||
ReturnValue, ///< Return value for thunk function.
|
||||
FirstParamMove ///< First offset for move construction of parameter copies.
|
||||
};
|
||||
Stmt *SubStmts[SubStmt::FirstParamMove];
|
||||
|
||||
friend class ASTStmtReader;
|
||||
public:
|
||||
CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
|
||||
Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
|
||||
Expr *ReturnValue, ArrayRef<Expr *> ParamMoves)
|
||||
: Stmt(CoroutineBodyStmtClass) {
|
||||
SubStmts[CoroutineBodyStmt::Body] = Body;
|
||||
SubStmts[CoroutineBodyStmt::Promise] = Promise;
|
||||
SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend;
|
||||
SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend;
|
||||
SubStmts[CoroutineBodyStmt::OnException] = OnException;
|
||||
SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough;
|
||||
SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue;
|
||||
// FIXME: Tail-allocate space for parameter move expressions and store them.
|
||||
assert(ParamMoves.empty() && "not implemented yet");
|
||||
}
|
||||
|
||||
/// \brief Retrieve the body of the coroutine as written. This will be either
|
||||
/// a CompoundStmt or a TryStmt.
|
||||
Stmt *getBody() const {
|
||||
return SubStmts[SubStmt::Body];
|
||||
}
|
||||
|
||||
Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; }
|
||||
VarDecl *getPromiseDecl() const {
|
||||
return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl());
|
||||
}
|
||||
|
||||
Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; }
|
||||
Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; }
|
||||
|
||||
Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; }
|
||||
Stmt *getFallthroughHandler() const {
|
||||
return SubStmts[SubStmt::OnFallthrough];
|
||||
}
|
||||
|
||||
Expr *getReturnValueInit() const {
|
||||
return cast<Expr>(SubStmts[SubStmt::ReturnValue]);
|
||||
}
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY {
|
||||
return getBody()->getLocStart();
|
||||
}
|
||||
SourceLocation getLocEnd() const LLVM_READONLY {
|
||||
return getBody()->getLocEnd();
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove);
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CoroutineBodyStmtClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a 'co_return' statement in the C++ Coroutines TS.
|
||||
///
|
||||
/// This statament models the initialization of the coroutine promise
|
||||
/// (encapsulating the eventual notional return value) from an expression
|
||||
/// (or braced-init-list), followed by termination of the coroutine.
|
||||
///
|
||||
/// This initialization is modeled by the evaluation of the operand
|
||||
/// followed by a call to one of:
|
||||
/// <promise>.return_value(<operand>)
|
||||
/// <promise>.return_void()
|
||||
/// which we name the "promise call".
|
||||
class CoreturnStmt : public Stmt {
|
||||
SourceLocation CoreturnLoc;
|
||||
|
||||
enum SubStmt { Operand, PromiseCall, Count };
|
||||
Stmt *SubStmts[SubStmt::Count];
|
||||
|
||||
friend class ASTStmtReader;
|
||||
public:
|
||||
CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall)
|
||||
: Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) {
|
||||
SubStmts[SubStmt::Operand] = Operand;
|
||||
SubStmts[SubStmt::PromiseCall] = PromiseCall;
|
||||
}
|
||||
|
||||
SourceLocation getKeywordLoc() const { return CoreturnLoc; }
|
||||
|
||||
/// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr
|
||||
/// if none was specified.
|
||||
Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); }
|
||||
|
||||
/// \brief Retrieve the promise call that results from this 'co_return'
|
||||
/// statement. Will be nullptr if either the coroutine has not yet been
|
||||
/// finalized or the coroutine has no eventual return type.
|
||||
Expr *getPromiseCall() const {
|
||||
return static_cast<Expr*>(SubStmts[PromiseCall]);
|
||||
}
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; }
|
||||
SourceLocation getLocEnd() const LLVM_READONLY {
|
||||
return getOperand()->getLocEnd();
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(SubStmts, SubStmts + SubStmt::Count);
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CoreturnStmtClass;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
@ -139,86 +139,6 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
|
||||
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
|
||||
};
|
||||
|
||||
/// A range of statement iterators.
|
||||
///
|
||||
/// This class provides some extra functionality beyond std::pair
|
||||
/// in order to allow the following idiom:
|
||||
/// for (StmtRange range = stmt->children(); range; ++range)
|
||||
struct StmtRange : std::pair<StmtIterator,StmtIterator> {
|
||||
StmtRange() {}
|
||||
StmtRange(const StmtIterator &begin, const StmtIterator &end)
|
||||
: std::pair<StmtIterator,StmtIterator>(begin, end) {}
|
||||
|
||||
bool empty() const { return first == second; }
|
||||
explicit operator bool() const { return !empty(); }
|
||||
|
||||
Stmt *operator->() const { return first.operator->(); }
|
||||
Stmt *&operator*() const { return first.operator*(); }
|
||||
|
||||
StmtRange &operator++() {
|
||||
assert(!empty() && "incrementing on empty range");
|
||||
++first;
|
||||
return *this;
|
||||
}
|
||||
|
||||
StmtRange operator++(int) {
|
||||
assert(!empty() && "incrementing on empty range");
|
||||
StmtRange copy = *this;
|
||||
++first;
|
||||
return copy;
|
||||
}
|
||||
|
||||
friend const StmtIterator &begin(const StmtRange &range) {
|
||||
return range.first;
|
||||
}
|
||||
friend const StmtIterator &end(const StmtRange &range) {
|
||||
return range.second;
|
||||
}
|
||||
};
|
||||
|
||||
/// A range of const statement iterators.
|
||||
///
|
||||
/// This class provides some extra functionality beyond std::pair
|
||||
/// in order to allow the following idiom:
|
||||
/// for (ConstStmtRange range = stmt->children(); range; ++range)
|
||||
struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
|
||||
ConstStmtRange() {}
|
||||
ConstStmtRange(const ConstStmtIterator &begin,
|
||||
const ConstStmtIterator &end)
|
||||
: std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
|
||||
ConstStmtRange(const StmtRange &range)
|
||||
: std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
|
||||
{}
|
||||
ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
|
||||
: std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
|
||||
|
||||
bool empty() const { return first == second; }
|
||||
explicit operator bool() const { return !empty(); }
|
||||
|
||||
const Stmt *operator->() const { return first.operator->(); }
|
||||
const Stmt *operator*() const { return first.operator*(); }
|
||||
|
||||
ConstStmtRange &operator++() {
|
||||
assert(!empty() && "incrementing on empty range");
|
||||
++first;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ConstStmtRange operator++(int) {
|
||||
assert(!empty() && "incrementing on empty range");
|
||||
ConstStmtRange copy = *this;
|
||||
++first;
|
||||
return copy;
|
||||
}
|
||||
|
||||
friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
|
||||
return range.first;
|
||||
}
|
||||
friend const ConstStmtIterator &end(const ConstStmtRange &range) {
|
||||
return range.second;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@
|
||||
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/ExprOpenMP.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/StmtObjC.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
@ -93,6 +94,7 @@ class StmtVisitorBase {
|
||||
case UO_Real: DISPATCH(UnaryReal, UnaryOperator);
|
||||
case UO_Imag: DISPATCH(UnaryImag, UnaryOperator);
|
||||
case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator);
|
||||
case UO_Coawait: DISPATCH(UnaryCoawait, UnaryOperator);
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +159,7 @@ class StmtVisitorBase {
|
||||
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
|
||||
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
|
||||
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
|
||||
UNARYOP_FALLBACK(Extension)
|
||||
UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(Coawait)
|
||||
#undef UNARYOP_FALLBACK
|
||||
|
||||
// Base case, ignore it. :)
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TrailingObjects.h"
|
||||
|
||||
namespace llvm {
|
||||
class FoldingSetNodeID;
|
||||
@ -198,22 +199,19 @@ class TemplateArgument {
|
||||
///
|
||||
/// We assume that storage for the template arguments provided
|
||||
/// outlives the TemplateArgument itself.
|
||||
TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) {
|
||||
explicit TemplateArgument(ArrayRef<TemplateArgument> Args) {
|
||||
this->Args.Kind = Pack;
|
||||
this->Args.Args = Args;
|
||||
this->Args.NumArgs = NumArgs;
|
||||
this->Args.Args = Args.data();
|
||||
this->Args.NumArgs = Args.size();
|
||||
}
|
||||
|
||||
static TemplateArgument getEmptyPack() {
|
||||
return TemplateArgument((TemplateArgument*)nullptr, 0);
|
||||
}
|
||||
static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
|
||||
|
||||
/// \brief Create a new template argument pack by copying the given set of
|
||||
/// template arguments.
|
||||
static TemplateArgument CreatePackCopy(ASTContext &Context,
|
||||
const TemplateArgument *Args,
|
||||
unsigned NumArgs);
|
||||
|
||||
ArrayRef<TemplateArgument> Args);
|
||||
|
||||
/// \brief Return the kind of stored template argument.
|
||||
ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
|
||||
|
||||
@ -523,7 +521,7 @@ class TemplateArgumentListInfo {
|
||||
|
||||
// This can leak if used in an AST node, use ASTTemplateArgumentListInfo
|
||||
// instead.
|
||||
void* operator new(size_t bytes, ASTContext& C);
|
||||
void *operator new(size_t bytes, ASTContext &C) = delete;
|
||||
|
||||
public:
|
||||
TemplateArgumentListInfo() {}
|
||||
@ -544,6 +542,10 @@ class TemplateArgumentListInfo {
|
||||
return Arguments.data();
|
||||
}
|
||||
|
||||
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
|
||||
return Arguments;
|
||||
}
|
||||
|
||||
const TemplateArgumentLoc &operator[](unsigned I) const {
|
||||
return Arguments[I];
|
||||
}
|
||||
@ -561,84 +563,72 @@ class TemplateArgumentListInfo {
|
||||
/// the "<int>" in "sort<int>".
|
||||
/// This is safe to be used inside an AST node, in contrast with
|
||||
/// TemplateArgumentListInfo.
|
||||
struct ASTTemplateArgumentListInfo {
|
||||
struct ASTTemplateArgumentListInfo final
|
||||
: private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
|
||||
TemplateArgumentLoc> {
|
||||
private:
|
||||
friend TrailingObjects;
|
||||
|
||||
ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
|
||||
|
||||
public:
|
||||
/// \brief The source location of the left angle bracket ('<').
|
||||
SourceLocation LAngleLoc;
|
||||
|
||||
|
||||
/// \brief The source location of the right angle bracket ('>').
|
||||
SourceLocation RAngleLoc;
|
||||
|
||||
union {
|
||||
/// \brief The number of template arguments in TemplateArgs.
|
||||
/// The actual template arguments (if any) are stored after the
|
||||
/// ExplicitTemplateArgumentList structure.
|
||||
unsigned NumTemplateArgs;
|
||||
|
||||
/// Force ASTTemplateArgumentListInfo to the right alignment
|
||||
/// for the following array of TemplateArgumentLocs.
|
||||
llvm::AlignedCharArray<
|
||||
llvm::AlignOf<TemplateArgumentLoc>::Alignment, 1> Aligner;
|
||||
};
|
||||
/// \brief The number of template arguments in TemplateArgs.
|
||||
unsigned NumTemplateArgs;
|
||||
|
||||
/// \brief Retrieve the template arguments
|
||||
TemplateArgumentLoc *getTemplateArgs() {
|
||||
return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template arguments
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
|
||||
return getTrailingObjects<TemplateArgumentLoc>();
|
||||
}
|
||||
|
||||
const TemplateArgumentLoc &operator[](unsigned I) const {
|
||||
return getTemplateArgs()[I];
|
||||
}
|
||||
|
||||
static const ASTTemplateArgumentListInfo *Create(ASTContext &C,
|
||||
const TemplateArgumentListInfo &List);
|
||||
|
||||
void initializeFrom(const TemplateArgumentListInfo &List);
|
||||
void initializeFrom(const TemplateArgumentListInfo &List,
|
||||
bool &Dependent, bool &InstantiationDependent,
|
||||
bool &ContainsUnexpandedParameterPack);
|
||||
void copyInto(TemplateArgumentListInfo &List) const;
|
||||
static std::size_t sizeFor(unsigned NumTemplateArgs);
|
||||
static const ASTTemplateArgumentListInfo *
|
||||
Create(ASTContext &C, const TemplateArgumentListInfo &List);
|
||||
};
|
||||
|
||||
/// \brief Extends ASTTemplateArgumentListInfo with the source location
|
||||
/// information for the template keyword; this is used as part of the
|
||||
/// representation of qualified identifiers, such as S<T>::template apply<T>.
|
||||
struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo {
|
||||
typedef ASTTemplateArgumentListInfo Base;
|
||||
/// \brief Represents an explicit template argument list in C++, e.g.,
|
||||
/// the "<int>" in "sort<int>".
|
||||
///
|
||||
/// It is intended to be used as a trailing object on AST nodes, and
|
||||
/// as such, doesn't contain the array of TemplateArgumentLoc itself,
|
||||
/// but expects the containing object to also provide storage for
|
||||
/// that.
|
||||
struct LLVM_ALIGNAS(LLVM_PTR_SIZE) ASTTemplateKWAndArgsInfo {
|
||||
/// \brief The source location of the left angle bracket ('<').
|
||||
SourceLocation LAngleLoc;
|
||||
|
||||
// NOTE: the source location of the (optional) template keyword is
|
||||
// stored after all template arguments.
|
||||
/// \brief The source location of the right angle bracket ('>').
|
||||
SourceLocation RAngleLoc;
|
||||
|
||||
/// \brief Get the source location of the template keyword.
|
||||
SourceLocation getTemplateKeywordLoc() const {
|
||||
return *reinterpret_cast<const SourceLocation*>
|
||||
(getTemplateArgs() + NumTemplateArgs);
|
||||
}
|
||||
/// \brief The source location of the template keyword; this is used
|
||||
/// as part of the representation of qualified identifiers, such as
|
||||
/// S<T>::template apply<T>. Will be empty if this expression does
|
||||
/// not have a template keyword.
|
||||
SourceLocation TemplateKWLoc;
|
||||
|
||||
/// \brief Sets the source location of the template keyword.
|
||||
void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) {
|
||||
*reinterpret_cast<SourceLocation*>
|
||||
(getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc;
|
||||
}
|
||||
/// \brief The number of template arguments in TemplateArgs.
|
||||
unsigned NumTemplateArgs;
|
||||
|
||||
static const ASTTemplateKWAndArgsInfo*
|
||||
Create(ASTContext &C, SourceLocation TemplateKWLoc,
|
||||
const TemplateArgumentListInfo &List);
|
||||
|
||||
void initializeFrom(SourceLocation TemplateKWLoc,
|
||||
const TemplateArgumentListInfo &List);
|
||||
void initializeFrom(SourceLocation TemplateKWLoc,
|
||||
const TemplateArgumentListInfo &List,
|
||||
bool &Dependent, bool &InstantiationDependent,
|
||||
TemplateArgumentLoc *OutArgArray);
|
||||
void initializeFrom(SourceLocation TemplateKWLoc,
|
||||
const TemplateArgumentListInfo &List,
|
||||
TemplateArgumentLoc *OutArgArray, bool &Dependent,
|
||||
bool &InstantiationDependent,
|
||||
bool &ContainsUnexpandedParameterPack);
|
||||
void initializeFrom(SourceLocation TemplateKWLoc);
|
||||
|
||||
static std::size_t sizeFor(unsigned NumTemplateArgs);
|
||||
void copyInto(const TemplateArgumentLoc *ArgArray,
|
||||
TemplateArgumentListInfo &List) const;
|
||||
};
|
||||
|
||||
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
|
@ -180,9 +180,7 @@ class TemplateName {
|
||||
|
||||
StorageType Storage;
|
||||
|
||||
explicit TemplateName(void *Ptr) {
|
||||
Storage = StorageType::getFromOpaqueValue(Ptr);
|
||||
}
|
||||
explicit TemplateName(void *Ptr);
|
||||
|
||||
public:
|
||||
// \brief Kind of name that is actually stored.
|
||||
@ -207,17 +205,15 @@ class TemplateName {
|
||||
};
|
||||
|
||||
TemplateName() : Storage() { }
|
||||
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
|
||||
explicit TemplateName(OverloadedTemplateStorage *Storage)
|
||||
: Storage(Storage) { }
|
||||
explicit TemplateName(TemplateDecl *Template);
|
||||
explicit TemplateName(OverloadedTemplateStorage *Storage);
|
||||
explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);
|
||||
explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
|
||||
: Storage(Storage) { }
|
||||
explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
|
||||
explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
|
||||
explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage);
|
||||
explicit TemplateName(QualifiedTemplateName *Qual);
|
||||
explicit TemplateName(DependentTemplateName *Dep);
|
||||
|
||||
/// \brief Determine whether this template name is NULL.
|
||||
bool isNull() const { return Storage.isNull(); }
|
||||
bool isNull() const;
|
||||
|
||||
// \brief Get the kind of name that is actually stored.
|
||||
NameKind getKind() const;
|
||||
@ -238,26 +234,14 @@ class TemplateName {
|
||||
/// name refers to, if known. If the template name does not refer to a
|
||||
/// specific set of function templates because it is a dependent name or
|
||||
/// refers to a single template, returns NULL.
|
||||
OverloadedTemplateStorage *getAsOverloadedTemplate() const {
|
||||
if (UncommonTemplateNameStorage *Uncommon =
|
||||
Storage.dyn_cast<UncommonTemplateNameStorage *>())
|
||||
return Uncommon->getAsOverloadedStorage();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
OverloadedTemplateStorage *getAsOverloadedTemplate() const;
|
||||
|
||||
/// \brief Retrieve the substituted template template parameter, if
|
||||
/// known.
|
||||
///
|
||||
/// \returns The storage for the substituted template template parameter,
|
||||
/// if known. Otherwise, returns NULL.
|
||||
SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const {
|
||||
if (UncommonTemplateNameStorage *uncommon =
|
||||
Storage.dyn_cast<UncommonTemplateNameStorage *>())
|
||||
return uncommon->getAsSubstTemplateTemplateParm();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const;
|
||||
|
||||
/// \brief Retrieve the substituted template template parameter pack, if
|
||||
/// known.
|
||||
@ -265,25 +249,15 @@ class TemplateName {
|
||||
/// \returns The storage for the substituted template template parameter pack,
|
||||
/// if known. Otherwise, returns NULL.
|
||||
SubstTemplateTemplateParmPackStorage *
|
||||
getAsSubstTemplateTemplateParmPack() const {
|
||||
if (UncommonTemplateNameStorage *Uncommon =
|
||||
Storage.dyn_cast<UncommonTemplateNameStorage *>())
|
||||
return Uncommon->getAsSubstTemplateTemplateParmPack();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
getAsSubstTemplateTemplateParmPack() const;
|
||||
|
||||
/// \brief Retrieve the underlying qualified template name
|
||||
/// structure, if any.
|
||||
QualifiedTemplateName *getAsQualifiedTemplateName() const {
|
||||
return Storage.dyn_cast<QualifiedTemplateName *>();
|
||||
}
|
||||
QualifiedTemplateName *getAsQualifiedTemplateName() const;
|
||||
|
||||
/// \brief Retrieve the underlying dependent template name
|
||||
/// structure, if any.
|
||||
DependentTemplateName *getAsDependentTemplateName() const {
|
||||
return Storage.dyn_cast<DependentTemplateName *>();
|
||||
}
|
||||
DependentTemplateName *getAsDependentTemplateName() const;
|
||||
|
||||
TemplateName getUnderlying() const;
|
||||
|
||||
@ -359,9 +333,6 @@ class SubstTemplateTemplateParmStorage
|
||||
TemplateName replacement);
|
||||
};
|
||||
|
||||
inline TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
|
||||
: Storage(Storage) { }
|
||||
|
||||
inline TemplateName TemplateName::getUnderlying() const {
|
||||
if (SubstTemplateTemplateParmStorage *subst
|
||||
= getAsSubstTemplateTemplateParm())
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -151,6 +151,14 @@ class TypeLoc {
|
||||
|
||||
TypeLoc IgnoreParens() const;
|
||||
|
||||
/// \brief Find a type with the location of an explicit type qualifier.
|
||||
///
|
||||
/// The result, if non-null, will be one of:
|
||||
/// QualifiedTypeLoc
|
||||
/// AtomicTypeLoc
|
||||
/// AttributedTypeLoc, for those type attributes that behave as qualifiers
|
||||
TypeLoc findExplicitQualifierLoc() const;
|
||||
|
||||
/// \brief Initializes this to state that every location in this
|
||||
/// type is the given location.
|
||||
///
|
||||
@ -162,19 +170,18 @@ class TypeLoc {
|
||||
|
||||
/// \brief Initializes this by copying its information from another
|
||||
/// TypeLoc of the same type.
|
||||
void initializeFullCopy(TypeLoc Other) const {
|
||||
void initializeFullCopy(TypeLoc Other) {
|
||||
assert(getType() == Other.getType());
|
||||
size_t Size = getFullDataSize();
|
||||
memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
|
||||
copy(Other);
|
||||
}
|
||||
|
||||
/// \brief Initializes this by copying its information from another
|
||||
/// TypeLoc of the same type. The given size must be the full data
|
||||
/// size.
|
||||
void initializeFullCopy(TypeLoc Other, unsigned Size) const {
|
||||
void initializeFullCopy(TypeLoc Other, unsigned Size) {
|
||||
assert(getType() == Other.getType());
|
||||
assert(getFullDataSize() == Size);
|
||||
memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
|
||||
copy(Other);
|
||||
}
|
||||
|
||||
/// Copies the other type loc into this one.
|
||||
@ -206,6 +213,7 @@ class TypeLoc {
|
||||
|
||||
/// \brief Return the TypeLoc for a type source info.
|
||||
inline TypeLoc TypeSourceInfo::getTypeLoc() const {
|
||||
// TODO: is this alignment already sufficient?
|
||||
return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1)));
|
||||
}
|
||||
|
||||
@ -736,6 +744,10 @@ class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
||||
return hasAttrExprOperand() || hasAttrEnumOperand();
|
||||
}
|
||||
|
||||
bool isQualifier() const {
|
||||
return getTypePtr()->isQualifier();
|
||||
}
|
||||
|
||||
/// The modified type, which is generally canonically different from
|
||||
/// the attribute type.
|
||||
/// int main(int, char**) __attribute__((noreturn))
|
||||
|
@ -51,7 +51,7 @@ class VTableComponent {
|
||||
CK_UnusedFunctionPointer
|
||||
};
|
||||
|
||||
VTableComponent() { }
|
||||
VTableComponent() = default;
|
||||
|
||||
static VTableComponent MakeVCallOffset(CharUnits Offset) {
|
||||
return VTableComponent(CK_VCallOffset, Offset);
|
||||
@ -122,31 +122,56 @@ class VTableComponent {
|
||||
}
|
||||
|
||||
const CXXRecordDecl *getRTTIDecl() const {
|
||||
assert(getKind() == CK_RTTI && "Invalid component kind!");
|
||||
|
||||
assert(isRTTIKind() && "Invalid component kind!");
|
||||
return reinterpret_cast<CXXRecordDecl *>(getPointer());
|
||||
}
|
||||
|
||||
const CXXMethodDecl *getFunctionDecl() const {
|
||||
assert(getKind() == CK_FunctionPointer);
|
||||
|
||||
assert(isFunctionPointerKind() && "Invalid component kind!");
|
||||
if (isDestructorKind())
|
||||
return getDestructorDecl();
|
||||
return reinterpret_cast<CXXMethodDecl *>(getPointer());
|
||||
}
|
||||
|
||||
const CXXDestructorDecl *getDestructorDecl() const {
|
||||
assert((getKind() == CK_CompleteDtorPointer ||
|
||||
getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
|
||||
|
||||
assert(isDestructorKind() && "Invalid component kind!");
|
||||
return reinterpret_cast<CXXDestructorDecl *>(getPointer());
|
||||
}
|
||||
|
||||
const CXXMethodDecl *getUnusedFunctionDecl() const {
|
||||
assert(getKind() == CK_UnusedFunctionPointer);
|
||||
|
||||
assert(getKind() == CK_UnusedFunctionPointer && "Invalid component kind!");
|
||||
return reinterpret_cast<CXXMethodDecl *>(getPointer());
|
||||
}
|
||||
|
||||
bool isDestructorKind() const { return isDestructorKind(getKind()); }
|
||||
|
||||
bool isUsedFunctionPointerKind() const {
|
||||
return isUsedFunctionPointerKind(getKind());
|
||||
}
|
||||
|
||||
bool isFunctionPointerKind() const {
|
||||
return isFunctionPointerKind(getKind());
|
||||
}
|
||||
|
||||
bool isRTTIKind() const { return isRTTIKind(getKind()); }
|
||||
|
||||
private:
|
||||
static bool isFunctionPointerKind(Kind ComponentKind) {
|
||||
return isUsedFunctionPointerKind(ComponentKind) ||
|
||||
ComponentKind == CK_UnusedFunctionPointer;
|
||||
}
|
||||
static bool isUsedFunctionPointerKind(Kind ComponentKind) {
|
||||
return ComponentKind == CK_FunctionPointer ||
|
||||
isDestructorKind(ComponentKind);
|
||||
}
|
||||
static bool isDestructorKind(Kind ComponentKind) {
|
||||
return ComponentKind == CK_CompleteDtorPointer ||
|
||||
ComponentKind == CK_DeletingDtorPointer;
|
||||
}
|
||||
static bool isRTTIKind(Kind ComponentKind) {
|
||||
return ComponentKind == CK_RTTI;
|
||||
}
|
||||
|
||||
VTableComponent(Kind ComponentKind, CharUnits Offset) {
|
||||
assert((ComponentKind == CK_VCallOffset ||
|
||||
ComponentKind == CK_VBaseOffset ||
|
||||
@ -158,12 +183,8 @@ class VTableComponent {
|
||||
}
|
||||
|
||||
VTableComponent(Kind ComponentKind, uintptr_t Ptr) {
|
||||
assert((ComponentKind == CK_RTTI ||
|
||||
ComponentKind == CK_FunctionPointer ||
|
||||
ComponentKind == CK_CompleteDtorPointer ||
|
||||
ComponentKind == CK_DeletingDtorPointer ||
|
||||
ComponentKind == CK_UnusedFunctionPointer) &&
|
||||
"Invalid component kind!");
|
||||
assert((isRTTIKind(ComponentKind) || isFunctionPointerKind(ComponentKind)) &&
|
||||
"Invalid component kind!");
|
||||
|
||||
assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
|
||||
|
||||
@ -178,11 +199,7 @@ class VTableComponent {
|
||||
}
|
||||
|
||||
uintptr_t getPointer() const {
|
||||
assert((getKind() == CK_RTTI ||
|
||||
getKind() == CK_FunctionPointer ||
|
||||
getKind() == CK_CompleteDtorPointer ||
|
||||
getKind() == CK_DeletingDtorPointer ||
|
||||
getKind() == CK_UnusedFunctionPointer) &&
|
||||
assert((getKind() == CK_RTTI || isFunctionPointerKind()) &&
|
||||
"Invalid component kind!");
|
||||
|
||||
return static_cast<uintptr_t>(Value & ~7ULL);
|
||||
@ -205,8 +222,11 @@ class VTableLayout {
|
||||
|
||||
typedef const VTableComponent *vtable_component_iterator;
|
||||
typedef const VTableThunkTy *vtable_thunk_iterator;
|
||||
typedef llvm::iterator_range<vtable_component_iterator>
|
||||
vtable_component_range;
|
||||
|
||||
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
|
||||
|
||||
private:
|
||||
uint64_t NumVTableComponents;
|
||||
std::unique_ptr<VTableComponent[]> VTableComponents;
|
||||
@ -233,6 +253,11 @@ class VTableLayout {
|
||||
return NumVTableComponents;
|
||||
}
|
||||
|
||||
vtable_component_range vtable_components() const {
|
||||
return vtable_component_range(vtable_component_begin(),
|
||||
vtable_component_end());
|
||||
}
|
||||
|
||||
vtable_component_iterator vtable_component_begin() const {
|
||||
return VTableComponents.get();
|
||||
}
|
||||
@ -376,10 +401,6 @@ struct VPtrInfo {
|
||||
VPtrInfo(const CXXRecordDecl *RD)
|
||||
: ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {}
|
||||
|
||||
// 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
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
|
||||
|
||||
#include "clang/ASTMatchers/ASTMatchers.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
|
||||
@ -208,7 +209,7 @@ class MatchFinder {
|
||||
NestedNameSpecifierLoc;
|
||||
std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
|
||||
/// \brief All the callbacks in one container to simplify iteration.
|
||||
std::vector<MatchCallback *> AllCallbacks;
|
||||
llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
|
||||
};
|
||||
|
||||
private:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -188,8 +188,11 @@ class ASTMatchFinder;
|
||||
/// Used by the implementation of Matcher<T> and DynTypedMatcher.
|
||||
/// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T>
|
||||
/// instead.
|
||||
class DynMatcherInterface : public RefCountedBaseVPTR {
|
||||
class DynMatcherInterface
|
||||
: public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
|
||||
public:
|
||||
virtual ~DynMatcherInterface() {}
|
||||
|
||||
/// \brief Returns true if \p DynNode can be matched.
|
||||
///
|
||||
/// May bind \p DynNode to an ID via \p Builder, or recurse into
|
||||
@ -209,8 +212,6 @@ class DynMatcherInterface : public RefCountedBaseVPTR {
|
||||
template <typename T>
|
||||
class MatcherInterface : public DynMatcherInterface {
|
||||
public:
|
||||
~MatcherInterface() override {}
|
||||
|
||||
/// \brief Returns true if 'Node' can be matched.
|
||||
///
|
||||
/// May bind 'Node' to an ID via 'Builder', or recurse into
|
||||
@ -281,6 +282,7 @@ class DynTypedMatcher {
|
||||
};
|
||||
static DynTypedMatcher
|
||||
constructVariadic(VariadicOperator Op,
|
||||
ast_type_traits::ASTNodeKind SupportedKind,
|
||||
std::vector<DynTypedMatcher> InnerMatchers);
|
||||
|
||||
/// \brief Get a "true" matcher for \p NodeKind.
|
||||
@ -556,22 +558,32 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Metafunction to determine if type T has a member called getDecl.
|
||||
// Metafunction to determine if type T has a member called
|
||||
// getDecl.
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__clang__)
|
||||
// For old versions of MSVC, we use a weird nonstandard __if_exists
|
||||
// statement, since before MSVC2015, it was not standards-conformant
|
||||
// enough to compile the usual code below.
|
||||
template <typename T> struct has_getDecl {
|
||||
struct Default { int getDecl; };
|
||||
struct Derived : T, Default { };
|
||||
|
||||
template<typename C, C> struct CheckT;
|
||||
|
||||
// If T::getDecl exists, an ambiguity arises and CheckT will
|
||||
// not be instantiable. This makes f(...) the only available
|
||||
// overload.
|
||||
template<typename C>
|
||||
static char (&f(CheckT<int Default::*, &C::getDecl>*))[1];
|
||||
template<typename C> static char (&f(...))[2];
|
||||
|
||||
static bool const value = sizeof(f<Derived>(nullptr)) == 2;
|
||||
__if_exists(T::getDecl) {
|
||||
enum { value = 1 };
|
||||
}
|
||||
__if_not_exists(T::getDecl) {
|
||||
enum { value = 0 };
|
||||
}
|
||||
};
|
||||
#else
|
||||
// There is a default template inheriting from "false_type". Then, a
|
||||
// partial specialization inherits from "true_type". However, this
|
||||
// specialization will only exist when the call to getDecl() isn't an
|
||||
// error -- it vanishes by SFINAE when the member doesn't exist.
|
||||
template <typename> struct type_sink_to_void { typedef void type; };
|
||||
template <typename T, typename = void> struct has_getDecl : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_getDecl<
|
||||
T, typename type_sink_to_void<decltype(std::declval<T>().getDecl())>::type>
|
||||
: std::true_type {};
|
||||
#endif
|
||||
|
||||
/// \brief Matches overloaded operators with a specific name.
|
||||
///
|
||||
@ -667,16 +679,30 @@ class HasDeclarationMatcher : public WrapperMatcherInterface<T> {
|
||||
return matchesDecl(Node.getDecl(), Finder, Builder);
|
||||
}
|
||||
|
||||
/// \brief Extracts the CXXRecordDecl or EnumDecl of a QualType and returns
|
||||
/// whether the inner matcher matches on it.
|
||||
/// \brief Extracts the TagDecl of a QualType and returns whether the inner
|
||||
/// matcher matches on it.
|
||||
bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
|
||||
BoundNodesTreeBuilder *Builder) const {
|
||||
/// FIXME: Add other ways to convert...
|
||||
if (Node.isNull())
|
||||
return false;
|
||||
if (const EnumType *AsEnum = dyn_cast<EnumType>(Node.getTypePtr()))
|
||||
return matchesDecl(AsEnum->getDecl(), Finder, Builder);
|
||||
return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder);
|
||||
|
||||
if (auto *TD = Node->getAsTagDecl())
|
||||
return matchesDecl(TD, Finder, Builder);
|
||||
else if (auto *TT = Node->getAs<TypedefType>())
|
||||
return matchesDecl(TT->getDecl(), Finder, Builder);
|
||||
// Do not use getAs<TemplateTypeParmType> instead of the direct dyn_cast.
|
||||
// Calling getAs will return the canonical type, but that type does not
|
||||
// store a TemplateTypeParmDecl. We *need* the uncanonical type, if it is
|
||||
// available, and using dyn_cast ensures that.
|
||||
else if (auto *TTP = dyn_cast<TemplateTypeParmType>(Node.getTypePtr()))
|
||||
return matchesDecl(TTP->getDecl(), Finder, Builder);
|
||||
else if (auto *OCIT = Node->getAs<ObjCInterfaceType>())
|
||||
return matchesDecl(OCIT->getDecl(), Finder, Builder);
|
||||
else if (auto *UUT = Node->getAs<UnresolvedUsingType>())
|
||||
return matchesDecl(UUT->getDecl(), Finder, Builder);
|
||||
else if (auto *ICNT = Node->getAs<InjectedClassNameType>())
|
||||
return matchesDecl(ICNT->getDecl(), Finder, Builder);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Gets the TemplateDecl from a TemplateSpecializationType
|
||||
@ -753,7 +779,7 @@ const bool IsBaseType<T>::value;
|
||||
/// at least one ancestor matched.
|
||||
///
|
||||
/// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal.
|
||||
/// In the future, we wan to implement this for all nodes for which it makes
|
||||
/// In the future, we want to implement this for all nodes for which it makes
|
||||
/// sense. In the case of matchesAncestorOf, we'll want to implement it for
|
||||
/// all nodes, as all nodes have ancestors.
|
||||
class ASTMatchFinder {
|
||||
@ -833,8 +859,10 @@ class ASTMatchFinder {
|
||||
BoundNodesTreeBuilder *Builder,
|
||||
AncestorMatchMode MatchMode) {
|
||||
static_assert(std::is_base_of<Decl, T>::value ||
|
||||
std::is_base_of<Stmt, T>::value,
|
||||
"only Decl or Stmt allowed for recursive matching");
|
||||
std::is_base_of<NestedNameSpecifierLoc, T>::value ||
|
||||
std::is_base_of<Stmt, T>::value ||
|
||||
std::is_base_of<TypeLoc, T>::value,
|
||||
"type not allowed for recursive matching");
|
||||
return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node),
|
||||
Matcher, Builder, MatchMode);
|
||||
}
|
||||
@ -1137,7 +1165,8 @@ template <typename... Ps> class VariadicOperatorMatcher {
|
||||
|
||||
template <typename T> operator Matcher<T>() const {
|
||||
return DynTypedMatcher::constructVariadic(
|
||||
Op, getMatchers<T>(llvm::index_sequence_for<Ps...>()))
|
||||
Op, ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
|
||||
getMatchers<T>(llvm::index_sequence_for<Ps...>()))
|
||||
.template unconditionalConvertTo<T>();
|
||||
}
|
||||
|
||||
@ -1191,8 +1220,10 @@ BindableMatcher<T> makeAllOfComposite(
|
||||
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
|
||||
PI(InnerMatchers.end()));
|
||||
return BindableMatcher<T>(
|
||||
DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
|
||||
std::move(DynMatchers))
|
||||
DynTypedMatcher::constructVariadic(
|
||||
DynTypedMatcher::VO_AllOf,
|
||||
ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
|
||||
std::move(DynMatchers))
|
||||
.template unconditionalConvertTo<T>());
|
||||
}
|
||||
|
||||
|
@ -104,11 +104,11 @@ class Diagnostics {
|
||||
/// \brief About to call the constructor for a matcher.
|
||||
enum ConstructMatcherEnum { ConstructMatcher };
|
||||
Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName,
|
||||
const SourceRange &MatcherRange);
|
||||
SourceRange MatcherRange);
|
||||
/// \brief About to recurse into parsing one argument for a matcher.
|
||||
enum MatcherArgEnum { MatcherArg };
|
||||
Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName,
|
||||
const SourceRange &MatcherRange, unsigned ArgNumber);
|
||||
SourceRange MatcherRange, unsigned ArgNumber);
|
||||
~Context();
|
||||
|
||||
private:
|
||||
@ -137,7 +137,7 @@ class Diagnostics {
|
||||
/// All the context information will be kept on the error message.
|
||||
/// \return a helper class to allow the caller to pass the arguments for the
|
||||
/// error message, using the << operator.
|
||||
ArgStream addError(const SourceRange &Range, ErrorType Error);
|
||||
ArgStream addError(SourceRange Range, ErrorType Error);
|
||||
|
||||
/// \brief Information stored for one frame of the context.
|
||||
struct ContextFrame {
|
||||
|
@ -81,7 +81,7 @@ class Parser {
|
||||
/// matcher if an error occurred. In that case, \c Error will contain a
|
||||
/// description of the error.
|
||||
virtual VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
|
||||
const SourceRange &NameRange,
|
||||
SourceRange NameRange,
|
||||
StringRef BindID,
|
||||
ArrayRef<ParserValue> Args,
|
||||
Diagnostics *Error) = 0;
|
||||
@ -129,7 +129,7 @@ class Parser {
|
||||
lookupMatcherCtor(StringRef MatcherName) override;
|
||||
|
||||
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
|
||||
const SourceRange &NameRange,
|
||||
SourceRange NameRange,
|
||||
StringRef BindID,
|
||||
ArrayRef<ParserValue> Args,
|
||||
Diagnostics *Error) override;
|
||||
|
@ -106,7 +106,7 @@ class Registry {
|
||||
/// the signature. In that case \c Error will contain the description of
|
||||
/// the error.
|
||||
static VariantMatcher constructMatcher(MatcherCtor Ctor,
|
||||
const SourceRange &NameRange,
|
||||
SourceRange NameRange,
|
||||
ArrayRef<ParserValue> Args,
|
||||
Diagnostics *Error);
|
||||
|
||||
@ -117,7 +117,7 @@ class Registry {
|
||||
/// If the matcher is not bindable, it sets an error in \c Error and returns
|
||||
/// a null matcher.
|
||||
static VariantMatcher constructBoundMatcher(MatcherCtor Ctor,
|
||||
const SourceRange &NameRange,
|
||||
SourceRange NameRange,
|
||||
StringRef BindID,
|
||||
ArrayRef<ParserValue> Args,
|
||||
Diagnostics *Error);
|
||||
|
@ -71,7 +71,7 @@ namespace consumed {
|
||||
virtual void warnParamReturnTypestateMismatch(SourceLocation Loc,
|
||||
StringRef VariableName,
|
||||
StringRef ExpectedState,
|
||||
StringRef ObservedState) {};
|
||||
StringRef ObservedState) {}
|
||||
|
||||
// FIXME: Add documentation.
|
||||
virtual void warnParamTypestateMismatch(SourceLocation LOC,
|
||||
@ -162,8 +162,8 @@ namespace consumed {
|
||||
ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
|
||||
|
||||
/// \brief Merge this state map with another map.
|
||||
void intersect(const ConsumedStateMap *Other);
|
||||
|
||||
void intersect(const ConsumedStateMap &Other);
|
||||
|
||||
void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack,
|
||||
const ConsumedStateMap *LoopBackStates,
|
||||
ConsumedWarningsHandlerBase &WarningsHandler);
|
||||
@ -196,15 +196,19 @@ namespace consumed {
|
||||
};
|
||||
|
||||
class ConsumedBlockInfo {
|
||||
std::vector<ConsumedStateMap*> StateMapsArray;
|
||||
std::vector<std::unique_ptr<ConsumedStateMap>> StateMapsArray;
|
||||
std::vector<unsigned int> VisitOrder;
|
||||
|
||||
public:
|
||||
ConsumedBlockInfo() { }
|
||||
~ConsumedBlockInfo() { llvm::DeleteContainerPointers(StateMapsArray); }
|
||||
ConsumedBlockInfo() = default;
|
||||
ConsumedBlockInfo &operator=(ConsumedBlockInfo &&Other) {
|
||||
StateMapsArray = std::move(Other.StateMapsArray);
|
||||
VisitOrder = std::move(Other.VisitOrder);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
|
||||
: StateMapsArray(NumBlocks, nullptr), VisitOrder(NumBlocks, 0) {
|
||||
: StateMapsArray(NumBlocks), VisitOrder(NumBlocks, 0) {
|
||||
unsigned int VisitOrderCounter = 0;
|
||||
for (PostOrderCFGView::iterator BI = SortedGraph->begin(),
|
||||
BE = SortedGraph->end(); BI != BE; ++BI) {
|
||||
@ -214,17 +218,18 @@ namespace consumed {
|
||||
|
||||
bool allBackEdgesVisited(const CFGBlock *CurrBlock,
|
||||
const CFGBlock *TargetBlock);
|
||||
|
||||
|
||||
void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap,
|
||||
bool &AlreadyOwned);
|
||||
void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap);
|
||||
|
||||
std::unique_ptr<ConsumedStateMap> &OwnedStateMap);
|
||||
void addInfo(const CFGBlock *Block,
|
||||
std::unique_ptr<ConsumedStateMap> StateMap);
|
||||
|
||||
ConsumedStateMap* borrowInfo(const CFGBlock *Block);
|
||||
|
||||
void discardInfo(const CFGBlock *Block);
|
||||
|
||||
ConsumedStateMap* getInfo(const CFGBlock *Block);
|
||||
|
||||
|
||||
std::unique_ptr<ConsumedStateMap> getInfo(const CFGBlock *Block);
|
||||
|
||||
bool isBackEdge(const CFGBlock *From, const CFGBlock *To);
|
||||
bool isBackEdgeTarget(const CFGBlock *Block);
|
||||
};
|
||||
@ -233,13 +238,12 @@ namespace consumed {
|
||||
class ConsumedAnalyzer {
|
||||
|
||||
ConsumedBlockInfo BlockInfo;
|
||||
ConsumedStateMap *CurrStates;
|
||||
|
||||
std::unique_ptr<ConsumedStateMap> CurrStates;
|
||||
|
||||
ConsumedState ExpectedReturnState;
|
||||
|
||||
void determineExpectedReturnState(AnalysisDeclContext &AC,
|
||||
const FunctionDecl *D);
|
||||
bool hasConsumableAttributes(const CXXRecordDecl *RD);
|
||||
bool splitState(const CFGBlock *CurrBlock,
|
||||
const ConsumedStmtVisitor &Visitor);
|
||||
|
||||
|
@ -287,10 +287,12 @@ class CapabilityExpr {
|
||||
}
|
||||
|
||||
const ValueDecl* valueDecl() const {
|
||||
if (Negated)
|
||||
if (Negated || CapExpr == nullptr)
|
||||
return nullptr;
|
||||
if (auto *P = dyn_cast<til::Project>(CapExpr))
|
||||
return P->clangDecl();
|
||||
if (auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
|
||||
return P->clangDecl();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1395,7 +1395,7 @@ class Goto : public Terminator {
|
||||
|
||||
/// Return the list of basic blocks that this terminator can branch to.
|
||||
ArrayRef<BasicBlock*> successors() {
|
||||
return ArrayRef<BasicBlock*>(&TargetBlock, 1);
|
||||
return TargetBlock;
|
||||
}
|
||||
|
||||
template <class V>
|
||||
@ -1445,7 +1445,7 @@ class Branch : public Terminator {
|
||||
|
||||
/// Return the list of basic blocks that this terminator can branch to.
|
||||
ArrayRef<BasicBlock*> successors() {
|
||||
return ArrayRef<BasicBlock*>(Branches, 2);
|
||||
return llvm::makeArrayRef(Branches);
|
||||
}
|
||||
|
||||
template <class V>
|
||||
@ -1479,7 +1479,7 @@ class Return : public Terminator {
|
||||
|
||||
/// Return an empty list.
|
||||
ArrayRef<BasicBlock*> successors() {
|
||||
return ArrayRef<BasicBlock*>();
|
||||
return None;
|
||||
}
|
||||
|
||||
SExpr *returnValue() { return Retval; }
|
||||
@ -1507,7 +1507,7 @@ inline ArrayRef<BasicBlock*> Terminator::successors() {
|
||||
case COP_Branch: return cast<Branch>(this)->successors();
|
||||
case COP_Return: return cast<Return>(this)->successors();
|
||||
default:
|
||||
return ArrayRef<BasicBlock*>();
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,6 @@ class CFGDeleteDtor : public CFGImplicitDtor {
|
||||
return static_cast<CXXDeleteExpr *>(Data2.getPointer());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
friend class CFGElement;
|
||||
CFGDeleteDtor() {}
|
||||
@ -693,7 +692,7 @@ class CFGBlock {
|
||||
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt,
|
||||
BumpVectorContext &C) {
|
||||
return iterator(Elements.insert(I.base(), Cnt,
|
||||
CFGAutomaticObjDtor(nullptr, 0), C));
|
||||
CFGAutomaticObjDtor(nullptr, nullptr), C));
|
||||
}
|
||||
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) {
|
||||
*I = CFGAutomaticObjDtor(VD, S);
|
||||
@ -767,7 +766,7 @@ class CFG {
|
||||
/// (not a pointer to CFGBlock).
|
||||
class graph_iterator {
|
||||
public:
|
||||
typedef const CFGBlock value_type;
|
||||
typedef CFGBlock value_type;
|
||||
typedef value_type& reference;
|
||||
typedef value_type* pointer;
|
||||
typedef BumpVector<CFGBlock*>::iterator ImplTy;
|
||||
@ -1110,4 +1109,5 @@ template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
|
||||
}
|
||||
};
|
||||
} // end llvm namespace
|
||||
#endif
|
||||
|
||||
#endif // LLVM_CLANG_ANALYSIS_CFG_H
|
||||
|
@ -33,8 +33,31 @@ namespace clang {
|
||||
class AnalysisDeclContext;
|
||||
class FunctionDecl;
|
||||
class LocationContext;
|
||||
class ProgramPointTag;
|
||||
|
||||
/// ProgramPoints can be "tagged" as representing points specific to a given
|
||||
/// analysis entity. Tags are abstract annotations, with an associated
|
||||
/// description and potentially other information.
|
||||
class ProgramPointTag {
|
||||
public:
|
||||
ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
|
||||
virtual ~ProgramPointTag();
|
||||
virtual StringRef getTagDescription() const = 0;
|
||||
|
||||
protected:
|
||||
/// Used to implement 'isKind' in subclasses.
|
||||
const void *getTagKind() { return TagKind; }
|
||||
|
||||
private:
|
||||
const void *TagKind;
|
||||
};
|
||||
|
||||
class SimpleProgramPointTag : public ProgramPointTag {
|
||||
std::string Desc;
|
||||
public:
|
||||
SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
|
||||
StringRef getTagDescription() const override;
|
||||
};
|
||||
|
||||
class ProgramPoint {
|
||||
public:
|
||||
enum Kind { BlockEdgeKind,
|
||||
@ -643,30 +666,6 @@ class EpsilonPoint : public ProgramPoint {
|
||||
}
|
||||
};
|
||||
|
||||
/// ProgramPoints can be "tagged" as representing points specific to a given
|
||||
/// analysis entity. Tags are abstract annotations, with an associated
|
||||
/// description and potentially other information.
|
||||
class ProgramPointTag {
|
||||
public:
|
||||
ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
|
||||
virtual ~ProgramPointTag();
|
||||
virtual StringRef getTagDescription() const = 0;
|
||||
|
||||
protected:
|
||||
/// Used to implement 'isKind' in subclasses.
|
||||
const void *getTagKind() { return TagKind; }
|
||||
|
||||
private:
|
||||
const void *TagKind;
|
||||
};
|
||||
|
||||
class SimpleProgramPointTag : public ProgramPointTag {
|
||||
std::string Desc;
|
||||
public:
|
||||
SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
|
||||
StringRef getTagDescription() const override;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
||||
|
@ -35,7 +35,12 @@ class BumpVectorContext {
|
||||
/// Construct a new BumpVectorContext that creates a new BumpPtrAllocator
|
||||
/// and destroys it when the BumpVectorContext object is destroyed.
|
||||
BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), 1) {}
|
||||
|
||||
|
||||
BumpVectorContext(BumpVectorContext &&Other) : Alloc(Other.Alloc) {
|
||||
Other.Alloc.setInt(false);
|
||||
Other.Alloc.setPointer(nullptr);
|
||||
}
|
||||
|
||||
/// Construct a new BumpVectorContext that reuses an existing
|
||||
/// BumpPtrAllocator. This BumpPtrAllocator is not destroyed when the
|
||||
/// BumpVectorContext object is destroyed.
|
||||
|
@ -113,7 +113,7 @@ def GlobalVar : SubsetSubject<Var,
|
||||
// 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}]>;
|
||||
[{S->getFunctionType(false) != nullptr}]>;
|
||||
|
||||
def OpenCLKernelFunction : SubsetSubject<Function, [{
|
||||
S->hasAttr<OpenCLKernelAttr>()
|
||||
@ -123,15 +123,19 @@ def OpenCLKernelFunction : SubsetSubject<Function, [{
|
||||
// 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 &&
|
||||
[{(S->getFunctionType(true) != nullptr &&
|
||||
isa<FunctionProtoType>(S->getFunctionType())) ||
|
||||
isa<ObjCMethodDecl>(S) ||
|
||||
isa<BlockDecl>(S)}]>;
|
||||
|
||||
// A single argument to an attribute
|
||||
class Argument<string name, bit optional> {
|
||||
class Argument<string name, bit optional, bit fake = 0> {
|
||||
string Name = name;
|
||||
bit Optional = optional;
|
||||
|
||||
/// A fake argument is used to store and serialize additional information
|
||||
/// in an attribute without actually changing its parsing or pretty-printing.
|
||||
bit Fake = fake;
|
||||
}
|
||||
|
||||
class BoolArgument<string name, bit opt = 0> : Argument<name, opt>;
|
||||
@ -167,7 +171,8 @@ class DefaultIntArgument<string name, int default> : IntArgument<name, 1> {
|
||||
// This argument is more complex, it includes the enumerator type name,
|
||||
// a list of strings to accept, and a list of enumerators to map them to.
|
||||
class EnumArgument<string name, string type, list<string> values,
|
||||
list<string> enums, bit opt = 0> : Argument<name, opt> {
|
||||
list<string> enums, bit opt = 0, bit fake = 0>
|
||||
: Argument<name, opt, fake> {
|
||||
string Type = type;
|
||||
list<string> Values = values;
|
||||
list<string> Enums = enums;
|
||||
@ -241,14 +246,18 @@ def COnly : LangOpt<"CPlusPlus", 1>;
|
||||
class TargetArch<list<string> arches> {
|
||||
list<string> Arches = arches;
|
||||
list<string> OSes;
|
||||
list<string> CXXABIs;
|
||||
}
|
||||
def TargetARM : TargetArch<["arm", "thumb"]>;
|
||||
def TargetMips : TargetArch<["mips", "mipsel"]>;
|
||||
def TargetMSP430 : TargetArch<["msp430"]>;
|
||||
def TargetX86 : TargetArch<["x86"]>;
|
||||
def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
|
||||
let OSes = ["Win32"];
|
||||
}
|
||||
def TargetMips : TargetArch<["mips", "mipsel"]>;
|
||||
def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
|
||||
let CXXABIs = ["Microsoft"];
|
||||
}
|
||||
|
||||
class Attr {
|
||||
// The various ways in which an attribute can be spelled in source
|
||||
@ -286,6 +295,8 @@ class Attr {
|
||||
// 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.
|
||||
// Note: Any additional data members will leak and should be constructed
|
||||
// externally on the ASTContext.
|
||||
code AdditionalMembers = [{}];
|
||||
// Any documentation that should be associated with the attribute. Since an
|
||||
// attribute may be documented under multiple categories, more than one
|
||||
@ -415,8 +426,8 @@ def Annotate : InheritableParamAttr {
|
||||
}
|
||||
|
||||
def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
|
||||
// NOTE: If you add any additional spellings, MSP430Interrupt's spellings
|
||||
// must match.
|
||||
// NOTE: If you add any additional spellings, MSP430Interrupt's and
|
||||
// MipsInterrupt's spellings must match.
|
||||
let Spellings = [GNU<"interrupt">];
|
||||
let Args = [EnumArgument<"Interrupt", "InterruptType",
|
||||
["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""],
|
||||
@ -445,8 +456,12 @@ def Availability : InheritableAttr {
|
||||
.Case("android", "Android")
|
||||
.Case("ios", "iOS")
|
||||
.Case("macosx", "OS X")
|
||||
.Case("tvos", "tvOS")
|
||||
.Case("watchos", "watchOS")
|
||||
.Case("ios_app_extension", "iOS (App Extension)")
|
||||
.Case("macosx_app_extension", "OS X (App Extension)")
|
||||
.Case("tvos_app_extension", "tvOS (App Extension)")
|
||||
.Case("watchos_app_extension", "watchOS (App Extension)")
|
||||
.Default(llvm::StringRef());
|
||||
} }];
|
||||
let HasCustomParsing = 1;
|
||||
@ -553,6 +568,11 @@ def CUDAConstant : InheritableAttr {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def CUDACudartBuiltin : IgnoredAttr {
|
||||
let Spellings = [GNU<"cudart_builtin">];
|
||||
let LangOpts = [CUDA];
|
||||
}
|
||||
|
||||
def CUDADevice : InheritableAttr {
|
||||
let Spellings = [GNU<"device">];
|
||||
let Subjects = SubjectList<[Function, Var]>;
|
||||
@ -560,6 +580,21 @@ def CUDADevice : InheritableAttr {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def CUDADeviceBuiltin : IgnoredAttr {
|
||||
let Spellings = [GNU<"device_builtin">];
|
||||
let LangOpts = [CUDA];
|
||||
}
|
||||
|
||||
def CUDADeviceBuiltinSurfaceType : IgnoredAttr {
|
||||
let Spellings = [GNU<"device_builtin_surface_type">];
|
||||
let LangOpts = [CUDA];
|
||||
}
|
||||
|
||||
def CUDADeviceBuiltinTextureType : IgnoredAttr {
|
||||
let Spellings = [GNU<"device_builtin_texture_type">];
|
||||
let LangOpts = [CUDA];
|
||||
}
|
||||
|
||||
def CUDAGlobal : InheritableAttr {
|
||||
let Spellings = [GNU<"global">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
@ -721,18 +756,6 @@ def FlagEnum : InheritableAttr {
|
||||
let Subjects = SubjectList<[Enum]>;
|
||||
let Documentation = [FlagEnumDocs];
|
||||
let LangOpts = [COnly];
|
||||
let AdditionalMembers = [{
|
||||
private:
|
||||
llvm::APInt FlagBits;
|
||||
public:
|
||||
llvm::APInt &getFlagBits() {
|
||||
return FlagBits;
|
||||
}
|
||||
|
||||
const llvm::APInt &getFlagBits() const {
|
||||
return FlagBits;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def Flatten : InheritableAttr {
|
||||
@ -746,7 +769,7 @@ def Format : InheritableAttr {
|
||||
let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">,
|
||||
IntArgument<"FirstArg">];
|
||||
let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto], WarnDiag,
|
||||
"ExpectedFunction">;
|
||||
"ExpectedFunctionWithProtoType">;
|
||||
let Documentation = [FormatDocs];
|
||||
}
|
||||
|
||||
@ -754,7 +777,7 @@ def FormatArg : InheritableAttr {
|
||||
let Spellings = [GCC<"format_arg">];
|
||||
let Args = [IntArgument<"FormatIdx">];
|
||||
let Subjects = SubjectList<[ObjCMethod, HasFunctionProto], WarnDiag,
|
||||
"ExpectedFunction">;
|
||||
"ExpectedFunctionWithProtoType">;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
@ -822,8 +845,8 @@ def MSABI : InheritableAttr {
|
||||
}
|
||||
|
||||
def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> {
|
||||
// NOTE: If you add any additional spellings, ARMInterrupt's spellings must
|
||||
// match.
|
||||
// NOTE: If you add any additional spellings, ARMInterrupt's and
|
||||
// MipsInterrupt's spellings must match.
|
||||
let Spellings = [GNU<"interrupt">];
|
||||
let Args = [UnsignedArgument<"Number">];
|
||||
let ParseKind = "Interrupt";
|
||||
@ -837,6 +860,22 @@ def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> {
|
||||
// NOTE: If you add any additional spellings, ARMInterrupt's and
|
||||
// MSP430Interrupt's spellings must match.
|
||||
let Spellings = [GNU<"interrupt">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Args = [EnumArgument<"Interrupt", "InterruptType",
|
||||
["vector=sw0", "vector=sw1", "vector=hw0",
|
||||
"vector=hw1", "vector=hw2", "vector=hw3",
|
||||
"vector=hw4", "vector=hw5", "eic", ""],
|
||||
["sw0", "sw1", "hw0", "hw1", "hw2", "hw3",
|
||||
"hw4", "hw5", "eic", "eic"]
|
||||
>];
|
||||
let ParseKind = "Interrupt";
|
||||
let Documentation = [MipsInterruptDocs];
|
||||
}
|
||||
|
||||
def Mode : Attr {
|
||||
let Spellings = [GCC<"mode">];
|
||||
let Args = [IdentifierArgument<"Mode">];
|
||||
@ -867,6 +906,19 @@ def ReturnsTwice : InheritableAttr {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def DisableTailCalls : InheritableAttr {
|
||||
let Spellings = [GNU<"disable_tail_calls">,
|
||||
CXX11<"clang", "disable_tail_calls">];
|
||||
let Subjects = SubjectList<[Function, ObjCMethod]>;
|
||||
let Documentation = [DisableTailCallsDocs];
|
||||
}
|
||||
|
||||
def NoAlias : InheritableAttr {
|
||||
let Spellings = [Declspec<"noalias">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Documentation = [NoAliasDocs];
|
||||
}
|
||||
|
||||
def NoCommon : InheritableAttr {
|
||||
let Spellings = [GCC<"nocommon">];
|
||||
let Subjects = SubjectList<[Var]>;
|
||||
@ -960,6 +1012,15 @@ def ReturnsNonNull : InheritableAttr {
|
||||
let Documentation = [ReturnsNonNullDocs];
|
||||
}
|
||||
|
||||
// pass_object_size(N) indicates that the parameter should have
|
||||
// __builtin_object_size with Type=N evaluated on the parameter at the callsite.
|
||||
def PassObjectSize : InheritableParamAttr {
|
||||
let Spellings = [GNU<"pass_object_size">];
|
||||
let Args = [IntArgument<"Type">];
|
||||
let Subjects = SubjectList<[ParmVar]>;
|
||||
let Documentation = [PassObjectSizeDocs];
|
||||
}
|
||||
|
||||
// Nullability type attributes.
|
||||
def TypeNonNull : TypeAttr {
|
||||
let Spellings = [Keyword<"_Nonnull">];
|
||||
@ -1000,11 +1061,22 @@ def NoInstrumentFunction : InheritableAttr {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def NotTailCalled : InheritableAttr {
|
||||
let Spellings = [GNU<"not_tail_called">, CXX11<"clang", "not_tail_called">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Documentation = [NotTailCalledDocs];
|
||||
}
|
||||
|
||||
def NoThrow : InheritableAttr {
|
||||
let Spellings = [GCC<"nothrow">, Declspec<"nothrow">];
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def NvWeak : IgnoredAttr {
|
||||
let Spellings = [GNU<"nv_weak">];
|
||||
let LangOpts = [CUDA];
|
||||
}
|
||||
|
||||
def ObjCBridge : InheritableAttr {
|
||||
let Spellings = [GNU<"objc_bridge">];
|
||||
let Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
|
||||
@ -1024,8 +1096,8 @@ def ObjCBridgeRelated : InheritableAttr {
|
||||
let Spellings = [GNU<"objc_bridge_related">];
|
||||
let Subjects = SubjectList<[Record], ErrorDiag>;
|
||||
let Args = [IdentifierArgument<"RelatedClass">,
|
||||
IdentifierArgument<"ClassMethod">,
|
||||
IdentifierArgument<"InstanceMethod">];
|
||||
IdentifierArgument<"ClassMethod", 1>,
|
||||
IdentifierArgument<"InstanceMethod", 1>];
|
||||
let HasCustomParsing = 1;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
@ -1169,7 +1241,8 @@ def Ownership : InheritableAttr {
|
||||
}
|
||||
}];
|
||||
let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">];
|
||||
let Subjects = SubjectList<[HasFunctionProto], WarnDiag, "ExpectedFunction">;
|
||||
let Subjects = SubjectList<[HasFunctionProto], WarnDiag,
|
||||
"ExpectedFunctionWithProtoType">;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
@ -1280,9 +1353,41 @@ def Pascal : InheritableAttr {
|
||||
|
||||
def Target : InheritableAttr {
|
||||
let Spellings = [GCC<"target">];
|
||||
let Args = [StringArgument<"features">];
|
||||
let Args = [StringArgument<"featuresStr">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
let Documentation = [TargetDocs];
|
||||
let AdditionalMembers = [{
|
||||
typedef std::pair<std::vector<std::string>, StringRef> ParsedTargetAttr;
|
||||
ParsedTargetAttr parse() const {
|
||||
ParsedTargetAttr Ret;
|
||||
SmallVector<StringRef, 1> AttrFeatures;
|
||||
getFeaturesStr().split(AttrFeatures, ",");
|
||||
|
||||
// Grab the various features and prepend a "+" to turn on the feature to
|
||||
// the backend and add them to our existing set of features.
|
||||
for (auto &Feature : AttrFeatures) {
|
||||
// Go ahead and trim whitespace rather than either erroring or
|
||||
// accepting it weirdly.
|
||||
Feature = Feature.trim();
|
||||
|
||||
// We don't support cpu tuning this way currently.
|
||||
// TODO: Support the fpmath option. It will require checking
|
||||
// overall feature validity for the function with the rest of the
|
||||
// attributes on the function.
|
||||
if (Feature.startswith("fpmath=") || Feature.startswith("tune="))
|
||||
continue;
|
||||
|
||||
// While we're here iterating check for a different target cpu.
|
||||
if (Feature.startswith("arch="))
|
||||
Ret.second = Feature.split("=").second.trim();
|
||||
else if (Feature.startswith("no-"))
|
||||
Ret.first.push_back("-" + Feature.split("-").second.str());
|
||||
else
|
||||
Ret.first.push_back("+" + Feature.str());
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def TransparentUnion : InheritableAttr {
|
||||
@ -1293,7 +1398,15 @@ def TransparentUnion : InheritableAttr {
|
||||
|
||||
def Unavailable : InheritableAttr {
|
||||
let Spellings = [GNU<"unavailable">];
|
||||
let Args = [StringArgument<"Message", 1>];
|
||||
let Args = [StringArgument<"Message", 1>,
|
||||
EnumArgument<"ImplicitReason", "ImplicitReason",
|
||||
["", "", "", ""],
|
||||
["IR_None",
|
||||
"IR_ARCForbiddenType",
|
||||
"IR_ForbiddenWeak",
|
||||
"IR_ARCForbiddenConversion",
|
||||
"IR_ARCInitReturnsUnrelated",
|
||||
"IR_ARCFieldWithOwnership"], 1, /*fake*/ 1>];
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
@ -1486,8 +1599,8 @@ 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 Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
|
||||
"ExpectedStructOrUnionOrTypedef">;
|
||||
let Args = [StringArgument<"Name">];
|
||||
let Accessors = [Accessor<"isShared",
|
||||
[GNU<"shared_capability">,
|
||||
@ -1814,7 +1927,7 @@ def TypeTagForDatatype : InheritableAttr {
|
||||
|
||||
// Microsoft-related attributes
|
||||
|
||||
def MSNoVTable : InheritableAttr {
|
||||
def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
|
||||
let Spellings = [Declspec<"novtable">];
|
||||
let Subjects = SubjectList<[CXXRecord]>;
|
||||
let Documentation = [MSNoVTableDocs];
|
||||
@ -1970,8 +2083,8 @@ def LoopHint : Attr {
|
||||
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
|
||||
"Unroll", "UnrollCount"]>,
|
||||
EnumArgument<"State", "LoopHintState",
|
||||
["default", "enable", "disable", "assume_safety"],
|
||||
["Default", "Enable", "Disable", "AssumeSafety"]>,
|
||||
["enable", "disable", "numeric", "assume_safety", "full"],
|
||||
["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>,
|
||||
ExprArgument<"Value">];
|
||||
|
||||
let AdditionalMembers = [{
|
||||
@ -1991,17 +2104,15 @@ def LoopHint : Attr {
|
||||
unsigned SpellingIndex = getSpellingListIndex();
|
||||
// For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
|
||||
// "nounroll" is already emitted as the pragma name.
|
||||
if (SpellingIndex == Pragma_nounroll) {
|
||||
OS << "\n";
|
||||
if (SpellingIndex == Pragma_nounroll)
|
||||
return;
|
||||
}
|
||||
else if (SpellingIndex == Pragma_unroll) {
|
||||
OS << getValueString(Policy) << "\n";
|
||||
OS << getValueString(Policy);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
|
||||
OS << getOptionName(option) << getValueString(Policy) << "\n";
|
||||
OS << getOptionName(option) << getValueString(Policy);
|
||||
}
|
||||
|
||||
// Return a string containing the loop hint argument including the
|
||||
@ -2010,13 +2121,12 @@ def LoopHint : Attr {
|
||||
std::string ValueName;
|
||||
llvm::raw_string_ostream OS(ValueName);
|
||||
OS << "(";
|
||||
if (option == VectorizeWidth || option == InterleaveCount ||
|
||||
option == UnrollCount)
|
||||
if (state == Numeric)
|
||||
value->printPretty(OS, nullptr, Policy);
|
||||
else if (state == Default)
|
||||
return "";
|
||||
else if (state == Enable)
|
||||
OS << (option == Unroll ? "full" : "enable");
|
||||
OS << "enable";
|
||||
else if (state == Full)
|
||||
OS << "full";
|
||||
else if (state == AssumeSafety)
|
||||
OS << "assume_safety";
|
||||
else
|
||||
@ -2031,7 +2141,7 @@ def LoopHint : Attr {
|
||||
if (SpellingIndex == Pragma_nounroll)
|
||||
return "#pragma nounroll";
|
||||
else if (SpellingIndex == Pragma_unroll)
|
||||
return "#pragma unroll" + getValueString(Policy);
|
||||
return "#pragma unroll" + (option == UnrollCount ? getValueString(Policy) : "");
|
||||
|
||||
assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
|
||||
return getOptionName(option) + getValueString(Policy);
|
||||
@ -2054,3 +2164,9 @@ def OMPThreadPrivateDecl : InheritableAttr {
|
||||
let SemaHandler = 0;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def InternalLinkage : InheritableAttr {
|
||||
let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">];
|
||||
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
|
||||
let Documentation = [InternalLinkageDocs];
|
||||
}
|
||||
|
@ -181,9 +181,9 @@ to enforce the provided alignment assumption.
|
||||
def EnableIfDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
.. Note:: Some features of this attribute are experimental. The meaning of
|
||||
multiple enable_if attributes on a single declaration is subject to change in
|
||||
a future version of clang. Also, the ABI is not standardized and the name
|
||||
.. Note:: Some features of this attribute are experimental. The meaning of
|
||||
multiple enable_if attributes on a single declaration is subject to change in
|
||||
a future version of clang. Also, the ABI is not standardized and the name
|
||||
mangling may change in future versions. To avoid that, use asm labels.
|
||||
|
||||
The ``enable_if`` attribute can be placed on function declarations to control
|
||||
@ -263,6 +263,103 @@ Query for this feature with ``__has_attribute(enable_if)``.
|
||||
}];
|
||||
}
|
||||
|
||||
def PassObjectSizeDocs : Documentation {
|
||||
let Category = DocCatVariable; // Technically it's a parameter doc, but eh.
|
||||
let Content = [{
|
||||
.. Note:: The mangling of functions with parameters that are annotated with
|
||||
``pass_object_size`` is subject to change. You can get around this by
|
||||
using ``__asm__("foo")`` to explicitly name your functions, thus preserving
|
||||
your ABI; also, non-overloadable C functions with ``pass_object_size`` are
|
||||
not mangled.
|
||||
|
||||
The ``pass_object_size(Type)`` attribute can be placed on function parameters to
|
||||
instruct clang to call ``__builtin_object_size(param, Type)`` at each callsite
|
||||
of said function, and implicitly pass the result of this call in as an invisible
|
||||
argument of type ``size_t`` directly after the parameter annotated with
|
||||
``pass_object_size``. Clang will also replace any calls to
|
||||
``__builtin_object_size(param, Type)`` in the function by said implicit
|
||||
parameter.
|
||||
|
||||
Example usage:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int bzero1(char *const p __attribute__((pass_object_size(0))))
|
||||
__attribute__((noinline)) {
|
||||
int i = 0;
|
||||
for (/**/; i < (int)__builtin_object_size(p, 0); ++i) {
|
||||
p[i] = 0;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int main() {
|
||||
char chars[100];
|
||||
int n = bzero1(&chars[0]);
|
||||
assert(n == sizeof(chars));
|
||||
return 0;
|
||||
}
|
||||
|
||||
If successfully evaluating ``__builtin_object_size(param, Type)`` at the
|
||||
callsite is not possible, then the "failed" value is passed in. So, using the
|
||||
definition of ``bzero1`` from above, the following code would exit cleanly:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int main2(int argc, char *argv[]) {
|
||||
int n = bzero1(argv);
|
||||
assert(n == -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
``pass_object_size`` plays a part in overload resolution. If two overload
|
||||
candidates are otherwise equally good, then the overload with one or more
|
||||
parameters with ``pass_object_size`` is preferred. This implies that the choice
|
||||
between two identical overloads both with ``pass_object_size`` on one or more
|
||||
parameters will always be ambiguous; for this reason, having two such overloads
|
||||
is illegal. For example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#define PS(N) __attribute__((pass_object_size(N)))
|
||||
// OK
|
||||
void Foo(char *a, char *b); // Overload A
|
||||
// OK -- overload A has no parameters with pass_object_size.
|
||||
void Foo(char *a PS(0), char *b PS(0)); // Overload B
|
||||
// Error -- Same signature (sans pass_object_size) as overload B, and both
|
||||
// overloads have one or more parameters with the pass_object_size attribute.
|
||||
void Foo(void *a PS(0), void *b);
|
||||
|
||||
// OK
|
||||
void Bar(void *a PS(0)); // Overload C
|
||||
// OK
|
||||
void Bar(char *c PS(1)); // Overload D
|
||||
|
||||
void main() {
|
||||
char known[10], *unknown;
|
||||
Foo(unknown, unknown); // Calls overload B
|
||||
Foo(known, unknown); // Calls overload B
|
||||
Foo(unknown, known); // Calls overload B
|
||||
Foo(known, known); // Calls overload B
|
||||
|
||||
Bar(known); // Calls overload D
|
||||
Bar(unknown); // Calls overload D
|
||||
}
|
||||
|
||||
Currently, ``pass_object_size`` is a bit restricted in terms of its usage:
|
||||
|
||||
* Only one use of ``pass_object_size`` is allowed per parameter.
|
||||
|
||||
* It is an error to take the address of a function with ``pass_object_size`` on
|
||||
any of its parameters. If you wish to do this, you can create an overload
|
||||
without ``pass_object_size`` on any parameters.
|
||||
|
||||
* It is an error to apply the ``pass_object_size`` attribute to parameters that
|
||||
are not pointers. Additionally, any parameter that ``pass_object_size`` is
|
||||
applied to must be marked ``const`` at its function's definition.
|
||||
}];
|
||||
}
|
||||
|
||||
def OverloadableDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
@ -580,6 +677,14 @@ are:
|
||||
Apple's Mac OS X operating system. The minimum deployment target is
|
||||
specified by the ``-mmacosx-version-min=*version*`` command-line argument.
|
||||
|
||||
``tvos``
|
||||
Apple's tvOS operating system. The minimum deployment target is specified by
|
||||
the ``-mtvos-version-min=*version*`` command-line argument.
|
||||
|
||||
``watchos``
|
||||
Apple's watchOS operating system. The minimum deployment target is specified by
|
||||
the ``-mwatchos-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
|
||||
@ -706,6 +811,46 @@ The semantics are as follows:
|
||||
}];
|
||||
}
|
||||
|
||||
def MipsInterruptDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on
|
||||
MIPS 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.
|
||||
|
||||
By default, the compiler will produce a function prologue and epilogue suitable for
|
||||
an interrupt service routine that handles an External Interrupt Controller (eic)
|
||||
generated interrupt. This behaviour can be explicitly requested with the "eic"
|
||||
argument.
|
||||
|
||||
Otherwise, for use with vectored interrupt mode, the argument passed should be
|
||||
of the form "vector=LEVEL" where LEVEL is one of the following values:
|
||||
"sw0", "sw1", "hw0", "hw1", "hw2", "hw3", "hw4", "hw5". The compiler will
|
||||
then set the interrupt mask to the corresponding level which will mask all
|
||||
interrupts up to and including the argument.
|
||||
|
||||
The semantics are as follows:
|
||||
|
||||
- The prologue is modified so that the Exception Program Counter (EPC) and
|
||||
Status coprocessor registers are saved to the stack. The interrupt mask is
|
||||
set so that the function can only be interrupted by a higher priority
|
||||
interrupt. The epilogue will restore the previous values of EPC and Status.
|
||||
|
||||
- The prologue and epilogue are modified to save and restore all non-kernel
|
||||
registers as necessary.
|
||||
|
||||
- The FPU is disabled in the prologue, as the floating pointer registers are not
|
||||
spilled to the stack.
|
||||
|
||||
- The function return sequence is changed to use an exception return instruction.
|
||||
|
||||
- The parameter sets the interrupt mask for the function corresponding to the
|
||||
interrupt level specified. If no mask is specified the interrupt mask
|
||||
defaults to "eic".
|
||||
}];
|
||||
}
|
||||
|
||||
def TargetDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
@ -1328,7 +1473,7 @@ def MSNoVTableDocs : Documentation {
|
||||
let Content = [{
|
||||
This attribute can be added to a class declaration or definition to signal to
|
||||
the compiler that constructors and destructors will not reference the virtual
|
||||
function table.
|
||||
function table. It is only supported when using the Microsoft C++ ABI.
|
||||
}];
|
||||
}
|
||||
|
||||
@ -1371,7 +1516,9 @@ Loop unrolling optimization hints can be specified with ``#pragma unroll`` and
|
||||
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:
|
||||
attempt to fully unroll the loop if the trip count is known at compile time and
|
||||
attempt to partially unroll the loop if the trip count is not known at compile
|
||||
time:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
@ -1439,7 +1586,6 @@ More details can be found in the OpenCL C language Spec v2.0, Section 6.5.
|
||||
|
||||
def OpenCLAddressSpaceGenericDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__generic(generic)";
|
||||
let Content = [{
|
||||
The generic address space attribute is only available with OpenCL v2.0 and later.
|
||||
It can be used with pointer types. Variables in global and local scope and
|
||||
@ -1452,7 +1598,6 @@ spaces.
|
||||
|
||||
def OpenCLAddressSpaceConstantDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__constant(constant)";
|
||||
let Content = [{
|
||||
The constant address space attribute signals that an object is located in
|
||||
a constant (non-modifiable) memory region. It is available to all work items.
|
||||
@ -1464,7 +1609,6 @@ have an initializer.
|
||||
|
||||
def OpenCLAddressSpaceGlobalDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__global(global)";
|
||||
let Content = [{
|
||||
The global address space attribute specifies that an object is allocated in
|
||||
global memory, which is accessible by all work items. The content stored in this
|
||||
@ -1477,7 +1621,6 @@ scope) variables and static local variable as well.
|
||||
|
||||
def OpenCLAddressSpaceLocalDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__local(local)";
|
||||
let Content = [{
|
||||
The local address space specifies that an object is allocated in the local (work
|
||||
group) memory area, which is accessible to all work items in the same work
|
||||
@ -1490,7 +1633,6 @@ space are allowed. Local address space variables cannot have an initializer.
|
||||
|
||||
def OpenCLAddressSpacePrivateDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__private(private)";
|
||||
let Content = [{
|
||||
The private address space specifies that an object is allocated in the private
|
||||
(work item) memory. Other work items cannot access the same memory area and its
|
||||
@ -1534,7 +1676,6 @@ In Objective-C, there is an alternate spelling for the nullability qualifiers th
|
||||
|
||||
def TypeNonNullDocs : Documentation {
|
||||
let Category = NullabilityDocs;
|
||||
let Heading = "_Nonnull";
|
||||
let Content = [{
|
||||
The ``_Nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``_Nonnull`` pointer type. For example, given a declaration such as:
|
||||
|
||||
@ -1548,7 +1689,6 @@ a caller of ``fetch`` should not provide a null value, and the compiler will pro
|
||||
|
||||
def TypeNullableDocs : Documentation {
|
||||
let Category = NullabilityDocs;
|
||||
let Heading = "_Nullable";
|
||||
let Content = [{
|
||||
The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullable`` pointer type can be null. For example, given:
|
||||
|
||||
@ -1562,7 +1702,6 @@ a caller of ``fetch_or_zero`` can provide null.
|
||||
|
||||
def TypeNullUnspecifiedDocs : Documentation {
|
||||
let Category = NullabilityDocs;
|
||||
let Heading = "_Null_unspecified";
|
||||
let Content = [{
|
||||
The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_Nonnull`` nor ``_Nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API.
|
||||
}];
|
||||
@ -1570,7 +1709,6 @@ The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_No
|
||||
|
||||
def NonNullDocs : Documentation {
|
||||
let Category = NullabilityDocs;
|
||||
let Heading = "nonnull";
|
||||
let Content = [{
|
||||
The ``nonnull`` attribute indicates that some function parameters must not be null, and can be used in several different ways. It's original usage (`from GCC <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes>`_) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. For example:
|
||||
|
||||
@ -1600,7 +1738,6 @@ Note that the ``nonnull`` attribute indicates that passing null to a non-null pa
|
||||
|
||||
def ReturnsNonNullDocs : Documentation {
|
||||
let Category = NullabilityDocs;
|
||||
let Heading = "returns_nonnull";
|
||||
let Content = [{
|
||||
The ``returns_nonnull`` attribute indicates that a particular function (or Objective-C method) always returns a non-null pointer. For example, a particular system ``malloc`` might be defined to terminate a process when memory is not available rather than returning a null pointer:
|
||||
|
||||
@ -1611,3 +1748,114 @@ The ``returns_nonnull`` attribute indicates that a particular function (or Objec
|
||||
The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable
|
||||
}];
|
||||
}
|
||||
|
||||
def NoAliasDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``noalias`` attribute indicates that the only memory accesses inside
|
||||
function are loads and stores from objects pointed to by its pointer-typed
|
||||
arguments, with arbitrary offsets.
|
||||
}];
|
||||
}
|
||||
|
||||
def NotTailCalledDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``not_tail_called`` attribute prevents tail-call optimization on statically bound calls. It has no effect on indirect calls. Virtual functions, objective-c methods, and functions marked as ``always_inline`` cannot be marked as ``not_tail_called``.
|
||||
|
||||
For example, it prevents tail-call optimization in the following case:
|
||||
|
||||
.. code-block: c
|
||||
|
||||
int __attribute__((not_tail_called)) foo1(int);
|
||||
|
||||
int foo2(int a) {
|
||||
return foo1(a); // No tail-call optimization on direct calls.
|
||||
}
|
||||
|
||||
However, it doesn't prevent tail-call optimization in this case:
|
||||
|
||||
.. code-block: c
|
||||
|
||||
int __attribute__((not_tail_called)) foo1(int);
|
||||
|
||||
int foo2(int a) {
|
||||
int (*fn)(int) = &foo1;
|
||||
|
||||
// not_tail_called has no effect on an indirect call even if the call can be
|
||||
// resolved at compile time.
|
||||
return (*fn)(a);
|
||||
}
|
||||
|
||||
Marking virtual functions as ``not_tail_called`` is an error:
|
||||
|
||||
.. code-block: c++
|
||||
|
||||
class Base {
|
||||
public:
|
||||
// not_tail_called on a virtual function is an error.
|
||||
[[clang::not_tail_called]] virtual int foo1();
|
||||
|
||||
virtual int foo2();
|
||||
|
||||
// Non-virtual functions can be marked ``not_tail_called``.
|
||||
[[clang::not_tail_called]] int foo3();
|
||||
};
|
||||
|
||||
class Derived1 : public Base {
|
||||
public:
|
||||
int foo1() override;
|
||||
|
||||
// not_tail_called on a virtual function is an error.
|
||||
[[clang::not_tail_called]] int foo2() override;
|
||||
};
|
||||
}];
|
||||
}
|
||||
|
||||
def InternalLinkageDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``internal_linkage`` attribute changes the linkage type of the declaration to internal.
|
||||
This is similar to C-style ``static``, but can be used on classes and class methods. When applied to a class definition,
|
||||
this attribute affects all methods and static data members of that class.
|
||||
This can be used to contain the ABI of a C++ library by excluding unwanted class methods from the export tables.
|
||||
}];
|
||||
}
|
||||
|
||||
def DisableTailCallsDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization inside the marked function.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int callee(int);
|
||||
|
||||
int foo(int a) __attribute__((disable_tail_calls)) {
|
||||
return callee(a); // This call is not tail-call optimized.
|
||||
}
|
||||
|
||||
Marking virtual functions as ``disable_tail_calls`` is legal.
|
||||
|
||||
.. code-block: c++
|
||||
|
||||
int callee(int);
|
||||
|
||||
class Base {
|
||||
public:
|
||||
[[clang::disable_tail_calls]] virtual int foo1() {
|
||||
return callee(); // This call is not tail-call optimized.
|
||||
}
|
||||
};
|
||||
|
||||
class Derived1 : public Base {
|
||||
public:
|
||||
int foo1() override {
|
||||
return callee(); // This call is tail-call optimized.
|
||||
}
|
||||
};
|
||||
|
||||
}];
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
#define LLVM_CLANG_BASIC_ATTRIBUTES_H
|
||||
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
@ -31,7 +31,7 @@ enum class AttrSyntax {
|
||||
/// \brief Return the version number associated with the attribute if we
|
||||
/// recognize and implement the attribute specified by the given information.
|
||||
int hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
|
||||
const IdentifierInfo *Attr, const llvm::Triple &T,
|
||||
const IdentifierInfo *Attr, const TargetInfo &Target,
|
||||
const LangOptions &LangOpts);
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -357,25 +357,25 @@ BUILTIN(__builtin_ctanhf, "XfXf", "Fnc")
|
||||
BUILTIN(__builtin_ctanhl, "XLdXLd", "Fnc")
|
||||
|
||||
// FP Comparisons.
|
||||
BUILTIN(__builtin_isgreater , "i.", "nc")
|
||||
BUILTIN(__builtin_isgreaterequal, "i.", "nc")
|
||||
BUILTIN(__builtin_isless , "i.", "nc")
|
||||
BUILTIN(__builtin_islessequal , "i.", "nc")
|
||||
BUILTIN(__builtin_islessgreater , "i.", "nc")
|
||||
BUILTIN(__builtin_isunordered , "i.", "nc")
|
||||
BUILTIN(__builtin_isgreater , "i.", "Fnc")
|
||||
BUILTIN(__builtin_isgreaterequal, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isless , "i.", "Fnc")
|
||||
BUILTIN(__builtin_islessequal , "i.", "Fnc")
|
||||
BUILTIN(__builtin_islessgreater , "i.", "Fnc")
|
||||
BUILTIN(__builtin_isunordered , "i.", "Fnc")
|
||||
|
||||
// Unary FP classification
|
||||
BUILTIN(__builtin_fpclassify, "iiiii.", "nc")
|
||||
BUILTIN(__builtin_isfinite, "i.", "nc")
|
||||
BUILTIN(__builtin_isinf, "i.", "nc")
|
||||
BUILTIN(__builtin_isinf_sign, "i.", "nc")
|
||||
BUILTIN(__builtin_isnan, "i.", "nc")
|
||||
BUILTIN(__builtin_isnormal, "i.", "nc")
|
||||
BUILTIN(__builtin_fpclassify, "iiiii.", "Fnc")
|
||||
BUILTIN(__builtin_isfinite, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isinf, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isinf_sign, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isnan, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isnormal, "i.", "Fnc")
|
||||
|
||||
// FP signbit builtins
|
||||
BUILTIN(__builtin_signbit, "id", "nc")
|
||||
BUILTIN(__builtin_signbitf, "if", "nc")
|
||||
BUILTIN(__builtin_signbitl, "iLd", "nc")
|
||||
BUILTIN(__builtin_signbit, "i.", "Fnc")
|
||||
BUILTIN(__builtin_signbitf, "if", "Fnc")
|
||||
BUILTIN(__builtin_signbitl, "iLd", "Fnc")
|
||||
|
||||
// Builtins for arithmetic.
|
||||
BUILTIN(__builtin_clzs , "iUs" , "nc")
|
||||
@ -388,9 +388,9 @@ BUILTIN(__builtin_ctz , "iUi" , "nc")
|
||||
BUILTIN(__builtin_ctzl , "iULi" , "nc")
|
||||
BUILTIN(__builtin_ctzll, "iULLi", "nc")
|
||||
// TODO: int ctzimax(uintmax_t)
|
||||
BUILTIN(__builtin_ffs , "ii" , "nc")
|
||||
BUILTIN(__builtin_ffsl , "iLi" , "nc")
|
||||
BUILTIN(__builtin_ffsll, "iLLi", "nc")
|
||||
BUILTIN(__builtin_ffs , "ii" , "Fnc")
|
||||
BUILTIN(__builtin_ffsl , "iLi" , "Fnc")
|
||||
BUILTIN(__builtin_ffsll, "iLLi", "Fnc")
|
||||
BUILTIN(__builtin_parity , "iUi" , "nc")
|
||||
BUILTIN(__builtin_parityl , "iULi" , "nc")
|
||||
BUILTIN(__builtin_parityll, "iULLi", "nc")
|
||||
@ -414,7 +414,7 @@ BUILTIN(__builtin_va_end, "vA", "n")
|
||||
BUILTIN(__builtin_va_copy, "vAA", "n")
|
||||
BUILTIN(__builtin_stdarg_start, "vA.", "n")
|
||||
BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc")
|
||||
BUILTIN(__builtin_bcmp, "iv*v*z", "n")
|
||||
BUILTIN(__builtin_bcmp, "iv*v*z", "Fn")
|
||||
BUILTIN(__builtin_bcopy, "vv*v*z", "n")
|
||||
BUILTIN(__builtin_bzero, "vv*z", "nF")
|
||||
BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:")
|
||||
@ -489,6 +489,7 @@ BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:")
|
||||
BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:")
|
||||
BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
|
||||
|
||||
BUILTIN(__builtin_unpredictable, "LiLi" , "nc")
|
||||
BUILTIN(__builtin_expect, "LiLiLi" , "nc")
|
||||
BUILTIN(__builtin_prefetch, "vvC*.", "nc")
|
||||
BUILTIN(__builtin_readcyclecounter, "ULLi", "n")
|
||||
@ -497,7 +498,7 @@ BUILTIN(__builtin_debugtrap, "v", "n")
|
||||
BUILTIN(__builtin_unreachable, "v", "nr")
|
||||
BUILTIN(__builtin_shufflevector, "v." , "nc")
|
||||
BUILTIN(__builtin_convertvector, "v." , "nct")
|
||||
BUILTIN(__builtin_alloca, "v*z" , "n")
|
||||
BUILTIN(__builtin_alloca, "v*z" , "Fn")
|
||||
BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
|
||||
|
||||
// "Overloaded" Atomic operator builtins. These are overloaded to support data
|
||||
@ -1216,6 +1217,9 @@ BUILTIN(__builtin_subcl, "ULiULiCULiCULiCULi*", "n")
|
||||
BUILTIN(__builtin_subcll, "ULLiULLiCULLiCULLiCULLi*", "n")
|
||||
|
||||
// Checked Arithmetic Builtins for Security.
|
||||
BUILTIN(__builtin_add_overflow, "v.", "nt")
|
||||
BUILTIN(__builtin_sub_overflow, "v.", "nt")
|
||||
BUILTIN(__builtin_mul_overflow, "v.", "nt")
|
||||
BUILTIN(__builtin_uadd_overflow, "bUiCUiCUi*", "n")
|
||||
BUILTIN(__builtin_uaddl_overflow, "bULiCULiCULi*", "n")
|
||||
BUILTIN(__builtin_uaddll_overflow, "bULLiCULLiCULLi*", "n")
|
||||
@ -1244,6 +1248,10 @@ BUILTIN(__builtin_operator_delete, "vv*", "n")
|
||||
BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
|
||||
BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn")
|
||||
|
||||
// Nontemporal loads/stores builtins
|
||||
BUILTIN(__builtin_nontemporal_store, "v.", "t")
|
||||
BUILTIN(__builtin_nontemporal_load, "v.", "t")
|
||||
|
||||
#undef BUILTIN
|
||||
#undef LIBBUILTIN
|
||||
#undef LANGBUILTIN
|
||||
|
@ -16,7 +16,7 @@
|
||||
#ifndef LLVM_CLANG_BASIC_BUILTINS_H
|
||||
#define LLVM_CLANG_BASIC_BUILTINS_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include <cstring>
|
||||
|
||||
// VC++ defines 'alloca' as an object-like macro, which interferes with our
|
||||
@ -24,22 +24,22 @@
|
||||
#undef alloca
|
||||
|
||||
namespace clang {
|
||||
class TargetInfo;
|
||||
class IdentifierTable;
|
||||
class ASTContext;
|
||||
class QualType;
|
||||
class LangOptions;
|
||||
class TargetInfo;
|
||||
class IdentifierTable;
|
||||
class ASTContext;
|
||||
class QualType;
|
||||
class LangOptions;
|
||||
|
||||
enum LanguageID {
|
||||
GNU_LANG = 0x1, // builtin requires GNU mode.
|
||||
C_LANG = 0x2, // builtin for c only.
|
||||
CXX_LANG = 0x4, // builtin for cplusplus only.
|
||||
OBJC_LANG = 0x8, // builtin for objective-c and objective-c++
|
||||
MS_LANG = 0x10, // builtin requires MS mode.
|
||||
ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
|
||||
ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
|
||||
ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.
|
||||
};
|
||||
enum LanguageID {
|
||||
GNU_LANG = 0x1, // builtin requires GNU mode.
|
||||
C_LANG = 0x2, // builtin for c only.
|
||||
CXX_LANG = 0x4, // builtin for cplusplus only.
|
||||
OBJC_LANG = 0x8, // builtin for objective-c and objective-c++
|
||||
MS_LANG = 0x10, // builtin requires MS mode.
|
||||
ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
|
||||
ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
|
||||
ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.
|
||||
};
|
||||
|
||||
namespace Builtin {
|
||||
enum ID {
|
||||
@ -51,112 +51,114 @@ enum ID {
|
||||
|
||||
struct Info {
|
||||
const char *Name, *Type, *Attributes, *HeaderName;
|
||||
LanguageID builtin_lang;
|
||||
|
||||
bool operator==(const Info &RHS) const {
|
||||
return !strcmp(Name, RHS.Name) &&
|
||||
!strcmp(Type, RHS.Type) &&
|
||||
!strcmp(Attributes, RHS.Attributes);
|
||||
}
|
||||
bool operator!=(const Info &RHS) const { return !(*this == RHS); }
|
||||
LanguageID Langs;
|
||||
const char *Features;
|
||||
};
|
||||
|
||||
/// \brief Holds information about both target-independent and
|
||||
/// target-specific builtins, allowing easy queries by clients.
|
||||
///
|
||||
/// Builtins from an optional auxiliary target are stored in
|
||||
/// AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to
|
||||
/// be translated back with getAuxBuiltinID() before use.
|
||||
class Context {
|
||||
const Info *TSRecords;
|
||||
unsigned NumTSRecords;
|
||||
llvm::ArrayRef<Info> TSRecords;
|
||||
llvm::ArrayRef<Info> AuxTSRecords;
|
||||
|
||||
public:
|
||||
Context();
|
||||
Context() {}
|
||||
|
||||
/// \brief Perform target-specific initialization
|
||||
void InitializeTarget(const TargetInfo &Target);
|
||||
|
||||
/// \param AuxTarget Target info to incorporate builtins from. May be nullptr.
|
||||
void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget);
|
||||
|
||||
/// \brief Mark the identifiers for all the builtins with their
|
||||
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
|
||||
/// such.
|
||||
void InitializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
|
||||
|
||||
/// \brief Populate the vector with the names of all of the builtins.
|
||||
void GetBuiltinNames(SmallVectorImpl<const char *> &Names);
|
||||
void initializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
|
||||
|
||||
/// \brief Return the identifier name for the specified builtin,
|
||||
/// e.g. "__builtin_abs".
|
||||
const char *GetName(unsigned ID) const {
|
||||
return GetRecord(ID).Name;
|
||||
const char *getName(unsigned ID) const {
|
||||
return getRecord(ID).Name;
|
||||
}
|
||||
|
||||
/// \brief Get the type descriptor string for the specified builtin.
|
||||
const char *GetTypeString(unsigned ID) const {
|
||||
return GetRecord(ID).Type;
|
||||
const char *getTypeString(unsigned ID) const {
|
||||
return getRecord(ID).Type;
|
||||
}
|
||||
|
||||
/// \brief Return true if this function is a target-specific builtin
|
||||
bool isTSBuiltin(unsigned ID) const {
|
||||
return ID >= Builtin::FirstTSBuiltin;
|
||||
}
|
||||
|
||||
/// \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') != nullptr;
|
||||
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') != nullptr;
|
||||
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') != nullptr;
|
||||
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') != nullptr;
|
||||
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') != nullptr;
|
||||
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') != nullptr;
|
||||
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') != nullptr;
|
||||
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') != nullptr;
|
||||
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') != nullptr;
|
||||
return strchr(getRecord(ID).Attributes, 't') != nullptr;
|
||||
}
|
||||
|
||||
/// \brief Determines whether this builtin has a result or any arguments which
|
||||
/// are pointer types.
|
||||
bool hasPtrArgsOrResult(unsigned ID) const {
|
||||
return strchr(GetRecord(ID).Type, '*') != nullptr;
|
||||
return strchr(getRecord(ID).Type, '*') != nullptr;
|
||||
}
|
||||
|
||||
/// \brief Completely forget that the given ID was ever considered a builtin,
|
||||
/// e.g., because the user provided a conflicting signature.
|
||||
void ForgetBuiltin(unsigned ID, IdentifierTable &Table);
|
||||
void forgetBuiltin(unsigned ID, IdentifierTable &Table);
|
||||
|
||||
/// \brief If this is a library function that comes from a specific
|
||||
/// header, retrieve that header name.
|
||||
const char *getHeaderName(unsigned ID) const {
|
||||
return GetRecord(ID).HeaderName;
|
||||
return getRecord(ID).HeaderName;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this builtin is like printf in its
|
||||
@ -174,14 +176,27 @@ class Context {
|
||||
///
|
||||
/// Such functions can be const when the MathErrno lang option is disabled.
|
||||
bool isConstWithoutErrno(unsigned ID) const {
|
||||
return strchr(GetRecord(ID).Attributes, 'e') != nullptr;
|
||||
return strchr(getRecord(ID).Attributes, 'e') != nullptr;
|
||||
}
|
||||
|
||||
const char *getRequiredFeatures(unsigned ID) const {
|
||||
return getRecord(ID).Features;
|
||||
}
|
||||
|
||||
/// \brief Return true if builtin ID belongs to AuxTarget.
|
||||
bool isAuxBuiltinID(unsigned ID) const {
|
||||
return ID >= (Builtin::FirstTSBuiltin + TSRecords.size());
|
||||
}
|
||||
|
||||
/// Return real buitin ID (i.e. ID it would have furing compilation
|
||||
/// for AuxTarget).
|
||||
unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); }
|
||||
|
||||
private:
|
||||
const Info &GetRecord(unsigned ID) const;
|
||||
const Info &getRecord(unsigned ID) const;
|
||||
|
||||
/// \brief Is this builtin supported according to the given language options?
|
||||
bool BuiltinIsSupported(const Builtin::Info &BuiltinInfo,
|
||||
bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
|
||||
const LangOptions &LangOpts);
|
||||
|
||||
/// \brief Helper function for isPrintfLike and isScanfLike.
|
||||
@ -190,5 +205,12 @@ class Context {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// \brief Kinds of BuiltinTemplateDecl.
|
||||
enum BuiltinTemplateKind : int {
|
||||
/// \brief This names the __make_integer_seq BuiltinTemplateDecl.
|
||||
BTK__make_integer_seq
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
#endif
|
||||
|
@ -60,5 +60,6 @@ BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
|
||||
BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
|
||||
BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
|
||||
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
|
||||
BUILTIN(__builtin_thread_pointer, "v*", "nc")
|
||||
|
||||
#undef BUILTIN
|
||||
|
@ -48,14 +48,14 @@ BUILTIN(__builtin_arm_vcvtr_f, "ffi", "nc")
|
||||
BUILTIN(__builtin_arm_vcvtr_d, "fdi", "nc")
|
||||
|
||||
// Coprocessor
|
||||
BUILTIN(__builtin_arm_mcr, "vUiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mcr2, "vUiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mrc, "UiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mrc2, "UiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mcr, "vUIiUIiUiUIiUIiUIi", "")
|
||||
BUILTIN(__builtin_arm_mcr2, "vUIiUIiUiUIiUIiUIi", "")
|
||||
BUILTIN(__builtin_arm_mrc, "UiUIiUIiUIiUIiUIi", "")
|
||||
BUILTIN(__builtin_arm_mrc2, "UiUIiUIiUIiUIiUIi", "")
|
||||
BUILTIN(__builtin_arm_cdp, "vUiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_cdp2, "vUiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mcrr, "vUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mcrr2, "vUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mcrr, "vUIiUIiUiUiUIi", "")
|
||||
BUILTIN(__builtin_arm_mcrr2, "vUIiUIiUiUiUIi", "")
|
||||
|
||||
// CRC32
|
||||
BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc")
|
||||
|
@ -50,7 +50,7 @@ BUILTIN(__builtin_ptx_read_lanemask_ge, "i", "nc")
|
||||
BUILTIN(__builtin_ptx_read_lanemask_gt, "i", "nc")
|
||||
|
||||
BUILTIN(__builtin_ptx_read_clock, "i", "n")
|
||||
BUILTIN(__builtin_ptx_read_clock64, "Li", "n")
|
||||
BUILTIN(__builtin_ptx_read_clock64, "LLi", "n")
|
||||
|
||||
BUILTIN(__builtin_ptx_read_pm0, "i", "n")
|
||||
BUILTIN(__builtin_ptx_read_pm1, "i", "n")
|
||||
@ -453,6 +453,9 @@ BUILTIN(__nvvm_atom_add_gen_ll, "LLiLLiD*LLi", "n")
|
||||
BUILTIN(__nvvm_atom_add_g_f, "ffD*1f", "n")
|
||||
BUILTIN(__nvvm_atom_add_s_f, "ffD*3f", "n")
|
||||
BUILTIN(__nvvm_atom_add_gen_f, "ffD*f", "n")
|
||||
BUILTIN(__nvvm_atom_add_g_d, "ddD*1d", "n")
|
||||
BUILTIN(__nvvm_atom_add_s_d, "ddD*3d", "n")
|
||||
BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n")
|
||||
|
||||
BUILTIN(__nvvm_atom_sub_g_i, "iiD*1i", "n")
|
||||
BUILTIN(__nvvm_atom_sub_s_i, "iiD*3i", "n")
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
// The format of this database matches clang/Basic/Builtins.def.
|
||||
|
||||
BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")
|
||||
|
||||
// This is just a placeholder, the types and attributes are wrong.
|
||||
BUILTIN(__builtin_altivec_vaddcuw, "V4UiV4UiV4Ui", "")
|
||||
|
||||
@ -278,12 +280,21 @@ BUILTIN(__builtin_vsx_xvrspip, "V4fV4f", "")
|
||||
BUILTIN(__builtin_vsx_xvcmpeqdp, "V2ULLiV2dV2d", "")
|
||||
BUILTIN(__builtin_vsx_xvcmpeqsp, "V4UiV4fV4f", "")
|
||||
|
||||
BUILTIN(__builtin_vsx_xvcmpeqdp_p, "iiV2dV2d", "")
|
||||
BUILTIN(__builtin_vsx_xvcmpeqsp_p, "iiV4fV4f", "")
|
||||
|
||||
BUILTIN(__builtin_vsx_xvcmpgedp, "V2ULLiV2dV2d", "")
|
||||
BUILTIN(__builtin_vsx_xvcmpgesp, "V4UiV4fV4f", "")
|
||||
|
||||
BUILTIN(__builtin_vsx_xvcmpgedp_p, "iiV2dV2d", "")
|
||||
BUILTIN(__builtin_vsx_xvcmpgesp_p, "iiV4fV4f", "")
|
||||
|
||||
BUILTIN(__builtin_vsx_xvcmpgtdp, "V2ULLiV2dV2d", "")
|
||||
BUILTIN(__builtin_vsx_xvcmpgtsp, "V4UiV4fV4f", "")
|
||||
|
||||
BUILTIN(__builtin_vsx_xvcmpgtdp_p, "iiV2dV2d", "")
|
||||
BUILTIN(__builtin_vsx_xvcmpgtsp_p, "iiV4fV4f", "")
|
||||
|
||||
BUILTIN(__builtin_vsx_xvrdpim, "V2dV2d", "")
|
||||
BUILTIN(__builtin_vsx_xvrspim, "V4fV4f", "")
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
// BuiltinsWebAssembly.def - WebAssembly 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// \brief This file defines the WebAssembly-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.
|
||||
|
||||
// Note that memory_size is not "c" (readnone) because it must be sequenced with
|
||||
// respect to grow_memory calls.
|
||||
BUILTIN(__builtin_wasm_memory_size, "z", "n")
|
||||
BUILTIN(__builtin_wasm_grow_memory, "vz", "n")
|
||||
|
||||
#undef BUILTIN
|
File diff suppressed because it is too large
Load Diff
@ -59,6 +59,7 @@ def Named : Decl<1>;
|
||||
def VarTemplate : DDecl<RedeclarableTemplate>;
|
||||
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
|
||||
def TemplateTemplateParm : DDecl<Template>;
|
||||
def BuiltinTemplate : DDecl<Template>;
|
||||
def Using : DDecl<Named>;
|
||||
def UsingShadow : DDecl<Named>;
|
||||
def ObjCMethod : DDecl<Named>, DeclContext;
|
||||
|
@ -864,28 +864,27 @@ class DiagnosticErrorTrap {
|
||||
/// the common fields to registers, eliminating increments of the NumArgs field,
|
||||
/// for example.
|
||||
class DiagnosticBuilder {
|
||||
mutable DiagnosticsEngine *DiagObj;
|
||||
mutable unsigned NumArgs;
|
||||
mutable DiagnosticsEngine *DiagObj = nullptr;
|
||||
mutable unsigned NumArgs = 0;
|
||||
|
||||
/// \brief Status variable indicating if this diagnostic is still active.
|
||||
///
|
||||
// NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)),
|
||||
// but LLVM is not currently smart enough to eliminate the null check that
|
||||
// Emit() would end up with if we used that as our status variable.
|
||||
mutable bool IsActive;
|
||||
mutable bool IsActive = false;
|
||||
|
||||
/// \brief Flag indicating that this diagnostic is being emitted via a
|
||||
/// call to ForceEmit.
|
||||
mutable bool IsForceEmit;
|
||||
mutable bool IsForceEmit = false;
|
||||
|
||||
void operator=(const DiagnosticBuilder &) = delete;
|
||||
friend class DiagnosticsEngine;
|
||||
|
||||
DiagnosticBuilder()
|
||||
: DiagObj(nullptr), NumArgs(0), IsActive(false), IsForceEmit(false) {}
|
||||
DiagnosticBuilder() = default;
|
||||
|
||||
explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
|
||||
: DiagObj(diagObj), NumArgs(0), IsActive(true), IsForceEmit(false) {
|
||||
: DiagObj(diagObj), IsActive(true) {
|
||||
assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
|
||||
diagObj->DiagRanges.clear();
|
||||
diagObj->DiagFixItHints.clear();
|
||||
@ -1077,14 +1076,14 @@ operator<<(const DiagnosticBuilder &DB, T *DC) {
|
||||
}
|
||||
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
const SourceRange &R) {
|
||||
SourceRange R) {
|
||||
DB.AddSourceRange(CharSourceRange::getTokenRange(R));
|
||||
return DB;
|
||||
}
|
||||
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
ArrayRef<SourceRange> Ranges) {
|
||||
for (const SourceRange &R: Ranges)
|
||||
for (SourceRange R : Ranges)
|
||||
DB.AddSourceRange(CharSourceRange::getTokenRange(R));
|
||||
return DB;
|
||||
}
|
||||
@ -1264,7 +1263,7 @@ class StoredDiagnostic {
|
||||
std::vector<FixItHint> FixIts;
|
||||
|
||||
public:
|
||||
StoredDiagnostic();
|
||||
StoredDiagnostic() = default;
|
||||
StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
|
||||
StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
|
||||
StringRef Message);
|
||||
@ -1272,7 +1271,6 @@ class StoredDiagnostic {
|
||||
StringRef Message, FullSourceLoc Loc,
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
ArrayRef<FixItHint> Fixits);
|
||||
~StoredDiagnostic();
|
||||
|
||||
/// \brief Evaluates true when this object stores a diagnostic.
|
||||
explicit operator bool() const { return Message.size() > 0; }
|
||||
|
@ -84,6 +84,10 @@ def err_module_not_built : Error<"could not build module '%0'">, DefaultFatal;
|
||||
def err_module_build_disabled: Error<
|
||||
"module '%0' is needed but has not been provided, and implicit use of module "
|
||||
"files is disabled">, DefaultFatal;
|
||||
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_lock_failure : Error<
|
||||
"could not acquire lock file for module '%0'">, DefaultFatal;
|
||||
def err_module_lock_timeout : Error<
|
||||
@ -194,9 +198,8 @@ def err_unable_to_make_temp : Error<
|
||||
"unable to make temporary file: %0">;
|
||||
|
||||
// Modules
|
||||
def err_module_file_conflict : Error<"module '%0' found in both '%1' and '%2'">;
|
||||
def err_module_format_unhandled : Error<
|
||||
"no handler registered for module format '%0'">;
|
||||
"no handler registered for module format '%0'">, DefaultFatal;
|
||||
|
||||
// TransformActions
|
||||
// TODO: Use a custom category name to distinguish rewriter errors.
|
||||
@ -208,4 +211,7 @@ def note_mt_message : Note<"[rewriter] %0">;
|
||||
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">;
|
||||
|
||||
// OpenMP
|
||||
def err_omp_more_one_clause : Error<
|
||||
"directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">;
|
||||
}
|
||||
|
@ -81,6 +81,8 @@ def err_drv_invalid_mfloat_abi : Error<
|
||||
"invalid float ABI '%0'">;
|
||||
def err_drv_invalid_libcxx_deployment : Error<
|
||||
"invalid deployment target for -stdlib=libc++ (requires %0 or later)">;
|
||||
def err_drv_invalid_argument_to_fdebug_prefix_map : Error<
|
||||
"invalid argument '%0' to -fdebug-prefix-map">;
|
||||
def err_drv_malformed_sanitizer_blacklist : Error<
|
||||
"malformed sanitizer blacklist: '%0'">;
|
||||
|
||||
@ -100,12 +102,18 @@ def err_drv_cc_print_options_failure : Error<
|
||||
"unable to open CC_PRINT_OPTIONS file: %0">;
|
||||
def err_drv_preamble_format : Error<
|
||||
"incorrect format for -preamble-bytes=N,END">;
|
||||
def err_drv_conflicting_deployment_targets : Error<
|
||||
"conflicting deployment targets, both '%0' and '%1' are present in environment">;
|
||||
def err_drv_objc_gc_arr : Error<
|
||||
"cannot specify both '-fobjc-arc' and '%0'">;
|
||||
def err_arc_unsupported_on_runtime : Error<
|
||||
"-fobjc-arc is not supported on platforms using the legacy runtime">;
|
||||
def err_arc_unsupported_on_toolchain : Error< // feel free to generalize this
|
||||
"-fobjc-arc is not supported on versions of OS X prior to 10.6">;
|
||||
def err_objc_weak_with_gc : Error<
|
||||
"-fobjc-weak is not supported in Objective-C garbage collection">;
|
||||
def err_objc_weak_unsupported : Error<
|
||||
"-fobjc-weak is not supported on the current deployment target">;
|
||||
def err_drv_mg_requires_m_or_mm : Error<
|
||||
"option '-MG' requires '-M' or '-MM'">;
|
||||
def err_drv_unknown_objc_runtime : Error<
|
||||
@ -117,6 +125,8 @@ def err_drv_optimization_remark_pattern : Error<
|
||||
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_lto_libpath : Warning<"libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead">,
|
||||
InGroup<LibLTO>;
|
||||
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">,
|
||||
@ -183,6 +193,10 @@ def err_drv_modules_validate_once_requires_timestamp : Error<
|
||||
"option '-fmodules-validate-once-per-build-session' requires "
|
||||
"'-fbuild-session-timestamp=<seconds since Epoch>' or '-fbuild-session-file=<file>'">;
|
||||
|
||||
def err_test_module_file_extension_format : Error<
|
||||
"-ftest-module-file-extension argument '%0' is not of the required form "
|
||||
"'blockname:major:minor:hashed:user info'">;
|
||||
|
||||
def warn_drv_invoking_fallback : Warning<"falling back to %0">,
|
||||
InGroup<Fallback>;
|
||||
|
||||
@ -192,4 +206,18 @@ def warn_target_unsupported_nan2008 : Warning<
|
||||
def warn_target_unsupported_nanlegacy : Warning<
|
||||
"ignoring '-mnan=legacy' option because the '%0' architecture does not support it">,
|
||||
InGroup<UnsupportedNan>;
|
||||
|
||||
def warn_drv_unable_to_find_directory_expected : Warning<
|
||||
"unable to find %0 directory, expected to be in '%1'">,
|
||||
InGroup<InvalidOrNonExistentDirectory>, DefaultIgnore;
|
||||
|
||||
def warn_drv_ps4_force_pic : Warning<
|
||||
"option '%0' was ignored by the PS4 toolchain, using '-fPIC'">,
|
||||
InGroup<OptionIgnored>;
|
||||
|
||||
def warn_drv_ps4_sdk_dir : Warning<
|
||||
"environment variable SCE_PS4_SDK_DIR is set, but points to invalid or nonexistent directory '%0'">,
|
||||
InGroup<InvalidOrNonExistentDirectory>;
|
||||
|
||||
def err_drv_unsupported_linker : Error<"unsupported value '%0' for -linker option">;
|
||||
}
|
||||
|
@ -45,6 +45,17 @@ 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 remark_fe_backend_optimization_remark_analysis_fpcommute : Remark<"%0; "
|
||||
"allow reordering by specifying '#pragma clang loop vectorize(enable)' "
|
||||
"before the loop or by providing the compiler option '-ffast-math'.">,
|
||||
BackendInfo, InGroup<BackendOptimizationRemarkAnalysis>;
|
||||
def remark_fe_backend_optimization_remark_analysis_aliasing : Remark<"%0; "
|
||||
"allow reordering by specifying '#pragma clang loop vectorize(enable)' "
|
||||
"before the loop. If the arrays will always be independent specify "
|
||||
"'#pragma clang loop vectorize(assume_safety)' before the loop or provide "
|
||||
"the '__restrict__' qualifier with the independent array arguments. "
|
||||
"Erroneous results will occur if these options are incorrectly applied!">,
|
||||
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 "
|
||||
@ -161,6 +172,9 @@ def warn_incompatible_analyzer_plugin_api : Warning<
|
||||
def note_incompatible_analyzer_plugin_api : Note<
|
||||
"current API version is '%0', but plugin was compiled with version '%1'">;
|
||||
|
||||
def warn_module_config_mismatch : Warning<
|
||||
"module file %0 cannot be loaded due to a configuration mismatch with the current "
|
||||
"compilation">, InGroup<DiagGroup<"module-file-config-mismatch">>, DefaultError;
|
||||
def err_module_map_not_found : Error<"module map file '%0' not found">,
|
||||
DefaultFatal;
|
||||
def err_missing_module_name : Error<
|
||||
@ -173,10 +187,6 @@ def err_no_submodule_suggest : Error<
|
||||
"no submodule named %0 in module '%1'; did you mean '%2'?">;
|
||||
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<
|
||||
@ -190,20 +200,17 @@ def remark_module_build : Remark<"building module '%0' as '%1'">,
|
||||
InGroup<ModuleBuild>;
|
||||
def remark_module_build_done : Remark<"finished building module '%0'">,
|
||||
InGroup<ModuleBuild>;
|
||||
def err_modules_embed_file_not_found :
|
||||
Error<"file '%0' specified by '-fmodules-embed-file=' not found">,
|
||||
DefaultFatal;
|
||||
|
||||
def err_test_module_file_extension_version : Error<
|
||||
"test module file extension '%0' has different version (%1.%2) than expected "
|
||||
"(%3.%4)">;
|
||||
|
||||
def err_conflicting_module_names : Error<
|
||||
"conflicting module names specified: '-fmodule-name=%0' and "
|
||||
"'-fmodule-implementation-of %1'">;
|
||||
def err_conflicting_module_files : Error<
|
||||
"module '%0' is defined in both '%1' and '%2'">;
|
||||
def err_module_file_not_found : Error<
|
||||
"module file '%0' not found">, DefaultFatal;
|
||||
def err_module_file_invalid : Error<
|
||||
"file '%0' is not a valid precompiled module file">, DefaultFatal;
|
||||
def note_module_file_imported_by : Note<
|
||||
"imported by %select{|module '%2' in }1'%0'">;
|
||||
def err_module_file_not_module : Error<
|
||||
"AST file '%0' was not built as a module">, DefaultFatal;
|
||||
|
||||
def err_missing_vfs_overlay_file : Error<
|
||||
"virtual filesystem overlay file '%0' not found">, DefaultFatal;
|
||||
|
@ -24,14 +24,17 @@ def : DiagGroup<"aggregate-return">;
|
||||
def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">;
|
||||
def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
|
||||
def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">;
|
||||
def GNUAutoType : DiagGroup<"gnu-auto-type">;
|
||||
def ArrayBounds : DiagGroup<"array-bounds">;
|
||||
def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">;
|
||||
def Availability : DiagGroup<"availability">;
|
||||
def Section : DiagGroup<"section">;
|
||||
def AutoImport : DiagGroup<"auto-import">;
|
||||
def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">;
|
||||
def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
|
||||
def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">;
|
||||
def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
|
||||
def BitFieldWidth : DiagGroup<"bitfield-width">;
|
||||
def ConstantConversion :
|
||||
DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >;
|
||||
def LiteralConversion : DiagGroup<"literal-conversion">;
|
||||
@ -44,6 +47,7 @@ def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
|
||||
def IntConversion : DiagGroup<"int-conversion">;
|
||||
def EnumConversion : DiagGroup<"enum-conversion">;
|
||||
def FloatConversion : DiagGroup<"float-conversion">;
|
||||
def DoublePromotion : DiagGroup<"double-promotion">;
|
||||
def EnumTooLarge : DiagGroup<"enum-too-large">;
|
||||
def UnsupportedNan : DiagGroup<"unsupported-nan">;
|
||||
def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">;
|
||||
@ -79,6 +83,7 @@ def AbstractFinalClass : DiagGroup<"abstract-final-class">;
|
||||
def CXX11CompatDeprecatedWritableStr :
|
||||
DiagGroup<"c++11-compat-deprecated-writable-strings">;
|
||||
|
||||
def DeprecatedAttributes : DiagGroup<"deprecated-attributes">;
|
||||
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
|
||||
def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
|
||||
def PartialAvailability : DiagGroup<"partial-availability">;
|
||||
@ -88,12 +93,14 @@ def DeprecatedRegister : DiagGroup<"deprecated-register">;
|
||||
def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
|
||||
[CXX11CompatDeprecatedWritableStr]>;
|
||||
// FIXME: Why is DeprecatedImplementations not in this group?
|
||||
def Deprecated : DiagGroup<"deprecated", [DeprecatedDeclarations,
|
||||
def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
|
||||
DeprecatedDeclarations,
|
||||
DeprecatedIncrementBool,
|
||||
DeprecatedRegister,
|
||||
DeprecatedWritableStr]>,
|
||||
DiagCategory<"Deprecations">;
|
||||
|
||||
def LibLTO : DiagGroup<"liblto">;
|
||||
def : DiagGroup<"disabled-optimization">;
|
||||
def : DiagGroup<"discard-qual">;
|
||||
def : DiagGroup<"div-by-zero">;
|
||||
@ -180,6 +187,9 @@ def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>;
|
||||
def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic",
|
||||
[CXXPre1zCompatPedantic]>;
|
||||
|
||||
def CXX1zCompat : DiagGroup<"c++1z-compat", [DeprecatedRegister,
|
||||
DeprecatedIncrementBool]>;
|
||||
|
||||
def : DiagGroup<"effc++">;
|
||||
def DivZero : DiagGroup<"division-by-zero">;
|
||||
def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
|
||||
@ -195,10 +205,12 @@ def DanglingElse: DiagGroup<"dangling-else">;
|
||||
def DanglingField : DiagGroup<"dangling-field">;
|
||||
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
|
||||
def FlagEnum : DiagGroup<"flag-enum">;
|
||||
def IncrementBool : DiagGroup<"increment-bool", [DeprecatedIncrementBool]>;
|
||||
def InfiniteRecursion : DiagGroup<"infinite-recursion">;
|
||||
def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">;
|
||||
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
|
||||
def : DiagGroup<"import">;
|
||||
def GNUIncludeNext : DiagGroup<"gnu-include-next">;
|
||||
def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">;
|
||||
def IncompatiblePointerTypesDiscardsQualifiers
|
||||
: DiagGroup<"incompatible-pointer-types-discards-qualifiers">;
|
||||
@ -213,6 +225,7 @@ def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module",
|
||||
def IncompleteModule : DiagGroup<"incomplete-module",
|
||||
[IncompleteUmbrella, NonModularIncludeInModule]>;
|
||||
|
||||
def CXX11InlineNamespace : DiagGroup<"c++11-inline-namespace">;
|
||||
def InvalidNoreturn : DiagGroup<"invalid-noreturn">;
|
||||
def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">;
|
||||
def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">;
|
||||
@ -247,6 +260,7 @@ def MismatchedTags : DiagGroup<"mismatched-tags">;
|
||||
def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
|
||||
def ModuleBuild : DiagGroup<"module-build">;
|
||||
def ModuleConflict : DiagGroup<"module-conflict">;
|
||||
def ModuleFileExtension : DiagGroup<"module-file-extension">;
|
||||
def NewlineEOF : DiagGroup<"newline-eof">;
|
||||
def Nullability : DiagGroup<"nullability">;
|
||||
def NullabilityDeclSpec : DiagGroup<"nullability-declspec">;
|
||||
@ -304,6 +318,7 @@ def : DiagGroup<"redundant-decls">;
|
||||
def RedeclaredClassMember : DiagGroup<"redeclared-class-member">;
|
||||
def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">;
|
||||
def RedundantMove : DiagGroup<"redundant-move">;
|
||||
def Register : DiagGroup<"register", [DeprecatedRegister]>;
|
||||
def ReturnStackAddress : DiagGroup<"return-stack-address">;
|
||||
def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;
|
||||
def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;
|
||||
@ -648,7 +663,10 @@ 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, SwitchBool]>;
|
||||
def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>;
|
||||
|
||||
// Warnings that should be in clang-cl /w4.
|
||||
def : DiagGroup<"CL4", [All, Extra]>;
|
||||
|
||||
// Warnings enabled by -pedantic. This is magically filled in by TableGen.
|
||||
def Pedantic : DiagGroup<"pedantic">;
|
||||
@ -675,11 +693,12 @@ def NonGCC : DiagGroup<"non-gcc",
|
||||
|
||||
// A warning group for warnings about using C++11 features as extensions in
|
||||
// earlier C++ versions.
|
||||
def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11LongLong]>;
|
||||
def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11InlineNamespace,
|
||||
CXX11LongLong]>;
|
||||
|
||||
// A warning group for warnings about using C++14 features as extensions in
|
||||
// earlier C++ versions.
|
||||
def CXX14 : DiagGroup<"c++14-extensions">;
|
||||
def CXX14 : DiagGroup<"c++14-extensions", [CXX14BinaryLiteral]>;
|
||||
|
||||
// A warning group for warnings about using C++1z features as extensions in
|
||||
// earlier C++ versions.
|
||||
@ -699,13 +718,15 @@ def C99 : DiagGroup<"c99-extensions">;
|
||||
|
||||
// A warning group for warnings about GCC extensions.
|
||||
def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
|
||||
GNUAutoType,
|
||||
GNUBinaryLiteral, GNUCaseRange,
|
||||
GNUComplexInteger, GNUCompoundLiteralInitializer,
|
||||
GNUConditionalOmittedOperand, GNUDesignator,
|
||||
GNUEmptyInitializer, GNUEmptyStruct,
|
||||
VLAExtension, GNUFlexibleArrayInitializer,
|
||||
GNUFlexibleArrayUnionMember, GNUFoldingConstant,
|
||||
GNUImaginaryConstant, GNULabelsAsValue,
|
||||
GNUImaginaryConstant, GNUIncludeNext,
|
||||
GNULabelsAsValue,
|
||||
RedeclaredClassMember, GNURedeclaredEnum,
|
||||
GNUStatementExpression, GNUStaticFloatInit,
|
||||
GNUStringLiteralOperatorTemplate,
|
||||
@ -715,8 +736,52 @@ def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
|
||||
// A warning group for warnings about code that clang accepts but gcc doesn't.
|
||||
def GccCompat : DiagGroup<"gcc-compat">;
|
||||
|
||||
// A warning group for warnings about Microsoft extensions.
|
||||
def Microsoft : DiagGroup<"microsoft">;
|
||||
// Warnings for Microsoft extensions.
|
||||
def MicrosoftCharize : DiagGroup<"microsoft-charize">;
|
||||
def MicrosoftInclude : DiagGroup<"microsoft-include">;
|
||||
def MicrosoftCppMacro : DiagGroup<"microsoft-cpp-macro">;
|
||||
def MicrosoftFixedEnum : DiagGroup<"microsoft-fixed-enum">;
|
||||
def MicrosoftSealed : DiagGroup<"microsoft-sealed">;
|
||||
def MicrosoftUnqualifiedFriend : DiagGroup<"microsoft-unqualified-friend">;
|
||||
def MicrosoftExceptionSpec : DiagGroup<"microsoft-exception-spec">;
|
||||
def MicrosoftUsingDecl : DiagGroup<"microsoft-using-decl">;
|
||||
def MicrosoftMutableReference : DiagGroup<"microsoft-mutable-reference">;
|
||||
def MicrosoftPureDefinition : DiagGroup<"microsoft-pure-definition">;
|
||||
def MicrosoftUnionMemberReference : DiagGroup<
|
||||
"microsoft-union-member-reference">;
|
||||
def MicrosoftExplicitConstructorCall : DiagGroup<
|
||||
"microsoft-explicit-constructor-call">;
|
||||
def MicrosoftEnumValue : DiagGroup<"microsoft-enum-value">;
|
||||
def MicrosoftDefaultArgRedefinition :
|
||||
DiagGroup<"microsoft-default-arg-redefinition">;
|
||||
def MicrosoftTemplate : DiagGroup<"microsoft-template">;
|
||||
def MicrosoftRedeclareStatic : DiagGroup<"microsoft-redeclare-static">;
|
||||
def MicrosoftEnumForwardReference :
|
||||
DiagGroup<"microsoft-enum-forward-reference">;
|
||||
def MicrosoftGoto : DiagGroup<"microsoft-goto">;
|
||||
def MicrosoftFlexibleArray : DiagGroup<"microsoft-flexible-array">;
|
||||
def MicrosoftExtraQualification : DiagGroup<"microsoft-extra-qualification">;
|
||||
def MicrosoftCast : DiagGroup<"microsoft-cast">;
|
||||
def MicrosoftConstInit : DiagGroup<"microsoft-const-init">;
|
||||
def MicrosoftVoidPseudoDtor : DiagGroup<"microsoft-void-pseudo-dtor">;
|
||||
def MicrosoftAnonTag : DiagGroup<"microsoft-anon-tag">;
|
||||
def MicrosoftCommentPaste : DiagGroup<"microsoft-comment-paste">;
|
||||
def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">;
|
||||
// Aliases.
|
||||
def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
|
||||
// -Wmsvc-include = -Wmicrosoft-include
|
||||
|
||||
// Warnings group for warnings about Microsoft extensions.
|
||||
def Microsoft : DiagGroup<"microsoft",
|
||||
[MicrosoftCharize, MicrosoftInclude, MicrosoftCppMacro, MicrosoftFixedEnum,
|
||||
MicrosoftSealed, MicrosoftUnqualifiedFriend, MicrosoftExceptionSpec,
|
||||
MicrosoftUsingDecl, MicrosoftMutableReference, MicrosoftPureDefinition,
|
||||
MicrosoftUnionMemberReference, MicrosoftExplicitConstructorCall,
|
||||
MicrosoftEnumValue, MicrosoftDefaultArgRedefinition, MicrosoftTemplate,
|
||||
MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto,
|
||||
MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast,
|
||||
MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
|
||||
MicrosoftCommentPaste, MicrosoftEndOfFile]>;
|
||||
|
||||
def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">;
|
||||
|
||||
@ -777,3 +842,7 @@ def CudaCompat : DiagGroup<"cuda-compat">;
|
||||
|
||||
// A warning group for things that will change semantics in the future.
|
||||
def FutureCompat : DiagGroup<"future-compat">;
|
||||
|
||||
def InvalidOrNonExistentDirectory : DiagGroup<"invalid-or-nonexistent-directory">;
|
||||
|
||||
def OptionIgnored : DiagGroup<"option-ignored">;
|
||||
|
@ -13,9 +13,8 @@
|
||||
|
||||
let Component = "Lex", CategoryName = "Lexical or Preprocessor Issue" in {
|
||||
|
||||
def null_in_string : Warning<"null character(s) preserved in string literal">,
|
||||
InGroup<NullCharacter>;
|
||||
def null_in_char : Warning<"null character(s) preserved in character literal">,
|
||||
def null_in_char_or_string : Warning<
|
||||
"null character(s) preserved in %select{char|string}0 literal">,
|
||||
InGroup<NullCharacter>;
|
||||
def null_in_file : Warning<"null character ignored">, InGroup<NullCharacter>;
|
||||
def warn_nested_block_comment : Warning<"'/*' within block comment">,
|
||||
@ -57,8 +56,15 @@ def warn_cxx98_compat_no_newline_eof : Warning<
|
||||
|
||||
def ext_dollar_in_identifier : Extension<"'$' in identifier">,
|
||||
InGroup<DiagGroup<"dollar-in-identifier-extension">>;
|
||||
def ext_charize_microsoft : Extension<"charizing operator #@ is a Microsoft extension">,
|
||||
InGroup<Microsoft>;
|
||||
def ext_charize_microsoft : Extension<
|
||||
"charizing operator #@ is a Microsoft extension">,
|
||||
InGroup<MicrosoftCharize>;
|
||||
def ext_comment_paste_microsoft : Extension<
|
||||
"pasting two '/' tokens into a '//' comment is a Microsoft extension">,
|
||||
InGroup<MicrosoftCommentPaste>;
|
||||
def ext_ctrl_z_eof_microsoft : Extension<
|
||||
"treating Ctrl-Z as end-of-file is a Microsoft extension">,
|
||||
InGroup<MicrosoftEndOfFile>;
|
||||
|
||||
def ext_token_used : Extension<"extension used">,
|
||||
InGroup<DiagGroup<"language-extension-token">>;
|
||||
@ -66,10 +72,8 @@ def ext_token_used : Extension<"extension used">,
|
||||
def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">,
|
||||
InGroup<CXX11Compat>, DefaultIgnore;
|
||||
|
||||
def ext_unterminated_string : ExtWarn<"missing terminating '\"' character">,
|
||||
InGroup<InvalidPPToken>;
|
||||
def ext_unterminated_char : ExtWarn<"missing terminating ' character">,
|
||||
InGroup<InvalidPPToken>;
|
||||
def ext_unterminated_char_or_string : ExtWarn<
|
||||
"missing terminating %select{'|'\"'}0 character">, InGroup<InvalidPPToken>;
|
||||
def ext_empty_character : ExtWarn<"empty character constant">,
|
||||
InGroup<InvalidPPToken>;
|
||||
def err_unterminated_block_comment : Error<"unterminated /* comment">;
|
||||
@ -153,13 +157,10 @@ def ext_nonstandard_escape : Extension<
|
||||
"use of non-standard escape character '\\%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">;
|
||||
def err_invalid_suffix_integer_constant : Error<
|
||||
"invalid suffix '%0' on integer constant">;
|
||||
def err_invalid_suffix_float_constant : Error<
|
||||
"invalid suffix '%0' on floating constant">;
|
||||
def err_invalid_digit : Error<
|
||||
"invalid digit '%0' in %select{decimal|octal|binary}1 constant">;
|
||||
def err_invalid_suffix_constant : Error<
|
||||
"invalid suffix '%0' on %select{integer|floating}1 constant">;
|
||||
def warn_cxx11_compat_digit_separator : Warning<
|
||||
"digit separators are incompatible with C++ standards before C++14">,
|
||||
InGroup<CXXPre14Compat>, DefaultIgnore;
|
||||
@ -174,22 +175,20 @@ def err_multichar_utf_character_literal : Error<
|
||||
def err_exponent_has_no_digits : Error<"exponent has no digits">;
|
||||
def ext_imaginary_constant : Extension<
|
||||
"imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;
|
||||
def err_hexconstant_requires_exponent : Error<
|
||||
"hexadecimal floating constants require an exponent">;
|
||||
def err_hexconstant_requires_digits : Error<
|
||||
"hexadecimal floating constants require a significand">;
|
||||
def err_hexconstant_requires: Error<
|
||||
"hexadecimal floating constants require %select{an exponent|a significand}0">;
|
||||
def ext_hexconstant_invalid : Extension<
|
||||
"hexadecimal floating constants are a C99 feature">, InGroup<C99>;
|
||||
def ext_binary_literal : Extension<
|
||||
"binary integer literals are a GNU extension">, InGroup<GNUBinaryLiteral>;
|
||||
def ext_binary_literal_cxx14 : Extension<
|
||||
"binary integer literals are a C++14 extension">, InGroup<CXX14>;
|
||||
"binary integer literals are a C++14 extension">, InGroup<CXX14BinaryLiteral>;
|
||||
def warn_cxx11_compat_binary_literal : Warning<
|
||||
"binary integer literals are incompatible with C++ standards before C++14">,
|
||||
InGroup<CXXPre14CompatPedantic>, DefaultIgnore;
|
||||
def err_pascal_string_too_long : Error<"Pascal string is too long">;
|
||||
def err_octal_escape_too_large : Error<"octal escape sequence out of range">;
|
||||
def err_hex_escape_too_large : Error<"hex escape sequence out of range">;
|
||||
def err_escape_too_large : Error<
|
||||
"%select{hex|octal}0 escape sequence out of range">;
|
||||
def ext_string_too_long : Extension<"string literal of length %0 exceeds "
|
||||
"maximum length %1 that %select{C90|ISO C99|C++}2 compilers are required to "
|
||||
"support">, InGroup<OverlengthStrings>;
|
||||
@ -255,10 +254,13 @@ def err_pp_hash_error : Error<"%0">;
|
||||
}
|
||||
|
||||
def pp_include_next_in_primary : Warning<
|
||||
"#include_next in primary source file">;
|
||||
"#include_next in primary source file">,
|
||||
InGroup<DiagGroup<"include-next-outside-header">>;
|
||||
def pp_include_macros_out_of_predefines : Error<
|
||||
"the #__include_macros directive is only for internal use by -imacros">;
|
||||
def pp_include_next_absolute_path : Warning<"#include_next with absolute path">;
|
||||
def pp_include_next_absolute_path : Warning<
|
||||
"#include_next with absolute path">,
|
||||
InGroup<DiagGroup<"include-next-absolute-path">>;
|
||||
def ext_c99_whitespace_required_after_macro_name : ExtWarn<
|
||||
"ISO C99 requires whitespace after the macro name">, InGroup<C99>;
|
||||
def ext_missing_whitespace_after_macro_name : ExtWarn<
|
||||
@ -266,9 +268,11 @@ def ext_missing_whitespace_after_macro_name : ExtWarn<
|
||||
def warn_missing_whitespace_after_macro_name : Warning<
|
||||
"whitespace recommended after macro name">;
|
||||
|
||||
def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">;
|
||||
def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">,
|
||||
InGroup<DiagGroup<"pragma-once-outside-header">>;
|
||||
def pp_pragma_sysheader_in_main_file : Warning<
|
||||
"#pragma system_header ignored in main file">;
|
||||
"#pragma system_header ignored in main file">,
|
||||
InGroup<DiagGroup<"pragma-system-header-outside-header">>;
|
||||
def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
|
||||
def pp_out_of_date_dependency : Warning<
|
||||
"current file is older than dependency %0">;
|
||||
@ -295,27 +299,29 @@ def warn_pp_macro_hides_keyword : Extension<
|
||||
def warn_pp_macro_is_reserved_id : Warning<
|
||||
"macro name is a reserved identifier">, DefaultIgnore,
|
||||
InGroup<ReservedIdAsMacro>;
|
||||
def warn_pp_objc_macro_redef_ignored : Warning<
|
||||
"ignoring redefinition of Objective-C qualifier macro">,
|
||||
InGroup<DiagGroup<"objc-macro-redefinition">>;
|
||||
|
||||
def pp_invalid_string_literal : Warning<
|
||||
"invalid string literal, ignoring final '\\'">;
|
||||
def warn_pp_expr_overflow : Warning<
|
||||
"integer overflow in preprocessor expression">;
|
||||
def warn_pp_convert_lhs_to_positive : Warning<
|
||||
"left side of operator converted from negative value to unsigned: %0">;
|
||||
def warn_pp_convert_rhs_to_positive : Warning<
|
||||
"right side of operator converted from negative value to unsigned: %0">;
|
||||
def warn_pp_convert_to_positive : Warning<
|
||||
"%select{left|right}0 side of operator converted from negative value to "
|
||||
"unsigned: %1">;
|
||||
|
||||
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">>;
|
||||
"#include resolved using non-portable Microsoft search rules as: %0">,
|
||||
InGroup<MicrosoftInclude>;
|
||||
|
||||
def ext_pp_ident_directive : Extension<"#ident is a language extension">;
|
||||
def ext_pp_include_next_directive : Extension<
|
||||
"#include_next is a language extension">;
|
||||
"#include_next is a language extension">, InGroup<GNUIncludeNext>;
|
||||
def ext_pp_warning_directive : Extension<"#warning is a language extension">;
|
||||
|
||||
def ext_pp_extra_tokens_at_eol : ExtWarn<
|
||||
@ -510,7 +516,7 @@ def ext_pp_bad_paste_ms : ExtWarn<
|
||||
def err_pp_operator_used_as_macro_name : Error<
|
||||
"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>;
|
||||
err_pp_operator_used_as_macro_name.Text>, InGroup<MicrosoftCppMacro>;
|
||||
def err_pp_illegal_floating_literal : Error<
|
||||
"floating point literal in preprocessor expression">;
|
||||
def err_pp_line_requires_integer : Error<
|
||||
@ -622,6 +628,8 @@ def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
|
||||
def warn_auto_module_import : Warning<
|
||||
"treating #%select{include|import|include_next|__include_macros}0 as an "
|
||||
"import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
|
||||
def note_implicit_top_level_module_import_here : Note<
|
||||
"submodule of top-level module '%0' implicitly imported here">;
|
||||
def warn_uncovered_module_header : Warning<
|
||||
"umbrella header for module '%0' does not include header '%1'">,
|
||||
InGroup<IncompleteUmbrella>;
|
||||
|
@ -51,14 +51,6 @@ def warn_extra_semi_after_mem_fn_def : Warning<
|
||||
"extra ';' after member function definition">,
|
||||
InGroup<ExtraSemi>, DefaultIgnore;
|
||||
|
||||
def ext_duplicate_declspec : ExtWarn<"duplicate '%0' declaration specifier">,
|
||||
InGroup<DuplicateDeclSpecifier>;
|
||||
def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">,
|
||||
InGroup<DuplicateDeclSpecifier>;
|
||||
def ext_plain_complex : ExtWarn<
|
||||
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
|
||||
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 made available as an identifier "
|
||||
@ -70,12 +62,6 @@ def ext_nullability : Extension<
|
||||
InGroup<DiagGroup<"nullability-extension">>;
|
||||
|
||||
def error_empty_enum : Error<"use of empty enum">;
|
||||
def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
|
||||
def err_invalid_short_spec : Error<"'short %0' is invalid">;
|
||||
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_decl_spec : Error<"'%0' is invalid in friend declarations">;
|
||||
|
||||
def ext_ident_list_in_param : Extension<
|
||||
"type-less parameter names in function declaration">;
|
||||
@ -101,7 +87,7 @@ def ext_cxx11_enum_fixed_underlying_type : Extension<
|
||||
InGroup<CXX11>;
|
||||
def ext_c_enum_fixed_underlying_type : Extension<
|
||||
"enumeration types with a fixed underlying type are a Microsoft extension">,
|
||||
InGroup<Microsoft>;
|
||||
InGroup<MicrosoftFixedEnum>;
|
||||
def warn_cxx98_compat_enum_fixed_underlying_type : Warning<
|
||||
"enumeration types with a fixed underlying type are incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
@ -271,7 +257,7 @@ def warn_cxx98_compat_ref_qualifier : Warning<
|
||||
"reference qualifiers on functions are incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
def ext_inline_namespace : ExtWarn<
|
||||
"inline namespaces are a C++11 feature">, InGroup<CXX11>;
|
||||
"inline namespaces are a C++11 feature">, InGroup<CXX11InlineNamespace>;
|
||||
def warn_cxx98_compat_inline_namespace : Warning<
|
||||
"inline namespaces are incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
@ -286,11 +272,6 @@ def err_init_list_bin_op : Error<"initializer list cannot be used on the "
|
||||
def warn_cxx98_compat_trailing_return_type : Warning<
|
||||
"trailing return types are incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
def ext_auto_type_specifier : ExtWarn<
|
||||
"'auto' type specifier is a C++11 extension">, InGroup<CXX11>;
|
||||
def warn_auto_storage_class : Warning<
|
||||
"'auto' storage class specifier is redundant and incompatible with C++11">,
|
||||
InGroup<CXX11Compat>, DefaultIgnore;
|
||||
def ext_auto_storage_class : ExtWarn<
|
||||
"'auto' storage class specifier is not permitted in C++11, and will not "
|
||||
"be supported in future releases">, InGroup<DiagGroup<"auto-storage-class">>;
|
||||
@ -299,6 +280,9 @@ def ext_decltype_auto_type_specifier : ExtWarn<
|
||||
def warn_cxx11_compat_decltype_auto_type_specifier : Warning<
|
||||
"'decltype(auto)' type specifier is incompatible with C++ standards before "
|
||||
"C++14">, InGroup<CXXPre14Compat>, DefaultIgnore;
|
||||
def ext_auto_type : Extension<
|
||||
"'__auto_type' is a GNU extension">,
|
||||
InGroup<GNUAutoType>;
|
||||
def ext_for_range : ExtWarn<
|
||||
"range-based for loop is a C++11 extension">, InGroup<CXX11>;
|
||||
def warn_cxx98_compat_for_range : Warning<
|
||||
@ -327,9 +311,6 @@ def err_unspecified_vla_size_with_static : Error<
|
||||
"'static' may not be used with an unspecified variable length array size">;
|
||||
def err_unspecified_size_with_static : Error<
|
||||
"'static' may not be used without an array size">;
|
||||
def warn_deprecated_register : Warning<
|
||||
"'register' storage class specifier is deprecated">,
|
||||
InGroup<DeprecatedRegister>;
|
||||
def err_expected_parentheses_around_typename : Error<
|
||||
"expected parentheses around type name in %0 expression">;
|
||||
|
||||
@ -348,39 +329,10 @@ def err_typename_invalid_constexpr : Error<
|
||||
def err_typename_identifiers_only : Error<
|
||||
"typename is allowed for identifiers only">;
|
||||
|
||||
def err_invalid_decl_spec_combination : Error<
|
||||
"cannot combine with previous '%0' declaration specifier">;
|
||||
def err_invalid_vector_decl_spec_combination : Error<
|
||||
"cannot combine with previous '%0' declaration specifier. "
|
||||
"'__vector' must be first">;
|
||||
def err_invalid_pixel_decl_spec_combination : Error<
|
||||
"'__pixel' must be preceded by '__vector'. "
|
||||
"'%0' declaration specifier not allowed here">;
|
||||
def err_invalid_vector_bool_decl_spec : Error<
|
||||
"cannot use '%0' with '__vector bool'">;
|
||||
def err_invalid_vector_long_decl_spec : Error<
|
||||
"cannot use 'long' with '__vector'">;
|
||||
def err_invalid_vector_float_decl_spec : Error<
|
||||
"cannot use 'float' with '__vector'">;
|
||||
def err_invalid_vector_double_decl_spec : Error <
|
||||
"use of 'double' with '__vector' requires VSX support to be enabled "
|
||||
"(available on POWER7 or later)">;
|
||||
def err_invalid_vector_long_long_decl_spec : Error <
|
||||
"use of 'long long' with '__vector bool' requires VSX support (available on "
|
||||
"POWER7 or later) or extended Altivec support (available on POWER8 or later) "
|
||||
"to be enabled">;
|
||||
def err_invalid_vector_long_double_decl_spec : Error<
|
||||
"cannot use 'long double' with '__vector'">;
|
||||
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_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_templated_using_directive_declaration : Error<
|
||||
"cannot template a using %select{directive|declaration}0">;
|
||||
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<
|
||||
@ -512,7 +464,7 @@ def note_missing_end_of_definition_before : Note<
|
||||
"still within definition of %q0 here">;
|
||||
def ext_ellipsis_exception_spec : Extension<
|
||||
"exception specification of '...' is a Microsoft extension">,
|
||||
InGroup<Microsoft>;
|
||||
InGroup<MicrosoftExceptionSpec>;
|
||||
def err_dynamic_and_noexcept_specification : Error<
|
||||
"cannot have both throw() and noexcept() clause on the same function">;
|
||||
def err_except_spec_unparsed : Error<
|
||||
@ -695,12 +647,9 @@ def warn_static_inline_explicit_inst_ignored : Warning<
|
||||
// Constructor template diagnostics.
|
||||
def err_out_of_line_constructor_template_id : Error<
|
||||
"out-of-line constructor for %0 cannot have template arguments">;
|
||||
def err_out_of_line_template_id_names_constructor : Error<
|
||||
def err_out_of_line_template_id_type_names_constructor : Error<
|
||||
"qualified reference to %0 is a constructor name rather than a "
|
||||
"template name wherever a constructor can be declared">;
|
||||
def err_out_of_line_type_names_constructor : Error<
|
||||
"qualified reference to %0 is a constructor name rather than a "
|
||||
"type wherever a constructor can be declared">;
|
||||
"%select{template name|type}1 wherever a constructor can be declared">;
|
||||
|
||||
def err_expected_qualified_after_typename : Error<
|
||||
"expected a qualified name after 'typename'">;
|
||||
@ -740,15 +689,11 @@ def err_missing_whitespace_digraph : Error<
|
||||
"%select{template name|const_cast|dynamic_cast|reinterpret_cast|static_cast}0"
|
||||
" which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?">;
|
||||
|
||||
def ext_deleted_function : ExtWarn<
|
||||
"deleted function definitions are a C++11 extension">, InGroup<CXX11>;
|
||||
def warn_cxx98_compat_deleted_function : Warning<
|
||||
"deleted function definitions are incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
def ext_defaulted_function : ExtWarn<
|
||||
"defaulted function definitions are a C++11 extension">, InGroup<CXX11>;
|
||||
def warn_cxx98_compat_defaulted_function : Warning<
|
||||
"defaulted function definitions are incompatible with C++98">,
|
||||
def ext_defaulted_deleted_function : ExtWarn<
|
||||
"%select{defaulted|deleted}0 function definitions are a C++11 extension">,
|
||||
InGroup<CXX11>;
|
||||
def warn_cxx98_compat_defaulted_deleted_function : Warning<
|
||||
"%select{defaulted|deleted}0 function definitions are incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
|
||||
// C++11 in-class member initialization
|
||||
@ -784,7 +729,7 @@ def err_override_control_interface : Error<
|
||||
"'%0' keyword not permitted with interface types">;
|
||||
def ext_ms_sealed_keyword : ExtWarn<
|
||||
"'sealed' keyword is a Microsoft extension">,
|
||||
InGroup<Microsoft>;
|
||||
InGroup<MicrosoftSealed>;
|
||||
|
||||
def err_access_specifier_interface : Error<
|
||||
"interface types cannot specify '%select{private|protected}0' access">;
|
||||
@ -821,10 +766,6 @@ def warn_cxx98_compat_lambda : Warning<
|
||||
def err_lambda_missing_parens : Error<
|
||||
"lambda requires '()' before %select{'mutable'|return type|"
|
||||
"attribute specifier}0">;
|
||||
def warn_init_capture_direct_list_init : Warning<
|
||||
"direct list initialization of a lambda init-capture will change meaning in "
|
||||
"a future version of Clang; insert an '=' to avoid a change in behavior">,
|
||||
InGroup<FutureCompat>;
|
||||
|
||||
// Availability attribute
|
||||
def err_expected_version : Error<
|
||||
@ -945,7 +886,7 @@ def err_pragma_comment_malformed : Error<
|
||||
def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
|
||||
// PS4 recognizes only #pragma comment(lib)
|
||||
def warn_pragma_comment_ignored : Warning<"'#pragma comment %0' ignored">,
|
||||
InGroup<Microsoft>;
|
||||
InGroup<IgnoredPragmas>;
|
||||
// - #pragma detect_mismatch
|
||||
def err_pragma_detect_mismatch_malformed : Error<
|
||||
"pragma detect_mismatch is malformed; it requires two comma-separated "
|
||||
@ -961,10 +902,6 @@ def err_pragma_optimize_invalid_argument : Error<
|
||||
def err_pragma_optimize_extra_argument : Error<
|
||||
"unexpected extra argument '%0' to '#pragma clang optimize'">;
|
||||
|
||||
// OpenCL Section 6.8.g
|
||||
def err_opencl_unknown_type_specifier : Error<
|
||||
"OpenCL does not support the '%0' %select{type qualifier|storage class specifier}1">;
|
||||
|
||||
// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
|
||||
def warn_pragma_expected_colon : Warning<
|
||||
"missing ':' after %0 - ignoring">, InGroup<IgnoredPragmas>;
|
||||
@ -979,6 +916,8 @@ def warn_pragma_omp_ignored : Warning<
|
||||
def warn_omp_extra_tokens_at_eol : Warning<
|
||||
"extra tokens at the end of '#pragma omp %0' are ignored">,
|
||||
InGroup<ExtraTokens>;
|
||||
def warn_pragma_expected_colon_r_paren : Warning<
|
||||
"missing ':' or ')' after %0 - ignoring">, InGroup<IgnoredPragmas>;
|
||||
def err_omp_unknown_directive : Error<
|
||||
"expected an OpenMP directive">;
|
||||
def err_omp_unexpected_directive : Error<
|
||||
@ -987,22 +926,26 @@ 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<
|
||||
"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">;
|
||||
"'#pragma omp %0' %select{|with '%2' clause }1cannot be an immediate substatement">;
|
||||
def err_omp_expected_identifier_for_critical : Error<
|
||||
"expected identifier specifying the name of the 'omp critical' directive">;
|
||||
def err_omp_unknown_map_type : Error<
|
||||
"incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
|
||||
def err_omp_unknown_map_type_modifier : Error<
|
||||
"incorrect map type modifier, expected 'always'">;
|
||||
def err_omp_map_type_missing : Error<
|
||||
"missing map type">;
|
||||
|
||||
// Pragma loop support.
|
||||
def err_pragma_loop_missing_argument : Error<
|
||||
"missing argument; expected %select{an integer value|"
|
||||
"%select{'enable', 'assume_safety'|'full'}1 or 'disable'}0">;
|
||||
"'enable', %select{'assume_safety'|'full'}1 or 'disable'}0">;
|
||||
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">;
|
||||
def err_pragma_invalid_keyword : Error<
|
||||
"invalid argument; expected %select{'enable', 'assume_safety'|'full'}0 or 'disable'">;
|
||||
"invalid argument; expected 'enable', %select{'assume_safety'|'full'}0 or 'disable'">;
|
||||
|
||||
// Pragma unroll support.
|
||||
def warn_pragma_unroll_cuda_value_in_parens : Warning<
|
||||
@ -1015,6 +958,7 @@ def err_module_expected_ident : Error<
|
||||
"expected a module name after module import">;
|
||||
def err_module_expected_semi : Error<
|
||||
"expected ';' after module name">;
|
||||
def err_missing_before_module_end : Error<"expected %0 at end of module">;
|
||||
}
|
||||
|
||||
let CategoryName = "Generics Issue" in {
|
||||
@ -1029,4 +973,9 @@ def err_objc_type_args_after_protocols : Error<
|
||||
"protocol qualifiers must precede type arguments">;
|
||||
}
|
||||
|
||||
let CategoryName = "Coroutines Issue" in {
|
||||
def err_for_co_await_not_range_for : Error<
|
||||
"'co_await' modifier can only be applied to range-based for loop">;
|
||||
}
|
||||
|
||||
} // end of Parser diagnostics
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,6 +53,20 @@ def err_pch_different_branch : Error<
|
||||
def err_pch_with_compiler_errors : Error<
|
||||
"PCH file contains compiler errors">;
|
||||
|
||||
def err_module_file_conflict : Error<
|
||||
"module '%0' is defined in both '%1' and '%2'">, DefaultFatal;
|
||||
def err_module_file_not_found : Error<
|
||||
"%select{PCH|module|AST}0 file '%1' not found%select{|: %3}2">, DefaultFatal;
|
||||
def err_module_file_out_of_date : Error<
|
||||
"%select{PCH|module|AST}0 file '%1' is out of date and "
|
||||
"needs to be rebuilt%select{|: %3}2">, DefaultFatal;
|
||||
def err_module_file_invalid : Error<
|
||||
"file '%1' is not a valid precompiled %select{PCH|module|AST}0 file">, DefaultFatal;
|
||||
def note_module_file_imported_by : Note<
|
||||
"imported by %select{|module '%2' in }1'%0'">;
|
||||
def err_module_file_not_module : Error<
|
||||
"AST file '%0' was not built as a module">, DefaultFatal;
|
||||
|
||||
def err_imported_module_not_found : Error<
|
||||
"module '%0' in AST file '%1' (imported by AST file '%2') "
|
||||
"is not defined in any loaded module map file; "
|
||||
@ -82,9 +96,6 @@ def err_pch_pp_detailed_record : Error<
|
||||
"'-detailed-preprocessing-record' but %select{precompiled header was not "
|
||||
"built with it|it is not present on the command line}0">;
|
||||
|
||||
def err_not_a_pch_file : Error<
|
||||
"'%0' does not appear to be a precompiled header file">, DefaultFatal;
|
||||
|
||||
def err_module_odr_violation_missing_decl : Error<
|
||||
"%q0 from module '%1' is not present in definition of %q2"
|
||||
"%select{ in module '%4'| provided earlier}3">, NoSFINAE;
|
||||
@ -100,6 +111,14 @@ def note_module_odr_violation_different_definitions : Note<
|
||||
def err_module_odr_violation_different_instantiations : Error<
|
||||
"instantiation of %q0 is different in different modules">;
|
||||
|
||||
def warn_module_uses_date_time : Warning<
|
||||
"%select{precompiled header|module}0 uses __DATE__ or __TIME__">,
|
||||
InGroup<DiagGroup<"pch-date-time">>;
|
||||
|
||||
def warn_duplicate_module_file_extension : Warning<
|
||||
"duplicate module file extension block name '%0'">,
|
||||
InGroup<ModuleFileExtension>;
|
||||
|
||||
} // let CategoryName
|
||||
} // let Component
|
||||
|
||||
|
@ -126,9 +126,9 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
///
|
||||
/// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
|
||||
/// directories (foo/ and foo/bar/) here.
|
||||
SmallVector<DirectoryEntry*, 4> VirtualDirectoryEntries;
|
||||
SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries;
|
||||
/// \brief The virtual files that we have allocated.
|
||||
SmallVector<FileEntry*, 4> VirtualFileEntries;
|
||||
SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
|
||||
|
||||
/// \brief A cache that maps paths to directory entries (either real or
|
||||
/// virtual) we have looked up
|
||||
@ -218,7 +218,8 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
bool CacheFailure = true);
|
||||
|
||||
/// \brief Returns the current file system options
|
||||
const FileSystemOptions &getFileSystemOptions() { return FileSystemOpts; }
|
||||
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
|
||||
const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
|
||||
|
||||
IntrusiveRefCntPtr<vfs::FileSystem> getVirtualFileSystem() const {
|
||||
return FS;
|
||||
@ -254,7 +255,13 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
/// \brief If path is not absolute and FileSystemOptions set the working
|
||||
/// directory, the path is modified to be relative to the given
|
||||
/// working directory.
|
||||
void FixupRelativePath(SmallVectorImpl<char> &path) const;
|
||||
/// \returns true if \c path changed.
|
||||
bool FixupRelativePath(SmallVectorImpl<char> &path) const;
|
||||
|
||||
/// Makes \c Path absolute taking into account FileSystemOptions and the
|
||||
/// working directory option.
|
||||
/// \returns true if \c Path changed to absolute.
|
||||
bool makeAbsolutePath(SmallVectorImpl<char> &Path) const;
|
||||
|
||||
/// \brief Produce an array mapping from the unique IDs assigned to each
|
||||
/// file to the corresponding FileEntry pointer.
|
||||
@ -266,9 +273,6 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
static void modifyFileEntry(FileEntry *File, off_t Size,
|
||||
time_t ModificationTime);
|
||||
|
||||
/// \brief Remove any './' components from a path.
|
||||
static bool removeDotPaths(SmallVectorImpl<char> &Path);
|
||||
|
||||
/// \brief Retrieve the canonical name for a given directory.
|
||||
///
|
||||
/// This is a very expensive operation, despite its results being cached,
|
||||
|
@ -62,7 +62,7 @@ class IdentifierInfo {
|
||||
// partially) from an AST file.
|
||||
bool ChangedAfterLoad : 1; // True if identifier has changed from the
|
||||
// definition loaded from an AST file.
|
||||
bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was
|
||||
bool RevertedTokenID : 1; // True if revertTokenIDToIdentifier was
|
||||
// called.
|
||||
bool OutOfDate : 1; // True if there may be additional
|
||||
// information about this identifier
|
||||
@ -152,7 +152,7 @@ class IdentifierInfo {
|
||||
/// tokens.
|
||||
tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
|
||||
|
||||
/// \brief True if RevertTokenIDToIdentifier() was called.
|
||||
/// \brief True if revertTokenIDToIdentifier() was called.
|
||||
bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
|
||||
|
||||
/// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
|
||||
@ -161,11 +161,16 @@ class IdentifierInfo {
|
||||
/// TokenID is normally read-only but there are 2 instances where we revert it
|
||||
/// to tok::identifier for libstdc++ 4.2. Keep track of when this happens
|
||||
/// using this method so we can inform serialization about it.
|
||||
void RevertTokenIDToIdentifier() {
|
||||
void revertTokenIDToIdentifier() {
|
||||
assert(TokenID != tok::identifier && "Already at tok::identifier");
|
||||
TokenID = tok::identifier;
|
||||
RevertedTokenID = true;
|
||||
}
|
||||
void revertIdentifierToTokenID(tok::TokenKind TK) {
|
||||
assert(TokenID == tok::identifier && "Should be at tok::identifier");
|
||||
TokenID = TK;
|
||||
RevertedTokenID = false;
|
||||
}
|
||||
|
||||
/// \brief Return the preprocessor keyword ID for this identifier.
|
||||
///
|
||||
@ -183,6 +188,18 @@ class IdentifierInfo {
|
||||
}
|
||||
void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
|
||||
|
||||
/// \brief True if setNotBuiltin() was called.
|
||||
bool hasRevertedBuiltin() const {
|
||||
return ObjCOrBuiltinID == tok::NUM_OBJC_KEYWORDS;
|
||||
}
|
||||
|
||||
/// \brief Revert the identifier to a non-builtin identifier. We do this if
|
||||
/// the name of a known builtin library function is used to declare that
|
||||
/// function, but an unexpected type is specified.
|
||||
void revertBuiltin() {
|
||||
setBuiltinID(0);
|
||||
}
|
||||
|
||||
/// \brief Return a value indicating whether this is a builtin function.
|
||||
///
|
||||
/// 0 is not-built-in. 1 is builtin-for-some-nonprimary-target.
|
||||
|
@ -90,6 +90,7 @@ 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")
|
||||
LANGOPT(DeclSpecKeyword , 1, 0, "__declspec keyword")
|
||||
BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers")
|
||||
BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode")
|
||||
BENIGN_LANGOPT(GNUMode , 1, 1, "GNU extensions")
|
||||
@ -117,6 +118,7 @@ LANGOPT(Freestanding, 1, 0, "freestanding implementation")
|
||||
LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
|
||||
LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
|
||||
LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly")
|
||||
LANGOPT(Coroutines , 1, 0, "C++ coroutines")
|
||||
|
||||
BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
|
||||
LANGOPT(POSIXThreads , 1, 0, "POSIX thread support")
|
||||
@ -131,7 +133,6 @@ COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module us
|
||||
BENIGN_LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery")
|
||||
BENIGN_LANGOPT(ImplicitModules, 1, 1, "build modules that are not specified via -fmodule-file")
|
||||
COMPATIBLE_LANGOPT(ModulesLocalVisibility, 1, 0, "local submodule visibility")
|
||||
COMPATIBLE_LANGOPT(ModulesHideInternalLinkage, 1, 1, "hiding non-visible internal linkage declarations from redeclaration lookup")
|
||||
COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
|
||||
COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
|
||||
LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
|
||||
@ -146,6 +147,7 @@ COMPATIBLE_LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro")
|
||||
COMPATIBLE_LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro")
|
||||
LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro")
|
||||
LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro")
|
||||
LANGOPT(UnsafeFPMath , 1, 0, "Unsafe Floating Point Math")
|
||||
|
||||
BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars")
|
||||
|
||||
@ -166,6 +168,7 @@ LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
|
||||
LANGOPT(CUDAIsDevice , 1, 0, "Compiling for CUDA device")
|
||||
LANGOPT(CUDAAllowHostCallsFromHostDevice, 1, 0, "Allow host device functions to call host functions")
|
||||
LANGOPT(CUDADisableTargetCallChecks, 1, 0, "Disable checks for call targets (host, device, etc.)")
|
||||
LANGOPT(CUDATargetOverloads, 1, 0, "Enable function overloads based on CUDA target attributes")
|
||||
|
||||
LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators")
|
||||
LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions")
|
||||
@ -188,7 +191,8 @@ LANGOPT(DefaultFPContract , 1, 0, "FP_CONTRACT")
|
||||
LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
|
||||
LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
|
||||
LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
|
||||
LANGOPT(ObjCARCWeak , 1, 0, "__weak support in the ARC runtime")
|
||||
LANGOPT(ObjCWeakRuntime , 1, 0, "__weak support in the ARC runtime")
|
||||
LANGOPT(ObjCWeak , 1, 0, "Objective-C __weak in ARC and MRC files")
|
||||
LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime")
|
||||
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
|
||||
ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef LLVM_CLANG_BASIC_MODULE_H
|
||||
#define LLVM_CLANG_BASIC_MODULE_H
|
||||
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
@ -35,9 +36,6 @@ namespace llvm {
|
||||
|
||||
namespace clang {
|
||||
|
||||
class DirectoryEntry;
|
||||
class FileEntry;
|
||||
class FileManager;
|
||||
class LangOptions;
|
||||
class TargetInfo;
|
||||
class IdentifierInfo;
|
||||
@ -152,6 +150,9 @@ class Module {
|
||||
/// \brief Whether this module is missing a feature from \c Requirements.
|
||||
unsigned IsMissingRequirement : 1;
|
||||
|
||||
/// \brief Whether we tried and failed to load a module file for this module.
|
||||
unsigned HasIncompatibleModuleFile : 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
|
||||
@ -356,6 +357,12 @@ class Module {
|
||||
/// its top-level module.
|
||||
std::string getFullModuleName() const;
|
||||
|
||||
/// \brief Whether the full name of this module is equal to joining
|
||||
/// \p nameParts with "."s.
|
||||
///
|
||||
/// This is more efficient than getFullModuleName().
|
||||
bool fullModuleNameIs(ArrayRef<StringRef> nameParts) const;
|
||||
|
||||
/// \brief Retrieve the top-level module for this (sub)module, which may
|
||||
/// be this module.
|
||||
Module *getTopLevelModule() {
|
||||
@ -469,6 +476,13 @@ class Module {
|
||||
submodule_iterator submodule_end() { return SubModules.end(); }
|
||||
submodule_const_iterator submodule_end() const { return SubModules.end(); }
|
||||
|
||||
llvm::iterator_range<submodule_iterator> submodules() {
|
||||
return llvm::make_range(submodule_begin(), submodule_end());
|
||||
}
|
||||
llvm::iterator_range<submodule_const_iterator> submodules() const {
|
||||
return llvm::make_range(submodule_begin(), submodule_end());
|
||||
}
|
||||
|
||||
/// \brief Appends this module's list of exported modules to \p Exported.
|
||||
///
|
||||
/// This provides a subset of immediately imported modules (the ones that are
|
||||
|
@ -41,6 +41,10 @@ class ObjCRuntime {
|
||||
/// version of iOS.
|
||||
iOS,
|
||||
|
||||
/// 'watchos' is a variant of iOS for Apple's watchOS. The version
|
||||
/// is a release version of watchOS.
|
||||
WatchOS,
|
||||
|
||||
/// 'gcc' is the Objective-C runtime shipped with GCC, implementing a
|
||||
/// fragile Objective-C ABI
|
||||
GCC,
|
||||
@ -81,6 +85,7 @@ class ObjCRuntime {
|
||||
case GNUstep: return true;
|
||||
case ObjFW: return true;
|
||||
case iOS: return true;
|
||||
case WatchOS: return true;
|
||||
}
|
||||
llvm_unreachable("bad kind");
|
||||
}
|
||||
@ -114,6 +119,7 @@ class ObjCRuntime {
|
||||
case FragileMacOSX:
|
||||
case MacOSX:
|
||||
case iOS:
|
||||
case WatchOS:
|
||||
return false;
|
||||
case GCC:
|
||||
case GNUstep:
|
||||
@ -133,9 +139,12 @@ class ObjCRuntime {
|
||||
/// \brief Does this runtime allow ARC at all?
|
||||
bool allowsARC() const {
|
||||
switch (getKind()) {
|
||||
case FragileMacOSX: return false;
|
||||
case FragileMacOSX:
|
||||
// No stub library for the fragile runtime.
|
||||
return getVersion() >= VersionTuple(10, 7);
|
||||
case MacOSX: return true;
|
||||
case iOS: return true;
|
||||
case WatchOS: return true;
|
||||
case GCC: return false;
|
||||
case GNUstep: return true;
|
||||
case ObjFW: return true;
|
||||
@ -150,9 +159,10 @@ class ObjCRuntime {
|
||||
/// library.
|
||||
bool hasNativeARC() const {
|
||||
switch (getKind()) {
|
||||
case FragileMacOSX: return false;
|
||||
case FragileMacOSX: return getVersion() >= VersionTuple(10, 7);
|
||||
case MacOSX: return getVersion() >= VersionTuple(10, 7);
|
||||
case iOS: return getVersion() >= VersionTuple(5);
|
||||
case WatchOS: return true;
|
||||
|
||||
case GCC: return false;
|
||||
case GNUstep: return getVersion() >= VersionTuple(1, 6);
|
||||
@ -168,6 +178,8 @@ class ObjCRuntime {
|
||||
return getVersion() >= VersionTuple(10, 8);
|
||||
case iOS:
|
||||
return (getVersion() >= VersionTuple(6));
|
||||
case WatchOS:
|
||||
return true;
|
||||
case GNUstep:
|
||||
return getVersion() >= VersionTuple(1, 7);
|
||||
|
||||
@ -197,6 +209,7 @@ class ObjCRuntime {
|
||||
case FragileMacOSX: return false;
|
||||
case MacOSX: return getVersion() >= VersionTuple(10, 8);
|
||||
case iOS: return getVersion() >= VersionTuple(6);
|
||||
case WatchOS: return true;
|
||||
|
||||
// This is really a lie, because some implementations and versions
|
||||
// of the runtime do not support ARC. Probably -fgnu-runtime
|
||||
@ -224,6 +237,7 @@ class ObjCRuntime {
|
||||
return true;
|
||||
case MacOSX:
|
||||
case iOS:
|
||||
case WatchOS:
|
||||
case GNUstep:
|
||||
case ObjFW:
|
||||
return false;
|
||||
@ -245,6 +259,7 @@ class ObjCRuntime {
|
||||
case FragileMacOSX: return getVersion() >= VersionTuple(10, 8);
|
||||
case MacOSX: return getVersion() >= VersionTuple(10, 8);
|
||||
case iOS: return getVersion() >= VersionTuple(5);
|
||||
case WatchOS: return true;
|
||||
case GCC: return false;
|
||||
case GNUstep: return false;
|
||||
case ObjFW: return false;
|
||||
@ -257,6 +272,7 @@ class ObjCRuntime {
|
||||
switch (getKind()) {
|
||||
case MacOSX: return true;
|
||||
case iOS: return true;
|
||||
case WatchOS: return true;
|
||||
case FragileMacOSX: return false;
|
||||
case GCC: return true;
|
||||
case GNUstep: return true;
|
||||
@ -270,6 +286,7 @@ class ObjCRuntime {
|
||||
switch (getKind()) {
|
||||
case MacOSX: return true;
|
||||
case iOS: return true;
|
||||
case WatchOS: return true;
|
||||
case FragileMacOSX: return false;
|
||||
case GCC: return true;
|
||||
case GNUstep: return true;
|
||||
@ -283,6 +300,7 @@ class ObjCRuntime {
|
||||
case FragileMacOSX:
|
||||
case MacOSX:
|
||||
case iOS:
|
||||
case WatchOS:
|
||||
return true;
|
||||
case GNUstep:
|
||||
return getVersion() >= VersionTuple(1, 7);
|
||||
|
@ -26,6 +26,9 @@ OPENCLEXT(cl_khr_local_int32_extended_atomics)
|
||||
OPENCLEXT(cl_khr_byte_addressable_store)
|
||||
OPENCLEXT(cl_khr_3d_image_writes)
|
||||
|
||||
// OpenCL 2.0
|
||||
OPENCLEXT(cl_khr_gl_msaa_sharing)
|
||||
|
||||
// Clang Extensions.
|
||||
OPENCLEXT(cl_clang_storage_class_specifiers)
|
||||
|
||||
|
@ -57,9 +57,30 @@
|
||||
#ifndef OPENMP_TARGET_CLAUSE
|
||||
# define OPENMP_TARGET_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_TARGET_DATA_CLAUSE
|
||||
# define OPENMP_TARGET_DATA_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_TEAMS_CLAUSE
|
||||
# define OPENMP_TEAMS_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_CANCEL_CLAUSE
|
||||
# define OPENMP_CANCEL_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_ORDERED_CLAUSE
|
||||
# define OPENMP_ORDERED_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_TASKLOOP_CLAUSE
|
||||
# define OPENMP_TASKLOOP_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_TASKLOOP_SIMD_CLAUSE
|
||||
# define OPENMP_TASKLOOP_SIMD_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_CRITICAL_CLAUSE
|
||||
# define OPENMP_CRITICAL_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DISTRIBUTE_CLAUSE
|
||||
#define OPENMP_DISTRIBUTE_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DEFAULT_KIND
|
||||
# define OPENMP_DEFAULT_KIND(Name)
|
||||
#endif
|
||||
@ -69,9 +90,18 @@
|
||||
#ifndef OPENMP_SCHEDULE_KIND
|
||||
#define OPENMP_SCHEDULE_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_SCHEDULE_MODIFIER
|
||||
#define OPENMP_SCHEDULE_MODIFIER(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DEPEND_KIND
|
||||
#define OPENMP_DEPEND_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_LINEAR_KIND
|
||||
#define OPENMP_LINEAR_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_MAP_KIND
|
||||
#define OPENMP_MAP_KIND(Name)
|
||||
#endif
|
||||
|
||||
// OpenMP directives.
|
||||
OPENMP_DIRECTIVE(threadprivate)
|
||||
@ -94,17 +124,22 @@ OPENMP_DIRECTIVE(atomic)
|
||||
OPENMP_DIRECTIVE(target)
|
||||
OPENMP_DIRECTIVE(teams)
|
||||
OPENMP_DIRECTIVE(cancel)
|
||||
OPENMP_DIRECTIVE_EXT(target_data, "target data")
|
||||
OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for")
|
||||
OPENMP_DIRECTIVE_EXT(parallel_for_simd, "parallel for simd")
|
||||
OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
|
||||
OPENMP_DIRECTIVE_EXT(for_simd, "for simd")
|
||||
OPENMP_DIRECTIVE_EXT(cancellation_point, "cancellation point")
|
||||
OPENMP_DIRECTIVE(taskloop)
|
||||
OPENMP_DIRECTIVE_EXT(taskloop_simd, "taskloop simd")
|
||||
OPENMP_DIRECTIVE(distribute)
|
||||
|
||||
// OpenMP clauses.
|
||||
OPENMP_CLAUSE(if, OMPIfClause)
|
||||
OPENMP_CLAUSE(final, OMPFinalClause)
|
||||
OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
|
||||
OPENMP_CLAUSE(safelen, OMPSafelenClause)
|
||||
OPENMP_CLAUSE(simdlen, OMPSimdlenClause)
|
||||
OPENMP_CLAUSE(collapse, OMPCollapseClause)
|
||||
OPENMP_CLAUSE(default, OMPDefaultClause)
|
||||
OPENMP_CLAUSE(private, OMPPrivateClause)
|
||||
@ -129,6 +164,17 @@ OPENMP_CLAUSE(update, OMPUpdateClause)
|
||||
OPENMP_CLAUSE(capture, OMPCaptureClause)
|
||||
OPENMP_CLAUSE(seq_cst, OMPSeqCstClause)
|
||||
OPENMP_CLAUSE(depend, OMPDependClause)
|
||||
OPENMP_CLAUSE(device, OMPDeviceClause)
|
||||
OPENMP_CLAUSE(threads, OMPThreadsClause)
|
||||
OPENMP_CLAUSE(simd, OMPSIMDClause)
|
||||
OPENMP_CLAUSE(map, OMPMapClause)
|
||||
OPENMP_CLAUSE(num_teams, OMPNumTeamsClause)
|
||||
OPENMP_CLAUSE(thread_limit, OMPThreadLimitClause)
|
||||
OPENMP_CLAUSE(priority, OMPPriorityClause)
|
||||
OPENMP_CLAUSE(grainsize, OMPGrainsizeClause)
|
||||
OPENMP_CLAUSE(nogroup, OMPNogroupClause)
|
||||
OPENMP_CLAUSE(num_tasks, OMPNumTasksClause)
|
||||
OPENMP_CLAUSE(hint, OMPHintClause)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel'.
|
||||
OPENMP_PARALLEL_CLAUSE(if)
|
||||
@ -147,6 +193,7 @@ OPENMP_SIMD_CLAUSE(lastprivate)
|
||||
OPENMP_SIMD_CLAUSE(linear)
|
||||
OPENMP_SIMD_CLAUSE(aligned)
|
||||
OPENMP_SIMD_CLAUSE(safelen)
|
||||
OPENMP_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_SIMD_CLAUSE(collapse)
|
||||
OPENMP_SIMD_CLAUSE(reduction)
|
||||
|
||||
@ -159,6 +206,7 @@ OPENMP_FOR_CLAUSE(collapse)
|
||||
OPENMP_FOR_CLAUSE(schedule)
|
||||
OPENMP_FOR_CLAUSE(ordered)
|
||||
OPENMP_FOR_CLAUSE(nowait)
|
||||
OPENMP_FOR_CLAUSE(linear)
|
||||
|
||||
// Clauses allowed for directive 'omp for simd'.
|
||||
OPENMP_FOR_SIMD_CLAUSE(private)
|
||||
@ -169,6 +217,7 @@ OPENMP_FOR_SIMD_CLAUSE(schedule)
|
||||
OPENMP_FOR_SIMD_CLAUSE(collapse)
|
||||
OPENMP_FOR_SIMD_CLAUSE(nowait)
|
||||
OPENMP_FOR_SIMD_CLAUSE(safelen)
|
||||
OPENMP_FOR_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_FOR_SIMD_CLAUSE(linear)
|
||||
OPENMP_FOR_SIMD_CLAUSE(aligned)
|
||||
|
||||
@ -185,6 +234,9 @@ OPENMP_SINGLE_CLAUSE(firstprivate)
|
||||
OPENMP_SINGLE_CLAUSE(copyprivate)
|
||||
OPENMP_SINGLE_CLAUSE(nowait)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'cancel'.
|
||||
OPENMP_CANCEL_CLAUSE(if)
|
||||
|
||||
// Static attributes for 'default' clause.
|
||||
OPENMP_DEFAULT_KIND(none)
|
||||
OPENMP_DEFAULT_KIND(shared)
|
||||
@ -201,10 +253,22 @@ OPENMP_SCHEDULE_KIND(guided)
|
||||
OPENMP_SCHEDULE_KIND(auto)
|
||||
OPENMP_SCHEDULE_KIND(runtime)
|
||||
|
||||
// Modifiers for 'schedule' clause.
|
||||
OPENMP_SCHEDULE_MODIFIER(monotonic)
|
||||
OPENMP_SCHEDULE_MODIFIER(nonmonotonic)
|
||||
OPENMP_SCHEDULE_MODIFIER(simd)
|
||||
|
||||
// Static attributes for 'depend' clause.
|
||||
OPENMP_DEPEND_KIND(in)
|
||||
OPENMP_DEPEND_KIND(out)
|
||||
OPENMP_DEPEND_KIND(inout)
|
||||
OPENMP_DEPEND_KIND(source)
|
||||
OPENMP_DEPEND_KIND(sink)
|
||||
|
||||
// Modifiers for 'linear' clause.
|
||||
OPENMP_LINEAR_KIND(val)
|
||||
OPENMP_LINEAR_KIND(ref)
|
||||
OPENMP_LINEAR_KIND(uval)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel for'.
|
||||
OPENMP_PARALLEL_FOR_CLAUSE(if)
|
||||
@ -220,6 +284,7 @@ OPENMP_PARALLEL_FOR_CLAUSE(lastprivate)
|
||||
OPENMP_PARALLEL_FOR_CLAUSE(collapse)
|
||||
OPENMP_PARALLEL_FOR_CLAUSE(schedule)
|
||||
OPENMP_PARALLEL_FOR_CLAUSE(ordered)
|
||||
OPENMP_PARALLEL_FOR_CLAUSE(linear)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel for simd'.
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(if)
|
||||
@ -235,6 +300,7 @@ OPENMP_PARALLEL_FOR_SIMD_CLAUSE(lastprivate)
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(collapse)
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(schedule)
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(safelen)
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(linear)
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(aligned)
|
||||
|
||||
@ -260,6 +326,7 @@ OPENMP_TASK_CLAUSE(shared)
|
||||
OPENMP_TASK_CLAUSE(untied)
|
||||
OPENMP_TASK_CLAUSE(mergeable)
|
||||
OPENMP_TASK_CLAUSE(depend)
|
||||
OPENMP_TASK_CLAUSE(priority)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'atomic'.
|
||||
OPENMP_ATOMIC_CLAUSE(read)
|
||||
@ -271,6 +338,14 @@ OPENMP_ATOMIC_CLAUSE(seq_cst)
|
||||
// Clauses allowed for OpenMP directive 'target'.
|
||||
// TODO More clauses for 'target' directive.
|
||||
OPENMP_TARGET_CLAUSE(if)
|
||||
OPENMP_TARGET_CLAUSE(device)
|
||||
OPENMP_TARGET_CLAUSE(map)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'target data'.
|
||||
// TODO More clauses for 'target data' directive.
|
||||
OPENMP_TARGET_DATA_CLAUSE(if)
|
||||
OPENMP_TARGET_DATA_CLAUSE(device)
|
||||
OPENMP_TARGET_DATA_CLAUSE(map)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'teams'.
|
||||
// TODO More clauses for 'teams' directive.
|
||||
@ -279,14 +354,83 @@ OPENMP_TEAMS_CLAUSE(private)
|
||||
OPENMP_TEAMS_CLAUSE(firstprivate)
|
||||
OPENMP_TEAMS_CLAUSE(shared)
|
||||
OPENMP_TEAMS_CLAUSE(reduction)
|
||||
OPENMP_TEAMS_CLAUSE(num_teams)
|
||||
OPENMP_TEAMS_CLAUSE(thread_limit)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'ordered'.
|
||||
// TODO More clauses for 'ordered' directive.
|
||||
OPENMP_ORDERED_CLAUSE(threads)
|
||||
OPENMP_ORDERED_CLAUSE(simd)
|
||||
OPENMP_ORDERED_CLAUSE(depend)
|
||||
|
||||
// Map types and map type modifier for 'map' clause.
|
||||
OPENMP_MAP_KIND(alloc)
|
||||
OPENMP_MAP_KIND(to)
|
||||
OPENMP_MAP_KIND(from)
|
||||
OPENMP_MAP_KIND(tofrom)
|
||||
OPENMP_MAP_KIND(delete)
|
||||
OPENMP_MAP_KIND(release)
|
||||
OPENMP_MAP_KIND(always)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'taskloop'.
|
||||
OPENMP_TASKLOOP_CLAUSE(if)
|
||||
OPENMP_TASKLOOP_CLAUSE(shared)
|
||||
OPENMP_TASKLOOP_CLAUSE(private)
|
||||
OPENMP_TASKLOOP_CLAUSE(firstprivate)
|
||||
OPENMP_TASKLOOP_CLAUSE(lastprivate)
|
||||
OPENMP_TASKLOOP_CLAUSE(default)
|
||||
OPENMP_TASKLOOP_CLAUSE(collapse)
|
||||
OPENMP_TASKLOOP_CLAUSE(final)
|
||||
OPENMP_TASKLOOP_CLAUSE(untied)
|
||||
OPENMP_TASKLOOP_CLAUSE(mergeable)
|
||||
OPENMP_TASKLOOP_CLAUSE(priority)
|
||||
OPENMP_TASKLOOP_CLAUSE(grainsize)
|
||||
OPENMP_TASKLOOP_CLAUSE(nogroup)
|
||||
OPENMP_TASKLOOP_CLAUSE(num_tasks)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'taskloop simd'.
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(if)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(shared)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(private)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(firstprivate)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(lastprivate)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(default)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(collapse)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(final)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(untied)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(mergeable)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(priority)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(linear)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(aligned)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(safelen)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(grainsize)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(nogroup)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'critical'.
|
||||
OPENMP_CRITICAL_CLAUSE(hint)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'distribute'
|
||||
OPENMP_DISTRIBUTE_CLAUSE(private)
|
||||
OPENMP_DISTRIBUTE_CLAUSE(firstprivate)
|
||||
OPENMP_DISTRIBUTE_CLAUSE(lastprivate)
|
||||
OPENMP_DISTRIBUTE_CLAUSE(collapse)
|
||||
|
||||
#undef OPENMP_TASKLOOP_SIMD_CLAUSE
|
||||
#undef OPENMP_TASKLOOP_CLAUSE
|
||||
#undef OPENMP_LINEAR_KIND
|
||||
#undef OPENMP_DEPEND_KIND
|
||||
#undef OPENMP_SCHEDULE_MODIFIER
|
||||
#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_CRITICAL_CLAUSE
|
||||
#undef OPENMP_ORDERED_CLAUSE
|
||||
#undef OPENMP_CANCEL_CLAUSE
|
||||
#undef OPENMP_SINGLE_CLAUSE
|
||||
#undef OPENMP_SECTIONS_CLAUSE
|
||||
#undef OPENMP_PARALLEL_CLAUSE
|
||||
@ -296,8 +440,10 @@ OPENMP_TEAMS_CLAUSE(reduction)
|
||||
#undef OPENMP_TASK_CLAUSE
|
||||
#undef OPENMP_ATOMIC_CLAUSE
|
||||
#undef OPENMP_TARGET_CLAUSE
|
||||
#undef OPENMP_TARGET_DATA_CLAUSE
|
||||
#undef OPENMP_TEAMS_CLAUSE
|
||||
#undef OPENMP_SIMD_CLAUSE
|
||||
#undef OPENMP_FOR_CLAUSE
|
||||
#undef OPENMP_FOR_SIMD_CLAUSE
|
||||
|
||||
#undef OPENMP_MAP_KIND
|
||||
#undef OPENMP_DISTRIBUTE_CLAUSE
|
||||
|
@ -62,6 +62,15 @@ enum OpenMPScheduleClauseKind {
|
||||
OMPC_SCHEDULE_unknown
|
||||
};
|
||||
|
||||
/// \brief OpenMP modifiers for 'schedule' clause.
|
||||
enum OpenMPScheduleClauseModifier {
|
||||
OMPC_SCHEDULE_MODIFIER_unknown = OMPC_SCHEDULE_unknown,
|
||||
#define OPENMP_SCHEDULE_MODIFIER(Name) \
|
||||
OMPC_SCHEDULE_MODIFIER_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_SCHEDULE_MODIFIER_last
|
||||
};
|
||||
|
||||
/// \brief OpenMP attributes for 'depend' clause.
|
||||
enum OpenMPDependClauseKind {
|
||||
#define OPENMP_DEPEND_KIND(Name) \
|
||||
@ -70,6 +79,22 @@ enum OpenMPDependClauseKind {
|
||||
OMPC_DEPEND_unknown
|
||||
};
|
||||
|
||||
/// \brief OpenMP attributes for 'linear' clause.
|
||||
enum OpenMPLinearClauseKind {
|
||||
#define OPENMP_LINEAR_KIND(Name) \
|
||||
OMPC_LINEAR_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_LINEAR_unknown
|
||||
};
|
||||
|
||||
/// \brief OpenMP mapping kind for 'map' clause.
|
||||
enum OpenMPMapClauseKind {
|
||||
#define OPENMP_MAP_KIND(Name) \
|
||||
OMPC_MAP_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_MAP_unknown
|
||||
};
|
||||
|
||||
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
|
||||
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
|
||||
|
||||
@ -95,12 +120,24 @@ bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind);
|
||||
/// otherwise - false.
|
||||
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind);
|
||||
|
||||
/// \brief Checks if the specified directive is a taskloop directive.
|
||||
/// \param DKind Specified directive.
|
||||
/// \return true - the directive is a worksharing directive like 'omp taskloop',
|
||||
/// otherwise - false.
|
||||
bool isOpenMPTaskLoopDirective(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 target-kind directive.
|
||||
/// \param DKind Specified directive.
|
||||
/// \return true - the directive is a target-like directive like 'omp target',
|
||||
/// otherwise - false.
|
||||
bool isOpenMPTargetDirective(OpenMPDirectiveKind DKind);
|
||||
|
||||
/// \brief Checks if the specified directive is a teams-kind directive.
|
||||
/// \param DKind Specified directive.
|
||||
/// \return true - the directive is a teams-like directive like 'omp teams',
|
||||
@ -113,6 +150,13 @@ bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind);
|
||||
/// otherwise - false.
|
||||
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind);
|
||||
|
||||
/// \brief Checks if the specified directive is a distribute directive.
|
||||
/// \param DKind Specified directive.
|
||||
/// \return true - the directive is a distribute-directive like 'omp
|
||||
/// distribute',
|
||||
/// otherwise - false.
|
||||
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind);
|
||||
|
||||
/// \brief Checks if the specified clause is one of private clauses like
|
||||
/// 'private', 'firstprivate', 'reduction' etc..
|
||||
/// \param Kind Clause kind.
|
||||
|
@ -101,6 +101,7 @@ OVERLOADED_OPERATOR_MULTI(Subscript , "[]" , false, t
|
||||
// ?: can *not* be overloaded, but we need the overload
|
||||
// resolution machinery for it.
|
||||
OVERLOADED_OPERATOR_MULTI(Conditional , "?" , false, true , false)
|
||||
OVERLOADED_OPERATOR(Coawait , "co_await", kw_co_await , true , false, false)
|
||||
|
||||
#undef OVERLOADED_OPERATOR_MULTI
|
||||
#undef OVERLOADED_OPERATOR
|
||||
|
@ -377,7 +377,7 @@ class PartialDiagnostic {
|
||||
}
|
||||
|
||||
friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
||||
const SourceRange &R) {
|
||||
SourceRange R) {
|
||||
PD.AddSourceRange(CharSourceRange::getTokenRange(R));
|
||||
return PD;
|
||||
}
|
||||
|
@ -84,11 +84,13 @@ SANITIZER("dataflow", DataFlow)
|
||||
// Control Flow Integrity
|
||||
SANITIZER("cfi-cast-strict", CFICastStrict)
|
||||
SANITIZER("cfi-derived-cast", CFIDerivedCast)
|
||||
SANITIZER("cfi-icall", CFIICall)
|
||||
SANITIZER("cfi-unrelated-cast", CFIUnrelatedCast)
|
||||
SANITIZER("cfi-nvcall", CFINVCall)
|
||||
SANITIZER("cfi-vcall", CFIVCall)
|
||||
SANITIZER_GROUP("cfi", CFI,
|
||||
CFIDerivedCast | CFIUnrelatedCast | CFINVCall | CFIVCall)
|
||||
CFIDerivedCast | CFIICall | CFIUnrelatedCast | CFINVCall |
|
||||
CFIVCall)
|
||||
|
||||
// Safe Stack
|
||||
SANITIZER("safe-stack", SafeStack)
|
||||
|
@ -43,6 +43,7 @@ class FileID {
|
||||
public:
|
||||
FileID() : ID(0) {}
|
||||
|
||||
bool isValid() const { return ID != 0; }
|
||||
bool isInvalid() const { return ID == 0; }
|
||||
|
||||
bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
|
||||
@ -252,7 +253,7 @@ class CharSourceRange {
|
||||
|
||||
SourceLocation getBegin() const { return Range.getBegin(); }
|
||||
SourceLocation getEnd() const { return Range.getEnd(); }
|
||||
const SourceRange &getAsRange() const { return Range; }
|
||||
SourceRange getAsRange() const { return Range; }
|
||||
|
||||
void setBegin(SourceLocation b) { Range.setBegin(b); }
|
||||
void setEnd(SourceLocation e) { Range.setEnd(e); }
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
@ -121,7 +122,7 @@ namespace SrcMgr {
|
||||
/// \brief The number of lines in this ContentCache.
|
||||
///
|
||||
/// This is only valid if SourceLineCache is non-null.
|
||||
unsigned NumLines : 31;
|
||||
unsigned NumLines;
|
||||
|
||||
/// \brief Indicates whether the buffer itself was provided to override
|
||||
/// the actual file contents.
|
||||
@ -134,12 +135,17 @@ namespace SrcMgr {
|
||||
/// file considered as a system one.
|
||||
unsigned IsSystemFile : 1;
|
||||
|
||||
/// \brief True if this file may be transient, that is, if it might not
|
||||
/// exist at some later point in time when this content entry is used,
|
||||
/// after serialization and deserialization.
|
||||
unsigned IsTransient : 1;
|
||||
|
||||
ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {}
|
||||
|
||||
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
|
||||
: Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
|
||||
SourceLineCache(nullptr), NumLines(0), BufferOverridden(false),
|
||||
IsSystemFile(false) {}
|
||||
IsSystemFile(false), IsTransient(false) {}
|
||||
|
||||
~ContentCache();
|
||||
|
||||
@ -148,7 +154,7 @@ namespace SrcMgr {
|
||||
/// is not transferred, so this is a logical error.
|
||||
ContentCache(const ContentCache &RHS)
|
||||
: Buffer(nullptr, false), SourceLineCache(nullptr),
|
||||
BufferOverridden(false), IsSystemFile(false) {
|
||||
BufferOverridden(false), IsSystemFile(false), IsTransient(false) {
|
||||
OrigEntry = RHS.OrigEntry;
|
||||
ContentsEntry = RHS.ContentsEntry;
|
||||
|
||||
@ -388,15 +394,16 @@ namespace SrcMgr {
|
||||
/// SourceManager keeps an array of these objects, and they are uniquely
|
||||
/// identified by the FileID datatype.
|
||||
class SLocEntry {
|
||||
unsigned Offset; // low bit is set for expansion info.
|
||||
unsigned Offset : 31;
|
||||
unsigned IsExpansion : 1;
|
||||
union {
|
||||
FileInfo File;
|
||||
ExpansionInfo Expansion;
|
||||
};
|
||||
public:
|
||||
unsigned getOffset() const { return Offset >> 1; }
|
||||
unsigned getOffset() const { return Offset; }
|
||||
|
||||
bool isExpansion() const { return Offset & 1; }
|
||||
bool isExpansion() const { return IsExpansion; }
|
||||
bool isFile() const { return !isExpansion(); }
|
||||
|
||||
const FileInfo &getFile() const {
|
||||
@ -410,15 +417,19 @@ namespace SrcMgr {
|
||||
}
|
||||
|
||||
static SLocEntry get(unsigned Offset, const FileInfo &FI) {
|
||||
assert(!(Offset & (1 << 31)) && "Offset is too large");
|
||||
SLocEntry E;
|
||||
E.Offset = Offset << 1;
|
||||
E.Offset = Offset;
|
||||
E.IsExpansion = false;
|
||||
E.File = FI;
|
||||
return E;
|
||||
}
|
||||
|
||||
static SLocEntry get(unsigned Offset, const ExpansionInfo &Expansion) {
|
||||
assert(!(Offset & (1 << 31)) && "Offset is too large");
|
||||
SLocEntry E;
|
||||
E.Offset = (Offset << 1) | 1;
|
||||
E.Offset = Offset;
|
||||
E.IsExpansion = true;
|
||||
E.Expansion = Expansion;
|
||||
return E;
|
||||
}
|
||||
@ -560,6 +571,11 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
/// (likely to change while trying to use them). Defaults to false.
|
||||
bool UserFilesAreVolatile;
|
||||
|
||||
/// \brief True if all files read during this compilation should be treated
|
||||
/// as transient (may not be present in later compilations using a module
|
||||
/// file created from this compilation). Defaults to false.
|
||||
bool FilesAreTransient;
|
||||
|
||||
struct OverriddenFilesInfoTy {
|
||||
/// \brief Files that have been overridden with the contents from another
|
||||
/// file.
|
||||
@ -615,7 +631,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
/// have already been loaded from the external source.
|
||||
///
|
||||
/// Same indexing as LoadedSLocEntryTable.
|
||||
std::vector<bool> SLocEntryLoaded;
|
||||
llvm::BitVector SLocEntryLoaded;
|
||||
|
||||
/// \brief An external source for source location entries.
|
||||
ExternalSLocEntrySource *ExternalSLocEntries;
|
||||
@ -851,6 +867,15 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
/// This should be called before parsing has begun.
|
||||
void disableFileContentsOverride(const FileEntry *File);
|
||||
|
||||
/// \brief Specify that a file is transient.
|
||||
void setFileIsTransient(const FileEntry *SourceFile);
|
||||
|
||||
/// \brief Specify that all files that are read during this compilation are
|
||||
/// transient.
|
||||
void setAllFilesAreTransient(bool Transient) {
|
||||
FilesAreTransient = Transient;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// FileID manipulation methods.
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -1139,10 +1164,14 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
/// \brief Tests whether the given source location represents a macro
|
||||
/// argument's expansion into the function-like macro definition.
|
||||
///
|
||||
/// \param StartLoc If non-null and function returns true, it is set to the
|
||||
/// start location of the macro argument expansion.
|
||||
///
|
||||
/// Such source locations only appear inside of the expansion
|
||||
/// locations representing where a particular function-like macro was
|
||||
/// expanded.
|
||||
bool isMacroArgExpansion(SourceLocation Loc) const;
|
||||
bool isMacroArgExpansion(SourceLocation Loc,
|
||||
SourceLocation *StartLoc = nullptr) const;
|
||||
|
||||
/// \brief Tests whether the given source location represents the expansion of
|
||||
/// a macro body.
|
||||
@ -1463,6 +1492,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
///
|
||||
void PrintStats() const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
/// \brief Get the number of local SLocEntries we have.
|
||||
unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); }
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace clang {
|
||||
/// \brief Specifies the width of a type, e.g., short, long, or long long.
|
||||
@ -64,6 +65,7 @@ namespace clang {
|
||||
TST_underlyingType, // __underlying_type for C++11
|
||||
TST_auto, // C++11 auto
|
||||
TST_decltype_auto, // C++1y decltype(auto)
|
||||
TST_auto_type, // __auto_type extension
|
||||
TST_unknown_anytype, // __unknown_anytype extension
|
||||
TST_atomic, // C11 _Atomic
|
||||
TST_error // erroneous type
|
||||
@ -156,6 +158,24 @@ namespace clang {
|
||||
return Kind != TSK_Undeclared && Kind != TSK_ExplicitSpecialization;
|
||||
}
|
||||
|
||||
/// \brief True if this template specialization kind is an explicit
|
||||
/// specialization, explicit instantiation declaration, or explicit
|
||||
/// instantiation definition.
|
||||
inline bool isTemplateExplicitInstantiationOrSpecialization(
|
||||
TemplateSpecializationKind Kind) {
|
||||
switch (Kind) {
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return true;
|
||||
|
||||
case TSK_Undeclared:
|
||||
case TSK_ImplicitInstantiation:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("bad template specialization kind");
|
||||
}
|
||||
|
||||
/// \brief Thread storage-class-specifier.
|
||||
enum ThreadStorageClassSpecifier {
|
||||
TSCS_unspecified,
|
||||
@ -178,7 +198,6 @@ namespace clang {
|
||||
SC_PrivateExtern,
|
||||
|
||||
// These are only legal on variables.
|
||||
SC_OpenCLWorkGroupLocal,
|
||||
SC_Auto,
|
||||
SC_Register
|
||||
};
|
||||
|
@ -48,6 +48,10 @@ def CXXCatchStmt : Stmt;
|
||||
def CXXTryStmt : Stmt;
|
||||
def CXXForRangeStmt : Stmt;
|
||||
|
||||
// C++ Coroutines TS statements
|
||||
def CoroutineBodyStmt : Stmt;
|
||||
def CoreturnStmt : Stmt;
|
||||
|
||||
// Expressions
|
||||
def Expr : Stmt<1>;
|
||||
def PredefinedExpr : DStmt<Expr>;
|
||||
@ -62,6 +66,7 @@ def UnaryOperator : DStmt<Expr>;
|
||||
def OffsetOfExpr : DStmt<Expr>;
|
||||
def UnaryExprOrTypeTraitExpr : DStmt<Expr>;
|
||||
def ArraySubscriptExpr : DStmt<Expr>;
|
||||
def OMPArraySectionExpr : DStmt<Expr>;
|
||||
def CallExpr : DStmt<Expr>;
|
||||
def MemberExpr : DStmt<Expr>;
|
||||
def CastExpr : DStmt<Expr, 1>;
|
||||
@ -139,6 +144,11 @@ def MaterializeTemporaryExpr : DStmt<Expr>;
|
||||
def LambdaExpr : DStmt<Expr>;
|
||||
def CXXFoldExpr : DStmt<Expr>;
|
||||
|
||||
// C++ Coroutines TS expressions
|
||||
def CoroutineSuspendExpr : DStmt<Expr, 1>;
|
||||
def CoawaitExpr : DStmt<CoroutineSuspendExpr>;
|
||||
def CoyieldExpr : DStmt<CoroutineSuspendExpr>;
|
||||
|
||||
// Obj-C Expressions.
|
||||
def ObjCStringLiteral : DStmt<Expr>;
|
||||
def ObjCBoxedExpr : DStmt<Expr>;
|
||||
@ -170,6 +180,7 @@ def TypoExpr : DStmt<Expr>;
|
||||
|
||||
// Microsoft Extensions.
|
||||
def MSPropertyRefExpr : DStmt<Expr>;
|
||||
def MSPropertySubscriptExpr : DStmt<Expr>;
|
||||
def CXXUuidofExpr : DStmt<Expr>;
|
||||
def SEHTryStmt : Stmt;
|
||||
def SEHExceptStmt : Stmt;
|
||||
@ -204,6 +215,10 @@ def OMPFlushDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPOrderedDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPAtomicDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetDataDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTeamsDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPCancellationPointDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPCancelDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTaskLoopDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTaskLoopSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPDistributeDirective : DStmt<OMPLoopDirective>;
|
||||
|
@ -185,6 +185,17 @@ namespace clang {
|
||||
LastTSBuiltin
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief WebAssembly builtins
|
||||
namespace WebAssembly {
|
||||
enum {
|
||||
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
|
||||
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
|
||||
#include "clang/Basic/BuiltinsWebAssembly.def"
|
||||
LastTSBuiltin
|
||||
};
|
||||
}
|
||||
|
||||
} // end namespace clang.
|
||||
|
||||
#endif
|
||||
|
@ -71,6 +71,11 @@ class TargetCXXABI {
|
||||
/// /help/topic/com.arm.doc.ihi0059a/IHI0059A_cppabi64.pdf
|
||||
iOS64,
|
||||
|
||||
/// WatchOS is a modernisation of the iOS ABI, which roughly means it's
|
||||
/// the iOS64 ABI ported to 32-bits. The primary difference from iOS64 is
|
||||
/// that RTTI objects must still be unique at the moment.
|
||||
WatchOS,
|
||||
|
||||
/// The generic AArch64 ABI is also a modified version of the Itanium ABI,
|
||||
/// but it has fewer divergences than the 32-bit ARM ABI.
|
||||
///
|
||||
@ -85,6 +90,21 @@ class TargetCXXABI {
|
||||
/// - representation of member function pointers adjusted as in ARM.
|
||||
GenericMIPS,
|
||||
|
||||
/// The WebAssembly ABI is a modified version of the Itanium ABI.
|
||||
///
|
||||
/// The changes from the Itanium ABI are:
|
||||
/// - representation of member function pointers is adjusted, as in ARM;
|
||||
/// - member functions are not specially aligned;
|
||||
/// - constructors and destructors return 'this', as in ARM;
|
||||
/// - guard variables are 32-bit on wasm32, as in ARM;
|
||||
/// - unused bits of guard variables are reserved, as in ARM;
|
||||
/// - inline functions are never key functions, as in ARM;
|
||||
/// - C++11 POD rules are used for tail padding, as in iOS64.
|
||||
///
|
||||
/// TODO: At present the WebAssembly ABI is not considered stable, so none
|
||||
/// of these details is necessarily final yet.
|
||||
WebAssembly,
|
||||
|
||||
/// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and
|
||||
/// compatible compilers).
|
||||
///
|
||||
@ -120,7 +140,9 @@ class TargetCXXABI {
|
||||
case GenericARM:
|
||||
case iOS:
|
||||
case iOS64:
|
||||
case WatchOS:
|
||||
case GenericMIPS:
|
||||
case WebAssembly:
|
||||
return true;
|
||||
|
||||
case Microsoft:
|
||||
@ -137,7 +159,9 @@ class TargetCXXABI {
|
||||
case GenericARM:
|
||||
case iOS:
|
||||
case iOS64:
|
||||
case WatchOS:
|
||||
case GenericMIPS:
|
||||
case WebAssembly:
|
||||
return false;
|
||||
|
||||
case Microsoft:
|
||||
@ -146,6 +170,36 @@ class TargetCXXABI {
|
||||
llvm_unreachable("bad ABI kind");
|
||||
}
|
||||
|
||||
/// \brief Are member functions differently aligned?
|
||||
///
|
||||
/// Many Itanium-style C++ ABIs require member functions to be aligned, so
|
||||
/// that a pointer to such a function is guaranteed to have a zero in the
|
||||
/// least significant bit, so that pointers to member functions can use that
|
||||
/// bit to distinguish between virtual and non-virtual functions. However,
|
||||
/// some Itanium-style C++ ABIs differentiate between virtual and non-virtual
|
||||
/// functions via other means, and consequently don't require that member
|
||||
/// functions be aligned.
|
||||
bool areMemberFunctionsAligned() const {
|
||||
switch (getKind()) {
|
||||
case WebAssembly:
|
||||
// WebAssembly doesn't require any special alignment for member functions.
|
||||
return false;
|
||||
case GenericARM:
|
||||
case GenericAArch64:
|
||||
case GenericMIPS:
|
||||
// TODO: ARM-style pointers to member functions put the discriminator in
|
||||
// the this adjustment, so they don't require functions to have any
|
||||
// special alignment and could therefore also return false.
|
||||
case GenericItanium:
|
||||
case iOS:
|
||||
case iOS64:
|
||||
case WatchOS:
|
||||
case Microsoft:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("bad ABI kind");
|
||||
}
|
||||
|
||||
/// \brief Is the default C++ member function calling convention
|
||||
/// the same as the default calling convention?
|
||||
bool isMemberFunctionCCDefault() const {
|
||||
@ -214,6 +268,8 @@ class TargetCXXABI {
|
||||
switch (getKind()) {
|
||||
case GenericARM:
|
||||
case iOS64:
|
||||
case WebAssembly:
|
||||
case WatchOS:
|
||||
return false;
|
||||
|
||||
case GenericAArch64:
|
||||
@ -261,7 +317,7 @@ class TargetCXXABI {
|
||||
switch (getKind()) {
|
||||
// To preserve binary compatibility, the generic Itanium ABI has
|
||||
// permanently locked the definition of POD to the rules of C++ TR1,
|
||||
// and that trickles down to all the derived ABIs.
|
||||
// and that trickles down to derived ABIs.
|
||||
case GenericItanium:
|
||||
case GenericAArch64:
|
||||
case GenericARM:
|
||||
@ -269,9 +325,11 @@ class TargetCXXABI {
|
||||
case GenericMIPS:
|
||||
return UseTailPaddingUnlessPOD03;
|
||||
|
||||
// iOS on ARM64 uses the C++11 POD rules. It does not honor the
|
||||
// Itanium exception about classes with over-large bitfields.
|
||||
// iOS on ARM64 and WebAssembly use the C++11 POD rules. They do not honor
|
||||
// the Itanium exception about classes with over-large bitfields.
|
||||
case iOS64:
|
||||
case WebAssembly:
|
||||
case WatchOS:
|
||||
return UseTailPaddingUnlessPOD11;
|
||||
|
||||
// MSVC always allocates fields in the tail-padding of a base class
|
||||
@ -282,9 +340,6 @@ class TargetCXXABI {
|
||||
llvm_unreachable("bad ABI kind");
|
||||
}
|
||||
|
||||
/// Try to parse an ABI name, returning false on error.
|
||||
bool tryParse(llvm::StringRef name);
|
||||
|
||||
friend bool operator==(const TargetCXXABI &left, const TargetCXXABI &right) {
|
||||
return left.getKind() == right.getKind();
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "clang/Basic/TargetOptions.h"
|
||||
#include "clang/Basic/VersionTuple.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
@ -72,7 +74,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
unsigned short MaxVectorAlign;
|
||||
unsigned short MaxTLSAlign;
|
||||
unsigned short SimdDefaultAlign;
|
||||
const char *DescriptionString;
|
||||
const char *DataLayoutString;
|
||||
const char *UserLabelPrefix;
|
||||
const char *MCountName;
|
||||
const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat,
|
||||
@ -88,6 +90,8 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
unsigned RealTypeUsesObjCFPRet : 3;
|
||||
unsigned ComplexLongDoubleUsesFP2Ret : 1;
|
||||
|
||||
unsigned HasBuiltinMSVaList : 1;
|
||||
|
||||
// TargetInfo Constructor. Default initializes all fields.
|
||||
TargetInfo(const llvm::Triple &T);
|
||||
|
||||
@ -104,9 +108,9 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
virtual ~TargetInfo();
|
||||
|
||||
/// \brief Retrieve the target options.
|
||||
TargetOptions &getTargetOpts() const {
|
||||
TargetOptions &getTargetOpts() const {
|
||||
assert(TargetOpts && "Missing target options");
|
||||
return *TargetOpts;
|
||||
return *TargetOpts;
|
||||
}
|
||||
|
||||
///===---- Target Data Type Query Methods -------------------------------===//
|
||||
@ -253,10 +257,11 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
unsigned getTypeWidth(IntType T) const;
|
||||
|
||||
/// \brief Return integer type with specified width.
|
||||
IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
|
||||
virtual 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;
|
||||
virtual IntType getLeastIntTypeByWidth(unsigned BitWidth,
|
||||
bool IsSigned) const;
|
||||
|
||||
/// \brief Return floating point type with specified width.
|
||||
RealType getRealTypeByWidth(unsigned BitWidth) const;
|
||||
@ -311,7 +316,9 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
unsigned getLongLongAlign() const { return LongLongAlign; }
|
||||
|
||||
/// \brief Determine whether the __int128 type is supported on this target.
|
||||
virtual 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.
|
||||
@ -509,8 +516,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
/// Return information about target-specific builtins for
|
||||
/// the current primary target, and info about which builtins are non-portable
|
||||
/// across the current set of primary and secondary targets.
|
||||
virtual void getTargetBuiltins(const Builtin::Info *&Records,
|
||||
unsigned &NumRecords) const = 0;
|
||||
virtual ArrayRef<Builtin::Info> getTargetBuiltins() const = 0;
|
||||
|
||||
/// The __builtin_clz* and __builtin_ctz* built-in
|
||||
/// functions are specified to have undefined results for zero inputs, but
|
||||
@ -523,6 +529,10 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
/// with this target.
|
||||
virtual BuiltinVaListKind getBuiltinVaListKind() const = 0;
|
||||
|
||||
/// Returns whether or not type \c __builtin_ms_va_list type is
|
||||
/// available on this target.
|
||||
bool hasBuiltinMSVaList() const { return HasBuiltinMSVaList; }
|
||||
|
||||
/// \brief Returns whether the passed in string is a valid clobber in an
|
||||
/// inline asm statement.
|
||||
///
|
||||
@ -556,6 +566,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
int Min;
|
||||
int Max;
|
||||
} ImmRange;
|
||||
llvm::SmallSet<int, 4> ImmSet;
|
||||
|
||||
std::string ConstraintStr; // constraint: "=rm"
|
||||
std::string Name; // Operand name: [foo] with no []'s.
|
||||
@ -591,8 +602,10 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
bool requiresImmediateConstant() const {
|
||||
return (Flags & CI_ImmediateConstant) != 0;
|
||||
}
|
||||
int getImmConstantMin() const { return ImmRange.Min; }
|
||||
int getImmConstantMax() const { return ImmRange.Max; }
|
||||
bool isValidAsmImmediate(const llvm::APInt &Value) const {
|
||||
return (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max)) ||
|
||||
ImmSet.count(Value.getZExtValue()) != 0;
|
||||
}
|
||||
|
||||
void setIsReadWrite() { Flags |= CI_ReadWrite; }
|
||||
void setEarlyClobber() { Flags |= CI_EarlyClobber; }
|
||||
@ -604,9 +617,23 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
ImmRange.Min = Min;
|
||||
ImmRange.Max = Max;
|
||||
}
|
||||
void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
|
||||
Flags |= CI_ImmediateConstant;
|
||||
for (int Exact : Exacts)
|
||||
ImmSet.insert(Exact);
|
||||
}
|
||||
void setRequiresImmediate(int Exact) {
|
||||
Flags |= CI_ImmediateConstant;
|
||||
ImmSet.insert(Exact);
|
||||
}
|
||||
void setRequiresImmediate() {
|
||||
Flags |= CI_ImmediateConstant;
|
||||
ImmRange.Min = INT_MIN;
|
||||
ImmRange.Max = INT_MAX;
|
||||
}
|
||||
|
||||
/// \brief Indicate that this is an input operand that is tied to
|
||||
/// the specified output operand.
|
||||
/// the specified output operand.
|
||||
///
|
||||
/// Copy over the various constraint information from the output.
|
||||
void setTiedOperand(unsigned N, ConstraintInfo &Output) {
|
||||
@ -617,15 +644,24 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
}
|
||||
};
|
||||
|
||||
// Validate the contents of the __builtin_cpu_supports(const char*) argument.
|
||||
virtual bool validateCpuSupports(StringRef Name) const { return false; }
|
||||
/// \brief Validate register name used for global register variables.
|
||||
///
|
||||
/// This function returns true if the register passed in RegName can be used
|
||||
/// for global register variables on this target. In addition, it returns
|
||||
/// true in HasSizeMismatch if the size of the register doesn't match the
|
||||
/// variable size passed in RegSize.
|
||||
virtual bool validateGlobalRegisterVariable(StringRef RegName,
|
||||
unsigned RegSize,
|
||||
bool &HasSizeMismatch) const {
|
||||
HasSizeMismatch = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// validateOutputConstraint, validateInputConstraint - Checks that
|
||||
// a constraint is valid and provides information about it.
|
||||
// FIXME: These should return a real error instead of just true/false.
|
||||
bool validateOutputConstraint(ConstraintInfo &Info) const;
|
||||
bool validateInputConstraint(ConstraintInfo *OutputConstraints,
|
||||
unsigned NumOutputs,
|
||||
bool validateInputConstraint(MutableArrayRef<ConstraintInfo> OutputConstraints,
|
||||
ConstraintInfo &info) const;
|
||||
|
||||
virtual bool validateOutputSize(StringRef /*Constraint*/,
|
||||
@ -644,9 +680,13 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
std::string &/*SuggestedModifier*/) const {
|
||||
return true;
|
||||
}
|
||||
virtual bool
|
||||
validateAsmConstraint(const char *&Name,
|
||||
TargetInfo::ConstraintInfo &info) const = 0;
|
||||
|
||||
bool resolveSymbolicName(const char *&Name,
|
||||
ConstraintInfo *OutputConstraints,
|
||||
unsigned NumOutputs, unsigned &Index) const;
|
||||
ArrayRef<ConstraintInfo> OutputConstraints,
|
||||
unsigned &Index) const;
|
||||
|
||||
// Constraint parm will be left pointing at the last character of
|
||||
// the constraint. In practice, it won't be changed unless the
|
||||
@ -658,24 +698,23 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
return std::string(1, *Constraint);
|
||||
}
|
||||
|
||||
/// \brief Returns a string of target-specific clobbers, in LLVM format.
|
||||
virtual const char *getClobbers() const = 0;
|
||||
|
||||
/// \brief Returns true if NaN encoding is IEEE 754-2008.
|
||||
/// Only MIPS allows a different encoding.
|
||||
virtual bool isNan2008() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Returns a string of target-specific clobbers, in LLVM format.
|
||||
virtual const char *getClobbers() const = 0;
|
||||
|
||||
|
||||
/// \brief Returns the target triple of the primary target.
|
||||
const llvm::Triple &getTriple() const {
|
||||
return Triple;
|
||||
}
|
||||
|
||||
const char *getTargetDescription() const {
|
||||
assert(DescriptionString);
|
||||
return DescriptionString;
|
||||
const char *getDataLayoutString() const {
|
||||
assert(DataLayoutString && "Uninitialized DataLayoutString!");
|
||||
return DataLayoutString;
|
||||
}
|
||||
|
||||
struct GCCRegAlias {
|
||||
@ -721,10 +760,13 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
/// language options which change the target configuration.
|
||||
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.
|
||||
virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const {
|
||||
}
|
||||
/// \brief Initialize the map with the default set of target features for the
|
||||
/// CPU this should include all legal feature strings on the target.
|
||||
///
|
||||
/// \return False on error (invalid features).
|
||||
virtual bool initFeatureMap(llvm::StringMap<bool> &Features,
|
||||
DiagnosticsEngine &Diags, StringRef CPU,
|
||||
const std::vector<std::string> &FeatureVec) const;
|
||||
|
||||
/// \brief Get the ABI currently in use.
|
||||
virtual StringRef getABI() const { return StringRef(); }
|
||||
@ -755,23 +797,6 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Use this specified C++ ABI.
|
||||
///
|
||||
/// \return False on error (invalid C++ ABI name).
|
||||
bool setCXXABI(llvm::StringRef name) {
|
||||
TargetCXXABI ABI;
|
||||
if (!ABI.tryParse(name)) return false;
|
||||
return setCXXABI(ABI);
|
||||
}
|
||||
|
||||
/// \brief Set the C++ ABI to be used by this implementation.
|
||||
///
|
||||
/// \return False on error (ABI not valid on this target)
|
||||
virtual bool setCXXABI(TargetCXXABI ABI) {
|
||||
TheCXXABI = ABI;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Enable or disable a specific target feature;
|
||||
/// the feature name must be valid.
|
||||
virtual void setFeatureEnabled(llvm::StringMap<bool> &Features,
|
||||
@ -787,6 +812,8 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
///
|
||||
/// The target may modify the features list, to change which options are
|
||||
/// passed onwards to the backend.
|
||||
/// FIXME: This part should be fixed so that we can change handleTargetFeatures
|
||||
/// to merely a TargetInfo initialization routine.
|
||||
///
|
||||
/// \return False on error.
|
||||
virtual bool handleTargetFeatures(std::vector<std::string> &Features,
|
||||
@ -798,7 +825,11 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
virtual bool hasFeature(StringRef Feature) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// \brief Validate the contents of the __builtin_cpu_supports(const char*)
|
||||
// argument.
|
||||
virtual bool validateCpuSupports(StringRef Name) const { return false; }
|
||||
|
||||
// \brief Returns maximal number of args passed in registers.
|
||||
unsigned getRegParmMax() const {
|
||||
assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle");
|
||||
@ -882,7 +913,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
};
|
||||
|
||||
/// \brief Determines whether a given calling convention is valid for the
|
||||
/// target. A calling convention can either be accepted, produce a warning
|
||||
/// target. A calling convention can either be accepted, produce a warning
|
||||
/// and be substituted with the default calling convention, or (someday)
|
||||
/// produce an error (such as using thiscall on a non-instance function).
|
||||
virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
|
||||
@ -910,17 +941,11 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
virtual enum IntType getPtrDiffTypeV(unsigned AddrSpace) const {
|
||||
return PtrDiffType;
|
||||
}
|
||||
virtual void getGCCRegNames(const char * const *&Names,
|
||||
unsigned &NumNames) const = 0;
|
||||
virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
|
||||
unsigned &NumAliases) const = 0;
|
||||
virtual void getGCCAddlRegNames(const AddlRegName *&Addl,
|
||||
unsigned &NumAddl) const {
|
||||
Addl = nullptr;
|
||||
NumAddl = 0;
|
||||
virtual ArrayRef<const char *> getGCCRegNames() const = 0;
|
||||
virtual ArrayRef<GCCRegAlias> getGCCRegAliases() const = 0;
|
||||
virtual ArrayRef<AddlRegName> getGCCAddlRegNames() const {
|
||||
return None;
|
||||
}
|
||||
virtual bool validateAsmConstraint(const char *&Name,
|
||||
TargetInfo::ConstraintInfo &info) const= 0;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -242,6 +242,8 @@ PUNCTUATOR(greatergreatergreater, ">>>")
|
||||
// KEYZVECTOR - This is a keyword for the System z vector extensions,
|
||||
// which are heavily based on AltiVec
|
||||
// KEYBORLAND - This is a keyword if Borland extensions are enabled
|
||||
// KEYCOROUTINES - This is a keyword if support for the C++ coroutines
|
||||
// TS is 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
|
||||
@ -282,7 +284,7 @@ KEYWORD(volatile , KEYALL)
|
||||
KEYWORD(while , KEYALL)
|
||||
KEYWORD(_Alignas , KEYALL)
|
||||
KEYWORD(_Alignof , KEYALL)
|
||||
KEYWORD(_Atomic , KEYALL|KEYNOMS18|KEYNOOPENCL)
|
||||
KEYWORD(_Atomic , KEYALL|KEYNOOPENCL)
|
||||
KEYWORD(_Bool , KEYNOCXX)
|
||||
KEYWORD(_Complex , KEYALL)
|
||||
KEYWORD(_Generic , KEYALL)
|
||||
@ -356,6 +358,11 @@ CXX11_KEYWORD(thread_local , 0)
|
||||
CONCEPTS_KEYWORD(concept)
|
||||
CONCEPTS_KEYWORD(requires)
|
||||
|
||||
// C++ coroutines TS keywords
|
||||
KEYWORD(co_await , KEYCOROUTINES)
|
||||
KEYWORD(co_return , KEYCOROUTINES)
|
||||
KEYWORD(co_yield , KEYCOROUTINES)
|
||||
|
||||
// GNU Extensions (in impl-reserved namespace)
|
||||
KEYWORD(_Decimal32 , KEYALL)
|
||||
KEYWORD(_Decimal64 , KEYALL)
|
||||
@ -377,6 +384,7 @@ KEYWORD(__real , KEYALL)
|
||||
KEYWORD(__thread , KEYALL)
|
||||
KEYWORD(__FUNCTION__ , KEYALL)
|
||||
KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
|
||||
KEYWORD(__auto_type , KEYALL)
|
||||
|
||||
// GNU Extensions (outside impl-reserved namespace)
|
||||
KEYWORD(typeof , KEYGNU)
|
||||
@ -469,8 +477,11 @@ KEYWORD(__array_extent , KEYCXX)
|
||||
KEYWORD(__private_extern__ , KEYALL)
|
||||
KEYWORD(__module_private__ , KEYALL)
|
||||
|
||||
// Extension that will be enabled for Microsoft, Borland and PS4, but can be
|
||||
// disabled via '-fno-declspec'.
|
||||
KEYWORD(__declspec , 0)
|
||||
|
||||
// Microsoft Extension.
|
||||
KEYWORD(__declspec , KEYMS|KEYBORLAND)
|
||||
KEYWORD(__cdecl , KEYALL)
|
||||
KEYWORD(__stdcall , KEYALL)
|
||||
KEYWORD(__fastcall , KEYALL)
|
||||
|
@ -45,14 +45,18 @@ class Status {
|
||||
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,
|
||||
Status(StringRef 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);
|
||||
|
||||
/// Get a copy of a Status with a different name.
|
||||
static Status copyWithNewName(const Status &In, StringRef NewName);
|
||||
static Status copyWithNewName(const llvm::sys::fs::file_status &In,
|
||||
StringRef NewName);
|
||||
|
||||
/// \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
|
||||
/// @{
|
||||
@ -63,8 +67,6 @@ class Status {
|
||||
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.
|
||||
@ -94,8 +96,6 @@ class File {
|
||||
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 {
|
||||
@ -199,6 +199,28 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> {
|
||||
/// \note The 'end' iterator is directory_iterator().
|
||||
virtual directory_iterator dir_begin(const Twine &Dir,
|
||||
std::error_code &EC) = 0;
|
||||
|
||||
/// Set the working directory. This will affect all following operations on
|
||||
/// this file system and may propagate down for nested file systems.
|
||||
virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
|
||||
/// Get the working directory of this file system.
|
||||
virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0;
|
||||
|
||||
/// Check whether a file exists. Provided for convenience.
|
||||
bool exists(const Twine &Path);
|
||||
|
||||
/// Make \a Path an absolute path.
|
||||
///
|
||||
/// Makes \a Path absolute using the current directory if it is not already.
|
||||
/// An empty \a Path will result in the current directory.
|
||||
///
|
||||
/// /absolute/path => /absolute/path
|
||||
/// relative/../path => <current-directory>/relative/../path
|
||||
///
|
||||
/// \param Path A path that is modified to be an absolute path.
|
||||
/// \returns success if \a path has been made absolute, otherwise a
|
||||
/// platform-specific error_code.
|
||||
std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
|
||||
};
|
||||
|
||||
/// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by
|
||||
@ -230,6 +252,8 @@ class OverlayFileSystem : public FileSystem {
|
||||
llvm::ErrorOr<std::unique_ptr<File>>
|
||||
openFileForRead(const Twine &Path) override;
|
||||
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
|
||||
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
|
||||
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
|
||||
|
||||
typedef FileSystemList::reverse_iterator iterator;
|
||||
|
||||
@ -241,6 +265,46 @@ class OverlayFileSystem : public FileSystem {
|
||||
iterator overlays_end() { return FSList.rend(); }
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
class InMemoryDirectory;
|
||||
} // end namespace detail
|
||||
|
||||
/// An in-memory file system.
|
||||
class InMemoryFileSystem : public FileSystem {
|
||||
std::unique_ptr<detail::InMemoryDirectory> Root;
|
||||
std::string WorkingDirectory;
|
||||
bool UseNormalizedPaths = true;
|
||||
|
||||
public:
|
||||
explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
|
||||
~InMemoryFileSystem() override;
|
||||
/// Add a buffer to the VFS with a path. The VFS owns the buffer.
|
||||
/// \return true if the file was successfully added, false if the file already
|
||||
/// exists in the file system with different contents.
|
||||
bool addFile(const Twine &Path, time_t ModificationTime,
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer);
|
||||
/// Add a buffer to the VFS with a path. The VFS does not own the buffer.
|
||||
/// \return true if the file was successfully added, false if the file already
|
||||
/// exists in the file system with different contents.
|
||||
bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
|
||||
llvm::MemoryBuffer *Buffer);
|
||||
std::string toString() const;
|
||||
/// Return true if this file system normalizes . and .. in paths.
|
||||
bool useNormalizedPaths() const { return UseNormalizedPaths; }
|
||||
|
||||
llvm::ErrorOr<Status> status(const Twine &Path) override;
|
||||
llvm::ErrorOr<std::unique_ptr<File>>
|
||||
openFileForRead(const Twine &Path) override;
|
||||
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
|
||||
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
|
||||
return WorkingDirectory;
|
||||
}
|
||||
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
|
||||
WorkingDirectory = Path.str();
|
||||
return std::error_code();
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Get a globally unique ID for a virtual file or directory.
|
||||
llvm::sys::fs::UniqueID getNextVirtualUniqueID();
|
||||
|
||||
|
@ -373,6 +373,10 @@ 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_QRDMLAH : Op<(call "vqadd", $p0, (call "vqrdmulh", $p1, $p2))>;
|
||||
def OP_QRDMLSH : Op<(call "vqsub", $p0, (call "vqrdmulh", $p1, $p2))>;
|
||||
def OP_QRDMLAH_LN : Op<(call "vqadd", $p0, (call "vqrdmulh", $p1, (splat $p2, $p3)))>;
|
||||
def OP_QRDMLSH_LN : Op<(call "vqsub", $p0, (call "vqrdmulh", $p1, (splat $p2, $p3)))>;
|
||||
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),
|
||||
@ -414,7 +418,7 @@ 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_F16 : Op<(call "vcombine", $p0, (call "vcvt_f16_f32", $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))>;
|
||||
@ -473,6 +477,11 @@ def OP_SCALAR_QDMULL_LN : ScalarMulOp<"vqdmull">;
|
||||
def OP_SCALAR_QDMULH_LN : ScalarMulOp<"vqdmulh">;
|
||||
def OP_SCALAR_QRDMULH_LN : ScalarMulOp<"vqrdmulh">;
|
||||
|
||||
def OP_SCALAR_QRDMLAH_LN : Op<(call "vqadd", $p0, (call "vqrdmulh", $p1,
|
||||
(call "vget_lane", $p2, $p3)))>;
|
||||
def OP_SCALAR_QRDMLSH_LN : Op<(call "vqsub", $p0, (call "vqrdmulh", $p1,
|
||||
(call "vget_lane", $p2, $p3)))>;
|
||||
|
||||
def OP_SCALAR_HALF_GET_LN : Op<(bitcast "float16_t",
|
||||
(call "vget_lane",
|
||||
(bitcast "int16x4_t", $p0), $p1))>;
|
||||
@ -514,6 +523,12 @@ def VMLS : IOpInst<"vmls", "dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLS>;
|
||||
def VMLSL : SOpInst<"vmlsl", "wwdd", "csiUcUsUi", OP_MLSL>;
|
||||
def VQDMULH : SInst<"vqdmulh", "ddd", "siQsQi">;
|
||||
def VQRDMULH : SInst<"vqrdmulh", "ddd", "siQsQi">;
|
||||
|
||||
let ArchGuard = "defined(__ARM_FEATURE_QRDMX)" in {
|
||||
def VQRDMLAH : SOpInst<"vqrdmlah", "dddd", "siQsQi", OP_QRDMLAH>;
|
||||
def VQRDMLSH : SOpInst<"vqrdmlsh", "dddd", "siQsQi", OP_QRDMLSH>;
|
||||
}
|
||||
|
||||
def VQDMLAL : SInst<"vqdmlal", "wwdd", "si">;
|
||||
def VQDMLSL : SInst<"vqdmlsl", "wwdd", "si">;
|
||||
def VMULL : SInst<"vmull", "wdd", "csiUcUsUiPc">;
|
||||
@ -687,16 +702,19 @@ def VGET_LOW : NoTestOpInst<"vget_low", "dk", "csilhfUcUsUiUlPcPs", OP_LO>;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// E.3.22 Converting vectors
|
||||
|
||||
def VCVT_F16_F32 : SInst<"vcvt_f16_f32", "md", "Hf">;
|
||||
def VCVT_F32_F16 : SInst<"vcvt_f32_f16", "wd", "h">;
|
||||
|
||||
def VCVT_S32 : SInst<"vcvt_s32", "xd", "fQf">;
|
||||
def VCVT_U32 : SInst<"vcvt_u32", "ud", "fQf">;
|
||||
def VCVT_F16 : SInst<"vcvt_f16", "hk", "f">;
|
||||
def VCVT_F32 : SInst<"vcvt_f32", "fd", "iUiQiQUi">;
|
||||
def VCVT_F32_F16 : SInst<"vcvt_f32_f16", "fd", "h">;
|
||||
let isVCVT_N = 1 in {
|
||||
def VCVT_N_S32 : SInst<"vcvt_n_s32", "xdi", "fQf">;
|
||||
def VCVT_N_U32 : SInst<"vcvt_n_u32", "udi", "fQf">;
|
||||
def VCVT_N_F32 : SInst<"vcvt_n_f32", "fdi", "iUiQiQUi">;
|
||||
}
|
||||
|
||||
def VMOVN : IInst<"vmovn", "hk", "silUsUiUl">;
|
||||
def VMOVL : SInst<"vmovl", "wd", "csiUcUsUi">;
|
||||
def VQMOVN : SInst<"vqmovn", "hk", "silUsUiUl">;
|
||||
@ -738,6 +756,12 @@ def VQDMULH_N : SInst<"vqdmulh_n", "dda", "siQsQi">;
|
||||
def VQDMULH_LANE : SOpInst<"vqdmulh_lane", "ddgi", "siQsQi", OP_QDMULH_LN>;
|
||||
def VQRDMULH_N : SInst<"vqrdmulh_n", "dda", "siQsQi">;
|
||||
def VQRDMULH_LANE : SOpInst<"vqrdmulh_lane", "ddgi", "siQsQi", OP_QRDMULH_LN>;
|
||||
|
||||
let ArchGuard = "defined(__ARM_FEATURE_QRDMX)" in {
|
||||
def VQRDMLAH_LANE : SOpInst<"vqrdmlah_lane", "dddgi", "siQsQi", OP_QRDMLAH_LN>;
|
||||
def VQRDMLSH_LANE : SOpInst<"vqrdmlsh_lane", "dddgi", "siQsQi", OP_QRDMLSH_LN>;
|
||||
}
|
||||
|
||||
def VMLA_N : IOpInst<"vmla_n", "ddda", "siUsUifQsQiQUsQUiQf", OP_MLA_N>;
|
||||
def VMLAL_N : SOpInst<"vmlal_n", "wwda", "siUsUi", OP_MLAL_N>;
|
||||
def VQDMLAL_N : SInst<"vqdmlal_n", "wwda", "si">;
|
||||
@ -923,6 +947,9 @@ def USQADD : SInst<"vsqadd", "ddd", "UcUsUiUlQUcQUsQUiQUl">;
|
||||
// Reciprocal/Sqrt
|
||||
def FRECPS : IInst<"vrecps", "ddd", "dQd">;
|
||||
def FRSQRTS : IInst<"vrsqrts", "ddd", "dQd">;
|
||||
def FRECPE : SInst<"vrecpe", "dd", "dQd">;
|
||||
def FRSQRTE : SInst<"vrsqrte", "dd", "dQd">;
|
||||
def FSQRT : SInst<"vsqrt", "dd", "fdQfQd">;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// bitwise reverse
|
||||
@ -942,20 +969,21 @@ 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_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_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 VCVT_S64 : SInst<"vcvt_s64", "xd", "dQd">;
|
||||
def VCVT_U64 : SInst<"vcvt_u64", "ud", "dQd">;
|
||||
def FRECPE : SInst<"vrecpe", "dd", "dQd">;
|
||||
def FRSQRTE : SInst<"vrsqrte", "dd", "dQd">;
|
||||
def FSQRT : SInst<"vsqrt", "dd", "fdQfQd">;
|
||||
def VCVT_F64 : SInst<"vcvt_f64", "Fd", "lUlQlQUl">;
|
||||
|
||||
def VCVT_HIGH_F16_F32 : SOpInst<"vcvt_high_f16", "hmj", "Hf", OP_VCVT_NA_HI_F16>;
|
||||
def VCVT_HIGH_F32_F16 : SOpInst<"vcvt_high_f32", "wk", "h", OP_VCVT_EX_HI_F32>;
|
||||
def VCVT_HIGH_F32_F64 : SOpInst<"vcvt_high_f32", "qfj", "d", OP_VCVT_NA_HI_F32>;
|
||||
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>;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Comparison
|
||||
@ -1153,6 +1181,11 @@ def VQDMULL_HIGH_LANEQ : SOpInst<"vqdmull_high_laneq", "wkki", "si",
|
||||
def VQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ddji", "siQsQi", OP_QDMULH_LN>;
|
||||
def VQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ddji", "siQsQi", OP_QRDMULH_LN>;
|
||||
|
||||
let ArchGuard = "defined(__ARM_FEATURE_QRDMX) && defined(__aarch64__)" in {
|
||||
def VQRDMLAH_LANEQ : SOpInst<"vqrdmlah_laneq", "dddji", "siQsQi", OP_QRDMLAH_LN>;
|
||||
def VQRDMLSH_LANEQ : SOpInst<"vqrdmlsh_laneq", "dddji", "siQsQi", OP_QRDMLSH_LN>;
|
||||
}
|
||||
|
||||
// Note: d type implemented by SCALAR_VMULX_LANE
|
||||
def VMULX_LANE : IOpInst<"vmulx_lane", "ddgi", "fQfQd", OP_MULX_LN>;
|
||||
// Note: d type is implemented by SCALAR_VMULX_LANEQ
|
||||
@ -1398,6 +1431,16 @@ def SCALAR_SQDMULH : SInst<"vqdmulh", "sss", "SsSi">;
|
||||
// Scalar Integer Saturating Rounding Doubling Multiply Half High
|
||||
def SCALAR_SQRDMULH : SInst<"vqrdmulh", "sss", "SsSi">;
|
||||
|
||||
let ArchGuard = "defined(__ARM_FEATURE_QRDMX) && defined(__aarch64__)" in {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Signed Saturating Rounding Doubling Multiply Accumulate Returning High Half
|
||||
def SCALAR_SQRDMLAH : SOpInst<"vqrdmlah", "ssss", "SsSi", OP_QRDMLAH>;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Signed Saturating Rounding Doubling Multiply Subtract Returning High Half
|
||||
def SCALAR_SQRDMLSH : SOpInst<"vqrdmlsh", "ssss", "SsSi", OP_QRDMLSH>;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Scalar Floating-point Multiply Extended
|
||||
def SCALAR_FMULX : IInst<"vmulx", "sss", "SfSd">;
|
||||
@ -1599,6 +1642,16 @@ def SCALAR_SQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QD
|
||||
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_LN>;
|
||||
|
||||
let ArchGuard = "defined(__ARM_FEATURE_QRDMX) && defined(__aarch64__)" in {
|
||||
// Signed Saturating Rounding Doubling Multiply Accumulate Returning High Half
|
||||
def SCALAR_SQRDMLAH_LANE : SOpInst<"vqrdmlah_lane", "sssdi", "SsSi", OP_SCALAR_QRDMLAH_LN>;
|
||||
def SCALAR_SQRDMLAH_LANEQ : SOpInst<"vqrdmlah_laneq", "sssji", "SsSi", OP_SCALAR_QRDMLAH_LN>;
|
||||
|
||||
// Signed Saturating Rounding Doubling Multiply Subtract Returning High Half
|
||||
def SCALAR_SQRDMLSH_LANE : SOpInst<"vqrdmlsh_lane", "sssdi", "SsSi", OP_SCALAR_QRDMLSH_LN>;
|
||||
def SCALAR_SQRDMLSH_LANEQ : SOpInst<"vqrdmlsh_laneq", "sssji", "SsSi", OP_SCALAR_QRDMLSH_LN>;
|
||||
}
|
||||
|
||||
def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
|
||||
def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
#define LLVM_CLANG_CODEGEN_BACKENDUTIL_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/IR/FunctionInfo.h"
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
@ -31,10 +33,12 @@ namespace clang {
|
||||
Backend_EmitObj ///< Emit native object files
|
||||
};
|
||||
|
||||
void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts,
|
||||
const TargetOptions &TOpts, const LangOptions &LOpts,
|
||||
StringRef TDesc, llvm::Module *M, BackendAction Action,
|
||||
raw_pwrite_stream *OS);
|
||||
void
|
||||
EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts,
|
||||
const TargetOptions &TOpts, const LangOptions &LOpts,
|
||||
StringRef TDesc, llvm::Module *M, BackendAction Action,
|
||||
raw_pwrite_stream *OS,
|
||||
std::unique_ptr<llvm::FunctionInfoIndex> Index = nullptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
|
||||
|
||||
#include "clang/AST/CanonicalType.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include <cassert>
|
||||
@ -126,7 +127,7 @@ class ABIArgInfo {
|
||||
static ABIArgInfo getIgnore() {
|
||||
return ABIArgInfo(Ignore);
|
||||
}
|
||||
static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true,
|
||||
static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
|
||||
bool Realign = false,
|
||||
llvm::Type *Padding = nullptr) {
|
||||
auto AI = ABIArgInfo(Indirect);
|
||||
@ -137,7 +138,7 @@ class ABIArgInfo {
|
||||
AI.setPaddingType(Padding);
|
||||
return AI;
|
||||
}
|
||||
static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true,
|
||||
static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
|
||||
bool Realign = false) {
|
||||
auto AI = getIndirect(Alignment, ByVal, Realign);
|
||||
AI.setInReg(true);
|
||||
@ -211,20 +212,20 @@ class ABIArgInfo {
|
||||
}
|
||||
|
||||
// Indirect accessors
|
||||
unsigned getIndirectAlign() const {
|
||||
CharUnits getIndirectAlign() const {
|
||||
assert(isIndirect() && "Invalid kind!");
|
||||
return IndirectAlign;
|
||||
return CharUnits::fromQuantity(IndirectAlign);
|
||||
}
|
||||
void setIndirectAlign(unsigned IA) {
|
||||
void setIndirectAlign(CharUnits IA) {
|
||||
assert(isIndirect() && "Invalid kind!");
|
||||
IndirectAlign = IA;
|
||||
IndirectAlign = IA.getQuantity();
|
||||
}
|
||||
|
||||
bool getIndirectByVal() const {
|
||||
assert(isIndirect() && "Invalid kind!");
|
||||
return IndirectByVal;
|
||||
}
|
||||
void setIndirectByVal(unsigned IBV) {
|
||||
void setIndirectByVal(bool IBV) {
|
||||
assert(isIndirect() && "Invalid kind!");
|
||||
IndirectByVal = IBV;
|
||||
}
|
||||
@ -370,6 +371,7 @@ class CGFunctionInfo : public llvm::FoldingSetNode {
|
||||
/// 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 ArgStructAlign;
|
||||
|
||||
unsigned NumArgs;
|
||||
ArgInfo *getArgsBuffer() {
|
||||
@ -463,7 +465,13 @@ class CGFunctionInfo : public llvm::FoldingSetNode {
|
||||
|
||||
/// \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; }
|
||||
CharUnits getArgStructAlignment() const {
|
||||
return CharUnits::fromQuantity(ArgStructAlign);
|
||||
}
|
||||
void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
|
||||
ArgStruct = Ty;
|
||||
ArgStructAlign = Align.getQuantity();
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
ID.AddInteger(getASTCallingConvention());
|
||||
@ -501,6 +509,29 @@ class CGFunctionInfo : public llvm::FoldingSetNode {
|
||||
}
|
||||
};
|
||||
|
||||
/// CGCalleeInfo - Class to encapsulate the information about a callee to be
|
||||
/// used during the generation of call/invoke instructions.
|
||||
class CGCalleeInfo {
|
||||
/// \brief The function proto type of the callee.
|
||||
const FunctionProtoType *CalleeProtoTy;
|
||||
/// \brief The function declaration of the callee.
|
||||
const Decl *CalleeDecl;
|
||||
|
||||
public:
|
||||
explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {}
|
||||
CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl)
|
||||
: CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
|
||||
CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
|
||||
: CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {}
|
||||
CGCalleeInfo(const Decl *calleeDecl)
|
||||
: CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
|
||||
|
||||
const FunctionProtoType *getCalleeFunctionProtoType() {
|
||||
return CalleeProtoTy;
|
||||
}
|
||||
const Decl *getCalleeDecl() { return CalleeDecl; }
|
||||
};
|
||||
|
||||
} // end namespace CodeGen
|
||||
} // end namespace clang
|
||||
|
||||
|
@ -36,6 +36,7 @@ namespace llvm {
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class CXXRecordDecl;
|
||||
class CXXMethodDecl;
|
||||
class CodeGenOptions;
|
||||
class CoverageSourceInfo;
|
||||
class DiagnosticsEngine;
|
||||
@ -50,7 +51,7 @@ class CodeGenModule;
|
||||
class CodeGenABITypes
|
||||
{
|
||||
public:
|
||||
CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD,
|
||||
CodeGenABITypes(ASTContext &C, llvm::Module &M,
|
||||
CoverageSourceInfo *CoverageInfo = nullptr);
|
||||
~CodeGenABITypes();
|
||||
|
||||
@ -60,12 +61,13 @@ class CodeGenABITypes
|
||||
const CGFunctionInfo &arrangeObjCMessageSendSignature(
|
||||
const ObjCMethodDecl *MD,
|
||||
QualType receiverType);
|
||||
const CGFunctionInfo &arrangeFreeFunctionType(
|
||||
CanQual<FunctionProtoType> Ty);
|
||||
const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty,
|
||||
const FunctionDecl *FD);
|
||||
const CGFunctionInfo &arrangeFreeFunctionType(
|
||||
CanQual<FunctionNoProtoType> Ty);
|
||||
const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
|
||||
const FunctionProtoType *FTP);
|
||||
const FunctionProtoType *FTP,
|
||||
const CXXMethodDecl *MD);
|
||||
const CGFunctionInfo &arrangeFreeFunctionCall(CanQualType returnType,
|
||||
ArrayRef<CanQualType> argTypes,
|
||||
FunctionType::ExtInfo info,
|
||||
@ -75,12 +77,12 @@ class CodeGenABITypes
|
||||
/// 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;
|
||||
HeaderSearchOptions *HSO;
|
||||
PreprocessorOptions *PPO;
|
||||
std::unique_ptr<CodeGenOptions> CGO;
|
||||
std::unique_ptr<HeaderSearchOptions> HSO;
|
||||
std::unique_ptr<PreprocessorOptions> PPO;
|
||||
|
||||
/// The CodeGenModule we use get to the CodeGenTypes object.
|
||||
CodeGen::CodeGenModule *CGM;
|
||||
std::unique_ptr<CodeGen::CodeGenModule> CGM;
|
||||
};
|
||||
|
||||
} // end namespace CodeGen
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user