Update clang to trunk r256633.

This commit is contained in:
dim 2015-12-30 13:34:49 +00:00
commit 63b24cc778
640 changed files with 69646 additions and 35341 deletions

View File

@ -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.
*

View File

@ -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);
/**
* @}
*/

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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(); }

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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; }

View File

@ -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,

View File

@ -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.

View File

@ -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 {

View File

@ -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.

View File

@ -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);

View File

@ -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());
}

View File

@ -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

View File

@ -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;

View 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

View File

@ -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

View File

@ -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;
/// @}
};

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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. :)

View File

@ -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,

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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:

View File

@ -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>());
}

View File

@ -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 {

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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];
}

View File

@ -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.
}
};
}];
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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")

View File

@ -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", "")

View File

@ -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

View File

@ -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;

View File

@ -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; }

View File

@ -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">;
}

View File

@ -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">;
}

View File

@ -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;

View File

@ -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">;

View File

@ -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>;

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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.

View File

@ -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")

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -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); }

View File

@ -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(); }

View File

@ -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
};

View File

@ -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>;

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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)

View File

@ -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();

View File

@ -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">;
}

View File

@ -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

View File

@ -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

View File

@ -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