Vendor import of stripped clang trunk r375505, the last commit before
the upstream Subversion repository was made read-only, and the LLVM project migrated to GitHub: https://llvm.org/svn/llvm-project/cfe/trunk@375505
This commit is contained in:
parent
2298981669
commit
519fc96c47
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=353942 svn path=/vendor/clang/clang-r375505/; revision=353943; tag=vendor/clang/clang-trunk-r375505
33
include/clang-c/FatalErrorHandler.h
Normal file
33
include/clang-c/FatalErrorHandler.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*===-- clang-c/FatalErrorHandler.h - Fatal Error Handling --------*- C -*-===*\
|
||||
|* *|
|
||||
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
|
||||
|* Exceptions. *|
|
||||
|* See https://llvm.org/LICENSE.txt for license information. *|
|
||||
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#ifndef LLVM_CLANG_C_FATAL_ERROR_HANDLER_H
|
||||
#define LLVM_CLANG_C_FATAL_ERROR_HANDLER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Installs error handler that prints error message to stderr and calls abort().
|
||||
* Replaces currently installed error handler (if any).
|
||||
*/
|
||||
void clang_install_aborting_llvm_fatal_error_handler(void);
|
||||
|
||||
/**
|
||||
* Removes currently installed error handler (if any).
|
||||
* If no error handler is intalled, the default strategy is to print error
|
||||
* message to stderr and call exit(1).
|
||||
*/
|
||||
void clang_uninstall_llvm_fatal_error_handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -1356,7 +1356,12 @@ enum CXTranslationUnit_Flags {
|
||||
* the case where these warnings are not of interest, as for an IDE for
|
||||
* example, which typically shows only the diagnostics in the main file.
|
||||
*/
|
||||
CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles = 0x4000
|
||||
CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles = 0x4000,
|
||||
|
||||
/**
|
||||
* Tells the preprocessor not to skip excluded conditional blocks.
|
||||
*/
|
||||
CXTranslationUnit_RetainExcludedConditionalBlocks = 0x8000
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2550,7 +2555,20 @@ enum CXCursorKind {
|
||||
*/
|
||||
CXCursor_BuiltinBitCastExpr = 280,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_BuiltinBitCastExpr,
|
||||
/** OpenMP master taskloop directive.
|
||||
*/
|
||||
CXCursor_OMPMasterTaskLoopDirective = 281,
|
||||
|
||||
/** OpenMP parallel master taskloop directive.
|
||||
*/
|
||||
CXCursor_OMPParallelMasterTaskLoopDirective = 282,
|
||||
|
||||
/** OpenMP master taskloop simd directive.
|
||||
*/
|
||||
CXCursor_OMPMasterTaskLoopSimdDirective = 283,
|
||||
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OMPMasterTaskLoopSimdDirective,
|
||||
|
||||
/**
|
||||
* Cursor that represents the translation unit itself.
|
||||
|
@ -53,6 +53,34 @@ class TypeInfoLValue {
|
||||
|
||||
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const;
|
||||
};
|
||||
|
||||
/// Symbolic representation of a dynamic allocation.
|
||||
class DynamicAllocLValue {
|
||||
unsigned Index;
|
||||
|
||||
public:
|
||||
DynamicAllocLValue() : Index(0) {}
|
||||
explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {}
|
||||
unsigned getIndex() { return Index - 1; }
|
||||
|
||||
explicit operator bool() const { return Index != 0; }
|
||||
|
||||
void *getOpaqueValue() {
|
||||
return reinterpret_cast<void *>(static_cast<uintptr_t>(Index)
|
||||
<< NumLowBitsAvailable);
|
||||
}
|
||||
static DynamicAllocLValue getFromOpaqueValue(void *Value) {
|
||||
DynamicAllocLValue V;
|
||||
V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable;
|
||||
return V;
|
||||
}
|
||||
|
||||
static unsigned getMaxIndex() {
|
||||
return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1;
|
||||
}
|
||||
|
||||
static constexpr int NumLowBitsAvailable = 3;
|
||||
};
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
@ -67,6 +95,17 @@ template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
|
||||
// to include Type.h.
|
||||
static constexpr int NumLowBitsAvailable = 3;
|
||||
};
|
||||
|
||||
template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
|
||||
static void *getAsVoidPointer(clang::DynamicAllocLValue V) {
|
||||
return V.getOpaqueValue();
|
||||
}
|
||||
static clang::DynamicAllocLValue getFromVoidPointer(void *P) {
|
||||
return clang::DynamicAllocLValue::getFromOpaqueValue(P);
|
||||
}
|
||||
static constexpr int NumLowBitsAvailable =
|
||||
clang::DynamicAllocLValue::NumLowBitsAvailable;
|
||||
};
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
@ -97,13 +136,15 @@ class APValue {
|
||||
};
|
||||
|
||||
class LValueBase {
|
||||
typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue>
|
||||
typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
|
||||
DynamicAllocLValue>
|
||||
PtrTy;
|
||||
|
||||
public:
|
||||
LValueBase() : Local{} {}
|
||||
LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
|
||||
LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
|
||||
static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
|
||||
static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
|
||||
|
||||
template <class T>
|
||||
@ -124,6 +165,7 @@ class APValue {
|
||||
unsigned getCallIndex() const;
|
||||
unsigned getVersion() const;
|
||||
QualType getTypeInfoType() const;
|
||||
QualType getDynamicAllocType() const;
|
||||
|
||||
friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
|
||||
friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
|
||||
@ -140,6 +182,8 @@ class APValue {
|
||||
LocalState Local;
|
||||
/// The type std::type_info, if this is a TypeInfoLValue.
|
||||
void *TypeInfoType;
|
||||
/// The QualType, if this is a DynamicAllocLValue.
|
||||
void *DynamicAllocType;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -139,6 +139,12 @@ class FullComment;
|
||||
|
||||
} // namespace comments
|
||||
|
||||
namespace interp {
|
||||
|
||||
class Context;
|
||||
|
||||
} // namespace interp
|
||||
|
||||
struct TypeInfo {
|
||||
uint64_t Width = 0;
|
||||
unsigned Align = 0;
|
||||
@ -179,7 +185,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
|
||||
mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
|
||||
mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
|
||||
mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
|
||||
mutable llvm::ContextualFoldingSet<ConstantArrayType, ASTContext &>
|
||||
ConstantArrayTypes;
|
||||
mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
|
||||
mutable std::vector<VariableArrayType*> VariableArrayTypes;
|
||||
mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
|
||||
@ -507,6 +514,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// need to be consistently numbered for the mangler).
|
||||
llvm::DenseMap<const DeclContext *, std::unique_ptr<MangleNumberingContext>>
|
||||
MangleNumberingContexts;
|
||||
llvm::DenseMap<const Decl *, std::unique_ptr<MangleNumberingContext>>
|
||||
ExtraMangleNumberingContexts;
|
||||
|
||||
/// Side-table of mangling numbers for declarations which rarely
|
||||
/// need them (like static local vars).
|
||||
@ -564,6 +573,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
const TargetInfo *Target = nullptr;
|
||||
const TargetInfo *AuxTarget = nullptr;
|
||||
clang::PrintingPolicy PrintingPolicy;
|
||||
std::unique_ptr<interp::Context> InterpContext;
|
||||
|
||||
public:
|
||||
IdentifierTable &Idents;
|
||||
@ -573,6 +583,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
IntrusiveRefCntPtr<ExternalASTSource> ExternalSource;
|
||||
ASTMutationListener *Listener = nullptr;
|
||||
|
||||
/// Returns the clang bytecode interpreter context.
|
||||
interp::Context &getInterpContext();
|
||||
|
||||
/// Container for either a single DynTypedNode or for an ArrayRef to
|
||||
/// DynTypedNode. For use with ParentMap.
|
||||
class DynTypedNodeList {
|
||||
@ -729,71 +742,49 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// True if comments are already loaded from ExternalASTSource.
|
||||
mutable bool CommentsLoaded = false;
|
||||
|
||||
class RawCommentAndCacheFlags {
|
||||
public:
|
||||
enum Kind {
|
||||
/// We searched for a comment attached to the particular declaration, but
|
||||
/// didn't find any.
|
||||
///
|
||||
/// getRaw() == 0.
|
||||
NoCommentInDecl = 0,
|
||||
|
||||
/// We have found a comment attached to this particular declaration.
|
||||
///
|
||||
/// getRaw() != 0.
|
||||
FromDecl,
|
||||
|
||||
/// This declaration does not have an attached comment, and we have
|
||||
/// searched the redeclaration chain.
|
||||
///
|
||||
/// If getRaw() == 0, the whole redeclaration chain does not have any
|
||||
/// comments.
|
||||
///
|
||||
/// If getRaw() != 0, it is a comment propagated from other
|
||||
/// redeclaration.
|
||||
FromRedecl
|
||||
};
|
||||
|
||||
Kind getKind() const LLVM_READONLY {
|
||||
return Data.getInt();
|
||||
}
|
||||
|
||||
void setKind(Kind K) {
|
||||
Data.setInt(K);
|
||||
}
|
||||
|
||||
const RawComment *getRaw() const LLVM_READONLY {
|
||||
return Data.getPointer();
|
||||
}
|
||||
|
||||
void setRaw(const RawComment *RC) {
|
||||
Data.setPointer(RC);
|
||||
}
|
||||
|
||||
const Decl *getOriginalDecl() const LLVM_READONLY {
|
||||
return OriginalDecl;
|
||||
}
|
||||
|
||||
void setOriginalDecl(const Decl *Orig) {
|
||||
OriginalDecl = Orig;
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::PointerIntPair<const RawComment *, 2, Kind> Data;
|
||||
const Decl *OriginalDecl;
|
||||
};
|
||||
|
||||
/// Mapping from declarations to comments attached to any
|
||||
/// redeclaration.
|
||||
/// Mapping from declaration to directly attached comment.
|
||||
///
|
||||
/// Raw comments are owned by Comments list. This mapping is populated
|
||||
/// lazily.
|
||||
mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments;
|
||||
mutable llvm::DenseMap<const Decl *, const RawComment *> DeclRawComments;
|
||||
|
||||
/// Mapping from canonical declaration to the first redeclaration in chain
|
||||
/// that has a comment attached.
|
||||
///
|
||||
/// Raw comments are owned by Comments list. This mapping is populated
|
||||
/// lazily.
|
||||
mutable llvm::DenseMap<const Decl *, const Decl *> RedeclChainComments;
|
||||
|
||||
/// Keeps track of redeclaration chains that don't have any comment attached.
|
||||
/// Mapping from canonical declaration to redeclaration chain that has no
|
||||
/// comments attached to any redeclaration. Specifically it's mapping to
|
||||
/// the last redeclaration we've checked.
|
||||
///
|
||||
/// Shall not contain declarations that have comments attached to any
|
||||
/// redeclaration in their chain.
|
||||
mutable llvm::DenseMap<const Decl *, const Decl *> CommentlessRedeclChains;
|
||||
|
||||
/// Mapping from declarations to parsed comments attached to any
|
||||
/// redeclaration.
|
||||
mutable llvm::DenseMap<const Decl *, comments::FullComment *> ParsedComments;
|
||||
|
||||
/// Attaches \p Comment to \p OriginalD and to its redeclaration chain
|
||||
/// and removes the redeclaration chain from the set of commentless chains.
|
||||
///
|
||||
/// Don't do anything if a comment has already been attached to \p OriginalD
|
||||
/// or its redeclaration chain.
|
||||
void cacheRawCommentForDecl(const Decl &OriginalD,
|
||||
const RawComment &Comment) const;
|
||||
|
||||
/// \returns searches \p CommentsInFile for doc comment for \p D.
|
||||
///
|
||||
/// \p RepresentativeLocForDecl is used as a location for searching doc
|
||||
/// comments. \p CommentsInFile is a mapping offset -> comment of files in the
|
||||
/// same file where \p RepresentativeLocForDecl is.
|
||||
RawComment *getRawCommentForDeclNoCacheImpl(
|
||||
const Decl *D, const SourceLocation RepresentativeLocForDecl,
|
||||
const std::map<unsigned, RawComment *> &CommentsInFile) const;
|
||||
|
||||
/// Return the documentation comment attached to a given declaration,
|
||||
/// without looking into cache.
|
||||
RawComment *getRawCommentForDeclNoCache(const Decl *D) const;
|
||||
@ -818,6 +809,16 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
getRawCommentForAnyRedecl(const Decl *D,
|
||||
const Decl **OriginalDecl = nullptr) const;
|
||||
|
||||
/// Searches existing comments for doc comments that should be attached to \p
|
||||
/// Decls. If any doc comment is found, it is parsed.
|
||||
///
|
||||
/// Requirement: All \p Decls are in the same file.
|
||||
///
|
||||
/// If the last comment in the file is already attached we assume
|
||||
/// there are not comments left to be attached to \p Decls.
|
||||
void attachCommentsToJustParsedDecls(ArrayRef<Decl *> Decls,
|
||||
const Preprocessor *PP);
|
||||
|
||||
/// Return parsed documentation comment attached to a given declaration.
|
||||
/// Returns nullptr if no comment is attached.
|
||||
///
|
||||
@ -1054,6 +1055,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
|
||||
CanQualType Id##Ty;
|
||||
#include "clang/Basic/OpenCLExtensionTypes.def"
|
||||
#define SVE_TYPE(Name, Id, SingletonId) \
|
||||
CanQualType SingletonId;
|
||||
#include "clang/Basic/AArch64SVEACLETypes.def"
|
||||
|
||||
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
|
||||
mutable QualType AutoDeductTy; // Deduction against 'auto'.
|
||||
@ -1329,6 +1333,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// Return the unique reference to the type for a constant array of
|
||||
/// the specified element type.
|
||||
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
|
||||
const Expr *SizeExpr,
|
||||
ArrayType::ArraySizeModifier ASM,
|
||||
unsigned IndexTypeQuals) const;
|
||||
|
||||
@ -1498,8 +1503,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
bool isKindOf) const;
|
||||
|
||||
QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
|
||||
ArrayRef<ObjCProtocolDecl *> protocols,
|
||||
QualType Canonical = QualType()) const;
|
||||
ArrayRef<ObjCProtocolDecl *> protocols) const;
|
||||
|
||||
bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
|
||||
|
||||
@ -2054,6 +2058,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// types.
|
||||
bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
|
||||
|
||||
/// Return true if the type has been explicitly qualified with ObjC ownership.
|
||||
/// A type may be implicitly qualified with ownership under ObjC ARC, and in
|
||||
/// some cases the compiler treats these differently.
|
||||
bool hasDirectOwnershipQualifier(QualType Ty) const;
|
||||
|
||||
/// Return true if this is an \c NSObject object with its \c NSObject
|
||||
/// attribute set.
|
||||
static bool isObjCNSObjectType(QualType Ty) {
|
||||
@ -2577,10 +2586,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
return T == getObjCSelType();
|
||||
}
|
||||
|
||||
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
|
||||
bool ObjCQualifiedIdTypesAreCompatible(const ObjCObjectPointerType *LHS,
|
||||
const ObjCObjectPointerType *RHS,
|
||||
bool ForCompare);
|
||||
|
||||
bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS);
|
||||
bool ObjCQualifiedClassTypesAreCompatible(const ObjCObjectPointerType *LHS,
|
||||
const ObjCObjectPointerType *RHS);
|
||||
|
||||
// Check the safety of assignment from LHS to RHS
|
||||
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
|
||||
@ -2802,6 +2813,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// Retrieve the context for computing mangling numbers in the given
|
||||
/// DeclContext.
|
||||
MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
|
||||
enum NeedExtraManglingDecl_t { NeedExtraManglingDecl };
|
||||
MangleNumberingContext &getManglingNumberContext(NeedExtraManglingDecl_t,
|
||||
const Decl *D);
|
||||
|
||||
std::unique_ptr<MangleNumberingContext> createMangleNumberingContext() const;
|
||||
|
||||
|
@ -24,7 +24,7 @@ class Stmt;
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
class Type;
|
||||
#define TYPE(DERIVED, BASE) class DERIVED##Type;
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
class CXXCtorInitializer;
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -87,6 +87,10 @@ class TypeSourceInfo;
|
||||
using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>;
|
||||
using ImportedCXXBaseSpecifierMap =
|
||||
llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>;
|
||||
using FileIDImportHandlerType =
|
||||
std::function<void(FileID /*ToID*/, FileID /*FromID*/)>;
|
||||
|
||||
enum class ODRHandlingType { Conservative, Liberal };
|
||||
|
||||
// An ImportPath is the list of the AST nodes which we visit during an
|
||||
// Import call.
|
||||
@ -210,6 +214,8 @@ class TypeSourceInfo;
|
||||
};
|
||||
|
||||
private:
|
||||
FileIDImportHandlerType FileIDImportHandler;
|
||||
|
||||
std::shared_ptr<ASTImporterSharedState> SharedState = nullptr;
|
||||
|
||||
/// The path which we go through during the import of a given AST node.
|
||||
@ -232,6 +238,8 @@ class TypeSourceInfo;
|
||||
/// Whether to perform a minimal import.
|
||||
bool Minimal;
|
||||
|
||||
ODRHandlingType ODRHandling;
|
||||
|
||||
/// Whether the last diagnostic came from the "from" context.
|
||||
bool LastDiagFromFrom = false;
|
||||
|
||||
@ -310,10 +318,20 @@ class TypeSourceInfo;
|
||||
|
||||
virtual ~ASTImporter();
|
||||
|
||||
/// Set a callback function for FileID import handling.
|
||||
/// The function is invoked when a FileID is imported from the From context.
|
||||
/// The imported FileID in the To context and the original FileID in the
|
||||
/// From context is passed to it.
|
||||
void setFileIDImportHandler(FileIDImportHandlerType H) {
|
||||
FileIDImportHandler = H;
|
||||
}
|
||||
|
||||
/// Whether the importer will perform a minimal import, creating
|
||||
/// to-be-completed forward declarations when possible.
|
||||
bool isMinimalImport() const { return Minimal; }
|
||||
|
||||
void setODRHandling(ODRHandlingType T) { ODRHandling = T; }
|
||||
|
||||
/// \brief Import the given object, returns the result.
|
||||
///
|
||||
/// \param To Import the object into this variable.
|
||||
@ -366,6 +384,20 @@ class TypeSourceInfo;
|
||||
/// imported. If it does not exist nullptr is returned.
|
||||
TranslationUnitDecl *GetFromTU(Decl *ToD);
|
||||
|
||||
/// Return the declaration in the "from" context from which the declaration
|
||||
/// in the "to" context was imported. If it was not imported or of the wrong
|
||||
/// type a null value is returned.
|
||||
template <typename DeclT>
|
||||
llvm::Optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const {
|
||||
auto FromI = ImportedFromDecls.find(ToD);
|
||||
if (FromI == ImportedFromDecls.end())
|
||||
return {};
|
||||
auto *FromD = dyn_cast<DeclT>(FromI->second);
|
||||
if (!FromD)
|
||||
return {};
|
||||
return FromD;
|
||||
}
|
||||
|
||||
/// Import the given declaration context from the "from"
|
||||
/// AST context into the "to" AST context.
|
||||
///
|
||||
@ -491,12 +523,11 @@ class TypeSourceInfo;
|
||||
///
|
||||
/// \param NumDecls the number of conflicting declarations in \p Decls.
|
||||
///
|
||||
/// \returns the name that the newly-imported declaration should have.
|
||||
virtual DeclarationName HandleNameConflict(DeclarationName Name,
|
||||
DeclContext *DC,
|
||||
unsigned IDNS,
|
||||
NamedDecl **Decls,
|
||||
unsigned NumDecls);
|
||||
/// \returns the name that the newly-imported declaration should have. Or
|
||||
/// an error if we can't handle the name conflict.
|
||||
virtual Expected<DeclarationName>
|
||||
HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS,
|
||||
NamedDecl **Decls, unsigned NumDecls);
|
||||
|
||||
/// Retrieve the context that AST nodes are being imported into.
|
||||
ASTContext &getToContext() const { return ToContext; }
|
||||
|
@ -47,7 +47,7 @@ class ASTImporterSharedState {
|
||||
ASTImporterSharedState() = default;
|
||||
|
||||
ASTImporterSharedState(TranslationUnitDecl &ToTU) {
|
||||
LookupTable = llvm::make_unique<ASTImporterLookupTable>(ToTU);
|
||||
LookupTable = std::make_unique<ASTImporterLookupTable>(ToTU);
|
||||
}
|
||||
|
||||
ASTImporterLookupTable *getLookupTable() { return LookupTable.get(); }
|
||||
|
@ -237,6 +237,9 @@ class ASTNodeTraverser
|
||||
|
||||
for (const auto &TP : *TPL)
|
||||
Visit(TP);
|
||||
|
||||
if (const Expr *RC = TPL->getRequiresClause())
|
||||
Visit(RC);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
|
||||
namespace clang {
|
||||
@ -42,14 +42,13 @@ struct StructuralEquivalenceContext {
|
||||
/// AST contexts for which we are checking structural equivalence.
|
||||
ASTContext &FromCtx, &ToCtx;
|
||||
|
||||
/// The set of "tentative" equivalences between two canonical
|
||||
/// declarations, mapping from a declaration in the first context to the
|
||||
/// declaration in the second context that we believe to be equivalent.
|
||||
llvm::DenseMap<Decl *, Decl *> TentativeEquivalences;
|
||||
// Queue of from-to Decl pairs that are to be checked to determine the final
|
||||
// result of equivalence of a starting Decl pair.
|
||||
std::queue<std::pair<Decl *, Decl *>> DeclsToCheck;
|
||||
|
||||
/// Queue of declarations in the first context whose equivalence
|
||||
/// with a declaration in the second context still needs to be verified.
|
||||
std::deque<Decl *> DeclsToCheck;
|
||||
// Set of from-to Decl pairs that are already visited during the check
|
||||
// (are in or were once in \c DeclsToCheck) of a starting Decl pair.
|
||||
llvm::DenseSet<std::pair<Decl *, Decl *>> VisitedDecls;
|
||||
|
||||
/// Declaration (from, to) pairs that are known not to be equivalent
|
||||
/// (which we have already complained about).
|
||||
@ -88,14 +87,14 @@ struct StructuralEquivalenceContext {
|
||||
/// Implementation functions (all static functions in
|
||||
/// ASTStructuralEquivalence.cpp) must never call this function because that
|
||||
/// will wreak havoc the internal state (\c DeclsToCheck and
|
||||
/// \c TentativeEquivalences members) and can cause faulty equivalent results.
|
||||
/// \c VisitedDecls members) and can cause faulty equivalent results.
|
||||
bool IsEquivalent(Decl *D1, Decl *D2);
|
||||
|
||||
/// Determine whether the two types are structurally equivalent.
|
||||
/// Implementation functions (all static functions in
|
||||
/// ASTStructuralEquivalence.cpp) must never call this function because that
|
||||
/// will wreak havoc the internal state (\c DeclsToCheck and
|
||||
/// \c TentativeEquivalences members) and can cause faulty equivalent results.
|
||||
/// \c VisitedDecls members) and can cause faulty equivalent results.
|
||||
bool IsEquivalent(QualType T1, QualType T2);
|
||||
|
||||
/// Find the index of the given anonymous struct/union within its
|
||||
|
@ -148,7 +148,7 @@ class ASTNodeKind {
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
NKI_Type,
|
||||
#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
NKI_OMPClause,
|
||||
#define OPENMP_CLAUSE(TextualSpelling, Class) NKI_##Class,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
@ -205,7 +205,7 @@ KIND_TO_KIND_ID(OMPClause)
|
||||
#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
#define OPENMP_CLAUSE(TextualSpelling, Class) KIND_TO_KIND_ID(Class)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
#undef KIND_TO_KIND_ID
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/AttrKinds.h"
|
||||
#include "clang/Basic/AttributeCommonInfo.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/OpenMPKinds.h"
|
||||
#include "clang/Basic/Sanitizers.h"
|
||||
@ -32,6 +33,7 @@
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class AttributeCommonInfo;
|
||||
class IdentifierInfo;
|
||||
class ObjCInterfaceDecl;
|
||||
class Expr;
|
||||
@ -40,84 +42,79 @@ namespace clang {
|
||||
class TypeSourceInfo;
|
||||
|
||||
/// Attr - This represents one attribute.
|
||||
class Attr {
|
||||
private:
|
||||
SourceRange Range;
|
||||
unsigned AttrKind : 16;
|
||||
class Attr : public AttributeCommonInfo {
|
||||
private:
|
||||
unsigned AttrKind : 16;
|
||||
|
||||
protected:
|
||||
/// An index into the spelling list of an
|
||||
/// attribute defined in Attr.td file.
|
||||
unsigned SpellingListIndex : 4;
|
||||
unsigned Inherited : 1;
|
||||
unsigned IsPackExpansion : 1;
|
||||
unsigned Implicit : 1;
|
||||
// FIXME: These are properties of the attribute kind, not state for this
|
||||
// instance of the attribute.
|
||||
unsigned IsLateParsed : 1;
|
||||
unsigned InheritEvenIfAlreadyPresent : 1;
|
||||
protected:
|
||||
/// An index into the spelling list of an
|
||||
/// attribute defined in Attr.td file.
|
||||
unsigned Inherited : 1;
|
||||
unsigned IsPackExpansion : 1;
|
||||
unsigned Implicit : 1;
|
||||
// FIXME: These are properties of the attribute kind, not state for this
|
||||
// instance of the attribute.
|
||||
unsigned IsLateParsed : 1;
|
||||
unsigned InheritEvenIfAlreadyPresent : 1;
|
||||
|
||||
void *operator new(size_t bytes) noexcept {
|
||||
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
|
||||
}
|
||||
void operator delete(void *data) noexcept {
|
||||
llvm_unreachable("Attrs cannot be released with regular 'delete'.");
|
||||
}
|
||||
void *operator new(size_t bytes) noexcept {
|
||||
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
|
||||
}
|
||||
void operator delete(void *data) 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) noexcept {
|
||||
return ::operator new(Bytes, C, Alignment);
|
||||
}
|
||||
void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
|
||||
return ::operator delete(Ptr, C, Alignment);
|
||||
}
|
||||
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) noexcept {
|
||||
return ::operator new(Bytes, C, Alignment);
|
||||
}
|
||||
void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
|
||||
return ::operator delete(Ptr, C, Alignment);
|
||||
}
|
||||
|
||||
protected:
|
||||
Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
|
||||
bool IsLateParsed)
|
||||
: Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
|
||||
Inherited(false), IsPackExpansion(false), Implicit(false),
|
||||
IsLateParsed(IsLateParsed), InheritEvenIfAlreadyPresent(false) {}
|
||||
protected:
|
||||
Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
|
||||
attr::Kind AK, bool IsLateParsed)
|
||||
: AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false),
|
||||
IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed),
|
||||
InheritEvenIfAlreadyPresent(false) {}
|
||||
|
||||
public:
|
||||
public:
|
||||
attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); }
|
||||
|
||||
attr::Kind getKind() const {
|
||||
return static_cast<attr::Kind>(AttrKind);
|
||||
}
|
||||
unsigned getSpellingListIndex() const {
|
||||
return getAttributeSpellingListIndex();
|
||||
}
|
||||
const char *getSpelling() const;
|
||||
|
||||
unsigned getSpellingListIndex() const { return SpellingListIndex; }
|
||||
const char *getSpelling() const;
|
||||
SourceLocation getLocation() const { return getRange().getBegin(); }
|
||||
|
||||
SourceLocation getLocation() const { return Range.getBegin(); }
|
||||
SourceRange getRange() const { return Range; }
|
||||
void setRange(SourceRange R) { Range = R; }
|
||||
bool isInherited() const { return Inherited; }
|
||||
|
||||
bool isInherited() const { return Inherited; }
|
||||
/// Returns true if the attribute has been implicitly created instead
|
||||
/// of explicitly written by the user.
|
||||
bool isImplicit() const { return Implicit; }
|
||||
void setImplicit(bool I) { Implicit = I; }
|
||||
|
||||
/// Returns true if the attribute has been implicitly created instead
|
||||
/// of explicitly written by the user.
|
||||
bool isImplicit() const { return Implicit; }
|
||||
void setImplicit(bool I) { Implicit = I; }
|
||||
void setPackExpansion(bool PE) { IsPackExpansion = PE; }
|
||||
bool isPackExpansion() const { return IsPackExpansion; }
|
||||
|
||||
void setPackExpansion(bool PE) { IsPackExpansion = PE; }
|
||||
bool isPackExpansion() const { return IsPackExpansion; }
|
||||
// Clone this attribute.
|
||||
Attr *clone(ASTContext &C) const;
|
||||
|
||||
// Clone this attribute.
|
||||
Attr *clone(ASTContext &C) const;
|
||||
bool isLateParsed() const { return IsLateParsed; }
|
||||
|
||||
bool isLateParsed() const { return IsLateParsed; }
|
||||
|
||||
// Pretty print this attribute.
|
||||
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
|
||||
};
|
||||
// Pretty print this attribute.
|
||||
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
|
||||
};
|
||||
|
||||
class TypeAttr : public Attr {
|
||||
protected:
|
||||
TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
|
||||
bool IsLateParsed)
|
||||
: Attr(AK, R, SpellingListIndex, IsLateParsed) {}
|
||||
TypeAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
|
||||
attr::Kind AK, bool IsLateParsed)
|
||||
: Attr(Context, CommonInfo, AK, IsLateParsed) {}
|
||||
|
||||
public:
|
||||
static bool classof(const Attr *A) {
|
||||
@ -128,9 +125,9 @@ class TypeAttr : public Attr {
|
||||
|
||||
class StmtAttr : public Attr {
|
||||
protected:
|
||||
StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
|
||||
bool IsLateParsed)
|
||||
: Attr(AK, R, SpellingListIndex, IsLateParsed) {}
|
||||
StmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
|
||||
attr::Kind AK, bool IsLateParsed)
|
||||
: Attr(Context, CommonInfo, AK, IsLateParsed) {}
|
||||
|
||||
public:
|
||||
static bool classof(const Attr *A) {
|
||||
@ -141,9 +138,10 @@ class StmtAttr : public Attr {
|
||||
|
||||
class InheritableAttr : public Attr {
|
||||
protected:
|
||||
InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
|
||||
bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
|
||||
: Attr(AK, R, SpellingListIndex, IsLateParsed) {
|
||||
InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
|
||||
attr::Kind AK, bool IsLateParsed,
|
||||
bool InheritEvenIfAlreadyPresent)
|
||||
: Attr(Context, CommonInfo, AK, IsLateParsed) {
|
||||
this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
|
||||
}
|
||||
|
||||
@ -165,9 +163,10 @@ class InheritableAttr : public Attr {
|
||||
|
||||
class InheritableParamAttr : public InheritableAttr {
|
||||
protected:
|
||||
InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
|
||||
InheritableParamAttr(ASTContext &Context,
|
||||
const AttributeCommonInfo &CommonInfo, attr::Kind AK,
|
||||
bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
|
||||
: InheritableAttr(AK, R, SpellingListIndex, IsLateParsed,
|
||||
: InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
|
||||
InheritEvenIfAlreadyPresent) {}
|
||||
|
||||
public:
|
||||
@ -182,11 +181,11 @@ class InheritableParamAttr : public InheritableAttr {
|
||||
/// for the parameter.
|
||||
class ParameterABIAttr : public InheritableParamAttr {
|
||||
protected:
|
||||
ParameterABIAttr(attr::Kind AK, SourceRange R,
|
||||
unsigned SpellingListIndex, bool IsLateParsed,
|
||||
ParameterABIAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
|
||||
attr::Kind AK, bool IsLateParsed,
|
||||
bool InheritEvenIfAlreadyPresent)
|
||||
: InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed,
|
||||
InheritEvenIfAlreadyPresent) {}
|
||||
: InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
|
||||
InheritEvenIfAlreadyPresent) {}
|
||||
|
||||
public:
|
||||
ParameterABI getABI() const {
|
||||
|
236
include/clang/AST/CXXRecordDeclDefinitionBits.def
Normal file
236
include/clang/AST/CXXRecordDeclDefinitionBits.def
Normal file
@ -0,0 +1,236 @@
|
||||
//===-- CXXRecordDeclDefinitionBits.def - Class definition bits -*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file enumerates the various bitfields that we want to store on C++ class
|
||||
// definitions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// @file CXXRecordDeclDefinitionBits.def
|
||||
///
|
||||
/// In this file, each of the bitfields representing data about a C++ class
|
||||
/// results in an expansion of the FIELD macro, which should be defined before
|
||||
/// including this file.
|
||||
///
|
||||
/// The macro have three operands:
|
||||
///
|
||||
/// Name: The name of the field, as a member of CXXRecordDecl::DefinitionData.
|
||||
///
|
||||
/// BitWidth: The width of the field in bits.
|
||||
///
|
||||
/// MergePolicy: How to behave when the value of the field is different in
|
||||
/// multiple translation units, one of:
|
||||
/// NO_MERGE: It is an ODR violation if the fields do not match.
|
||||
/// MERGE_OR: Merge the fields by ORing them together.
|
||||
|
||||
#ifndef FIELD
|
||||
#error define FIELD before including this file
|
||||
#endif
|
||||
|
||||
/// True if this class has any user-declared constructors.
|
||||
FIELD(UserDeclaredConstructor, 1, NO_MERGE)
|
||||
|
||||
/// The user-declared special members which this class has.
|
||||
FIELD(UserDeclaredSpecialMembers, 6, NO_MERGE)
|
||||
|
||||
/// True when this class is an aggregate.
|
||||
FIELD(Aggregate, 1, NO_MERGE)
|
||||
|
||||
/// True when this class is a POD-type.
|
||||
FIELD(PlainOldData, 1, NO_MERGE)
|
||||
|
||||
/// True when this class is empty for traits purposes, that is:
|
||||
/// * has no data members other than 0-width bit-fields and empty fields
|
||||
/// marked [[no_unique_address]]
|
||||
/// * has no virtual function/base, and
|
||||
/// * doesn't inherit from a non-empty class.
|
||||
/// Doesn't take union-ness into account.
|
||||
FIELD(Empty, 1, NO_MERGE)
|
||||
|
||||
/// True when this class is polymorphic, i.e., has at
|
||||
/// least one virtual member or derives from a polymorphic class.
|
||||
FIELD(Polymorphic, 1, NO_MERGE)
|
||||
|
||||
/// True when this class is abstract, i.e., has at least
|
||||
/// one pure virtual function, (that can come from a base class).
|
||||
FIELD(Abstract, 1, NO_MERGE)
|
||||
|
||||
/// True when this class is standard-layout, per the applicable
|
||||
/// language rules (including DRs).
|
||||
FIELD(IsStandardLayout, 1, NO_MERGE)
|
||||
|
||||
/// True when this class was standard-layout under the C++11
|
||||
/// definition.
|
||||
///
|
||||
/// C++11 [class]p7. A standard-layout class is a class that:
|
||||
/// * has no non-static data members of type non-standard-layout class (or
|
||||
/// array of such types) or reference,
|
||||
/// * has no virtual functions (10.3) and no virtual base classes (10.1),
|
||||
/// * has the same access control (Clause 11) for all non-static data
|
||||
/// members
|
||||
/// * has no non-standard-layout base classes,
|
||||
/// * either has no non-static data members in the most derived class and at
|
||||
/// most one base class with non-static data members, or has no base
|
||||
/// classes with non-static data members, and
|
||||
/// * has no base classes of the same type as the first non-static data
|
||||
/// member.
|
||||
FIELD(IsCXX11StandardLayout, 1, NO_MERGE)
|
||||
|
||||
/// True when any base class has any declared non-static data
|
||||
/// members or bit-fields.
|
||||
/// This is a helper bit of state used to implement IsStandardLayout more
|
||||
/// efficiently.
|
||||
FIELD(HasBasesWithFields, 1, NO_MERGE)
|
||||
|
||||
/// True when any base class has any declared non-static data
|
||||
/// members.
|
||||
/// This is a helper bit of state used to implement IsCXX11StandardLayout
|
||||
/// more efficiently.
|
||||
FIELD(HasBasesWithNonStaticDataMembers, 1, NO_MERGE)
|
||||
|
||||
/// True when there are private non-static data members.
|
||||
FIELD(HasPrivateFields, 1, NO_MERGE)
|
||||
|
||||
/// True when there are protected non-static data members.
|
||||
FIELD(HasProtectedFields, 1, NO_MERGE)
|
||||
|
||||
/// True when there are private non-static data members.
|
||||
FIELD(HasPublicFields, 1, NO_MERGE)
|
||||
|
||||
/// True if this class (or any subobject) has mutable fields.
|
||||
FIELD(HasMutableFields, 1, NO_MERGE)
|
||||
|
||||
/// True if this class (or any nested anonymous struct or union)
|
||||
/// has variant members.
|
||||
FIELD(HasVariantMembers, 1, NO_MERGE)
|
||||
|
||||
/// True if there no non-field members declared by the user.
|
||||
FIELD(HasOnlyCMembers, 1, NO_MERGE)
|
||||
|
||||
/// True if any field has an in-class initializer, including those
|
||||
/// within anonymous unions or structs.
|
||||
FIELD(HasInClassInitializer, 1, NO_MERGE)
|
||||
|
||||
/// True if any field is of reference type, and does not have an
|
||||
/// in-class initializer.
|
||||
///
|
||||
/// In this case, value-initialization of this class is illegal in C++98
|
||||
/// even if the class has a trivial default constructor.
|
||||
FIELD(HasUninitializedReferenceMember, 1, NO_MERGE)
|
||||
|
||||
/// True if any non-mutable field whose type doesn't have a user-
|
||||
/// provided default ctor also doesn't have an in-class initializer.
|
||||
FIELD(HasUninitializedFields, 1, NO_MERGE)
|
||||
|
||||
/// True if there are any member using-declarations that inherit
|
||||
/// constructors from a base class.
|
||||
FIELD(HasInheritedConstructor, 1, NO_MERGE)
|
||||
|
||||
/// True if there are any member using-declarations named
|
||||
/// 'operator='.
|
||||
FIELD(HasInheritedAssignment, 1, NO_MERGE)
|
||||
|
||||
/// These flags are \c true if a defaulted corresponding special
|
||||
/// member can't be fully analyzed without performing overload resolution.
|
||||
/// @{
|
||||
FIELD(NeedOverloadResolutionForCopyConstructor, 1, NO_MERGE)
|
||||
FIELD(NeedOverloadResolutionForMoveConstructor, 1, NO_MERGE)
|
||||
FIELD(NeedOverloadResolutionForMoveAssignment, 1, NO_MERGE)
|
||||
FIELD(NeedOverloadResolutionForDestructor, 1, NO_MERGE)
|
||||
/// @}
|
||||
|
||||
/// These flags are \c true if an implicit defaulted corresponding
|
||||
/// special member would be defined as deleted.
|
||||
/// @{
|
||||
FIELD(DefaultedCopyConstructorIsDeleted, 1, NO_MERGE)
|
||||
FIELD(DefaultedMoveConstructorIsDeleted, 1, NO_MERGE)
|
||||
FIELD(DefaultedMoveAssignmentIsDeleted, 1, NO_MERGE)
|
||||
FIELD(DefaultedDestructorIsDeleted, 1, NO_MERGE)
|
||||
/// @}
|
||||
|
||||
/// The trivial special members which this class has, per
|
||||
/// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25,
|
||||
/// C++11 [class.dtor]p5, or would have if the member were not suppressed.
|
||||
///
|
||||
/// This excludes any user-declared but not user-provided special members
|
||||
/// which have been declared but not yet defined.
|
||||
FIELD(HasTrivialSpecialMembers, 6, MERGE_OR)
|
||||
|
||||
/// These bits keep track of the triviality of special functions for the
|
||||
/// purpose of calls. Only the bits corresponding to SMF_CopyConstructor,
|
||||
/// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
|
||||
FIELD(HasTrivialSpecialMembersForCall, 6, MERGE_OR)
|
||||
|
||||
/// The declared special members of this class which are known to be
|
||||
/// non-trivial.
|
||||
///
|
||||
/// This excludes any user-declared but not user-provided special members
|
||||
/// which have been declared but not yet defined, and any implicit special
|
||||
/// members which have not yet been declared.
|
||||
FIELD(DeclaredNonTrivialSpecialMembers, 6, MERGE_OR)
|
||||
|
||||
/// These bits keep track of the declared special members that are
|
||||
/// non-trivial for the purpose of calls.
|
||||
/// Only the bits corresponding to SMF_CopyConstructor,
|
||||
/// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
|
||||
FIELD(DeclaredNonTrivialSpecialMembersForCall, 6, MERGE_OR)
|
||||
|
||||
/// True when this class has a destructor with no semantic effect.
|
||||
FIELD(HasIrrelevantDestructor, 1, NO_MERGE)
|
||||
|
||||
/// True when this class has at least one user-declared constexpr
|
||||
/// constructor which is neither the copy nor move constructor.
|
||||
FIELD(HasConstexprNonCopyMoveConstructor, 1, MERGE_OR)
|
||||
|
||||
/// True if this class has a (possibly implicit) defaulted default
|
||||
/// constructor.
|
||||
FIELD(HasDefaultedDefaultConstructor, 1, MERGE_OR)
|
||||
|
||||
/// True if a defaulted default constructor for this class would
|
||||
/// be constexpr.
|
||||
FIELD(DefaultedDefaultConstructorIsConstexpr, 1, NO_MERGE)
|
||||
|
||||
/// True if this class has a constexpr default constructor.
|
||||
///
|
||||
/// This is true for either a user-declared constexpr default constructor
|
||||
/// or an implicitly declared constexpr default constructor.
|
||||
FIELD(HasConstexprDefaultConstructor, 1, MERGE_OR)
|
||||
|
||||
/// True if a defaulted destructor for this class would be constexpr.
|
||||
FIELD(DefaultedDestructorIsConstexpr, 1, NO_MERGE)
|
||||
|
||||
/// True when this class contains at least one non-static data
|
||||
/// member or base class of non-literal or volatile type.
|
||||
FIELD(HasNonLiteralTypeFieldsOrBases, 1, NO_MERGE)
|
||||
|
||||
/// Whether we have a C++11 user-provided default constructor (not
|
||||
/// explicitly deleted or defaulted).
|
||||
FIELD(UserProvidedDefaultConstructor, 1, NO_MERGE)
|
||||
|
||||
/// The special members which have been declared for this class,
|
||||
/// either by the user or implicitly.
|
||||
FIELD(DeclaredSpecialMembers, 6, MERGE_OR)
|
||||
|
||||
/// Whether an implicit copy constructor could have a const-qualified
|
||||
/// parameter, for initializing virtual bases and for other subobjects.
|
||||
FIELD(ImplicitCopyConstructorCanHaveConstParamForVBase, 1, NO_MERGE)
|
||||
FIELD(ImplicitCopyConstructorCanHaveConstParamForNonVBase, 1, NO_MERGE)
|
||||
|
||||
/// Whether an implicit copy assignment operator would have a
|
||||
/// const-qualified parameter.
|
||||
FIELD(ImplicitCopyAssignmentHasConstParam, 1, NO_MERGE)
|
||||
|
||||
/// Whether any declared copy constructor has a const-qualified
|
||||
/// parameter.
|
||||
FIELD(HasDeclaredCopyConstructorWithConstParam, 1, MERGE_OR)
|
||||
|
||||
/// Whether any declared copy assignment operator has either a
|
||||
/// const-qualified reference parameter or a non-reference parameter.
|
||||
FIELD(HasDeclaredCopyAssignmentWithConstParam, 1, MERGE_OR)
|
||||
|
||||
#undef FIELD
|
@ -14,6 +14,7 @@
|
||||
#define LLVM_CLANG_AST_CHARUNITS_H
|
||||
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/Support/Alignment.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
|
||||
@ -177,6 +178,10 @@ namespace clang {
|
||||
/// getQuantity - Get the raw integer representation of this quantity.
|
||||
QuantityType getQuantity() const { return Quantity; }
|
||||
|
||||
/// getAsAlign - Returns Quantity as a valid llvm::Align,
|
||||
/// Beware llvm::Align assumes power of two 8-bit bytes.
|
||||
llvm::Align getAsAlign() const { return llvm::Align(Quantity); }
|
||||
|
||||
/// alignTo - Returns the next integer (mod 2**64) that is
|
||||
/// greater than or equal to this quantity and is a multiple of \p Align.
|
||||
/// Align must be non-zero.
|
||||
|
@ -139,6 +139,7 @@ def Post : BlockCommand<"post">;
|
||||
def Pre : BlockCommand<"pre">;
|
||||
def Remark : BlockCommand<"remark">;
|
||||
def Remarks : BlockCommand<"remarks">;
|
||||
def Retval : BlockCommand<"retval">;
|
||||
def Sa : BlockCommand<"sa">;
|
||||
def See : BlockCommand<"see">;
|
||||
def Since : BlockCommand<"since">;
|
||||
|
@ -352,8 +352,7 @@ class Lexer {
|
||||
|
||||
void lex(Token &T);
|
||||
|
||||
StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr,
|
||||
bool *Invalid = nullptr) const;
|
||||
StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr) const;
|
||||
};
|
||||
|
||||
} // end namespace comments
|
||||
|
@ -310,6 +310,14 @@ class NamedDecl : public Decl {
|
||||
void printQualifiedName(raw_ostream &OS) const;
|
||||
void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const;
|
||||
|
||||
/// Print only the nested name specifier part of a fully-qualified name,
|
||||
/// including the '::' at the end. E.g.
|
||||
/// when `printQualifiedName(D)` prints "A::B::i",
|
||||
/// this function prints "A::B::".
|
||||
void printNestedNameSpecifier(raw_ostream &OS) const;
|
||||
void printNestedNameSpecifier(raw_ostream &OS,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
// FIXME: Remove string version.
|
||||
std::string getQualifiedNameAsString() const;
|
||||
|
||||
@ -800,12 +808,19 @@ struct EvaluatedStmt {
|
||||
/// valid if CheckedICE is true.
|
||||
bool IsICE : 1;
|
||||
|
||||
/// Whether this variable is known to have constant destruction. That is,
|
||||
/// whether running the destructor on the initial value is a side-effect
|
||||
/// (and doesn't inspect any state that might have changed during program
|
||||
/// execution). This is currently only computed if the destructor is
|
||||
/// non-trivial.
|
||||
bool HasConstantDestruction : 1;
|
||||
|
||||
Stmt *Value;
|
||||
APValue Evaluated;
|
||||
|
||||
EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
|
||||
CheckingICE(false), IsICE(false) {}
|
||||
|
||||
EvaluatedStmt()
|
||||
: WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
|
||||
CheckingICE(false), IsICE(false), HasConstantDestruction(false) {}
|
||||
};
|
||||
|
||||
/// Represents a variable declaration or definition.
|
||||
@ -1226,6 +1241,14 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
|
||||
void setInit(Expr *I);
|
||||
|
||||
/// Get the initializing declaration of this variable, if any. This is
|
||||
/// usually the definition, except that for a static data member it can be
|
||||
/// the in-class declaration.
|
||||
VarDecl *getInitializingDeclaration();
|
||||
const VarDecl *getInitializingDeclaration() const {
|
||||
return const_cast<VarDecl *>(this)->getInitializingDeclaration();
|
||||
}
|
||||
|
||||
/// Determine whether this variable's value might be usable in a
|
||||
/// constant expression, according to the relevant language standard.
|
||||
/// This only checks properties of the declaration, and does not check
|
||||
@ -1251,6 +1274,14 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
/// to untyped APValue if the value could not be evaluated.
|
||||
APValue *getEvaluatedValue() const;
|
||||
|
||||
/// Evaluate the destruction of this variable to determine if it constitutes
|
||||
/// constant destruction.
|
||||
///
|
||||
/// \pre isInitICE()
|
||||
/// \return \c true if this variable has constant destruction, \c false if
|
||||
/// not.
|
||||
bool evaluateDestruction(SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
|
||||
|
||||
/// Determines whether it is already known whether the
|
||||
/// initializer is an integral constant expression or not.
|
||||
bool isInitKnownICE() const;
|
||||
@ -1489,9 +1520,14 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
// has no definition within this source file.
|
||||
bool isKnownToBeDefined() const;
|
||||
|
||||
/// Do we need to emit an exit-time destructor for this variable?
|
||||
/// Is destruction of this variable entirely suppressed? If so, the variable
|
||||
/// need not have a usable destructor at all.
|
||||
bool isNoDestroy(const ASTContext &) const;
|
||||
|
||||
/// Do we need to emit an exit-time destructor for this variable, and if so,
|
||||
/// what kind?
|
||||
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; }
|
||||
@ -4078,13 +4114,9 @@ class BlockDecl : public Decl, public DeclContext {
|
||||
void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
|
||||
bool CapturesCXXThis);
|
||||
|
||||
unsigned getBlockManglingNumber() const {
|
||||
return ManglingNumber;
|
||||
}
|
||||
unsigned getBlockManglingNumber() const { return ManglingNumber; }
|
||||
|
||||
Decl *getBlockManglingContextDecl() const {
|
||||
return ManglingContextDecl;
|
||||
}
|
||||
Decl *getBlockManglingContextDecl() const { return ManglingContextDecl; }
|
||||
|
||||
void setBlockMangling(unsigned Number, Decl *Ctx) {
|
||||
ManglingNumber = Number;
|
||||
|
@ -959,7 +959,7 @@ class alignas(8) Decl {
|
||||
/// as this declaration, or NULL if there is no previous declaration.
|
||||
Decl *getPreviousDecl() { return getPreviousDeclImpl(); }
|
||||
|
||||
/// Retrieve the most recent declaration that declares the same entity
|
||||
/// Retrieve the previous declaration that declares the same entity
|
||||
/// as this declaration, or NULL if there is no previous declaration.
|
||||
const Decl *getPreviousDecl() const {
|
||||
return const_cast<Decl *>(this)->getPreviousDeclImpl();
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/PointerLikeTypeTraits.h"
|
||||
@ -73,52 +74,6 @@ class TemplateDecl;
|
||||
class TemplateParameterList;
|
||||
class UsingDecl;
|
||||
|
||||
/// Represents any kind of function declaration, whether it is a
|
||||
/// concrete function or a function template.
|
||||
class AnyFunctionDecl {
|
||||
NamedDecl *Function;
|
||||
|
||||
AnyFunctionDecl(NamedDecl *ND) : Function(ND) {}
|
||||
|
||||
public:
|
||||
AnyFunctionDecl(FunctionDecl *FD) : Function(FD) {}
|
||||
AnyFunctionDecl(FunctionTemplateDecl *FTD);
|
||||
|
||||
/// Implicily converts any function or function template into a
|
||||
/// named declaration.
|
||||
operator NamedDecl *() const { return Function; }
|
||||
|
||||
/// Retrieve the underlying function or function template.
|
||||
NamedDecl *get() const { return Function; }
|
||||
|
||||
static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) {
|
||||
return AnyFunctionDecl(ND);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// Provide PointerLikeTypeTraits for non-cvr pointers.
|
||||
template<>
|
||||
struct PointerLikeTypeTraits< ::clang::AnyFunctionDecl> {
|
||||
static void *getAsVoidPointer(::clang::AnyFunctionDecl F) {
|
||||
return F.get();
|
||||
}
|
||||
|
||||
static ::clang::AnyFunctionDecl getFromVoidPointer(void *P) {
|
||||
return ::clang::AnyFunctionDecl::getFromNamedDecl(
|
||||
static_cast< ::clang::NamedDecl*>(P));
|
||||
}
|
||||
|
||||
enum { NumLowBitsAvailable = 2 };
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// Represents an access specifier followed by colon ':'.
|
||||
///
|
||||
/// An objects of this class represents sugar for the syntactic occurrence
|
||||
@ -322,207 +277,9 @@ class CXXRecordDecl : public RecordDecl {
|
||||
};
|
||||
|
||||
struct DefinitionData {
|
||||
/// True if this class has any user-declared constructors.
|
||||
unsigned UserDeclaredConstructor : 1;
|
||||
|
||||
/// The user-declared special members which this class has.
|
||||
unsigned UserDeclaredSpecialMembers : 6;
|
||||
|
||||
/// True when this class is an aggregate.
|
||||
unsigned Aggregate : 1;
|
||||
|
||||
/// True when this class is a POD-type.
|
||||
unsigned PlainOldData : 1;
|
||||
|
||||
/// True when this class is empty for traits purposes, that is:
|
||||
/// * has no data members other than 0-width bit-fields and empty fields
|
||||
/// marked [[no_unique_address]]
|
||||
/// * has no virtual function/base, and
|
||||
/// * doesn't inherit from a non-empty class.
|
||||
/// Doesn't take union-ness into account.
|
||||
unsigned Empty : 1;
|
||||
|
||||
/// True when this class is polymorphic, i.e., has at
|
||||
/// least one virtual member or derives from a polymorphic class.
|
||||
unsigned Polymorphic : 1;
|
||||
|
||||
/// True when this class is abstract, i.e., has at least
|
||||
/// one pure virtual function, (that can come from a base class).
|
||||
unsigned Abstract : 1;
|
||||
|
||||
/// True when this class is standard-layout, per the applicable
|
||||
/// language rules (including DRs).
|
||||
unsigned IsStandardLayout : 1;
|
||||
|
||||
/// True when this class was standard-layout under the C++11
|
||||
/// definition.
|
||||
///
|
||||
/// C++11 [class]p7. A standard-layout class is a class that:
|
||||
/// * has no non-static data members of type non-standard-layout class (or
|
||||
/// array of such types) or reference,
|
||||
/// * has no virtual functions (10.3) and no virtual base classes (10.1),
|
||||
/// * has the same access control (Clause 11) for all non-static data
|
||||
/// members
|
||||
/// * has no non-standard-layout base classes,
|
||||
/// * either has no non-static data members in the most derived class and at
|
||||
/// most one base class with non-static data members, or has no base
|
||||
/// classes with non-static data members, and
|
||||
/// * has no base classes of the same type as the first non-static data
|
||||
/// member.
|
||||
unsigned IsCXX11StandardLayout : 1;
|
||||
|
||||
/// True when any base class has any declared non-static data
|
||||
/// members or bit-fields.
|
||||
/// This is a helper bit of state used to implement IsStandardLayout more
|
||||
/// efficiently.
|
||||
unsigned HasBasesWithFields : 1;
|
||||
|
||||
/// True when any base class has any declared non-static data
|
||||
/// members.
|
||||
/// This is a helper bit of state used to implement IsCXX11StandardLayout
|
||||
/// more efficiently.
|
||||
unsigned HasBasesWithNonStaticDataMembers : 1;
|
||||
|
||||
/// True when there are private non-static data members.
|
||||
unsigned HasPrivateFields : 1;
|
||||
|
||||
/// True when there are protected non-static data members.
|
||||
unsigned HasProtectedFields : 1;
|
||||
|
||||
/// True when there are private non-static data members.
|
||||
unsigned HasPublicFields : 1;
|
||||
|
||||
/// True if this class (or any subobject) has mutable fields.
|
||||
unsigned HasMutableFields : 1;
|
||||
|
||||
/// True if this class (or any nested anonymous struct or union)
|
||||
/// has variant members.
|
||||
unsigned HasVariantMembers : 1;
|
||||
|
||||
/// True if there no non-field members declared by the user.
|
||||
unsigned HasOnlyCMembers : 1;
|
||||
|
||||
/// True if any field has an in-class initializer, including those
|
||||
/// within anonymous unions or structs.
|
||||
unsigned HasInClassInitializer : 1;
|
||||
|
||||
/// True if any field is of reference type, and does not have an
|
||||
/// in-class initializer.
|
||||
///
|
||||
/// In this case, value-initialization of this class is illegal in C++98
|
||||
/// even if the class has a trivial default constructor.
|
||||
unsigned HasUninitializedReferenceMember : 1;
|
||||
|
||||
/// True if any non-mutable field whose type doesn't have a user-
|
||||
/// provided default ctor also doesn't have an in-class initializer.
|
||||
unsigned HasUninitializedFields : 1;
|
||||
|
||||
/// True if there are any member using-declarations that inherit
|
||||
/// constructors from a base class.
|
||||
unsigned HasInheritedConstructor : 1;
|
||||
|
||||
/// True if there are any member using-declarations named
|
||||
/// 'operator='.
|
||||
unsigned HasInheritedAssignment : 1;
|
||||
|
||||
/// These flags are \c true if a defaulted corresponding special
|
||||
/// member can't be fully analyzed without performing overload resolution.
|
||||
/// @{
|
||||
unsigned NeedOverloadResolutionForCopyConstructor : 1;
|
||||
unsigned NeedOverloadResolutionForMoveConstructor : 1;
|
||||
unsigned NeedOverloadResolutionForMoveAssignment : 1;
|
||||
unsigned NeedOverloadResolutionForDestructor : 1;
|
||||
/// @}
|
||||
|
||||
/// These flags are \c true if an implicit defaulted corresponding
|
||||
/// special member would be defined as deleted.
|
||||
/// @{
|
||||
unsigned DefaultedCopyConstructorIsDeleted : 1;
|
||||
unsigned DefaultedMoveConstructorIsDeleted : 1;
|
||||
unsigned DefaultedMoveAssignmentIsDeleted : 1;
|
||||
unsigned DefaultedDestructorIsDeleted : 1;
|
||||
/// @}
|
||||
|
||||
/// The trivial special members which this class has, per
|
||||
/// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25,
|
||||
/// C++11 [class.dtor]p5, or would have if the member were not suppressed.
|
||||
///
|
||||
/// This excludes any user-declared but not user-provided special members
|
||||
/// which have been declared but not yet defined.
|
||||
unsigned HasTrivialSpecialMembers : 6;
|
||||
|
||||
/// These bits keep track of the triviality of special functions for the
|
||||
/// purpose of calls. Only the bits corresponding to SMF_CopyConstructor,
|
||||
/// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
|
||||
unsigned HasTrivialSpecialMembersForCall : 6;
|
||||
|
||||
/// The declared special members of this class which are known to be
|
||||
/// non-trivial.
|
||||
///
|
||||
/// This excludes any user-declared but not user-provided special members
|
||||
/// which have been declared but not yet defined, and any implicit special
|
||||
/// members which have not yet been declared.
|
||||
unsigned DeclaredNonTrivialSpecialMembers : 6;
|
||||
|
||||
/// These bits keep track of the declared special members that are
|
||||
/// non-trivial for the purpose of calls.
|
||||
/// Only the bits corresponding to SMF_CopyConstructor,
|
||||
/// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
|
||||
unsigned DeclaredNonTrivialSpecialMembersForCall : 6;
|
||||
|
||||
/// True when this class has a destructor with no semantic effect.
|
||||
unsigned HasIrrelevantDestructor : 1;
|
||||
|
||||
/// True when this class has at least one user-declared constexpr
|
||||
/// constructor which is neither the copy nor move constructor.
|
||||
unsigned HasConstexprNonCopyMoveConstructor : 1;
|
||||
|
||||
/// True if this class has a (possibly implicit) defaulted default
|
||||
/// constructor.
|
||||
unsigned HasDefaultedDefaultConstructor : 1;
|
||||
|
||||
/// True if a defaulted default constructor for this class would
|
||||
/// be constexpr.
|
||||
unsigned DefaultedDefaultConstructorIsConstexpr : 1;
|
||||
|
||||
/// True if this class has a constexpr default constructor.
|
||||
///
|
||||
/// This is true for either a user-declared constexpr default constructor
|
||||
/// or an implicitly declared constexpr default constructor.
|
||||
unsigned HasConstexprDefaultConstructor : 1;
|
||||
|
||||
/// True when this class contains at least one non-static data
|
||||
/// member or base class of non-literal or volatile type.
|
||||
unsigned HasNonLiteralTypeFieldsOrBases : 1;
|
||||
|
||||
/// True when visible conversion functions are already computed
|
||||
/// and are available.
|
||||
unsigned ComputedVisibleConversions : 1;
|
||||
|
||||
/// Whether we have a C++11 user-provided default constructor (not
|
||||
/// explicitly deleted or defaulted).
|
||||
unsigned UserProvidedDefaultConstructor : 1;
|
||||
|
||||
/// The special members which have been declared for this class,
|
||||
/// either by the user or implicitly.
|
||||
unsigned DeclaredSpecialMembers : 6;
|
||||
|
||||
/// Whether an implicit copy constructor could have a const-qualified
|
||||
/// parameter, for initializing virtual bases and for other subobjects.
|
||||
unsigned ImplicitCopyConstructorCanHaveConstParamForVBase : 1;
|
||||
unsigned ImplicitCopyConstructorCanHaveConstParamForNonVBase : 1;
|
||||
|
||||
/// Whether an implicit copy assignment operator would have a
|
||||
/// const-qualified parameter.
|
||||
unsigned ImplicitCopyAssignmentHasConstParam : 1;
|
||||
|
||||
/// Whether any declared copy constructor has a const-qualified
|
||||
/// parameter.
|
||||
unsigned HasDeclaredCopyConstructorWithConstParam : 1;
|
||||
|
||||
/// Whether any declared copy assignment operator has either a
|
||||
/// const-qualified reference parameter or a non-reference parameter.
|
||||
unsigned HasDeclaredCopyAssignmentWithConstParam : 1;
|
||||
#define FIELD(Name, Width, Merge) \
|
||||
unsigned Name : Width;
|
||||
#include "CXXRecordDeclDefinitionBits.def"
|
||||
|
||||
/// Whether this class describes a C++ lambda.
|
||||
unsigned IsLambda : 1;
|
||||
@ -530,6 +287,10 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// Whether we are currently parsing base specifiers.
|
||||
unsigned IsParsingBaseSpecifiers : 1;
|
||||
|
||||
/// True when visible conversion functions are already computed
|
||||
/// and are available.
|
||||
unsigned ComputedVisibleConversions : 1;
|
||||
|
||||
unsigned HasODRHash : 1;
|
||||
|
||||
/// A hash of parts of the class to help in ODR checking.
|
||||
@ -628,9 +389,12 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// The number of explicit captures in this lambda.
|
||||
unsigned NumExplicitCaptures : 13;
|
||||
|
||||
/// Has known `internal` linkage.
|
||||
unsigned HasKnownInternalLinkage : 1;
|
||||
|
||||
/// The number used to indicate this lambda expression for name
|
||||
/// mangling in the Itanium C++ ABI.
|
||||
unsigned ManglingNumber = 0;
|
||||
unsigned ManglingNumber : 31;
|
||||
|
||||
/// The declaration that provides context for this lambda, if the
|
||||
/// actual DeclContext does not suffice. This is used for lambdas that
|
||||
@ -645,12 +409,12 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// The type of the call method.
|
||||
TypeSourceInfo *MethodTyInfo;
|
||||
|
||||
LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
|
||||
bool Dependent, bool IsGeneric,
|
||||
LambdaCaptureDefault CaptureDefault)
|
||||
: DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
|
||||
CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0),
|
||||
MethodTyInfo(Info) {
|
||||
LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent,
|
||||
bool IsGeneric, LambdaCaptureDefault CaptureDefault)
|
||||
: DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
|
||||
CaptureDefault(CaptureDefault), NumCaptures(0),
|
||||
NumExplicitCaptures(0), HasKnownInternalLinkage(0), ManglingNumber(0),
|
||||
MethodTyInfo(Info) {
|
||||
IsLambda = true;
|
||||
|
||||
// C++1z [expr.prim.lambda]p4:
|
||||
@ -1214,6 +978,10 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// if this is a closure type.
|
||||
CXXMethodDecl *getLambdaCallOperator() const;
|
||||
|
||||
/// Retrieve the dependent lambda call operator of the closure type
|
||||
/// if this is a templated closure type.
|
||||
FunctionTemplateDecl *getDependentLambdaCallOperator() const;
|
||||
|
||||
/// Retrieve the lambda static invoker, the address of which
|
||||
/// is returned by the conversion operator, and the body of which
|
||||
/// is forwarded to the lambda call operator.
|
||||
@ -1398,7 +1166,8 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// would be constexpr.
|
||||
bool defaultedDefaultConstructorIsConstexpr() const {
|
||||
return data().DefaultedDefaultConstructorIsConstexpr &&
|
||||
(!isUnion() || hasInClassInitializer() || !hasVariantMembers());
|
||||
(!isUnion() || hasInClassInitializer() || !hasVariantMembers() ||
|
||||
getASTContext().getLangOpts().CPlusPlus2a);
|
||||
}
|
||||
|
||||
/// Determine whether this class has a constexpr default constructor.
|
||||
@ -1486,6 +1255,16 @@ class CXXRecordDecl : public RecordDecl {
|
||||
!(data().HasTrivialSpecialMembers & SMF_MoveAssignment));
|
||||
}
|
||||
|
||||
/// Determine whether a defaulted default constructor for this class
|
||||
/// would be constexpr.
|
||||
bool defaultedDestructorIsConstexpr() const {
|
||||
return data().DefaultedDestructorIsConstexpr &&
|
||||
getASTContext().getLangOpts().CPlusPlus2a;
|
||||
}
|
||||
|
||||
/// Determine whether this class has a constexpr destructor.
|
||||
bool hasConstexprDestructor() const;
|
||||
|
||||
/// Determine whether this class has a trivial destructor
|
||||
/// (C++ [class.dtor]p3)
|
||||
bool hasTrivialDestructor() const {
|
||||
@ -1577,8 +1356,10 @@ class CXXRecordDecl : public RecordDecl {
|
||||
///
|
||||
/// Only in C++17 and beyond, are lambdas literal types.
|
||||
bool isLiteral() const {
|
||||
return hasTrivialDestructor() &&
|
||||
(!isLambda() || getASTContext().getLangOpts().CPlusPlus17) &&
|
||||
ASTContext &Ctx = getASTContext();
|
||||
return (Ctx.getLangOpts().CPlusPlus2a ? hasConstexprDestructor()
|
||||
: hasTrivialDestructor()) &&
|
||||
(!isLambda() || Ctx.getLangOpts().CPlusPlus17) &&
|
||||
!hasNonLiteralTypeFieldsOrBases() &&
|
||||
(isAggregate() || isLambda() ||
|
||||
hasConstexprNonCopyMoveConstructor() ||
|
||||
@ -1927,6 +1708,13 @@ class CXXRecordDecl : public RecordDecl {
|
||||
return getLambdaData().ManglingNumber;
|
||||
}
|
||||
|
||||
/// The lambda is known to has internal linkage no matter whether it has name
|
||||
/// mangling number.
|
||||
bool hasKnownLambdaInternalLinkage() const {
|
||||
assert(isLambda() && "Not a lambda closure type!");
|
||||
return getLambdaData().HasKnownInternalLinkage;
|
||||
}
|
||||
|
||||
/// Retrieve the declaration that provides additional context for a
|
||||
/// lambda, when the normal declaration context is not specific enough.
|
||||
///
|
||||
@ -1940,9 +1728,12 @@ class CXXRecordDecl : public RecordDecl {
|
||||
|
||||
/// Set the mangling number and context declaration for a lambda
|
||||
/// class.
|
||||
void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) {
|
||||
void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl,
|
||||
bool HasKnownInternalLinkage = false) {
|
||||
assert(isLambda() && "Not a lambda closure type!");
|
||||
getLambdaData().ManglingNumber = ManglingNumber;
|
||||
getLambdaData().ContextDecl = ContextDecl;
|
||||
getLambdaData().HasKnownInternalLinkage = HasKnownInternalLinkage;
|
||||
}
|
||||
|
||||
/// Returns the inheritance model used for this record.
|
||||
@ -2265,7 +2056,7 @@ class CXXMethodDecl : public FunctionDecl {
|
||||
const CXXRecordDecl *Decl);
|
||||
|
||||
Qualifiers getMethodQualifiers() const {
|
||||
return getType()->getAs<FunctionProtoType>()->getMethodQuals();
|
||||
return getType()->castAs<FunctionProtoType>()->getMethodQuals();
|
||||
}
|
||||
|
||||
/// Retrieve the ref-qualifier associated with this method.
|
||||
@ -2280,7 +2071,7 @@ class CXXMethodDecl : public FunctionDecl {
|
||||
/// };
|
||||
/// @endcode
|
||||
RefQualifierKind getRefQualifier() const {
|
||||
return getType()->getAs<FunctionProtoType>()->getRefQualifier();
|
||||
return getType()->castAs<FunctionProtoType>()->getRefQualifier();
|
||||
}
|
||||
|
||||
bool hasInlineBody() const;
|
||||
@ -2600,9 +2391,9 @@ class CXXConstructorDecl final
|
||||
|
||||
ExplicitSpecifier getExplicitSpecifierInternal() const {
|
||||
if (CXXConstructorDeclBits.HasTrailingExplicitSpecifier)
|
||||
return *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>();
|
||||
return *getTrailingObjects<ExplicitSpecifier>();
|
||||
return ExplicitSpecifier(
|
||||
nullptr, getCanonicalDecl()->CXXConstructorDeclBits.IsSimpleExplicit
|
||||
nullptr, CXXConstructorDeclBits.IsSimpleExplicit
|
||||
? ExplicitSpecKind::ResolvedTrue
|
||||
: ExplicitSpecKind::ResolvedFalse);
|
||||
}
|
||||
@ -2643,10 +2434,10 @@ class CXXConstructorDecl final
|
||||
InheritedConstructor Inherited = InheritedConstructor());
|
||||
|
||||
ExplicitSpecifier getExplicitSpecifier() {
|
||||
return getExplicitSpecifierInternal();
|
||||
return getCanonicalDecl()->getExplicitSpecifierInternal();
|
||||
}
|
||||
const ExplicitSpecifier getExplicitSpecifier() const {
|
||||
return getExplicitSpecifierInternal();
|
||||
return getCanonicalDecl()->getExplicitSpecifierInternal();
|
||||
}
|
||||
|
||||
/// Return true if the declartion is already resolved to be explicit.
|
||||
@ -2847,9 +2638,9 @@ class CXXDestructorDecl : public CXXMethodDecl {
|
||||
CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, bool isInline,
|
||||
bool isImplicitlyDeclared)
|
||||
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind)
|
||||
: CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, CSK_unspecified, SourceLocation()) {
|
||||
SC_None, isInline, ConstexprKind, SourceLocation()) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
}
|
||||
|
||||
@ -2859,9 +2650,9 @@ class CXXDestructorDecl : public CXXMethodDecl {
|
||||
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo* TInfo,
|
||||
bool isInline,
|
||||
bool isImplicitlyDeclared);
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, bool isImplicitlyDeclared,
|
||||
ConstexprSpecKind ConstexprKind);
|
||||
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
|
||||
|
||||
void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
|
||||
@ -2934,7 +2725,7 @@ class CXXConversionDecl : public CXXMethodDecl {
|
||||
|
||||
/// Returns the type that this conversion function is converting to.
|
||||
QualType getConversionType() const {
|
||||
return getType()->getAs<FunctionType>()->getReturnType();
|
||||
return getType()->castAs<FunctionType>()->getReturnType();
|
||||
}
|
||||
|
||||
/// Determine whether this conversion function is a conversion from
|
||||
@ -2971,8 +2762,10 @@ class LinkageSpecDecl : public Decl, public DeclContext {
|
||||
/// ensure a stable ABI for this, we choose the DW_LANG_ encodings
|
||||
/// from the dwarf standard.
|
||||
enum LanguageIDs {
|
||||
lang_c = /* DW_LANG_C */ 0x0002,
|
||||
lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004
|
||||
lang_c = llvm::dwarf::DW_LANG_C,
|
||||
lang_cxx = llvm::dwarf::DW_LANG_C_plus_plus,
|
||||
lang_cxx_11 = llvm::dwarf::DW_LANG_C_plus_plus_11,
|
||||
lang_cxx_14 = llvm::dwarf::DW_LANG_C_plus_plus_14
|
||||
};
|
||||
|
||||
private:
|
||||
@ -3469,12 +3262,6 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl {
|
||||
return IsVirtual;
|
||||
}
|
||||
|
||||
/// Get the constructor or constructor template in the derived class
|
||||
/// correspnding to this using shadow declaration, if it has been implicitly
|
||||
/// declared already.
|
||||
CXXConstructorDecl *getConstructor() const;
|
||||
void setConstructor(NamedDecl *Ctor);
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == ConstructorUsingShadow; }
|
||||
};
|
||||
|
@ -168,6 +168,16 @@ class TemplateParameterList final
|
||||
return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
|
||||
}
|
||||
|
||||
/// \brief All associated constraints derived from this template parameter
|
||||
/// list, including the requires clause and any constraints derived from
|
||||
/// constrained-parameters.
|
||||
///
|
||||
/// The constraints in the resulting list are to be treated as if in a
|
||||
/// conjunction ("and").
|
||||
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const;
|
||||
|
||||
bool hasAssociatedConstraints() const;
|
||||
|
||||
SourceLocation getTemplateLoc() const { return TemplateLoc; }
|
||||
SourceLocation getLAngleLoc() const { return LAngleLoc; }
|
||||
SourceLocation getRAngleLoc() const { return RAngleLoc; }
|
||||
@ -369,33 +379,7 @@ class DefaultArgStorage {
|
||||
// Kinds of Templates
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Stores the template parameter list and associated constraints for
|
||||
/// \c TemplateDecl objects that track associated constraints.
|
||||
class ConstrainedTemplateDeclInfo {
|
||||
friend TemplateDecl;
|
||||
|
||||
public:
|
||||
ConstrainedTemplateDeclInfo() = default;
|
||||
|
||||
TemplateParameterList *getTemplateParameters() const {
|
||||
return TemplateParams;
|
||||
}
|
||||
|
||||
Expr *getAssociatedConstraints() const { return AssociatedConstraints; }
|
||||
|
||||
protected:
|
||||
void setTemplateParameters(TemplateParameterList *TParams) {
|
||||
TemplateParams = TParams;
|
||||
}
|
||||
|
||||
void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; }
|
||||
|
||||
TemplateParameterList *TemplateParams = nullptr;
|
||||
Expr *AssociatedConstraints = nullptr;
|
||||
};
|
||||
|
||||
|
||||
/// The base class of all kinds of template declarations (e.g.,
|
||||
/// \brief The base class of all kinds of template declarations (e.g.,
|
||||
/// class, function, etc.).
|
||||
///
|
||||
/// The TemplateDecl class stores the list of template parameters and a
|
||||
@ -404,54 +388,32 @@ class TemplateDecl : public NamedDecl {
|
||||
void anchor() override;
|
||||
|
||||
protected:
|
||||
// Construct a template decl with name, parameters, and templated element.
|
||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl);
|
||||
|
||||
// Construct a template decl with the given name and parameters.
|
||||
// Used when there is no templated element (e.g., for tt-params).
|
||||
TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
|
||||
SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params)
|
||||
: NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
|
||||
TemplateParams(CTDI) {
|
||||
this->setTemplateParameters(Params);
|
||||
}
|
||||
|
||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params)
|
||||
: TemplateDecl(nullptr, DK, DC, L, Name, Params) {}
|
||||
|
||||
// Construct a template decl with name, parameters, and templated element.
|
||||
TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
|
||||
SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
|
||||
TemplateParams(CTDI) {
|
||||
this->setTemplateParameters(Params);
|
||||
}
|
||||
|
||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: TemplateDecl(nullptr, DK, DC, L, Name, Params, Decl) {}
|
||||
: TemplateDecl(DK, DC, L, Name, Params, nullptr) {}
|
||||
|
||||
public:
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
|
||||
/// Get the list of template parameters
|
||||
TemplateParameterList *getTemplateParameters() const {
|
||||
const auto *const CTDI =
|
||||
TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
|
||||
return CTDI ? CTDI->getTemplateParameters()
|
||||
: TemplateParams.get<TemplateParameterList *>();
|
||||
return TemplateParams;
|
||||
}
|
||||
|
||||
/// Get the constraint-expression from the associated requires-clause (if any)
|
||||
const Expr *getRequiresClause() const {
|
||||
const TemplateParameterList *const TP = getTemplateParameters();
|
||||
return TP ? TP->getRequiresClause() : nullptr;
|
||||
}
|
||||
/// \brief Get the total constraint-expression associated with this template,
|
||||
/// including constraint-expressions derived from the requires-clause,
|
||||
/// trailing requires-clause (for functions and methods) and constrained
|
||||
/// template parameters.
|
||||
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const;
|
||||
|
||||
Expr *getAssociatedConstraints() const {
|
||||
const auto *const C = cast<TemplateDecl>(getCanonicalDecl());
|
||||
const auto *const CTDI =
|
||||
C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
|
||||
return CTDI ? CTDI->getAssociatedConstraints() : nullptr;
|
||||
}
|
||||
bool hasAssociatedConstraints() const;
|
||||
|
||||
/// Get the underlying, templated declaration.
|
||||
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
|
||||
@ -470,29 +432,10 @@ class TemplateDecl : public NamedDecl {
|
||||
|
||||
protected:
|
||||
NamedDecl *TemplatedDecl;
|
||||
|
||||
/// The template parameter list and optional requires-clause
|
||||
/// associated with this declaration; alternatively, a
|
||||
/// \c ConstrainedTemplateDeclInfo if the associated constraints of the
|
||||
/// template are being tracked by this particular declaration.
|
||||
llvm::PointerUnion<TemplateParameterList *,
|
||||
ConstrainedTemplateDeclInfo *>
|
||||
TemplateParams;
|
||||
TemplateParameterList *TemplateParams;
|
||||
|
||||
void setTemplateParameters(TemplateParameterList *TParams) {
|
||||
if (auto *const CTDI =
|
||||
TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>()) {
|
||||
CTDI->setTemplateParameters(TParams);
|
||||
} else {
|
||||
TemplateParams = TParams;
|
||||
}
|
||||
}
|
||||
|
||||
void setAssociatedConstraints(Expr *AC) {
|
||||
assert(isCanonicalDecl() &&
|
||||
"Attaching associated constraints to non-canonical Decl");
|
||||
TemplateParams.get<ConstrainedTemplateDeclInfo *>()
|
||||
->setAssociatedConstraints(AC);
|
||||
TemplateParams = TParams;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -889,17 +832,10 @@ class RedeclarableTemplateDecl : public TemplateDecl,
|
||||
virtual CommonBase *newCommon(ASTContext &C) const = 0;
|
||||
|
||||
// Construct a template decl with name, parameters, and templated element.
|
||||
RedeclarableTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK,
|
||||
ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
DeclarationName Name, TemplateParameterList *Params,
|
||||
NamedDecl *Decl)
|
||||
: TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C)
|
||||
{}
|
||||
|
||||
RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {}
|
||||
: TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C) {}
|
||||
|
||||
public:
|
||||
friend class ASTDeclReader;
|
||||
@ -2026,6 +1962,20 @@ class ClassTemplatePartialSpecializationDecl
|
||||
return TemplateParams;
|
||||
}
|
||||
|
||||
/// \brief All associated constraints of this partial specialization,
|
||||
/// including the requires clause and any constraints derived from
|
||||
/// constrained-parameters.
|
||||
///
|
||||
/// The constraints in the resulting list are to be treated as if in a
|
||||
/// conjunction ("and").
|
||||
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
||||
TemplateParams->getAssociatedConstraints(AC);
|
||||
}
|
||||
|
||||
bool hasAssociatedConstraints() const {
|
||||
return TemplateParams->hasAssociatedConstraints();
|
||||
}
|
||||
|
||||
/// Get the template arguments as written.
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
return ArgsAsWritten;
|
||||
@ -2145,16 +2095,10 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
|
||||
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
|
||||
getPartialSpecializations();
|
||||
|
||||
ClassTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, ASTContext &C,
|
||||
DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: RedeclarableTemplateDecl(CTDI, ClassTemplate, C, DC, L, Name, Params,
|
||||
Decl) {}
|
||||
|
||||
ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
DeclarationName Name, TemplateParameterList *Params,
|
||||
NamedDecl *Decl)
|
||||
: ClassTemplateDecl(nullptr, C, DC, L, Name, Params, Decl) {}
|
||||
: RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {}
|
||||
|
||||
CommonBase *newCommon(ASTContext &C) const override;
|
||||
|
||||
@ -2180,14 +2124,12 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
|
||||
return getTemplatedDecl()->isThisDeclarationADefinition();
|
||||
}
|
||||
|
||||
// FIXME: remove default argument for AssociatedConstraints
|
||||
/// Create a class template node.
|
||||
/// \brief Create a class template node.
|
||||
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,
|
||||
DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
NamedDecl *Decl,
|
||||
Expr *AssociatedConstraints = nullptr);
|
||||
NamedDecl *Decl);
|
||||
|
||||
/// Create an empty class template node.
|
||||
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
@ -2527,10 +2469,6 @@ class ClassScopeFunctionSpecializationDecl : public Decl {
|
||||
}
|
||||
};
|
||||
|
||||
/// Implementation of inline functions that require the template declarations
|
||||
inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
|
||||
: Function(FTD) {}
|
||||
|
||||
/// Represents a variable template specialization, which refers to
|
||||
/// a variable template with a given set of template arguments.
|
||||
///
|
||||
@ -2866,7 +2804,21 @@ class VarTemplatePartialSpecializationDecl
|
||||
return ArgsAsWritten;
|
||||
}
|
||||
|
||||
/// Retrieve the member variable template partial specialization from
|
||||
/// \brief All associated constraints of this partial specialization,
|
||||
/// including the requires clause and any constraints derived from
|
||||
/// constrained-parameters.
|
||||
///
|
||||
/// The constraints in the resulting list are to be treated as if in a
|
||||
/// conjunction ("and").
|
||||
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
||||
TemplateParams->getAssociatedConstraints(AC);
|
||||
}
|
||||
|
||||
bool hasAssociatedConstraints() const {
|
||||
return TemplateParams->hasAssociatedConstraints();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the member variable template partial specialization from
|
||||
/// which this particular variable template partial specialization was
|
||||
/// instantiated.
|
||||
///
|
||||
@ -3095,11 +3047,9 @@ class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
|
||||
protected:
|
||||
Expr *ConstraintExpr;
|
||||
|
||||
ConceptDecl(DeclContext *DC,
|
||||
SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
Expr *ConstraintExpr)
|
||||
: TemplateDecl(nullptr, Concept, DC, L, Name, Params),
|
||||
ConceptDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, Expr *ConstraintExpr)
|
||||
: TemplateDecl(Concept, DC, L, Name, Params),
|
||||
ConstraintExpr(ConstraintExpr) {};
|
||||
public:
|
||||
static ConceptDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
|
@ -906,6 +906,11 @@ class Expr : public ValueStmt {
|
||||
return skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
|
||||
}
|
||||
|
||||
/// Checks that the two Expr's will refer to the same value as a comparison
|
||||
/// operand. The caller must ensure that the values referenced by the Expr's
|
||||
/// are not modified between E1 and E2 or the result my be invalid.
|
||||
static bool isSameComparisonOperand(const Expr* E1, const Expr* E2);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() >= firstExprConstant &&
|
||||
T->getStmtClass() <= lastExprConstant;
|
||||
@ -2619,9 +2624,8 @@ class CallExpr : public Expr {
|
||||
/// + sizeof(Stmt *) bytes of storage, aligned to alignof(CallExpr):
|
||||
///
|
||||
/// \code{.cpp}
|
||||
/// llvm::AlignedCharArray<alignof(CallExpr),
|
||||
/// sizeof(CallExpr) + sizeof(Stmt *)> Buffer;
|
||||
/// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer.buffer, etc);
|
||||
/// alignas(CallExpr) char Buffer[sizeof(CallExpr) + sizeof(Stmt *)];
|
||||
/// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer, etc);
|
||||
/// \endcode
|
||||
static CallExpr *CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
|
||||
ExprValueKind VK, SourceLocation RParenLoc,
|
||||
@ -4496,6 +4500,8 @@ class InitListExpr : public Expr {
|
||||
|
||||
// Explicit InitListExpr's originate from source code (and have valid source
|
||||
// locations). Implicit InitListExpr's are created by the semantic analyzer.
|
||||
// FIXME: This is wrong; InitListExprs created by semantic analysis have
|
||||
// valid source locations too!
|
||||
bool isExplicit() const {
|
||||
return LBraceLoc.isValid() && RBraceLoc.isValid();
|
||||
}
|
||||
@ -4830,6 +4836,10 @@ class DesignatedInitExpr final
|
||||
SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; }
|
||||
void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; }
|
||||
|
||||
/// Whether this designated initializer should result in direct-initialization
|
||||
/// of the designated subobject (eg, '{.foo{1, 2, 3}}').
|
||||
bool isDirectInit() const { return EqualOrColonLoc.isInvalid(); }
|
||||
|
||||
/// Determines whether this designated initializer used the
|
||||
/// deprecated GNU syntax for designated initializers.
|
||||
bool usesGNUSyntax() const { return GNUSyntax; }
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
@ -185,15 +186,20 @@ class CXXMemberCallExpr final : public CallExpr {
|
||||
static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
|
||||
EmptyShell Empty);
|
||||
|
||||
/// Retrieves the implicit object argument for the member call.
|
||||
/// Retrieve the implicit object argument for the member call.
|
||||
///
|
||||
/// For example, in "x.f(5)", this returns the sub-expression "x".
|
||||
Expr *getImplicitObjectArgument() const;
|
||||
|
||||
/// Retrieves the declaration of the called method.
|
||||
/// Retrieve the type of the object argument.
|
||||
///
|
||||
/// Note that this always returns a non-pointer type.
|
||||
QualType getObjectType() const;
|
||||
|
||||
/// Retrieve the declaration of the called method.
|
||||
CXXMethodDecl *getMethodDecl() const;
|
||||
|
||||
/// Retrieves the CXXRecordDecl for the underlying type of
|
||||
/// Retrieve the CXXRecordDecl for the underlying type of
|
||||
/// the implicit object argument.
|
||||
///
|
||||
/// Note that this is may not be the same declaration as that of the class
|
||||
@ -248,6 +254,96 @@ class CUDAKernelCallExpr final : public CallExpr {
|
||||
}
|
||||
};
|
||||
|
||||
/// A rewritten comparison expression that was originally written using
|
||||
/// operator syntax.
|
||||
///
|
||||
/// In C++20, the following rewrites are performed:
|
||||
/// - <tt>a == b</tt> -> <tt>b == a</tt>
|
||||
/// - <tt>a != b</tt> -> <tt>!(a == b)</tt>
|
||||
/// - <tt>a != b</tt> -> <tt>!(b == a)</tt>
|
||||
/// - For \c \@ in \c <, \c <=, \c >, \c >=, \c <=>:
|
||||
/// - <tt>a @ b</tt> -> <tt>(a <=> b) @ 0</tt>
|
||||
/// - <tt>a @ b</tt> -> <tt>0 @ (b <=> a)</tt>
|
||||
///
|
||||
/// This expression provides access to both the original syntax and the
|
||||
/// rewritten expression.
|
||||
///
|
||||
/// Note that the rewritten calls to \c ==, \c <=>, and \c \@ are typically
|
||||
/// \c CXXOperatorCallExprs, but could theoretically be \c BinaryOperators.
|
||||
class CXXRewrittenBinaryOperator : public Expr {
|
||||
friend class ASTStmtReader;
|
||||
|
||||
/// The rewritten semantic form.
|
||||
Stmt *SemanticForm;
|
||||
|
||||
public:
|
||||
CXXRewrittenBinaryOperator(Expr *SemanticForm, bool IsReversed)
|
||||
: Expr(CXXRewrittenBinaryOperatorClass, SemanticForm->getType(),
|
||||
SemanticForm->getValueKind(), SemanticForm->getObjectKind(),
|
||||
SemanticForm->isTypeDependent(), SemanticForm->isValueDependent(),
|
||||
SemanticForm->isInstantiationDependent(),
|
||||
SemanticForm->containsUnexpandedParameterPack()),
|
||||
SemanticForm(SemanticForm) {
|
||||
CXXRewrittenBinaryOperatorBits.IsReversed = IsReversed;
|
||||
}
|
||||
CXXRewrittenBinaryOperator(EmptyShell Empty)
|
||||
: Expr(CXXRewrittenBinaryOperatorClass, Empty), SemanticForm() {}
|
||||
|
||||
/// Get an equivalent semantic form for this expression.
|
||||
Expr *getSemanticForm() { return cast<Expr>(SemanticForm); }
|
||||
const Expr *getSemanticForm() const { return cast<Expr>(SemanticForm); }
|
||||
|
||||
struct DecomposedForm {
|
||||
/// The original opcode, prior to rewriting.
|
||||
BinaryOperatorKind Opcode;
|
||||
/// The original left-hand side.
|
||||
const Expr *LHS;
|
||||
/// The original right-hand side.
|
||||
const Expr *RHS;
|
||||
/// The inner \c == or \c <=> operator expression.
|
||||
const Expr *InnerBinOp;
|
||||
};
|
||||
|
||||
/// Decompose this operator into its syntactic form.
|
||||
DecomposedForm getDecomposedForm() const LLVM_READONLY;
|
||||
|
||||
/// Determine whether this expression was rewritten in reverse form.
|
||||
bool isReversed() const { return CXXRewrittenBinaryOperatorBits.IsReversed; }
|
||||
|
||||
BinaryOperatorKind getOperator() const { return getDecomposedForm().Opcode; }
|
||||
const Expr *getLHS() const { return getDecomposedForm().LHS; }
|
||||
const Expr *getRHS() const { return getDecomposedForm().RHS; }
|
||||
|
||||
SourceLocation getOperatorLoc() const LLVM_READONLY {
|
||||
return getDecomposedForm().InnerBinOp->getExprLoc();
|
||||
}
|
||||
SourceLocation getExprLoc() const LLVM_READONLY { return getOperatorLoc(); }
|
||||
|
||||
/// Compute the begin and end locations from the decomposed form.
|
||||
/// The locations of the semantic form are not reliable if this is
|
||||
/// a reversed expression.
|
||||
//@{
|
||||
SourceLocation getBeginLoc() const LLVM_READONLY {
|
||||
return getDecomposedForm().LHS->getBeginLoc();
|
||||
}
|
||||
SourceLocation getEndLoc() const LLVM_READONLY {
|
||||
return getDecomposedForm().RHS->getEndLoc();
|
||||
}
|
||||
SourceRange getSourceRange() const LLVM_READONLY {
|
||||
DecomposedForm DF = getDecomposedForm();
|
||||
return SourceRange(DF.LHS->getBeginLoc(), DF.RHS->getEndLoc());
|
||||
}
|
||||
//@}
|
||||
|
||||
child_range children() {
|
||||
return child_range(&SemanticForm, &SemanticForm + 1);
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXRewrittenBinaryOperatorClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// Abstract class common to all of the C++ "named"/"keyword" casts.
|
||||
///
|
||||
/// This abstract class is inherited by all of the classes
|
||||
@ -1902,6 +1998,10 @@ class LambdaExpr final : public Expr,
|
||||
/// lambda expression.
|
||||
CXXMethodDecl *getCallOperator() const;
|
||||
|
||||
/// Retrieve the function template call operator associated with this
|
||||
/// lambda expression.
|
||||
FunctionTemplateDecl *getDependentCallOperator() const;
|
||||
|
||||
/// If this is a generic lambda expression, retrieve the template
|
||||
/// parameter list associated with it, or else return null.
|
||||
TemplateParameterList *getTemplateParameterList() const;
|
||||
@ -2091,8 +2191,7 @@ class CXXNewExpr final
|
||||
bool IsParenTypeId);
|
||||
|
||||
QualType getAllocatedType() const {
|
||||
assert(getType()->isPointerType());
|
||||
return getType()->getAs<PointerType>()->getPointeeType();
|
||||
return getType()->castAs<PointerType>()->getPointeeType();
|
||||
}
|
||||
|
||||
TypeSourceInfo *getAllocatedTypeSourceInfo() const {
|
||||
@ -2270,8 +2369,8 @@ class CXXDeleteExpr : public Expr {
|
||||
CXXDeleteExpr(QualType Ty, bool GlobalDelete, bool ArrayForm,
|
||||
bool ArrayFormAsWritten, bool UsualArrayDeleteWantsSize,
|
||||
FunctionDecl *OperatorDelete, Expr *Arg, SourceLocation Loc)
|
||||
: Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
|
||||
Arg->isInstantiationDependent(),
|
||||
: Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary, false,
|
||||
Arg->isValueDependent(), Arg->isInstantiationDependent(),
|
||||
Arg->containsUnexpandedParameterPack()),
|
||||
OperatorDelete(OperatorDelete), Argument(Arg) {
|
||||
CXXDeleteExprBits.GlobalDelete = GlobalDelete;
|
||||
@ -4335,9 +4434,6 @@ class MaterializeTemporaryExpr : public Expr {
|
||||
};
|
||||
llvm::PointerUnion<Stmt *, ExtraState *> State;
|
||||
|
||||
void initializeExtraState(const ValueDecl *ExtendedBy,
|
||||
unsigned ManglingNumber);
|
||||
|
||||
public:
|
||||
MaterializeTemporaryExpr(QualType T, Expr *Temporary,
|
||||
bool BoundToLvalueReference)
|
||||
@ -4745,6 +4841,125 @@ class BuiltinBitCastExpr final
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents the specialization of a concept - evaluates to a prvalue
|
||||
/// of type bool.
|
||||
///
|
||||
/// According to C++2a [expr.prim.id]p3 an id-expression that denotes the
|
||||
/// specialization of a concept results in a prvalue of type bool.
|
||||
class ConceptSpecializationExpr final : public Expr,
|
||||
private llvm::TrailingObjects<ConceptSpecializationExpr,
|
||||
TemplateArgument> {
|
||||
friend class ASTStmtReader;
|
||||
friend TrailingObjects;
|
||||
|
||||
// \brief The optional nested name specifier used when naming the concept.
|
||||
NestedNameSpecifierLoc NestedNameSpec;
|
||||
|
||||
/// \brief The location of the template keyword, if specified when naming the
|
||||
/// concept.
|
||||
SourceLocation TemplateKWLoc;
|
||||
|
||||
/// \brief The location of the concept name in the expression.
|
||||
SourceLocation ConceptNameLoc;
|
||||
|
||||
/// \brief The declaration found by name lookup when the expression was
|
||||
/// created.
|
||||
/// Can differ from NamedConcept when, for example, the concept was found
|
||||
/// through a UsingShadowDecl.
|
||||
NamedDecl *FoundDecl;
|
||||
|
||||
/// \brief The concept named, and whether or not the concept with the given
|
||||
/// arguments was satisfied when the expression was created.
|
||||
/// If any of the template arguments are dependent (this expr would then be
|
||||
/// isValueDependent()), this bit is to be ignored.
|
||||
llvm::PointerIntPair<ConceptDecl *, 1, bool> NamedConcept;
|
||||
|
||||
/// \brief The template argument list source info used to specialize the
|
||||
/// concept.
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
|
||||
|
||||
/// \brief The number of template arguments in the tail-allocated list of
|
||||
/// converted template arguments.
|
||||
unsigned NumTemplateArgs;
|
||||
|
||||
ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS,
|
||||
SourceLocation TemplateKWLoc,
|
||||
SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
|
||||
ConceptDecl *NamedConcept,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
ArrayRef<TemplateArgument> ConvertedArgs,
|
||||
Optional<bool> IsSatisfied);
|
||||
|
||||
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
|
||||
|
||||
public:
|
||||
|
||||
static ConceptSpecializationExpr *
|
||||
Create(ASTContext &C, NestedNameSpecifierLoc NNS,
|
||||
SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
|
||||
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied);
|
||||
|
||||
static ConceptSpecializationExpr *
|
||||
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
|
||||
|
||||
const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
|
||||
return NestedNameSpec;
|
||||
}
|
||||
|
||||
NamedDecl *getFoundDecl() const {
|
||||
return FoundDecl;
|
||||
}
|
||||
|
||||
ConceptDecl *getNamedConcept() const {
|
||||
return NamedConcept.getPointer();
|
||||
}
|
||||
|
||||
ArrayRef<TemplateArgument> getTemplateArguments() const {
|
||||
return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
|
||||
NumTemplateArgs);
|
||||
}
|
||||
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
return ArgsAsWritten;
|
||||
}
|
||||
|
||||
/// \brief Set new template arguments for this concept specialization.
|
||||
void setTemplateArguments(const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
ArrayRef<TemplateArgument> Converted);
|
||||
|
||||
/// \brief Whether or not the concept with the given arguments was satisfied
|
||||
/// when the expression was created. This method assumes that the expression
|
||||
/// is not dependent!
|
||||
bool isSatisfied() const {
|
||||
assert(!isValueDependent()
|
||||
&& "isSatisfied called on a dependent ConceptSpecializationExpr");
|
||||
return NamedConcept.getInt();
|
||||
}
|
||||
|
||||
SourceLocation getConceptNameLoc() const { return ConceptNameLoc; }
|
||||
|
||||
SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == ConceptSpecializationExprClass;
|
||||
}
|
||||
|
||||
SourceLocation getBeginLoc() const LLVM_READONLY { return ConceptNameLoc; }
|
||||
SourceLocation getEndLoc() const LLVM_READONLY {
|
||||
return ArgsAsWritten->RAngleLoc;
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_EXPRCXX_H
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define LLVM_CLANG_AST_EXTERNALASTMERGER_H
|
||||
|
||||
#include "clang/AST/ASTImporter.h"
|
||||
#include "clang/AST/ASTImporterSharedState.h"
|
||||
#include "clang/AST/ExternalASTSource.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
@ -22,7 +23,7 @@ namespace clang {
|
||||
/// ExternalASTSource implementation that merges information from several
|
||||
/// ASTContexts.
|
||||
///
|
||||
/// ExtermalASTMerger maintains a vector of ASTImporters that it uses to import
|
||||
/// ExternalASTMerger maintains a vector of ASTImporters that it uses to import
|
||||
/// (potentially incomplete) Decls and DeclContexts from the source ASTContexts
|
||||
/// in response to ExternalASTSource API calls.
|
||||
///
|
||||
@ -36,7 +37,7 @@ namespace clang {
|
||||
/// lookup. In this case, Origins contains an entry overriding lookup and
|
||||
/// specifying the correct pair of DeclContext/ASTContext.
|
||||
///
|
||||
/// - The DeclContext of origin was determined by another ExterenalASTMerger.
|
||||
/// - The DeclContext of origin was determined by another ExternalASTMerger.
|
||||
/// (This is possible when the source ASTContext for one of the Importers has
|
||||
/// its own ExternalASTMerger). The origin must be properly forwarded in this
|
||||
/// case.
|
||||
@ -79,20 +80,47 @@ class ExternalASTMerger : public ExternalASTSource {
|
||||
/// import SourceLocations properly. Additionally, when import occurs for
|
||||
/// a DeclContext whose origin has been overridden, then this
|
||||
/// ExternalASTMerger must be able to determine that.
|
||||
struct ImporterSource {
|
||||
class ImporterSource {
|
||||
ASTContext &AST;
|
||||
FileManager &FM;
|
||||
const OriginMap &OM;
|
||||
/// True iff the source only exists temporary, i.e., it will be removed from
|
||||
/// the ExternalASTMerger during the life time of the ExternalASTMerger.
|
||||
bool Temporary;
|
||||
/// If the ASTContext of this source has an ExternalASTMerger that imports
|
||||
/// into this source, then this will point to that other ExternalASTMerger.
|
||||
ExternalASTMerger *Merger;
|
||||
|
||||
public:
|
||||
ImporterSource(ASTContext &AST, FileManager &FM, const OriginMap &OM,
|
||||
bool Temporary = false, ExternalASTMerger *Merger = nullptr)
|
||||
: AST(AST), FM(FM), OM(OM), Temporary(Temporary), Merger(Merger) {}
|
||||
ASTContext &getASTContext() const { return AST; }
|
||||
FileManager &getFileManager() const { return FM; }
|
||||
const OriginMap &getOriginMap() const { return OM; }
|
||||
bool isTemporary() const { return Temporary; }
|
||||
ExternalASTMerger *getMerger() const { return Merger; }
|
||||
};
|
||||
|
||||
private:
|
||||
/// The target for this ExtenralASTMerger.
|
||||
/// The target for this ExternalASTMerger.
|
||||
ImporterTarget Target;
|
||||
/// ExternalASTMerger has multiple ASTImporters that import into the same
|
||||
/// TU. This is the shared state for all ASTImporters of this
|
||||
/// ExternalASTMerger.
|
||||
/// See also the CrossTranslationUnitContext that has a similar setup.
|
||||
std::shared_ptr<ASTImporterSharedState> SharedState;
|
||||
|
||||
public:
|
||||
ExternalASTMerger(const ImporterTarget &Target,
|
||||
llvm::ArrayRef<ImporterSource> Sources);
|
||||
|
||||
/// Asks all connected ASTImporters if any of them imported the given
|
||||
/// declaration. If any ASTImporter did import the given declaration,
|
||||
/// then this function returns the declaration that D was imported from.
|
||||
/// Returns nullptr if no ASTImporter did import import D.
|
||||
Decl *FindOriginalDecl(Decl *D);
|
||||
|
||||
/// Add a set of ASTContexts as possible origins.
|
||||
///
|
||||
/// Usually the set will be initialized in the constructor, but long-lived
|
||||
@ -145,7 +173,7 @@ class ExternalASTMerger : public ExternalASTSource {
|
||||
/// OriginContext.
|
||||
bool HasImporterForOrigin(ASTContext &OriginContext);
|
||||
|
||||
/// Returns a reference to the ASTRImporter from Importers whose origin
|
||||
/// Returns a reference to the ASTImporter from Importers whose origin
|
||||
/// is OriginContext. This allows manual import of ASTs while preserving the
|
||||
/// OriginMap correctly.
|
||||
ASTImporter &ImporterForOrigin(ASTContext &OriginContext);
|
||||
|
@ -251,7 +251,21 @@ class ArgType {
|
||||
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
|
||||
AnyCharTy, CStrTy, WCStrTy, WIntTy };
|
||||
|
||||
enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic };
|
||||
/// How well a given conversion specifier matches its argument.
|
||||
enum MatchKind {
|
||||
/// The conversion specifier and the argument types are incompatible. For
|
||||
/// instance, "%d" and float.
|
||||
NoMatch = 0,
|
||||
/// The conversion specifier and the argument type are compatible. For
|
||||
/// instance, "%d" and _Bool.
|
||||
Match = 1,
|
||||
/// The conversion specifier and the argument type are disallowed by the C
|
||||
/// standard, but are in practice harmless. For instance, "%p" and int*.
|
||||
NoMatchPedantic,
|
||||
/// The conversion specifier and the argument type are compatible, but still
|
||||
/// seems likely to be an error. For instance, "%hd" and _Bool.
|
||||
NoMatchTypeConfusion,
|
||||
};
|
||||
|
||||
private:
|
||||
const Kind K;
|
||||
@ -748,6 +762,12 @@ bool ParseScanfString(FormatStringHandler &H,
|
||||
const char *beg, const char *end, const LangOptions &LO,
|
||||
const TargetInfo &Target);
|
||||
|
||||
/// Return true if the given string has at least one formatting specifier.
|
||||
bool parseFormatStringHasFormattingSpecifiers(const char *Begin,
|
||||
const char *End,
|
||||
const LangOptions &LO,
|
||||
const TargetInfo &Target);
|
||||
|
||||
} // end analyze_format_string namespace
|
||||
} // end clang namespace
|
||||
#endif
|
||||
|
@ -59,6 +59,7 @@ class GlobalDecl {
|
||||
GlobalDecl(const CapturedDecl *D) { Init(D); }
|
||||
GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
|
||||
GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); }
|
||||
GlobalDecl(const OMPDeclareMapperDecl *D) { Init(D); }
|
||||
GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {}
|
||||
GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {}
|
||||
GlobalDecl(const VarDecl *D, DynamicInitKind StubKind)
|
||||
|
@ -141,6 +141,8 @@ class JSONNodeDumper
|
||||
JOS.attribute(Key, Value);
|
||||
}
|
||||
|
||||
void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false);
|
||||
|
||||
// Writes the attributes of a SourceLocation object without.
|
||||
void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling);
|
||||
|
||||
|
@ -56,7 +56,7 @@ class MangleContext {
|
||||
|
||||
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
|
||||
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
|
||||
llvm::DenseMap<const TagDecl*, uint64_t> AnonStructIds;
|
||||
llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds;
|
||||
|
||||
public:
|
||||
ManglerKind getKind() const { return Kind; }
|
||||
@ -82,9 +82,9 @@ class MangleContext {
|
||||
return Result.first->second;
|
||||
}
|
||||
|
||||
uint64_t getAnonymousStructId(const TagDecl *TD) {
|
||||
std::pair<llvm::DenseMap<const TagDecl *, uint64_t>::iterator, bool>
|
||||
Result = AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size()));
|
||||
uint64_t getAnonymousStructId(const NamedDecl *D) {
|
||||
std::pair<llvm::DenseMap<const NamedDecl *, uint64_t>::iterator, bool>
|
||||
Result = AnonStructIds.insert(std::make_pair(D, AnonStructIds.size()));
|
||||
return Result.first->second;
|
||||
}
|
||||
|
||||
@ -170,6 +170,8 @@ class ItaniumMangleContext : public MangleContext {
|
||||
virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
|
||||
raw_ostream &) = 0;
|
||||
|
||||
virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;
|
||||
|
||||
static bool classof(const MangleContext *C) {
|
||||
return C->getKind() == MK_Itanium;
|
||||
}
|
||||
@ -248,8 +250,16 @@ class ASTNameGenerator {
|
||||
public:
|
||||
explicit ASTNameGenerator(ASTContext &Ctx);
|
||||
~ASTNameGenerator();
|
||||
|
||||
/// Writes name for \p D to \p OS.
|
||||
/// \returns true on failure, false on success.
|
||||
bool writeName(const Decl *D, raw_ostream &OS);
|
||||
|
||||
/// \returns name for \p D
|
||||
std::string getName(const Decl *D);
|
||||
|
||||
/// \returns all applicable mangled names.
|
||||
/// For example C++ constructors/destructors can have multiple.
|
||||
std::vector<std::string> getAllManglings(const Decl *D);
|
||||
|
||||
private:
|
||||
|
@ -55,9 +55,6 @@ class NSAPI {
|
||||
/// The Objective-C NSString selectors.
|
||||
Selector getNSStringSelector(NSStringMethodKind MK) const;
|
||||
|
||||
/// Return NSStringMethodKind if \param Sel is such a selector.
|
||||
Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const;
|
||||
|
||||
/// Returns true if the expression \param E is a reference of
|
||||
/// "NSUTF8StringEncoding" enum constant.
|
||||
bool isNSUTF8StringEncodingConstant(const Expr *E) const {
|
||||
|
@ -519,7 +519,7 @@ class OMPIfClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp task' has simple 'final'
|
||||
/// clause with condition 'a > 5'.
|
||||
class OMPFinalClause : public OMPClause {
|
||||
class OMPFinalClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
|
||||
/// Location of '('.
|
||||
@ -534,18 +534,25 @@ class OMPFinalClause : public OMPClause {
|
||||
public:
|
||||
/// Build 'final' clause with condition \a Cond.
|
||||
///
|
||||
/// \param Cond Condition of the clause.
|
||||
/// \param HelperCond Helper condition for the construct.
|
||||
/// \param CaptureRegion Innermost OpenMP region where expressions in this
|
||||
/// clause must be captured.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param Cond Condition of the clause.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
Condition(Cond) {}
|
||||
OMPFinalClause(Expr *Cond, Stmt *HelperCond,
|
||||
OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_final, StartLoc, EndLoc), OMPClauseWithPreInit(this),
|
||||
LParenLoc(LParenLoc), Condition(Cond) {
|
||||
setPreInitStmt(HelperCond, CaptureRegion);
|
||||
}
|
||||
|
||||
/// Build an empty clause.
|
||||
OMPFinalClause()
|
||||
: OMPClause(OMPC_final, SourceLocation(), SourceLocation()) {}
|
||||
: OMPClause(OMPC_final, SourceLocation(), SourceLocation()),
|
||||
OMPClauseWithPreInit(this) {}
|
||||
|
||||
/// Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
@ -562,11 +569,10 @@ class OMPFinalClause : public OMPClause {
|
||||
return const_child_range(&Condition, &Condition + 1);
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
child_range used_children();
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
auto Children = const_cast<OMPFinalClause *>(this)->used_children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
@ -2099,10 +2105,12 @@ class OMPFirstprivateClause final
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
reinterpret_cast<Stmt **>(varlist_end()));
|
||||
}
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
auto Children = const_cast<OMPFirstprivateClause *>(this)->used_children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
@ -2616,10 +2624,12 @@ class OMPReductionClause final
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
reinterpret_cast<Stmt **>(varlist_end()));
|
||||
}
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
auto Children = const_cast<OMPReductionClause *>(this)->used_children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
@ -3212,6 +3222,14 @@ class OMPLinearClause final
|
||||
return llvm::makeArrayRef(getUpdates().end(), varlist_size());
|
||||
}
|
||||
|
||||
/// Gets the list of used expressions for linear variables.
|
||||
MutableArrayRef<Expr *> getUsedExprs() {
|
||||
return MutableArrayRef<Expr *>(getFinals().end() + 2, varlist_size() + 1);
|
||||
}
|
||||
ArrayRef<const Expr *> getUsedExprs() const {
|
||||
return llvm::makeArrayRef(getFinals().end() + 2, varlist_size() + 1);
|
||||
}
|
||||
|
||||
/// Sets the list of the copies of original linear variables.
|
||||
/// \param PL List of expressions.
|
||||
void setPrivates(ArrayRef<Expr *> PL);
|
||||
@ -3291,6 +3309,9 @@ class OMPLinearClause final
|
||||
/// \param FL List of expressions.
|
||||
void setFinals(ArrayRef<Expr *> FL);
|
||||
|
||||
/// Sets the list of used expressions for the linear clause.
|
||||
void setUsedExprs(ArrayRef<Expr *> UE);
|
||||
|
||||
using privates_iterator = MutableArrayRef<Expr *>::iterator;
|
||||
using privates_const_iterator = ArrayRef<const Expr *>::iterator;
|
||||
using privates_range = llvm::iterator_range<privates_iterator>;
|
||||
@ -3343,6 +3364,21 @@ class OMPLinearClause final
|
||||
return finals_const_range(getFinals().begin(), getFinals().end());
|
||||
}
|
||||
|
||||
using used_expressions_iterator = MutableArrayRef<Expr *>::iterator;
|
||||
using used_expressions_const_iterator = ArrayRef<const Expr *>::iterator;
|
||||
using used_expressions_range =
|
||||
llvm::iterator_range<used_expressions_iterator>;
|
||||
using used_expressions_const_range =
|
||||
llvm::iterator_range<used_expressions_const_iterator>;
|
||||
|
||||
used_expressions_range used_expressions() {
|
||||
return finals_range(getUsedExprs().begin(), getUsedExprs().end());
|
||||
}
|
||||
|
||||
used_expressions_const_range used_expressions() const {
|
||||
return finals_const_range(getUsedExprs().begin(), getUsedExprs().end());
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
reinterpret_cast<Stmt **>(varlist_end()));
|
||||
@ -3353,11 +3389,11 @@ class OMPLinearClause final
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
child_range used_children();
|
||||
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
auto Children = const_cast<OMPLinearClause *>(this)->used_children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
@ -4995,12 +5031,17 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_tofrom)
|
||||
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
reinterpret_cast<Stmt **>(varlist_end()));
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
auto Children = const_cast<OMPMapClause *>(this)->used_children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_map;
|
||||
}
|
||||
@ -5165,7 +5206,7 @@ class OMPThreadLimitClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp teams' has clause 'priority' with
|
||||
/// single expression 'n'.
|
||||
class OMPPriorityClause : public OMPClause {
|
||||
class OMPPriorityClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
|
||||
/// Location of '('.
|
||||
@ -5182,18 +5223,25 @@ class OMPPriorityClause : public OMPClause {
|
||||
public:
|
||||
/// Build 'priority' clause.
|
||||
///
|
||||
/// \param E Expression associated with this clause.
|
||||
/// \param Priority Expression associated with this clause.
|
||||
/// \param HelperPriority Helper priority for the construct.
|
||||
/// \param CaptureRegion Innermost OpenMP region where expressions in this
|
||||
/// clause must be captured.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPPriorityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
Priority(E) {}
|
||||
OMPPriorityClause(Expr *Priority, Stmt *HelperPriority,
|
||||
OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_priority, StartLoc, EndLoc), OMPClauseWithPreInit(this),
|
||||
LParenLoc(LParenLoc), Priority(Priority) {
|
||||
setPreInitStmt(HelperPriority, CaptureRegion);
|
||||
}
|
||||
|
||||
/// Build an empty clause.
|
||||
OMPPriorityClause()
|
||||
: OMPClause(OMPC_priority, SourceLocation(), SourceLocation()) {}
|
||||
: OMPClause(OMPC_priority, SourceLocation(), SourceLocation()),
|
||||
OMPClauseWithPreInit(this) {}
|
||||
|
||||
/// Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
@ -5213,11 +5261,10 @@ class OMPPriorityClause : public OMPClause {
|
||||
return const_child_range(&Priority, &Priority + 1);
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
child_range used_children();
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
auto Children = const_cast<OMPPriorityClause *>(this)->used_children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
@ -5233,7 +5280,7 @@ class OMPPriorityClause : public OMPClause {
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp taskloop' has clause 'grainsize'
|
||||
/// with single expression '4'.
|
||||
class OMPGrainsizeClause : public OMPClause {
|
||||
class OMPGrainsizeClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
|
||||
/// Location of '('.
|
||||
@ -5249,16 +5296,23 @@ class OMPGrainsizeClause : public OMPClause {
|
||||
/// Build 'grainsize' clause.
|
||||
///
|
||||
/// \param Size Expression associated with this clause.
|
||||
/// \param HelperSize Helper grainsize for the construct.
|
||||
/// \param CaptureRegion Innermost OpenMP region where expressions in this
|
||||
/// clause must be captured.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPGrainsizeClause(Expr *Size, SourceLocation StartLoc,
|
||||
OMPGrainsizeClause(Expr *Size, Stmt *HelperSize,
|
||||
OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
Grainsize(Size) {}
|
||||
: OMPClause(OMPC_grainsize, StartLoc, EndLoc), OMPClauseWithPreInit(this),
|
||||
LParenLoc(LParenLoc), Grainsize(Size) {
|
||||
setPreInitStmt(HelperSize, CaptureRegion);
|
||||
}
|
||||
|
||||
/// Build an empty clause.
|
||||
explicit OMPGrainsizeClause()
|
||||
: OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()) {}
|
||||
: OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()),
|
||||
OMPClauseWithPreInit(this) {}
|
||||
|
||||
/// Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
@ -5275,11 +5329,10 @@ class OMPGrainsizeClause : public OMPClause {
|
||||
return const_child_range(&Grainsize, &Grainsize + 1);
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
child_range used_children();
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
auto Children = const_cast<OMPGrainsizeClause *>(this)->used_children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
@ -5334,7 +5387,7 @@ class OMPNogroupClause : public OMPClause {
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp taskloop' has clause 'num_tasks'
|
||||
/// with single expression '4'.
|
||||
class OMPNumTasksClause : public OMPClause {
|
||||
class OMPNumTasksClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
|
||||
/// Location of '('.
|
||||
@ -5350,16 +5403,23 @@ class OMPNumTasksClause : public OMPClause {
|
||||
/// Build 'num_tasks' clause.
|
||||
///
|
||||
/// \param Size Expression associated with this clause.
|
||||
/// \param HelperSize Helper grainsize for the construct.
|
||||
/// \param CaptureRegion Innermost OpenMP region where expressions in this
|
||||
/// clause must be captured.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPNumTasksClause(Expr *Size, SourceLocation StartLoc,
|
||||
OMPNumTasksClause(Expr *Size, Stmt *HelperSize,
|
||||
OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
NumTasks(Size) {}
|
||||
: OMPClause(OMPC_num_tasks, StartLoc, EndLoc), OMPClauseWithPreInit(this),
|
||||
LParenLoc(LParenLoc), NumTasks(Size) {
|
||||
setPreInitStmt(HelperSize, CaptureRegion);
|
||||
}
|
||||
|
||||
/// Build an empty clause.
|
||||
explicit OMPNumTasksClause()
|
||||
: OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()) {}
|
||||
: OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()),
|
||||
OMPClauseWithPreInit(this) {}
|
||||
|
||||
/// Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
@ -5376,11 +5436,10 @@ class OMPNumTasksClause : public OMPClause {
|
||||
return const_child_range(&NumTasks, &NumTasks + 1);
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
child_range used_children();
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
auto Children = const_cast<OMPNumTasksClause *>(this)->used_children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
|
@ -66,8 +66,9 @@ CAST_OPERATION(BitCast)
|
||||
/// bool b; reinterpret_cast<char&>(b) = 'a';
|
||||
CAST_OPERATION(LValueBitCast)
|
||||
|
||||
/// CK_LValueToRValueBitCast - A conversion that causes us to reinterpret an
|
||||
/// lvalue as an rvalue of a different type. Created by __builtin_bit_cast.
|
||||
/// CK_LValueToRValueBitCast - A conversion that causes us to reinterpret the
|
||||
/// object representation of an lvalue as an rvalue. Created by
|
||||
/// __builtin_bit_cast.
|
||||
CAST_OPERATION(LValueToRValueBitCast)
|
||||
|
||||
/// CK_LValueToRValue - A conversion which causes the extraction of
|
||||
|
78
include/clang/AST/OptionalDiagnostic.h
Normal file
78
include/clang/AST/OptionalDiagnostic.h
Normal file
@ -0,0 +1,78 @@
|
||||
//===- OptionalDiagnostic.h - An optional diagnostic ------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// Implements a partial diagnostic which may not be emitted.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_OPTIONALDIAGNOSTIC_H
|
||||
#define LLVM_CLANG_AST_OPTIONALDIAGNOSTIC_H
|
||||
|
||||
#include "clang/AST/APValue.h"
|
||||
#include "clang/Basic/PartialDiagnostic.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// A partial diagnostic which we might know in advance that we are not going
|
||||
/// to emit.
|
||||
class OptionalDiagnostic {
|
||||
PartialDiagnostic *Diag;
|
||||
|
||||
public:
|
||||
explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr) : Diag(Diag) {}
|
||||
|
||||
template <typename T> OptionalDiagnostic &operator<<(const T &v) {
|
||||
if (Diag)
|
||||
*Diag << v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OptionalDiagnostic &operator<<(const llvm::APSInt &I) {
|
||||
if (Diag) {
|
||||
SmallVector<char, 32> Buffer;
|
||||
I.toString(Buffer);
|
||||
*Diag << StringRef(Buffer.data(), Buffer.size());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OptionalDiagnostic &operator<<(const llvm::APFloat &F) {
|
||||
if (Diag) {
|
||||
// FIXME: Force the precision of the source value down so we don't
|
||||
// print digits which are usually useless (we don't really care here if
|
||||
// we truncate a digit by accident in edge cases). Ideally,
|
||||
// APFloat::toString would automatically print the shortest
|
||||
// representation which rounds to the correct value, but it's a bit
|
||||
// tricky to implement. Could use std::to_chars.
|
||||
unsigned precision = llvm::APFloat::semanticsPrecision(F.getSemantics());
|
||||
precision = (precision * 59 + 195) / 196;
|
||||
SmallVector<char, 32> Buffer;
|
||||
F.toString(Buffer, precision);
|
||||
*Diag << StringRef(Buffer.data(), Buffer.size());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OptionalDiagnostic &operator<<(const APFixedPoint &FX) {
|
||||
if (Diag) {
|
||||
SmallVector<char, 32> Buffer;
|
||||
FX.toString(Buffer);
|
||||
*Diag << StringRef(Buffer.data(), Buffer.size());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
@ -10,8 +10,11 @@
|
||||
#define LLVM_CLANG_AST_RAWCOMMENTLIST_H
|
||||
|
||||
#include "clang/Basic/CommentOptions.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <map>
|
||||
|
||||
namespace clang {
|
||||
|
||||
@ -196,17 +199,25 @@ class RawCommentList {
|
||||
void addComment(const RawComment &RC, const CommentOptions &CommentOpts,
|
||||
llvm::BumpPtrAllocator &Allocator);
|
||||
|
||||
ArrayRef<RawComment *> getComments() const {
|
||||
return Comments;
|
||||
}
|
||||
/// \returns A mapping from an offset of the start of the comment to the
|
||||
/// comment itself, or nullptr in case there are no comments in \p File.
|
||||
const std::map<unsigned, RawComment *> *getCommentsInFile(FileID File) const;
|
||||
|
||||
bool empty() const;
|
||||
|
||||
unsigned getCommentBeginLine(RawComment *C, FileID File,
|
||||
unsigned Offset) const;
|
||||
unsigned getCommentEndOffset(RawComment *C) const;
|
||||
|
||||
private:
|
||||
SourceManager &SourceMgr;
|
||||
std::vector<RawComment *> Comments;
|
||||
|
||||
void addDeserializedComments(ArrayRef<RawComment *> DeserializedComments);
|
||||
// mapping: FileId -> comment begin offset -> comment
|
||||
llvm::DenseMap<FileID, std::map<unsigned, RawComment *>> OrderedComments;
|
||||
mutable llvm::DenseMap<RawComment *, unsigned> CommentBeginLine;
|
||||
mutable llvm::DenseMap<RawComment *, unsigned> CommentEndOffset;
|
||||
|
||||
friend class ASTReader;
|
||||
friend class ASTWriter;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -431,7 +431,7 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
// Declare Traverse*() for all concrete Type classes.
|
||||
#define ABSTRACT_TYPE(CLASS, BASE)
|
||||
#define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T);
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
// The above header #undefs ABSTRACT_TYPE and TYPE upon exit.
|
||||
|
||||
// Define WalkUpFrom*() and empty Visit*() for all Type classes.
|
||||
@ -444,7 +444,7 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
return true; \
|
||||
} \
|
||||
bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
|
||||
// ---- Methods on TypeLocs ----
|
||||
// FIXME: this currently just calls the matching Type methods
|
||||
@ -460,7 +460,7 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
bool VisitTypeLoc(TypeLoc TL) { return true; }
|
||||
|
||||
// QualifiedTypeLoc and UnqualTypeLoc are not declared in
|
||||
// TypeNodes.def and thus need to be handled specially.
|
||||
// TypeNodes.inc and thus need to be handled specially.
|
||||
bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) {
|
||||
return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
|
||||
}
|
||||
@ -478,7 +478,7 @@ template <typename Derived> class RecursiveASTVisitor {
|
||||
return true; \
|
||||
} \
|
||||
bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
|
||||
// ---- Methods on Decls ----
|
||||
|
||||
@ -676,7 +676,7 @@ bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
|
||||
#define TYPE(CLASS, BASE) \
|
||||
case Type::CLASS: \
|
||||
DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr()));
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -722,12 +722,6 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
|
||||
break;
|
||||
#include "clang/AST/DeclNodes.inc"
|
||||
}
|
||||
|
||||
// Visit any attributes attached to this declaration.
|
||||
for (auto *I : D->attrs()) {
|
||||
if (!getDerived().TraverseAttr(I))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -965,8 +959,11 @@ DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); })
|
||||
|
||||
DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); })
|
||||
|
||||
DEF_TRAVERSE_TYPE(ConstantArrayType,
|
||||
{ TRY_TO(TraverseType(T->getElementType())); })
|
||||
DEF_TRAVERSE_TYPE(ConstantArrayType, {
|
||||
TRY_TO(TraverseType(T->getElementType()));
|
||||
if (T->getSizeExpr())
|
||||
TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr())));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(IncompleteArrayType,
|
||||
{ TRY_TO(TraverseType(T->getElementType())); })
|
||||
@ -1407,6 +1404,11 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
|
||||
{ CODE; } \
|
||||
if (ReturnValue && ShouldVisitChildren) \
|
||||
TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \
|
||||
if (ReturnValue) { \
|
||||
/* Visit any attributes attached to this declaration. */ \
|
||||
for (auto *I : D->attrs()) \
|
||||
TRY_TO(getDerived().TraverseAttr(I)); \
|
||||
} \
|
||||
if (ReturnValue && getDerived().shouldTraversePostOrder()) \
|
||||
TRY_TO(WalkUpFrom##DECL(D)); \
|
||||
return ReturnValue; \
|
||||
@ -1631,9 +1633,11 @@ template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
|
||||
TemplateParameterList *TPL) {
|
||||
if (TPL) {
|
||||
for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
|
||||
I != E; ++I) {
|
||||
TRY_TO(TraverseDecl(*I));
|
||||
for (NamedDecl *D : *TPL) {
|
||||
TRY_TO(TraverseDecl(D));
|
||||
}
|
||||
if (Expr *RequiresClause = TPL->getRequiresClause()) {
|
||||
TRY_TO(TraverseStmt(RequiresClause));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -2023,11 +2027,18 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
|
||||
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
|
||||
// Constructor initializers.
|
||||
for (auto *I : Ctor->inits()) {
|
||||
TRY_TO(TraverseConstructorInitializer(I));
|
||||
if (I->isWritten() || getDerived().shouldVisitImplicitCode())
|
||||
TRY_TO(TraverseConstructorInitializer(I));
|
||||
}
|
||||
}
|
||||
|
||||
if (D->isThisDeclarationADefinition()) {
|
||||
bool VisitBody = D->isThisDeclarationADefinition();
|
||||
// If a method is set to default outside the class definition the compiler
|
||||
// generates the method body and adds it to the AST.
|
||||
if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
|
||||
VisitBody &= !MD->isDefaulted() || getDerived().shouldVisitImplicitCode();
|
||||
|
||||
if (VisitBody) {
|
||||
TRY_TO(TraverseStmt(D->getBody())); // Function body.
|
||||
}
|
||||
return true;
|
||||
@ -2308,19 +2319,30 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
|
||||
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.
|
||||
// If shouldVisitImplicitCode() returns false, this method traverses only the
|
||||
// syntactic form of InitListExpr.
|
||||
// If shouldVisitImplicitCode() 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.
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(
|
||||
InitListExpr *S, DataRecursionQueue *Queue) {
|
||||
if (S->isSemanticForm() && S->isSyntacticForm()) {
|
||||
// `S` does not have alternative forms, traverse only once.
|
||||
TRY_TO(TraverseSynOrSemInitListExpr(S, Queue));
|
||||
return true;
|
||||
}
|
||||
TRY_TO(TraverseSynOrSemInitListExpr(
|
||||
S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
|
||||
TRY_TO(TraverseSynOrSemInitListExpr(
|
||||
S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
|
||||
if (getDerived().shouldVisitImplicitCode()) {
|
||||
// Only visit the semantic form if the clients are interested in implicit
|
||||
// compiler-generated.
|
||||
TRY_TO(TraverseSynOrSemInitListExpr(
|
||||
S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2584,6 +2606,15 @@ DEF_TRAVERSE_STMT(SEHLeaveStmt, {})
|
||||
DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
|
||||
|
||||
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
|
||||
DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, {
|
||||
if (!getDerived().shouldVisitImplicitCode()) {
|
||||
CXXRewrittenBinaryOperator::DecomposedForm Decomposed =
|
||||
S->getDecomposedForm();
|
||||
TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.LHS)));
|
||||
TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.RHS)));
|
||||
ShouldVisitChildren = false;
|
||||
}
|
||||
})
|
||||
DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
|
||||
DEF_TRAVERSE_STMT(TypoExpr, {})
|
||||
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
|
||||
@ -2639,6 +2670,12 @@ DEF_TRAVERSE_STMT(CoyieldExpr, {
|
||||
}
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(ConceptSpecializationExpr, {
|
||||
TRY_TO(TraverseTemplateArgumentLocsHelper(
|
||||
S->getTemplateArgsAsWritten()->getTemplateArgs(),
|
||||
S->getTemplateArgsAsWritten()->NumTemplateArgs));
|
||||
})
|
||||
|
||||
// These literals (all of them) do not need any action.
|
||||
DEF_TRAVERSE_STMT(IntegerLiteral, {})
|
||||
DEF_TRAVERSE_STMT(FixedPointLiteral, {})
|
||||
@ -2768,6 +2805,15 @@ DEF_TRAVERSE_STMT(OMPTaskLoopDirective,
|
||||
DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPMasterTaskLoopDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPMasterTaskLoopSimdDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPDistributeDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
@ -2826,6 +2872,8 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_uniform:
|
||||
case OMPC_device_type:
|
||||
case OMPC_match:
|
||||
case OMPC_unknown:
|
||||
break;
|
||||
}
|
||||
@ -2870,6 +2918,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) {
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(TraverseStmt(C->getCondition()));
|
||||
return true;
|
||||
}
|
||||
@ -3240,6 +3289,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause(
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause(
|
||||
OMPPriorityClause *C) {
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(TraverseStmt(C->getPriority()));
|
||||
return true;
|
||||
}
|
||||
@ -3247,6 +3297,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause(
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause(
|
||||
OMPGrainsizeClause *C) {
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(TraverseStmt(C->getGrainsize()));
|
||||
return true;
|
||||
}
|
||||
@ -3254,6 +3305,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause(
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause(
|
||||
OMPNumTasksClause *C) {
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(TraverseStmt(C->getNumTasks()));
|
||||
return true;
|
||||
}
|
||||
|
@ -604,6 +604,15 @@ class alignas(void *) Stmt {
|
||||
unsigned FPFeatures : 3;
|
||||
};
|
||||
|
||||
class CXXRewrittenBinaryOperatorBitfields {
|
||||
friend class ASTStmtReader;
|
||||
friend class CXXRewrittenBinaryOperator;
|
||||
|
||||
unsigned : NumCallExprBits;
|
||||
|
||||
unsigned IsReversed : 1;
|
||||
};
|
||||
|
||||
class CXXBoolLiteralExprBitfields {
|
||||
friend class CXXBoolLiteralExpr;
|
||||
|
||||
@ -978,6 +987,7 @@ class alignas(void *) Stmt {
|
||||
|
||||
// C++ Expressions
|
||||
CXXOperatorCallExprBitfields CXXOperatorCallExprBits;
|
||||
CXXRewrittenBinaryOperatorBitfields CXXRewrittenBinaryOperatorBits;
|
||||
CXXBoolLiteralExprBitfields CXXBoolLiteralExprBits;
|
||||
CXXNullPtrLiteralExprBitfields CXXNullPtrLiteralExprBits;
|
||||
CXXThisExprBitfields CXXThisExprBits;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/OpenMPClause.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/Basic/OpenMPKinds.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
|
||||
@ -448,7 +449,8 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
PreInitsOffset = 8,
|
||||
// The '...End' enumerators do not correspond to child expressions - they
|
||||
// specify the offset to the end (and start of the following counters/
|
||||
// updates/finals arrays).
|
||||
// updates/finals/dependent_counters/dependent_inits/finals_conditions
|
||||
// arrays).
|
||||
DefaultEnd = 9,
|
||||
// The following 8 exprs are used by worksharing and distribute loops only.
|
||||
IsLastIterVariableOffset = 9,
|
||||
@ -474,7 +476,8 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
CombinedNextUpperBoundOffset = 27,
|
||||
CombinedDistConditionOffset = 28,
|
||||
CombinedParForInDistConditionOffset = 29,
|
||||
// Offset to the end (and start of the following counters/updates/finals
|
||||
// Offset to the end (and start of the following
|
||||
// counters/updates/finals/dependent_counters/dependent_inits/finals_conditions
|
||||
// arrays) for combined distribute loop directives.
|
||||
CombinedDistributeEnd = 30,
|
||||
};
|
||||
@ -517,6 +520,30 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
|
||||
}
|
||||
|
||||
/// Get the dependent counters storage.
|
||||
MutableArrayRef<Expr *> getDependentCounters() {
|
||||
Expr **Storage = reinterpret_cast<Expr **>(
|
||||
&*std::next(child_begin(),
|
||||
getArraysOffset(getDirectiveKind()) + 5 * CollapsedNum));
|
||||
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
|
||||
}
|
||||
|
||||
/// Get the dependent inits storage.
|
||||
MutableArrayRef<Expr *> getDependentInits() {
|
||||
Expr **Storage = reinterpret_cast<Expr **>(
|
||||
&*std::next(child_begin(),
|
||||
getArraysOffset(getDirectiveKind()) + 6 * CollapsedNum));
|
||||
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
|
||||
}
|
||||
|
||||
/// Get the finals conditions storage.
|
||||
MutableArrayRef<Expr *> getFinalsConditions() {
|
||||
Expr **Storage = reinterpret_cast<Expr **>(
|
||||
&*std::next(child_begin(),
|
||||
getArraysOffset(getDirectiveKind()) + 7 * CollapsedNum));
|
||||
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Build instance of loop directive of class \a Kind.
|
||||
///
|
||||
@ -551,9 +578,10 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
/// Children number.
|
||||
static unsigned numLoopChildren(unsigned CollapsedNum,
|
||||
OpenMPDirectiveKind Kind) {
|
||||
return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters,
|
||||
// PrivateCounters, Inits,
|
||||
// Updates and Finals
|
||||
return getArraysOffset(Kind) +
|
||||
8 * CollapsedNum; // Counters, PrivateCounters, Inits,
|
||||
// Updates, Finals, DependentCounters,
|
||||
// DependentInits, FinalsConditions.
|
||||
}
|
||||
|
||||
void setIterationVariable(Expr *IV) {
|
||||
@ -703,6 +731,9 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
void setInits(ArrayRef<Expr *> A);
|
||||
void setUpdates(ArrayRef<Expr *> A);
|
||||
void setFinals(ArrayRef<Expr *> A);
|
||||
void setDependentCounters(ArrayRef<Expr *> A);
|
||||
void setDependentInits(ArrayRef<Expr *> A);
|
||||
void setFinalsConditions(ArrayRef<Expr *> A);
|
||||
|
||||
public:
|
||||
/// The expressions built to support OpenMP loops in combined/composite
|
||||
@ -798,6 +829,15 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
SmallVector<Expr *, 4> Updates;
|
||||
/// Final loop counter values for GodeGen.
|
||||
SmallVector<Expr *, 4> Finals;
|
||||
/// List of counters required for the generation of the non-rectangular
|
||||
/// loops.
|
||||
SmallVector<Expr *, 4> DependentCounters;
|
||||
/// List of initializers required for the generation of the non-rectangular
|
||||
/// loops.
|
||||
SmallVector<Expr *, 4> DependentInits;
|
||||
/// List of final conditions required for the generation of the
|
||||
/// non-rectangular loops.
|
||||
SmallVector<Expr *, 4> FinalsConditions;
|
||||
/// Init statement for all captured expressions.
|
||||
Stmt *PreInits;
|
||||
|
||||
@ -813,7 +853,9 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
}
|
||||
|
||||
/// Initialize all the fields to null.
|
||||
/// \param Size Number of elements in the counters/finals/updates arrays.
|
||||
/// \param Size Number of elements in the
|
||||
/// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
|
||||
/// arrays.
|
||||
void clear(unsigned Size) {
|
||||
IterationVarRef = nullptr;
|
||||
LastIteration = nullptr;
|
||||
@ -839,12 +881,18 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
Inits.resize(Size);
|
||||
Updates.resize(Size);
|
||||
Finals.resize(Size);
|
||||
DependentCounters.resize(Size);
|
||||
DependentInits.resize(Size);
|
||||
FinalsConditions.resize(Size);
|
||||
for (unsigned i = 0; i < Size; ++i) {
|
||||
Counters[i] = nullptr;
|
||||
PrivateCounters[i] = nullptr;
|
||||
Inits[i] = nullptr;
|
||||
Updates[i] = nullptr;
|
||||
Finals[i] = nullptr;
|
||||
DependentCounters[i] = nullptr;
|
||||
DependentInits[i] = nullptr;
|
||||
FinalsConditions[i] = nullptr;
|
||||
}
|
||||
PreInits = nullptr;
|
||||
DistCombinedFields.LB = nullptr;
|
||||
@ -1040,10 +1088,22 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
// This relies on the loop form is already checked by Sema.
|
||||
const Stmt *Body =
|
||||
getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
|
||||
Body = cast<ForStmt>(Body)->getBody();
|
||||
if (auto *For = dyn_cast<ForStmt>(Body)) {
|
||||
Body = For->getBody();
|
||||
} else {
|
||||
assert(isa<CXXForRangeStmt>(Body) &&
|
||||
"Expected canonical for loop or range-based for loop.");
|
||||
Body = cast<CXXForRangeStmt>(Body)->getBody();
|
||||
}
|
||||
for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) {
|
||||
Body = Body->IgnoreContainers();
|
||||
Body = cast<ForStmt>(Body)->getBody();
|
||||
if (auto *For = dyn_cast<ForStmt>(Body)) {
|
||||
Body = For->getBody();
|
||||
} else {
|
||||
assert(isa<CXXForRangeStmt>(Body) &&
|
||||
"Expected canonical for loop or range-based for loop.");
|
||||
Body = cast<CXXForRangeStmt>(Body)->getBody();
|
||||
}
|
||||
}
|
||||
return Body;
|
||||
}
|
||||
@ -1078,6 +1138,24 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
return const_cast<OMPLoopDirective *>(this)->getFinals();
|
||||
}
|
||||
|
||||
ArrayRef<Expr *> dependent_counters() { return getDependentCounters(); }
|
||||
|
||||
ArrayRef<Expr *> dependent_counters() const {
|
||||
return const_cast<OMPLoopDirective *>(this)->getDependentCounters();
|
||||
}
|
||||
|
||||
ArrayRef<Expr *> dependent_inits() { return getDependentInits(); }
|
||||
|
||||
ArrayRef<Expr *> dependent_inits() const {
|
||||
return const_cast<OMPLoopDirective *>(this)->getDependentInits();
|
||||
}
|
||||
|
||||
ArrayRef<Expr *> finals_conditions() { return getFinalsConditions(); }
|
||||
|
||||
ArrayRef<Expr *> finals_conditions() const {
|
||||
return const_cast<OMPLoopDirective *>(this)->getFinalsConditions();
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPSimdDirectiveClass ||
|
||||
T->getStmtClass() == OMPForDirectiveClass ||
|
||||
@ -1086,6 +1164,9 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
|
||||
T->getStmtClass() == OMPTaskLoopDirectiveClass ||
|
||||
T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
|
||||
T->getStmtClass() == OMPMasterTaskLoopDirectiveClass ||
|
||||
T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass ||
|
||||
T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass ||
|
||||
T->getStmtClass() == OMPDistributeDirectiveClass ||
|
||||
T->getStmtClass() == OMPTargetParallelForDirectiveClass ||
|
||||
T->getStmtClass() == OMPDistributeParallelForDirectiveClass ||
|
||||
@ -3041,6 +3122,211 @@ class OMPTaskLoopSimdDirective : public OMPLoopDirective {
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents '#pragma omp master taskloop' directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp master taskloop private(a,b) grainsize(val) num_tasks(num)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp master taskloop' has clauses
|
||||
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
|
||||
/// and 'num_tasks' with expression 'num'.
|
||||
///
|
||||
class OMPMasterTaskLoopDirective : public OMPLoopDirective {
|
||||
friend class ASTStmtReader;
|
||||
/// Build directive with the given start and end location.
|
||||
///
|
||||
/// \param StartLoc Starting location of the directive kind.
|
||||
/// \param EndLoc Ending location of the directive.
|
||||
/// \param CollapsedNum Number of collapsed nested loops.
|
||||
/// \param NumClauses Number of clauses.
|
||||
///
|
||||
OMPMasterTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
unsigned CollapsedNum, unsigned NumClauses)
|
||||
: OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass,
|
||||
OMPD_master_taskloop, StartLoc, EndLoc, CollapsedNum,
|
||||
NumClauses) {}
|
||||
|
||||
/// Build an empty directive.
|
||||
///
|
||||
/// \param CollapsedNum Number of collapsed nested loops.
|
||||
/// \param NumClauses Number of clauses.
|
||||
///
|
||||
explicit OMPMasterTaskLoopDirective(unsigned CollapsedNum,
|
||||
unsigned NumClauses)
|
||||
: OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass,
|
||||
OMPD_master_taskloop, SourceLocation(),
|
||||
SourceLocation(), CollapsedNum, NumClauses) {}
|
||||
|
||||
public:
|
||||
/// Creates directive with a list of \a Clauses.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param StartLoc Starting location of the directive kind.
|
||||
/// \param EndLoc Ending Location of the directive.
|
||||
/// \param CollapsedNum Number of collapsed loops.
|
||||
/// \param Clauses List of clauses.
|
||||
/// \param AssociatedStmt Statement, associated with the directive.
|
||||
/// \param Exprs Helper expressions for CodeGen.
|
||||
///
|
||||
static OMPMasterTaskLoopDirective *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AssociatedStmt, const HelperExprs &Exprs);
|
||||
|
||||
/// Creates an empty directive with the place
|
||||
/// for \a NumClauses clauses.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param CollapsedNum Number of collapsed nested loops.
|
||||
/// \param NumClauses Number of clauses.
|
||||
///
|
||||
static OMPMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses,
|
||||
unsigned CollapsedNum,
|
||||
EmptyShell);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPMasterTaskLoopDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents '#pragma omp master taskloop simd' directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp master taskloop simd private(a,b) grainsize(val) num_tasks(num)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp master taskloop simd' has clauses
|
||||
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
|
||||
/// and 'num_tasks' with expression 'num'.
|
||||
///
|
||||
class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective {
|
||||
friend class ASTStmtReader;
|
||||
/// Build directive with the given start and end location.
|
||||
///
|
||||
/// \param StartLoc Starting location of the directive kind.
|
||||
/// \param EndLoc Ending location of the directive.
|
||||
/// \param CollapsedNum Number of collapsed nested loops.
|
||||
/// \param NumClauses Number of clauses.
|
||||
///
|
||||
OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
unsigned CollapsedNum, unsigned NumClauses)
|
||||
: OMPLoopDirective(this, OMPMasterTaskLoopSimdDirectiveClass,
|
||||
OMPD_master_taskloop_simd, StartLoc, EndLoc,
|
||||
CollapsedNum, NumClauses) {}
|
||||
|
||||
/// Build an empty directive.
|
||||
///
|
||||
/// \param CollapsedNum Number of collapsed nested loops.
|
||||
/// \param NumClauses Number of clauses.
|
||||
///
|
||||
explicit OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum,
|
||||
unsigned NumClauses)
|
||||
: OMPLoopDirective(this, OMPMasterTaskLoopSimdDirectiveClass,
|
||||
OMPD_master_taskloop_simd, SourceLocation(),
|
||||
SourceLocation(), CollapsedNum, NumClauses) {}
|
||||
|
||||
public:
|
||||
/// Creates directive with a list of \p Clauses.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param StartLoc Starting location of the directive kind.
|
||||
/// \param EndLoc Ending Location of the directive.
|
||||
/// \param CollapsedNum Number of collapsed loops.
|
||||
/// \param Clauses List of clauses.
|
||||
/// \param AssociatedStmt Statement, associated with the directive.
|
||||
/// \param Exprs Helper expressions for CodeGen.
|
||||
///
|
||||
static OMPMasterTaskLoopSimdDirective *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AssociatedStmt, const HelperExprs &Exprs);
|
||||
|
||||
/// Creates an empty directive with the place for \p NumClauses clauses.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param CollapsedNum Number of collapsed nested loops.
|
||||
/// \param NumClauses Number of clauses.
|
||||
///
|
||||
static OMPMasterTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses,
|
||||
unsigned CollapsedNum,
|
||||
EmptyShell);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents '#pragma omp parallel master taskloop' directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp parallel master taskloop private(a,b) grainsize(val)
|
||||
/// num_tasks(num)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp parallel master taskloop' has clauses
|
||||
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
|
||||
/// and 'num_tasks' with expression 'num'.
|
||||
///
|
||||
class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
|
||||
friend class ASTStmtReader;
|
||||
/// Build directive with the given start and end location.
|
||||
///
|
||||
/// \param StartLoc Starting location of the directive kind.
|
||||
/// \param EndLoc Ending location of the directive.
|
||||
/// \param CollapsedNum Number of collapsed nested loops.
|
||||
/// \param NumClauses Number of clauses.
|
||||
///
|
||||
OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc,
|
||||
SourceLocation EndLoc,
|
||||
unsigned CollapsedNum, unsigned NumClauses)
|
||||
: OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass,
|
||||
OMPD_parallel_master_taskloop, StartLoc, EndLoc,
|
||||
CollapsedNum, NumClauses) {}
|
||||
|
||||
/// Build an empty directive.
|
||||
///
|
||||
/// \param CollapsedNum Number of collapsed nested loops.
|
||||
/// \param NumClauses Number of clauses.
|
||||
///
|
||||
explicit OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum,
|
||||
unsigned NumClauses)
|
||||
: OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass,
|
||||
OMPD_parallel_master_taskloop, SourceLocation(),
|
||||
SourceLocation(), CollapsedNum, NumClauses) {}
|
||||
|
||||
public:
|
||||
/// Creates directive with a list of \a Clauses.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param StartLoc Starting location of the directive kind.
|
||||
/// \param EndLoc Ending Location of the directive.
|
||||
/// \param CollapsedNum Number of collapsed loops.
|
||||
/// \param Clauses List of clauses.
|
||||
/// \param AssociatedStmt Statement, associated with the directive.
|
||||
/// \param Exprs Helper expressions for CodeGen.
|
||||
///
|
||||
static OMPParallelMasterTaskLoopDirective *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AssociatedStmt, const HelperExprs &Exprs);
|
||||
|
||||
/// Creates an empty directive with the place
|
||||
/// for \a NumClauses clauses.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param CollapsedNum Number of collapsed nested loops.
|
||||
/// \param NumClauses Number of clauses.
|
||||
///
|
||||
static OMPParallelMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses,
|
||||
unsigned CollapsedNum,
|
||||
EmptyShell);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents '#pragma omp distribute' directive.
|
||||
///
|
||||
/// \code
|
||||
|
@ -146,8 +146,6 @@ class TextNodeDumper
|
||||
|
||||
const comments::CommandTraits *Traits;
|
||||
|
||||
const ASTContext *Context;
|
||||
|
||||
const char *getCommandName(unsigned CommandID);
|
||||
|
||||
public:
|
||||
|
@ -126,7 +126,7 @@ using CanQualType = CanQual<Type>;
|
||||
|
||||
// Provide forward declarations for all of the *Type classes.
|
||||
#define TYPE(Class, Base) class Class##Type;
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
|
||||
/// The collection of all-type qualifiers we support.
|
||||
/// Clang supports five independent qualifiers:
|
||||
@ -972,6 +972,9 @@ class QualType {
|
||||
friend bool operator!=(const QualType &LHS, const QualType &RHS) {
|
||||
return LHS.Value != RHS.Value;
|
||||
}
|
||||
friend bool operator<(const QualType &LHS, const QualType &RHS) {
|
||||
return LHS.Value < RHS.Value;
|
||||
}
|
||||
|
||||
static std::string getAsString(SplitQualType split,
|
||||
const PrintingPolicy &Policy) {
|
||||
@ -1434,10 +1437,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
|
||||
public:
|
||||
enum TypeClass {
|
||||
#define TYPE(Class, Base) Class,
|
||||
#define LAST_TYPE(Class) TypeLast = Class,
|
||||
#define LAST_TYPE(Class) TypeLast = Class
|
||||
#define ABSTRACT_TYPE(Class, Base)
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
TagFirst = Record, TagLast = Enum
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
};
|
||||
|
||||
private:
|
||||
@ -1511,6 +1513,15 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
|
||||
unsigned SizeModifier : 3;
|
||||
};
|
||||
|
||||
class ConstantArrayTypeBitfields {
|
||||
friend class ConstantArrayType;
|
||||
|
||||
unsigned : NumTypeBits + 3 + 3;
|
||||
|
||||
/// Whether we have a stored size expression.
|
||||
unsigned HasStoredSizeExpr : 1;
|
||||
};
|
||||
|
||||
class BuiltinTypeBitfields {
|
||||
friend class BuiltinType;
|
||||
|
||||
@ -1732,6 +1743,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
|
||||
union {
|
||||
TypeBitfields TypeBits;
|
||||
ArrayTypeBitfields ArrayTypeBits;
|
||||
ConstantArrayTypeBitfields ConstantArrayTypeBits;
|
||||
AttributedTypeBitfields AttributedTypeBits;
|
||||
AutoTypeBitfields AutoTypeBits;
|
||||
BuiltinTypeBitfields BuiltinTypeBits;
|
||||
@ -2053,6 +2065,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
|
||||
bool isCARCBridgableType() const;
|
||||
bool isTemplateTypeParmType() const; // C++ template type parameter
|
||||
bool isNullPtrType() const; // C++11 std::nullptr_t
|
||||
bool isNothrowT() const; // C++ std::nothrow_t
|
||||
bool isAlignValT() const; // C++17 std::align_val_t
|
||||
bool isStdByteType() const; // C++17 std::byte
|
||||
bool isAtomicType() const; // C11 _Atomic()
|
||||
@ -2416,7 +2429,7 @@ template <> inline const Class##Type *Type::getAs() const { \
|
||||
template <> inline const Class##Type *Type::castAs() const { \
|
||||
return cast<Class##Type>(CanonicalType); \
|
||||
}
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
|
||||
/// This class is used for builtin types like 'int'. Builtin
|
||||
/// types are always canonical and have a literal name field.
|
||||
@ -2429,6 +2442,9 @@ class BuiltinType : public Type {
|
||||
// OpenCL extension types
|
||||
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) Id,
|
||||
#include "clang/Basic/OpenCLExtensionTypes.def"
|
||||
// SVE Types
|
||||
#define SVE_TYPE(Name, Id, SingletonId) Id,
|
||||
#include "clang/Basic/AArch64SVEACLETypes.def"
|
||||
// All other builtin types
|
||||
#define BUILTIN_TYPE(Id, SingletonId) Id,
|
||||
#define LAST_BUILTIN_TYPE(Id) LastKind = Id
|
||||
@ -2858,22 +2874,8 @@ class ArrayType : public Type, public llvm::FoldingSetNode {
|
||||
protected:
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
// C++ [temp.dep.type]p1:
|
||||
// A type is dependent if it is...
|
||||
// - an array type constructed from any dependent type or whose
|
||||
// size is specified by a constant expression that is
|
||||
// value-dependent,
|
||||
ArrayType(TypeClass tc, QualType et, QualType can,
|
||||
ArraySizeModifier sm, unsigned tq,
|
||||
bool ContainsUnexpandedParameterPack)
|
||||
: Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
|
||||
et->isInstantiationDependentType() || tc == DependentSizedArray,
|
||||
(tc == VariableArray || et->isVariablyModifiedType()),
|
||||
ContainsUnexpandedParameterPack),
|
||||
ElementType(et) {
|
||||
ArrayTypeBits.IndexTypeQuals = tq;
|
||||
ArrayTypeBits.SizeModifier = sm;
|
||||
}
|
||||
ArrayType(TypeClass tc, QualType et, QualType can, ArraySizeModifier sm,
|
||||
unsigned tq, const Expr *sz = nullptr);
|
||||
|
||||
public:
|
||||
QualType getElementType() const { return ElementType; }
|
||||
@ -2901,25 +2903,35 @@ class ArrayType : public Type, public llvm::FoldingSetNode {
|
||||
/// Represents the canonical version of C arrays with a specified constant size.
|
||||
/// For example, the canonical type for 'int A[4 + 4*100]' is a
|
||||
/// ConstantArrayType where the element type is 'int' and the size is 404.
|
||||
class ConstantArrayType : public ArrayType {
|
||||
class ConstantArrayType final
|
||||
: public ArrayType,
|
||||
private llvm::TrailingObjects<ConstantArrayType, const Expr *> {
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
friend TrailingObjects;
|
||||
|
||||
llvm::APInt Size; // Allows us to unique the type.
|
||||
|
||||
ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
|
||||
ArraySizeModifier sm, unsigned tq)
|
||||
: ArrayType(ConstantArray, et, can, sm, tq,
|
||||
et->containsUnexpandedParameterPack()),
|
||||
Size(size) {}
|
||||
const Expr *sz, ArraySizeModifier sm, unsigned tq)
|
||||
: ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) {
|
||||
ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr;
|
||||
if (ConstantArrayTypeBits.HasStoredSizeExpr) {
|
||||
assert(!can.isNull() && "canonical constant array should not have size");
|
||||
*getTrailingObjects<const Expr*>() = sz;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
ConstantArrayType(TypeClass tc, QualType et, QualType can,
|
||||
const llvm::APInt &size, ArraySizeModifier sm, unsigned tq)
|
||||
: ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()),
|
||||
Size(size) {}
|
||||
unsigned numTrailingObjects(OverloadToken<const Expr*>) const {
|
||||
return ConstantArrayTypeBits.HasStoredSizeExpr;
|
||||
}
|
||||
|
||||
public:
|
||||
const llvm::APInt &getSize() const { return Size; }
|
||||
const Expr *getSizeExpr() const {
|
||||
return ConstantArrayTypeBits.HasStoredSizeExpr
|
||||
? *getTrailingObjects<const Expr *>()
|
||||
: nullptr;
|
||||
}
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -2933,19 +2945,15 @@ class ConstantArrayType : public ArrayType {
|
||||
/// can require, which limits the maximum size of the array.
|
||||
static unsigned getMaxSizeBits(const ASTContext &Context);
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getElementType(), getSize(),
|
||||
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
|
||||
Profile(ID, Ctx, getElementType(), getSize(), getSizeExpr(),
|
||||
getSizeModifier(), getIndexTypeCVRQualifiers());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
|
||||
const llvm::APInt &ArraySize, ArraySizeModifier SizeMod,
|
||||
unsigned TypeQuals) {
|
||||
ID.AddPointer(ET.getAsOpaquePtr());
|
||||
ID.AddInteger(ArraySize.getZExtValue());
|
||||
ID.AddInteger(SizeMod);
|
||||
ID.AddInteger(TypeQuals);
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx,
|
||||
QualType ET, const llvm::APInt &ArraySize,
|
||||
const Expr *SizeExpr, ArraySizeModifier SizeMod,
|
||||
unsigned TypeQuals);
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ConstantArray;
|
||||
@ -2960,8 +2968,7 @@ class IncompleteArrayType : public ArrayType {
|
||||
|
||||
IncompleteArrayType(QualType et, QualType can,
|
||||
ArraySizeModifier sm, unsigned tq)
|
||||
: ArrayType(IncompleteArray, et, can, sm, tq,
|
||||
et->containsUnexpandedParameterPack()) {}
|
||||
: ArrayType(IncompleteArray, et, can, sm, tq) {}
|
||||
|
||||
public:
|
||||
friend class StmtIteratorBase;
|
||||
@ -3013,8 +3020,7 @@ class VariableArrayType : public ArrayType {
|
||||
VariableArrayType(QualType et, QualType can, Expr *e,
|
||||
ArraySizeModifier sm, unsigned tq,
|
||||
SourceRange brackets)
|
||||
: ArrayType(VariableArray, et, can, sm, tq,
|
||||
et->containsUnexpandedParameterPack()),
|
||||
: ArrayType(VariableArray, et, can, sm, tq, e),
|
||||
SizeExpr((Stmt*) e), Brackets(brackets) {}
|
||||
|
||||
public:
|
||||
@ -4429,7 +4435,7 @@ class TagType : public Type {
|
||||
bool isBeingDefined() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
|
||||
return T->getTypeClass() == Enum || T->getTypeClass() == Record;
|
||||
}
|
||||
};
|
||||
|
||||
@ -5563,7 +5569,7 @@ class ObjCTypeParamType : public Type,
|
||||
|
||||
public:
|
||||
bool isSugared() const { return true; }
|
||||
QualType desugar() const { return getCanonicalTypeInternal(); }
|
||||
QualType desugar() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ObjCTypeParam;
|
||||
@ -6347,6 +6353,7 @@ inline bool QualType::isCForbiddenLValueType() const {
|
||||
/// \returns True for types specified in C++0x [basic.fundamental].
|
||||
inline bool Type::isFundamentalType() const {
|
||||
return isVoidType() ||
|
||||
isNullPtrType() ||
|
||||
// FIXME: It's really annoying that we don't have an
|
||||
// 'isArithmeticType()' which agrees with the standard definition.
|
||||
(isArithmeticType() && !isEnumeralType());
|
||||
|
@ -106,7 +106,7 @@ class TypeLoc {
|
||||
#define ABSTRACT_TYPE(Class, Base)
|
||||
#define TYPE(Class, Base) \
|
||||
Class = Type::Class,
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
Qualified
|
||||
};
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
TYPELOC(Qualified, TypeLoc)
|
||||
#define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc)
|
||||
#define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc)
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
|
||||
#undef DECLARATOR_TYPELOC
|
||||
#undef TYPESPEC_TYPELOC
|
||||
|
@ -1,135 +0,0 @@
|
||||
//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the AST type info database. Each type node is
|
||||
// enumerated by providing its name (e.g., "Builtin" or "Enum") and
|
||||
// base class (e.g., "Type" or "TagType"). Depending on where in the
|
||||
// abstract syntax tree the type will show up, the enumeration uses
|
||||
// one of five different macros:
|
||||
//
|
||||
// TYPE(Class, Base) - A type that can show up anywhere in the AST,
|
||||
// and might be dependent, canonical, or non-canonical. All clients
|
||||
// will need to understand these types.
|
||||
//
|
||||
// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
|
||||
// the type hierarchy but has no concrete instances.
|
||||
//
|
||||
// NON_CANONICAL_TYPE(Class, Base) - A type that can show up
|
||||
// anywhere in the AST but will never be a part of a canonical
|
||||
// type. Clients that only need to deal with canonical types
|
||||
// (ignoring, e.g., typedefs and other type aliases used for
|
||||
// pretty-printing) can ignore these types.
|
||||
//
|
||||
// DEPENDENT_TYPE(Class, Base) - A type that will only show up
|
||||
// within a C++ template that has not been instantiated, e.g., a
|
||||
// type that is always dependent. Clients that do not need to deal
|
||||
// with uninstantiated C++ templates can ignore these types.
|
||||
//
|
||||
// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
|
||||
// is non-canonical unless it is dependent. Defaults to TYPE because
|
||||
// it is neither reliably dependent nor reliably non-canonical.
|
||||
//
|
||||
// There is a sixth macro, independent of the others. Most clients
|
||||
// will not need to use it.
|
||||
//
|
||||
// LEAF_TYPE(Class) - A type that never has inner types. Clients
|
||||
// which can operate on such types more efficiently may wish to do so.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ABSTRACT_TYPE
|
||||
# define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base)
|
||||
#endif
|
||||
|
||||
#ifndef NON_CANONICAL_TYPE
|
||||
# define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base)
|
||||
#endif
|
||||
|
||||
#ifndef DEPENDENT_TYPE
|
||||
# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
|
||||
#endif
|
||||
|
||||
#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
|
||||
# define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
|
||||
#endif
|
||||
|
||||
TYPE(Builtin, Type)
|
||||
TYPE(Complex, Type)
|
||||
TYPE(Pointer, Type)
|
||||
TYPE(BlockPointer, Type)
|
||||
ABSTRACT_TYPE(Reference, Type)
|
||||
TYPE(LValueReference, ReferenceType)
|
||||
TYPE(RValueReference, ReferenceType)
|
||||
TYPE(MemberPointer, Type)
|
||||
ABSTRACT_TYPE(Array, Type)
|
||||
TYPE(ConstantArray, ArrayType)
|
||||
TYPE(IncompleteArray, ArrayType)
|
||||
TYPE(VariableArray, ArrayType)
|
||||
DEPENDENT_TYPE(DependentSizedArray, ArrayType)
|
||||
DEPENDENT_TYPE(DependentSizedExtVector, Type)
|
||||
DEPENDENT_TYPE(DependentAddressSpace, Type)
|
||||
TYPE(Vector, Type)
|
||||
DEPENDENT_TYPE(DependentVector, Type)
|
||||
TYPE(ExtVector, VectorType)
|
||||
ABSTRACT_TYPE(Function, Type)
|
||||
TYPE(FunctionProto, FunctionType)
|
||||
TYPE(FunctionNoProto, FunctionType)
|
||||
DEPENDENT_TYPE(UnresolvedUsing, Type)
|
||||
NON_CANONICAL_TYPE(Paren, Type)
|
||||
NON_CANONICAL_TYPE(Typedef, Type)
|
||||
NON_CANONICAL_TYPE(MacroQualified, Type)
|
||||
NON_CANONICAL_TYPE(Adjusted, Type)
|
||||
NON_CANONICAL_TYPE(Decayed, AdjustedType)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(UnaryTransform, Type)
|
||||
ABSTRACT_TYPE(Tag, Type)
|
||||
TYPE(Record, TagType)
|
||||
TYPE(Enum, TagType)
|
||||
NON_CANONICAL_TYPE(Elaborated, Type)
|
||||
NON_CANONICAL_TYPE(Attributed, Type)
|
||||
DEPENDENT_TYPE(TemplateTypeParm, Type)
|
||||
NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
|
||||
DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
|
||||
ABSTRACT_TYPE(Deduced, Type)
|
||||
TYPE(Auto, DeducedType)
|
||||
TYPE(DeducedTemplateSpecialization, DeducedType)
|
||||
DEPENDENT_TYPE(InjectedClassName, Type)
|
||||
DEPENDENT_TYPE(DependentName, Type)
|
||||
DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
|
||||
NON_CANONICAL_TYPE(ObjCTypeParam, Type)
|
||||
TYPE(ObjCObject, Type)
|
||||
TYPE(ObjCInterface, ObjCObjectType)
|
||||
TYPE(ObjCObjectPointer, Type)
|
||||
TYPE(Pipe, Type)
|
||||
TYPE(Atomic, Type)
|
||||
|
||||
#ifdef LAST_TYPE
|
||||
LAST_TYPE(Atomic)
|
||||
#undef LAST_TYPE
|
||||
#endif
|
||||
|
||||
// These types are always leaves in the type hierarchy.
|
||||
#ifdef LEAF_TYPE
|
||||
LEAF_TYPE(Enum)
|
||||
LEAF_TYPE(Builtin)
|
||||
LEAF_TYPE(Record)
|
||||
LEAF_TYPE(InjectedClassName)
|
||||
LEAF_TYPE(ObjCInterface)
|
||||
LEAF_TYPE(TemplateTypeParm)
|
||||
#undef LEAF_TYPE
|
||||
#endif
|
||||
|
||||
#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
|
||||
#undef DEPENDENT_TYPE
|
||||
#undef NON_CANONICAL_TYPE
|
||||
#undef ABSTRACT_TYPE
|
||||
#undef TYPE
|
@ -70,7 +70,7 @@ class TypeVisitor {
|
||||
switch (T->getTypeClass()) {
|
||||
#define ABSTRACT_TYPE(CLASS, PARENT)
|
||||
#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type);
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
}
|
||||
llvm_unreachable("Unknown type class!");
|
||||
}
|
||||
@ -80,7 +80,7 @@ class TypeVisitor {
|
||||
#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \
|
||||
DISPATCH(PARENT); \
|
||||
}
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
|
||||
/// Method called if \c ImpClass doesn't provide specific handler
|
||||
/// for some type class.
|
||||
|
@ -19,15 +19,15 @@
|
||||
//
|
||||
// For more complicated match expressions we're often interested in accessing
|
||||
// multiple parts of the matched AST nodes once a match is found. In that case,
|
||||
// use the id(...) matcher around the match expressions that match the nodes
|
||||
// you want to access.
|
||||
// call `.bind("name")` on match expressions that match the nodes you want to
|
||||
// access.
|
||||
//
|
||||
// For example, when we're interested in child classes of a certain class, we
|
||||
// would write:
|
||||
// cxxRecordDecl(hasName("MyClass"), has(id("child", recordDecl())))
|
||||
// cxxRecordDecl(hasName("MyClass"), has(recordDecl().bind("child")))
|
||||
// When the match is found via the MatchFinder, a user provided callback will
|
||||
// be called with a BoundNodes instance that contains a mapping from the
|
||||
// strings that we provided for the id(...) calls to the nodes that were
|
||||
// strings that we provided for the `.bind()` calls to the nodes that were
|
||||
// matched.
|
||||
// In the given example, each time our matcher finds a match we get a callback
|
||||
// where "child" is bound to the RecordDecl node of the matching child
|
||||
@ -131,15 +131,6 @@ class BoundNodes {
|
||||
internal::BoundNodesMap MyBoundNodes;
|
||||
};
|
||||
|
||||
/// If the provided matcher matches a node, binds the node to \c ID.
|
||||
///
|
||||
/// FIXME: Do we want to support this now that we have bind()?
|
||||
template <typename T>
|
||||
internal::Matcher<T> id(StringRef ID,
|
||||
const internal::BindableMatcher<T> &InnerMatcher) {
|
||||
return InnerMatcher.bind(ID);
|
||||
}
|
||||
|
||||
/// Types of matchers for the top-level classes in the AST class
|
||||
/// hierarchy.
|
||||
/// @{
|
||||
@ -2611,8 +2602,9 @@ hasOverloadedOperatorName(StringRef Name) {
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name);
|
||||
}
|
||||
|
||||
/// Matches C++ classes that are directly or indirectly derived from
|
||||
/// a class matching \c Base.
|
||||
/// Matches C++ classes that are directly or indirectly derived from a class
|
||||
/// matching \c Base, or Objective-C classes that directly or indirectly
|
||||
/// subclass a class matching \c Base.
|
||||
///
|
||||
/// Note that a class is not considered to be derived from itself.
|
||||
///
|
||||
@ -2632,33 +2624,128 @@ hasOverloadedOperatorName(StringRef Name) {
|
||||
/// typedef Foo X;
|
||||
/// class Bar : public Foo {}; // derived from a type that X is a typedef of
|
||||
/// \endcode
|
||||
AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
|
||||
internal::Matcher<NamedDecl>, Base) {
|
||||
return Finder->classIsDerivedFrom(&Node, Base, Builder);
|
||||
///
|
||||
/// In the following example, Bar matches isDerivedFrom(hasName("NSObject"))
|
||||
/// \code
|
||||
/// @interface NSObject @end
|
||||
/// @interface Bar : NSObject @end
|
||||
/// \endcode
|
||||
///
|
||||
/// Usable as: Matcher<CXXRecordDecl>, Matcher<ObjCInterfaceDecl>
|
||||
AST_POLYMORPHIC_MATCHER_P(
|
||||
isDerivedFrom,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
|
||||
internal::Matcher<NamedDecl>, Base) {
|
||||
// Check if the node is a C++ struct/union/class.
|
||||
if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
|
||||
return Finder->classIsDerivedFrom(RD, Base, Builder, /*Directly=*/false);
|
||||
|
||||
// The node must be an Objective-C class.
|
||||
const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
|
||||
return Finder->objcClassIsDerivedFrom(InterfaceDecl, Base, Builder,
|
||||
/*Directly=*/false);
|
||||
}
|
||||
|
||||
/// Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
|
||||
AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) {
|
||||
assert(!BaseName.empty());
|
||||
return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
|
||||
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
|
||||
isDerivedFrom,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
|
||||
std::string, BaseName, 1) {
|
||||
if (BaseName.empty())
|
||||
return false;
|
||||
|
||||
const auto M = isDerivedFrom(hasName(BaseName));
|
||||
|
||||
if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
|
||||
return Matcher<CXXRecordDecl>(M).matches(*RD, Finder, Builder);
|
||||
|
||||
const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
|
||||
return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
|
||||
}
|
||||
|
||||
/// Similar to \c isDerivedFrom(), but also matches classes that directly
|
||||
/// match \c Base.
|
||||
AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
|
||||
internal::Matcher<NamedDecl>, Base, 0) {
|
||||
return Matcher<CXXRecordDecl>(anyOf(Base, isDerivedFrom(Base)))
|
||||
.matches(Node, Finder, Builder);
|
||||
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
|
||||
isSameOrDerivedFrom,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
|
||||
internal::Matcher<NamedDecl>, Base, 0) {
|
||||
const auto M = anyOf(Base, isDerivedFrom(Base));
|
||||
|
||||
if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
|
||||
return Matcher<CXXRecordDecl>(M).matches(*RD, Finder, Builder);
|
||||
|
||||
const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
|
||||
return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
|
||||
}
|
||||
|
||||
/// Overloaded method as shortcut for
|
||||
/// \c isSameOrDerivedFrom(hasName(...)).
|
||||
AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
|
||||
BaseName, 1) {
|
||||
assert(!BaseName.empty());
|
||||
return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
|
||||
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
|
||||
isSameOrDerivedFrom,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
|
||||
std::string, BaseName, 1) {
|
||||
if (BaseName.empty())
|
||||
return false;
|
||||
|
||||
const auto M = isSameOrDerivedFrom(hasName(BaseName));
|
||||
|
||||
if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
|
||||
return Matcher<CXXRecordDecl>(M).matches(*RD, Finder, Builder);
|
||||
|
||||
const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
|
||||
return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
|
||||
}
|
||||
|
||||
/// Matches C++ or Objective-C classes that are directly derived from a class
|
||||
/// matching \c Base.
|
||||
///
|
||||
/// Note that a class is not considered to be derived from itself.
|
||||
///
|
||||
/// Example matches Y, C (Base == hasName("X"))
|
||||
/// \code
|
||||
/// class X;
|
||||
/// class Y : public X {}; // directly derived
|
||||
/// class Z : public Y {}; // indirectly derived
|
||||
/// typedef X A;
|
||||
/// typedef A B;
|
||||
/// class C : public B {}; // derived from a typedef of X
|
||||
/// \endcode
|
||||
///
|
||||
/// In the following example, Bar matches isDerivedFrom(hasName("X")):
|
||||
/// \code
|
||||
/// class Foo;
|
||||
/// typedef Foo X;
|
||||
/// class Bar : public Foo {}; // derived from a type that X is a typedef of
|
||||
/// \endcode
|
||||
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
|
||||
isDirectlyDerivedFrom,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
|
||||
internal::Matcher<NamedDecl>, Base, 0) {
|
||||
// Check if the node is a C++ struct/union/class.
|
||||
if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
|
||||
return Finder->classIsDerivedFrom(RD, Base, Builder, /*Directly=*/true);
|
||||
|
||||
// The node must be an Objective-C class.
|
||||
const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
|
||||
return Finder->objcClassIsDerivedFrom(InterfaceDecl, Base, Builder,
|
||||
/*Directly=*/true);
|
||||
}
|
||||
|
||||
/// Overloaded method as shortcut for \c isDirectlyDerivedFrom(hasName(...)).
|
||||
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
|
||||
isDirectlyDerivedFrom,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
|
||||
std::string, BaseName, 1) {
|
||||
if (BaseName.empty())
|
||||
return false;
|
||||
const auto M = isDirectlyDerivedFrom(hasName(BaseName));
|
||||
|
||||
if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
|
||||
return Matcher<CXXRecordDecl>(M).matches(*RD, Finder, Builder);
|
||||
|
||||
const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
|
||||
return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
|
||||
}
|
||||
/// Matches the first method of a class or struct that satisfies \c
|
||||
/// InnerMatcher.
|
||||
///
|
||||
@ -6358,10 +6445,9 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
|
||||
/// expr(nullPointerConstant())
|
||||
/// matches the initializer for v1, v2, v3, cp, and ip. Does not match the
|
||||
/// initializer for i.
|
||||
AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) {
|
||||
return anyOf(
|
||||
gnuNullExpr(), cxxNullPtrLiteralExpr(),
|
||||
integerLiteral(equals(0), hasParent(expr(hasType(pointerType())))));
|
||||
AST_MATCHER(Expr, nullPointerConstant) {
|
||||
return Node.isNullPointerConstant(Finder->getASTContext(),
|
||||
Expr::NPC_ValueDependentIsNull);
|
||||
}
|
||||
|
||||
/// Matches declaration of the function the statement belongs to
|
||||
@ -6375,7 +6461,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) {
|
||||
/// \endcode
|
||||
/// returnStmt(forFunction(hasName("operator=")))
|
||||
/// matches 'return *this'
|
||||
/// but does match 'return > 0'
|
||||
/// but does not match 'return v > 0'
|
||||
AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>,
|
||||
InnerMatcher) {
|
||||
const auto &Parents = Finder->getASTContext().getParents(Node);
|
||||
@ -6498,14 +6584,15 @@ AST_MATCHER(FunctionDecl, hasTrailingReturn) {
|
||||
}
|
||||
|
||||
/// Matches expressions that match InnerMatcher that are possibly wrapped in an
|
||||
/// elidable constructor.
|
||||
/// elidable constructor and other corresponding bookkeeping nodes.
|
||||
///
|
||||
/// In C++17 copy elidable constructors are no longer being
|
||||
/// generated in the AST as it is not permitted by the standard. They are
|
||||
/// however part of the AST in C++14 and earlier. Therefore, to write a matcher
|
||||
/// that works in all language modes, the matcher has to skip elidable
|
||||
/// constructor AST nodes if they appear in the AST. This matcher can be used to
|
||||
/// skip those elidable constructors.
|
||||
/// In C++17, elidable copy constructors are no longer being generated in the
|
||||
/// AST as it is not permitted by the standard. They are, however, part of the
|
||||
/// AST in C++14 and earlier. So, a matcher must abstract over these differences
|
||||
/// to work in all language modes. This matcher skips elidable constructor-call
|
||||
/// AST nodes, `ExprWithCleanups` nodes wrapping elidable constructor-calls and
|
||||
/// various implicit nodes inside the constructor calls, all of which will not
|
||||
/// appear in the C++17 AST.
|
||||
///
|
||||
/// Given
|
||||
///
|
||||
@ -6517,13 +6604,20 @@ AST_MATCHER(FunctionDecl, hasTrailingReturn) {
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// ``varDecl(hasInitializer(any(
|
||||
/// ignoringElidableConstructorCall(callExpr()),
|
||||
/// exprWithCleanups(ignoringElidableConstructorCall(callExpr()))))``
|
||||
/// matches ``H D = G()``
|
||||
/// ``varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())))``
|
||||
/// matches ``H D = G()`` in C++11 through C++17 (and beyond).
|
||||
AST_MATCHER_P(Expr, ignoringElidableConstructorCall,
|
||||
ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
|
||||
if (const auto *CtorExpr = dyn_cast<CXXConstructExpr>(&Node)) {
|
||||
// E tracks the node that we are examining.
|
||||
const Expr *E = &Node;
|
||||
// If present, remove an outer `ExprWithCleanups` corresponding to the
|
||||
// underlying `CXXConstructExpr`. This check won't cover all cases of added
|
||||
// `ExprWithCleanups` corresponding to `CXXConstructExpr` nodes (because the
|
||||
// EWC is placed on the outermost node of the expression, which this may not
|
||||
// be), but, it still improves the coverage of this matcher.
|
||||
if (const auto *CleanupsExpr = dyn_cast<ExprWithCleanups>(&Node))
|
||||
E = CleanupsExpr->getSubExpr();
|
||||
if (const auto *CtorExpr = dyn_cast<CXXConstructExpr>(E)) {
|
||||
if (CtorExpr->isElidable()) {
|
||||
if (const auto *MaterializeTemp =
|
||||
dyn_cast<MaterializeTemporaryExpr>(CtorExpr->getArg(0))) {
|
||||
|
@ -183,7 +183,8 @@ class BoundNodesMap {
|
||||
/// Note that we're using std::map here, as for memoization:
|
||||
/// - we need a comparison operator
|
||||
/// - we need an assignment operator
|
||||
using IDToNodeMap = std::map<std::string, ast_type_traits::DynTypedNode>;
|
||||
using IDToNodeMap =
|
||||
std::map<std::string, ast_type_traits::DynTypedNode, std::less<>>;
|
||||
|
||||
const IDToNodeMap &getMap() const {
|
||||
return NodeMap;
|
||||
@ -971,13 +972,23 @@ class ASTMatchFinder {
|
||||
|
||||
virtual ~ASTMatchFinder() = default;
|
||||
|
||||
/// Returns true if the given class is directly or indirectly derived
|
||||
/// Returns true if the given C++ class is directly or indirectly derived
|
||||
/// from a base type matching \c base.
|
||||
///
|
||||
/// A class is considered to be also derived from itself.
|
||||
/// A class is not considered to be derived from itself.
|
||||
virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
|
||||
const Matcher<NamedDecl> &Base,
|
||||
BoundNodesTreeBuilder *Builder) = 0;
|
||||
BoundNodesTreeBuilder *Builder,
|
||||
bool Directly) = 0;
|
||||
|
||||
/// Returns true if the given Objective-C class is directly or indirectly
|
||||
/// derived from a base class matching \c base.
|
||||
///
|
||||
/// A class is not considered to be derived from itself.
|
||||
virtual bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
|
||||
const Matcher<NamedDecl> &Base,
|
||||
BoundNodesTreeBuilder *Builder,
|
||||
bool Directly) = 0;
|
||||
|
||||
template <typename T>
|
||||
bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher,
|
||||
@ -1315,7 +1326,7 @@ class ForEachMatcher : public WrapperMatcherInterface<T> {
|
||||
///
|
||||
/// Input matchers can have any type (including other polymorphic matcher
|
||||
/// types), and the actual Matcher<T> is generated on demand with an implicit
|
||||
/// coversion operator.
|
||||
/// conversion operator.
|
||||
template <typename... Ps> class VariadicOperatorMatcher {
|
||||
public:
|
||||
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
|
||||
@ -1324,14 +1335,14 @@ template <typename... Ps> class VariadicOperatorMatcher {
|
||||
template <typename T> operator Matcher<T>() const {
|
||||
return DynTypedMatcher::constructVariadic(
|
||||
Op, ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
|
||||
getMatchers<T>(llvm::index_sequence_for<Ps...>()))
|
||||
getMatchers<T>(std::index_sequence_for<Ps...>()))
|
||||
.template unconditionalConvertTo<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
// Helper method to unpack the tuple into a vector.
|
||||
template <typename T, std::size_t... Is>
|
||||
std::vector<DynTypedMatcher> getMatchers(llvm::index_sequence<Is...>) const {
|
||||
std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) const {
|
||||
return {Matcher<T>(std::get<Is>(Params))...};
|
||||
}
|
||||
|
||||
|
@ -183,9 +183,8 @@ class AnalysisDeclContext {
|
||||
const ImplicitParamDecl *getSelfDecl() const;
|
||||
|
||||
const StackFrameContext *getStackFrame(LocationContext const *Parent,
|
||||
const Stmt *S,
|
||||
const CFGBlock *Blk,
|
||||
unsigned Idx);
|
||||
const Stmt *S, const CFGBlock *Blk,
|
||||
unsigned BlockCount, unsigned Idx);
|
||||
|
||||
const BlockInvocationContext *
|
||||
getBlockInvocationContext(const LocationContext *parent,
|
||||
@ -258,7 +257,7 @@ class LocationContext : public llvm::FoldingSetNode {
|
||||
return getAnalysisDeclContext()->getAnalysis<T>();
|
||||
}
|
||||
|
||||
ParentMap &getParentMap() const {
|
||||
const ParentMap &getParentMap() const {
|
||||
return getAnalysisDeclContext()->getParentMap();
|
||||
}
|
||||
|
||||
@ -303,15 +302,19 @@ class StackFrameContext : public LocationContext {
|
||||
// The parent block of the callsite.
|
||||
const CFGBlock *Block;
|
||||
|
||||
// The number of times the 'Block' has been visited.
|
||||
// It allows discriminating between stack frames of the same call that is
|
||||
// called multiple times in a loop.
|
||||
const unsigned BlockCount;
|
||||
|
||||
// The index of the callsite in the CFGBlock.
|
||||
unsigned Index;
|
||||
const unsigned Index;
|
||||
|
||||
StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
|
||||
const Stmt *s, const CFGBlock *blk,
|
||||
unsigned idx,
|
||||
int64_t ID)
|
||||
: LocationContext(StackFrame, ctx, parent, ID), CallSite(s),
|
||||
Block(blk), Index(idx) {}
|
||||
const Stmt *s, const CFGBlock *blk, unsigned blockCount,
|
||||
unsigned idx, int64_t ID)
|
||||
: LocationContext(StackFrame, ctx, parent, ID), CallSite(s), Block(blk),
|
||||
BlockCount(blockCount), Index(idx) {}
|
||||
|
||||
public:
|
||||
~StackFrameContext() override = default;
|
||||
@ -329,9 +332,10 @@ class StackFrameContext : public LocationContext {
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
|
||||
const LocationContext *parent, const Stmt *s,
|
||||
const CFGBlock *blk, unsigned idx) {
|
||||
const CFGBlock *blk, unsigned blockCount, unsigned idx) {
|
||||
ProfileCommon(ID, StackFrame, ctx, parent, s);
|
||||
ID.AddPointer(blk);
|
||||
ID.AddInteger(blockCount);
|
||||
ID.AddInteger(idx);
|
||||
}
|
||||
|
||||
@ -410,8 +414,8 @@ class LocationContextManager {
|
||||
|
||||
const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const Stmt *s,
|
||||
const CFGBlock *blk, unsigned idx);
|
||||
const Stmt *s, const CFGBlock *blk,
|
||||
unsigned blockCount, unsigned idx);
|
||||
|
||||
const ScopeContext *getScope(AnalysisDeclContext *ctx,
|
||||
const LocationContext *parent,
|
||||
@ -483,26 +487,25 @@ class AnalysisDeclContextManager {
|
||||
bool synthesizeBodies() const { return SynthesizeBodies; }
|
||||
|
||||
const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
|
||||
LocationContext const *Parent,
|
||||
const Stmt *S,
|
||||
const CFGBlock *Blk,
|
||||
unsigned Idx) {
|
||||
return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
|
||||
const LocationContext *Parent,
|
||||
const Stmt *S, const CFGBlock *Blk,
|
||||
unsigned BlockCount, unsigned Idx) {
|
||||
return LocContexts.getStackFrame(Ctx, Parent, S, Blk, BlockCount, Idx);
|
||||
}
|
||||
|
||||
// Get the top level stack frame.
|
||||
const StackFrameContext *getStackFrame(const Decl *D) {
|
||||
return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
|
||||
0);
|
||||
0, 0);
|
||||
}
|
||||
|
||||
// Get a stack frame with parent.
|
||||
StackFrameContext const *getStackFrame(const Decl *D,
|
||||
LocationContext const *Parent,
|
||||
const Stmt *S,
|
||||
const CFGBlock *Blk,
|
||||
unsigned Idx) {
|
||||
return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
|
||||
const LocationContext *Parent,
|
||||
const Stmt *S, const CFGBlock *Blk,
|
||||
unsigned BlockCount, unsigned Idx) {
|
||||
return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, BlockCount,
|
||||
Idx);
|
||||
}
|
||||
|
||||
/// Get a reference to {@code BodyFarm} instance.
|
||||
|
@ -121,6 +121,12 @@ class CFGElement {
|
||||
x |= Data1.getInt();
|
||||
return (Kind) x;
|
||||
}
|
||||
|
||||
void dumpToStream(llvm::raw_ostream &OS) const;
|
||||
|
||||
void dump() const {
|
||||
dumpToStream(llvm::errs());
|
||||
}
|
||||
};
|
||||
|
||||
class CFGStmt : public CFGElement {
|
||||
@ -610,6 +616,153 @@ class CFGBlock {
|
||||
bool empty() const { return Impl.empty(); }
|
||||
};
|
||||
|
||||
/// A convenience class for comparing CFGElements, since methods of CFGBlock
|
||||
/// like operator[] return CFGElements by value. This is practically a wrapper
|
||||
/// around a (CFGBlock, Index) pair.
|
||||
template <bool IsConst> class ElementRefImpl {
|
||||
|
||||
template <bool IsOtherConst> friend class ElementRefImpl;
|
||||
|
||||
using CFGBlockPtr =
|
||||
typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
|
||||
|
||||
using CFGElementPtr = typename std::conditional<IsConst, const CFGElement *,
|
||||
CFGElement *>::type;
|
||||
|
||||
protected:
|
||||
CFGBlockPtr Parent;
|
||||
size_t Index;
|
||||
|
||||
public:
|
||||
ElementRefImpl(CFGBlockPtr Parent, size_t Index)
|
||||
: Parent(Parent), Index(Index) {}
|
||||
|
||||
template <bool IsOtherConst>
|
||||
ElementRefImpl(ElementRefImpl<IsOtherConst> Other)
|
||||
: ElementRefImpl(Other.Parent, Other.Index) {}
|
||||
|
||||
size_t getIndexInBlock() const { return Index; }
|
||||
|
||||
CFGBlockPtr getParent() { return Parent; }
|
||||
CFGBlockPtr getParent() const { return Parent; }
|
||||
|
||||
bool operator<(ElementRefImpl Other) const {
|
||||
return std::make_pair(Parent, Index) <
|
||||
std::make_pair(Other.Parent, Other.Index);
|
||||
}
|
||||
|
||||
bool operator==(ElementRefImpl Other) const {
|
||||
return Parent == Other.Parent && Index == Other.Index;
|
||||
}
|
||||
|
||||
bool operator!=(ElementRefImpl Other) const { return !(*this == Other); }
|
||||
CFGElement operator*() const { return (*Parent)[Index]; }
|
||||
CFGElementPtr operator->() const { return &*(Parent->begin() + Index); }
|
||||
|
||||
void dumpToStream(llvm::raw_ostream &OS) const {
|
||||
OS << getIndexInBlock() + 1 << ": ";
|
||||
(*this)->dumpToStream(OS);
|
||||
}
|
||||
|
||||
void dump() const {
|
||||
dumpToStream(llvm::errs());
|
||||
}
|
||||
};
|
||||
|
||||
template <bool IsReverse, bool IsConst> class ElementRefIterator {
|
||||
|
||||
template <bool IsOtherReverse, bool IsOtherConst>
|
||||
friend class ElementRefIterator;
|
||||
|
||||
using CFGBlockRef =
|
||||
typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
|
||||
|
||||
using UnderlayingIteratorTy = typename std::conditional<
|
||||
IsConst,
|
||||
typename std::conditional<IsReverse,
|
||||
ElementList::const_reverse_iterator,
|
||||
ElementList::const_iterator>::type,
|
||||
typename std::conditional<IsReverse, ElementList::reverse_iterator,
|
||||
ElementList::iterator>::type>::type;
|
||||
|
||||
using IteratorTraits = typename std::iterator_traits<UnderlayingIteratorTy>;
|
||||
using ElementRef = typename CFGBlock::ElementRefImpl<IsConst>;
|
||||
|
||||
public:
|
||||
using difference_type = typename IteratorTraits::difference_type;
|
||||
using value_type = ElementRef;
|
||||
using pointer = ElementRef *;
|
||||
using iterator_category = typename IteratorTraits::iterator_category;
|
||||
|
||||
private:
|
||||
CFGBlockRef Parent;
|
||||
UnderlayingIteratorTy Pos;
|
||||
|
||||
public:
|
||||
ElementRefIterator(CFGBlockRef Parent, UnderlayingIteratorTy Pos)
|
||||
: Parent(Parent), Pos(Pos) {}
|
||||
|
||||
template <bool IsOtherConst>
|
||||
ElementRefIterator(ElementRefIterator<false, IsOtherConst> E)
|
||||
: ElementRefIterator(E.Parent, E.Pos.base()) {}
|
||||
|
||||
template <bool IsOtherConst>
|
||||
ElementRefIterator(ElementRefIterator<true, IsOtherConst> E)
|
||||
: ElementRefIterator(E.Parent, llvm::make_reverse_iterator(E.Pos)) {}
|
||||
|
||||
bool operator<(ElementRefIterator Other) const {
|
||||
assert(Parent == Other.Parent);
|
||||
return Pos < Other.Pos;
|
||||
}
|
||||
|
||||
bool operator==(ElementRefIterator Other) const {
|
||||
return Parent == Other.Parent && Pos == Other.Pos;
|
||||
}
|
||||
|
||||
bool operator!=(ElementRefIterator Other) const {
|
||||
return !(*this == Other);
|
||||
}
|
||||
|
||||
private:
|
||||
template <bool IsOtherConst>
|
||||
static size_t
|
||||
getIndexInBlock(CFGBlock::ElementRefIterator<true, IsOtherConst> E) {
|
||||
return E.Parent->size() - (E.Pos - E.Parent->rbegin()) - 1;
|
||||
}
|
||||
|
||||
template <bool IsOtherConst>
|
||||
static size_t
|
||||
getIndexInBlock(CFGBlock::ElementRefIterator<false, IsOtherConst> E) {
|
||||
return E.Pos - E.Parent->begin();
|
||||
}
|
||||
|
||||
public:
|
||||
value_type operator*() { return {Parent, getIndexInBlock(*this)}; }
|
||||
|
||||
difference_type operator-(ElementRefIterator Other) const {
|
||||
return Pos - Other.Pos;
|
||||
}
|
||||
|
||||
ElementRefIterator operator++() {
|
||||
++this->Pos;
|
||||
return *this;
|
||||
}
|
||||
ElementRefIterator operator++(int) {
|
||||
ElementRefIterator Ret = *this;
|
||||
++*this;
|
||||
return Ret;
|
||||
}
|
||||
ElementRefIterator operator+(size_t count) {
|
||||
this->Pos += count;
|
||||
return *this;
|
||||
}
|
||||
ElementRefIterator operator-(size_t count) {
|
||||
this->Pos -= count;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
/// The set of statements in the basic block.
|
||||
ElementList Elements;
|
||||
|
||||
@ -715,6 +868,8 @@ class CFGBlock {
|
||||
using reverse_iterator = ElementList::reverse_iterator;
|
||||
using const_reverse_iterator = ElementList::const_reverse_iterator;
|
||||
|
||||
size_t getIndexInCFG() const;
|
||||
|
||||
CFGElement front() const { return Elements.front(); }
|
||||
CFGElement back() const { return Elements.back(); }
|
||||
|
||||
@ -728,6 +883,38 @@ class CFGBlock {
|
||||
const_reverse_iterator rbegin() const { return Elements.rbegin(); }
|
||||
const_reverse_iterator rend() const { return Elements.rend(); }
|
||||
|
||||
using CFGElementRef = ElementRefImpl<false>;
|
||||
using ConstCFGElementRef = ElementRefImpl<true>;
|
||||
|
||||
using ref_iterator = ElementRefIterator<false, false>;
|
||||
using ref_iterator_range = llvm::iterator_range<ref_iterator>;
|
||||
using const_ref_iterator = ElementRefIterator<false, true>;
|
||||
using const_ref_iterator_range = llvm::iterator_range<const_ref_iterator>;
|
||||
|
||||
using reverse_ref_iterator = ElementRefIterator<true, false>;
|
||||
using reverse_ref_iterator_range = llvm::iterator_range<reverse_ref_iterator>;
|
||||
|
||||
using const_reverse_ref_iterator = ElementRefIterator<true, true>;
|
||||
using const_reverse_ref_iterator_range =
|
||||
llvm::iterator_range<const_reverse_ref_iterator>;
|
||||
|
||||
ref_iterator ref_begin() { return {this, begin()}; }
|
||||
ref_iterator ref_end() { return {this, end()}; }
|
||||
const_ref_iterator ref_begin() const { return {this, begin()}; }
|
||||
const_ref_iterator ref_end() const { return {this, end()}; }
|
||||
|
||||
reverse_ref_iterator rref_begin() { return {this, rbegin()}; }
|
||||
reverse_ref_iterator rref_end() { return {this, rend()}; }
|
||||
const_reverse_ref_iterator rref_begin() const { return {this, rbegin()}; }
|
||||
const_reverse_ref_iterator rref_end() const { return {this, rend()}; }
|
||||
|
||||
ref_iterator_range refs() { return {ref_begin(), ref_end()}; }
|
||||
const_ref_iterator_range refs() const { return {ref_begin(), ref_end()}; }
|
||||
reverse_ref_iterator_range rrefs() { return {rref_begin(), rref_end()}; }
|
||||
const_reverse_ref_iterator_range rrefs() const {
|
||||
return {rref_begin(), rref_end()};
|
||||
}
|
||||
|
||||
unsigned size() const { return Elements.size(); }
|
||||
bool empty() const { return Elements.empty(); }
|
||||
|
||||
@ -855,6 +1042,10 @@ class CFGBlock {
|
||||
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
|
||||
void setHasNoReturnElement() { HasNoReturnElement = true; }
|
||||
|
||||
/// Returns true if the block would eventually end with a sink (a noreturn
|
||||
/// node).
|
||||
bool isInevitablySinking() const;
|
||||
|
||||
CFGTerminator getTerminator() const { return Terminator; }
|
||||
|
||||
Stmt *getTerminatorStmt() { return Terminator.getStmt(); }
|
||||
@ -894,7 +1085,7 @@ class CFGBlock {
|
||||
void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
|
||||
void printTerminatorJson(raw_ostream &Out, const LangOptions &LO,
|
||||
bool AddQuotes) const;
|
||||
|
||||
|
||||
void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
|
||||
OS << "BB#" << getBlockID();
|
||||
}
|
||||
@ -1010,7 +1201,6 @@ class CFGBlock {
|
||||
*I = CFGScopeEnd(VD, S);
|
||||
return ++I;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// CFGCallback defines methods that should be called when a logical
|
||||
@ -1023,6 +1213,7 @@ class CFGCallback {
|
||||
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
|
||||
virtual void compareBitwiseEquality(const BinaryOperator *B,
|
||||
bool isAlwaysTrue) {}
|
||||
virtual void compareBitwiseOr(const BinaryOperator *B) {}
|
||||
};
|
||||
|
||||
/// Represents a source-level, intra-procedural CFG that represents the
|
||||
|
@ -131,6 +131,7 @@ class CallGraph : public RecursiveASTVisitor<CallGraph> {
|
||||
|
||||
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
||||
bool shouldVisitTemplateInstantiations() const { return true; }
|
||||
bool shouldVisitImplicitCode() const { return true; }
|
||||
|
||||
private:
|
||||
/// Add the given declaration to the call graph.
|
||||
|
@ -52,11 +52,6 @@ class SourceManager;
|
||||
|
||||
namespace ento {
|
||||
|
||||
class ExplodedNode;
|
||||
class SymExpr;
|
||||
|
||||
using SymbolRef = const SymExpr *;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// High-level interface for handlers of path-sensitive diagnostics.
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -125,6 +120,13 @@ class PathDiagnosticConsumer {
|
||||
};
|
||||
|
||||
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
|
||||
|
||||
bool shouldGenerateDiagnostics() const {
|
||||
return getGenerationScheme() != None;
|
||||
}
|
||||
|
||||
bool shouldAddPathEdges() const { return getGenerationScheme() == Extensive; }
|
||||
|
||||
virtual bool supportsLogicalOpControlFlow() const { return false; }
|
||||
|
||||
/// Return true if the PathDiagnosticConsumer supports individual
|
||||
@ -269,19 +271,21 @@ class PathDiagnosticLocation {
|
||||
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC,
|
||||
const SourceManager &SM);
|
||||
|
||||
/// Create a location corresponding to the given valid ExplodedNode.
|
||||
/// Create a location corresponding to the given valid ProgramPoint.
|
||||
static PathDiagnosticLocation create(const ProgramPoint &P,
|
||||
const SourceManager &SMng);
|
||||
|
||||
/// Create a location corresponding to the next valid ExplodedNode as end
|
||||
/// of path location.
|
||||
static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N,
|
||||
const SourceManager &SM);
|
||||
|
||||
/// Convert the given location into a single kind location.
|
||||
static PathDiagnosticLocation createSingleLocation(
|
||||
const PathDiagnosticLocation &PDL);
|
||||
|
||||
/// Construct a source location that corresponds to either the beginning
|
||||
/// or the end of the given statement, or a nearby valid source location
|
||||
/// if the statement does not have a valid source location of its own.
|
||||
static SourceLocation
|
||||
getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC,
|
||||
bool UseEndOfStatement = false);
|
||||
|
||||
bool operator==(const PathDiagnosticLocation &X) const {
|
||||
return K == X.K && Loc == X.Loc && Range == X.Range;
|
||||
}
|
||||
@ -326,13 +330,6 @@ class PathDiagnosticLocation {
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
/// Given an exploded node, retrieve the statement that should be used
|
||||
/// for the diagnostic location.
|
||||
static const Stmt *getStmt(const ExplodedNode *N);
|
||||
|
||||
/// Retrieve the statement corresponding to the successor node.
|
||||
static const Stmt *getNextStmt(const ExplodedNode *N);
|
||||
};
|
||||
|
||||
class PathDiagnosticLocationPair {
|
||||
@ -386,6 +383,7 @@ class PathDiagnosticPiece: public llvm::FoldingSetNode {
|
||||
StringRef Tag;
|
||||
|
||||
std::vector<SourceRange> ranges;
|
||||
std::vector<FixItHint> fixits;
|
||||
|
||||
protected:
|
||||
PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
|
||||
@ -430,9 +428,16 @@ class PathDiagnosticPiece: public llvm::FoldingSetNode {
|
||||
ranges.push_back(SourceRange(B,E));
|
||||
}
|
||||
|
||||
void addFixit(FixItHint F) {
|
||||
fixits.push_back(F);
|
||||
}
|
||||
|
||||
/// Return the SourceRanges associated with this PathDiagnosticPiece.
|
||||
ArrayRef<SourceRange> getRanges() const { return ranges; }
|
||||
|
||||
/// Return the fix-it hints associated with this PathDiagnosticPiece.
|
||||
ArrayRef<FixItHint> getFixits() const { return fixits; }
|
||||
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
|
||||
|
||||
void setAsLastInMainSourceFile() {
|
||||
@ -446,7 +451,9 @@ class PathDiagnosticPiece: public llvm::FoldingSetNode {
|
||||
virtual void dump() const = 0;
|
||||
};
|
||||
|
||||
class PathPieces : public std::list<std::shared_ptr<PathDiagnosticPiece>> {
|
||||
using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
|
||||
|
||||
class PathPieces : public std::list<PathDiagnosticPieceRef> {
|
||||
void flattenTo(PathPieces &Primary, PathPieces &Current,
|
||||
bool ShouldFlattenMacros) const;
|
||||
|
||||
@ -486,65 +493,13 @@ class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
|
||||
}
|
||||
};
|
||||
|
||||
/// Interface for classes constructing Stack hints.
|
||||
///
|
||||
/// If a PathDiagnosticEvent occurs in a different frame than the final
|
||||
/// diagnostic the hints can be used to summarize the effect of the call.
|
||||
class StackHintGenerator {
|
||||
public:
|
||||
virtual ~StackHintGenerator() = 0;
|
||||
|
||||
/// Construct the Diagnostic message for the given ExplodedNode.
|
||||
virtual std::string getMessage(const ExplodedNode *N) = 0;
|
||||
};
|
||||
|
||||
/// Constructs a Stack hint for the given symbol.
|
||||
///
|
||||
/// The class knows how to construct the stack hint message based on
|
||||
/// traversing the CallExpr associated with the call and checking if the given
|
||||
/// symbol is returned or is one of the arguments.
|
||||
/// The hint can be customized by redefining 'getMessageForX()' methods.
|
||||
class StackHintGeneratorForSymbol : public StackHintGenerator {
|
||||
private:
|
||||
SymbolRef Sym;
|
||||
std::string Msg;
|
||||
|
||||
public:
|
||||
StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
|
||||
~StackHintGeneratorForSymbol() override = default;
|
||||
|
||||
/// Search the call expression for the symbol Sym and dispatch the
|
||||
/// 'getMessageForX()' methods to construct a specific message.
|
||||
std::string getMessage(const ExplodedNode *N) override;
|
||||
|
||||
/// Produces the message of the following form:
|
||||
/// 'Msg via Nth parameter'
|
||||
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
|
||||
|
||||
virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
|
||||
return Msg;
|
||||
}
|
||||
|
||||
virtual std::string getMessageForSymbolNotFound() {
|
||||
return Msg;
|
||||
}
|
||||
};
|
||||
|
||||
class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
|
||||
Optional<bool> IsPrunable;
|
||||
|
||||
/// If the event occurs in a different frame than the final diagnostic,
|
||||
/// supply a message that will be used to construct an extra hint on the
|
||||
/// returns from all the calls on the stack from this event to the final
|
||||
/// diagnostic.
|
||||
std::unique_ptr<StackHintGenerator> CallStackHint;
|
||||
|
||||
public:
|
||||
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
|
||||
StringRef s, bool addPosRange = true,
|
||||
StackHintGenerator *stackHint = nullptr)
|
||||
: PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
|
||||
CallStackHint(stackHint) {}
|
||||
StringRef s, bool addPosRange = true)
|
||||
: PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
|
||||
~PathDiagnosticEventPiece() override;
|
||||
|
||||
/// Mark the diagnostic piece as being potentially prunable. This
|
||||
@ -561,16 +516,6 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
|
||||
return IsPrunable.hasValue() ? IsPrunable.getValue() : false;
|
||||
}
|
||||
|
||||
bool hasCallStackHint() { return (bool)CallStackHint; }
|
||||
|
||||
/// Produce the hint for the given node. The node contains
|
||||
/// information about the call for which the diagnostic can be generated.
|
||||
std::string getCallStackMessage(const ExplodedNode *N) {
|
||||
if (CallStackHint)
|
||||
return CallStackHint->getMessage(N);
|
||||
return {};
|
||||
}
|
||||
|
||||
void dump() const override;
|
||||
|
||||
static bool classof(const PathDiagnosticPiece *P) {
|
||||
@ -726,8 +671,6 @@ class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
|
||||
|
||||
PathPieces subPieces;
|
||||
|
||||
bool containsEvent() const;
|
||||
|
||||
void flattenLocations() override {
|
||||
PathDiagnosticSpotPiece::flattenLocations();
|
||||
for (const auto &I : subPieces)
|
||||
@ -782,7 +725,7 @@ using FilesToLineNumsMap = std::map<FileID, std::set<unsigned>>;
|
||||
/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
|
||||
/// each which represent the pieces of the path.
|
||||
class PathDiagnostic : public llvm::FoldingSetNode {
|
||||
std::string CheckName;
|
||||
std::string CheckerName;
|
||||
const Decl *DeclWithIssue;
|
||||
std::string BugType;
|
||||
std::string VerboseDesc;
|
||||
@ -806,7 +749,7 @@ class PathDiagnostic : public llvm::FoldingSetNode {
|
||||
|
||||
public:
|
||||
PathDiagnostic() = delete;
|
||||
PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
|
||||
PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue,
|
||||
StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
|
||||
StringRef category, PathDiagnosticLocation LocationToUnique,
|
||||
const Decl *DeclToUnique,
|
||||
@ -836,7 +779,7 @@ class PathDiagnostic : public llvm::FoldingSetNode {
|
||||
|
||||
bool isWithinCall() const { return !pathStack.empty(); }
|
||||
|
||||
void setEndOfPath(std::shared_ptr<PathDiagnosticPiece> EndPiece) {
|
||||
void setEndOfPath(PathDiagnosticPieceRef EndPiece) {
|
||||
assert(!Loc.isValid() && "End location already set!");
|
||||
Loc = EndPiece->getLocation();
|
||||
assert(Loc.isValid() && "Invalid location for end-of-path piece");
|
||||
@ -849,26 +792,16 @@ class PathDiagnostic : public llvm::FoldingSetNode {
|
||||
VerboseDesc += S;
|
||||
}
|
||||
|
||||
/// If the last piece of the report point to the header file, resets
|
||||
/// the location of the report to be the last location in the main source
|
||||
/// file.
|
||||
void resetDiagnosticLocationToMainFile();
|
||||
|
||||
StringRef getVerboseDescription() const { return VerboseDesc; }
|
||||
|
||||
StringRef getShortDescription() const {
|
||||
return ShortDesc.empty() ? VerboseDesc : ShortDesc;
|
||||
}
|
||||
|
||||
StringRef getCheckName() const { return CheckName; }
|
||||
StringRef getCheckerName() const { return CheckerName; }
|
||||
StringRef getBugType() const { return BugType; }
|
||||
StringRef getCategory() const { return Category; }
|
||||
|
||||
/// Return the semantic context where an issue occurred. If the
|
||||
/// issue occurs along a path, this represents the "central" area
|
||||
/// where the bug manifests.
|
||||
const Decl *getDeclWithIssue() const { return DeclWithIssue; }
|
||||
|
||||
using meta_iterator = std::deque<std::string>::const_iterator;
|
||||
|
||||
meta_iterator meta_begin() const { return OtherDesc.begin(); }
|
||||
@ -883,10 +816,23 @@ class PathDiagnostic : public llvm::FoldingSetNode {
|
||||
return *ExecutedLines;
|
||||
}
|
||||
|
||||
/// Return the semantic context where an issue occurred. If the
|
||||
/// issue occurs along a path, this represents the "central" area
|
||||
/// where the bug manifests.
|
||||
const Decl *getDeclWithIssue() const { return DeclWithIssue; }
|
||||
|
||||
void setDeclWithIssue(const Decl *D) {
|
||||
DeclWithIssue = D;
|
||||
}
|
||||
|
||||
PathDiagnosticLocation getLocation() const {
|
||||
return Loc;
|
||||
}
|
||||
|
||||
void setLocation(PathDiagnosticLocation NewLoc) {
|
||||
Loc = NewLoc;
|
||||
}
|
||||
|
||||
/// Get the location on which the report should be uniqued.
|
||||
PathDiagnosticLocation getUniqueingLoc() const {
|
||||
return UniqueingLoc;
|
||||
@ -917,7 +863,6 @@ class PathDiagnostic : public llvm::FoldingSetNode {
|
||||
};
|
||||
|
||||
} // namespace ento
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
|
70
include/clang/Basic/AArch64SVEACLETypes.def
Normal file
70
include/clang/Basic/AArch64SVEACLETypes.def
Normal file
@ -0,0 +1,70 @@
|
||||
//===-- AArch64SVEACLETypes.def - Metadata about SVE types ------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines various SVE builtin types. The macros are:
|
||||
//
|
||||
// SVE_TYPE(Name, Id, SingletonId) - A builtin type that has not been
|
||||
// covered by any other #define. Defining this macro covers all
|
||||
// the builtins.
|
||||
//
|
||||
// SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP) -
|
||||
// An SVE scalable vector.
|
||||
//
|
||||
// SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind) - An SVE scalable
|
||||
// predicate.
|
||||
//
|
||||
// where:
|
||||
//
|
||||
// - Name is the name of the builtin type.
|
||||
//
|
||||
// - BuiltinType::Id is the enumerator defining the type.
|
||||
//
|
||||
// - Context.SingletonId is the global singleton of this type.
|
||||
//
|
||||
// - ElKind enumerates the type of the elements.
|
||||
//
|
||||
// - ElBits is the size of one element in bits.
|
||||
//
|
||||
// - IsSigned is true for vectors of signed integer elements and
|
||||
// for vectors of floating-point elements.
|
||||
//
|
||||
// - IsFP is true for vectors of floating-point elements.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SVE_VECTOR_TYPE
|
||||
#define SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP)\
|
||||
SVE_TYPE(Name, Id, SingletonId)
|
||||
#endif
|
||||
|
||||
#ifndef SVE_PREDICATE_TYPE
|
||||
#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind)\
|
||||
SVE_TYPE(Name, Id, SingletonId)
|
||||
#endif
|
||||
|
||||
//===- Vector point types -----------------------------------------------===//
|
||||
|
||||
SVE_VECTOR_TYPE("__SVInt8_t", SveInt8, SveInt8Ty, SveElSInt8, 8, true, false)
|
||||
SVE_VECTOR_TYPE("__SVInt16_t", SveInt16, SveInt16Ty, SveElSInt16, 16, true, false)
|
||||
SVE_VECTOR_TYPE("__SVInt32_t", SveInt32, SveInt32Ty, SveElSInt32, 32, true, false)
|
||||
SVE_VECTOR_TYPE("__SVInt64_t", SveInt64, SveInt64Ty, SveElSInt64, 64, true, false)
|
||||
|
||||
SVE_VECTOR_TYPE("__SVUint8_t", SveUint8, SveUint8Ty, SveElUInt8, 8, false, false)
|
||||
SVE_VECTOR_TYPE("__SVUint16_t", SveUint16, SveUint16Ty, SveElUInt16, 16, false, false)
|
||||
SVE_VECTOR_TYPE("__SVUint32_t", SveUint32, SveUint32Ty, SveElUInt32, 32, false, false)
|
||||
SVE_VECTOR_TYPE("__SVUint64_t", SveUint64, SveUint64Ty, SveElUInt64, 64, false, false)
|
||||
|
||||
SVE_VECTOR_TYPE("__SVFloat16_t", SveFloat16, SveFloat16Ty, SveElHalf, 16, true, true)
|
||||
SVE_VECTOR_TYPE("__SVFloat32_t", SveFloat32, SveFloat32Ty, SveElFloat, 32, true, true)
|
||||
SVE_VECTOR_TYPE("__SVFloat64_t", SveFloat64, SveFloat64Ty, SveElDouble, 64, true, true)
|
||||
|
||||
SVE_PREDICATE_TYPE("__SVBool_t", SveBool, SveBoolTy, SveElBool)
|
||||
|
||||
#undef SVE_VECTOR_TYPE
|
||||
#undef SVE_PREDICATE_TYPE
|
||||
#undef SVE_TYPE
|
@ -722,9 +722,25 @@ def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
|
||||
|
||||
def AsmLabel : InheritableAttr {
|
||||
let Spellings = [Keyword<"asm">, Keyword<"__asm__">];
|
||||
let Args = [StringArgument<"Label">];
|
||||
let Args = [
|
||||
// Label specifies the mangled name for the decl.
|
||||
StringArgument<"Label">,
|
||||
|
||||
// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
|
||||
// the global C symbol prefix) or not. If not, the mangle-suppression prefix
|
||||
// ('\01') is omitted from the decl name at the LLVM IR level.
|
||||
//
|
||||
// Non-literal labels are used by some external AST sources like LLDB.
|
||||
BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
|
||||
];
|
||||
let SemaHandler = 0;
|
||||
let Documentation = [Undocumented];
|
||||
let Documentation = [AsmLabelDocs];
|
||||
let AdditionalMembers =
|
||||
[{
|
||||
bool isEquivalent(AsmLabelAttr *Other) const {
|
||||
return getLabel() == Other->getLabel() && getIsLiteralLabel() == Other->getIsLiteralLabel();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def Availability : InheritableAttr {
|
||||
@ -911,6 +927,17 @@ def Const : InheritableAttr {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def ConstInit : InheritableAttr {
|
||||
// This attribute does not have a C [[]] spelling because it requires the
|
||||
// CPlusPlus language option.
|
||||
let Spellings = [Keyword<"constinit">,
|
||||
Clang<"require_constant_initialization", 0>];
|
||||
let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
|
||||
let Accessors = [Accessor<"isConstinit", [Keyword<"constinit">]>];
|
||||
let Documentation = [ConstInitDocs];
|
||||
let LangOpts = [CPlusPlus];
|
||||
}
|
||||
|
||||
def Constructor : InheritableAttr {
|
||||
let Spellings = [GCC<"constructor">];
|
||||
let Args = [DefaultIntArgument<"Priority", 65535>];
|
||||
@ -1170,7 +1197,7 @@ def ExtVectorType : Attr {
|
||||
|
||||
def FallThrough : StmtAttr {
|
||||
let Spellings = [CXX11<"", "fallthrough", 201603>, C2x<"", "fallthrough">,
|
||||
CXX11<"clang", "fallthrough">];
|
||||
CXX11<"clang", "fallthrough">, GCC<"fallthrough">];
|
||||
// let Subjects = [NullStmt];
|
||||
let Documentation = [FallthroughDocs];
|
||||
}
|
||||
@ -1935,15 +1962,6 @@ def ReqdWorkGroupSize : InheritableAttr {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def RequireConstantInit : InheritableAttr {
|
||||
// This attribute does not have a C [[]] spelling because it requires the
|
||||
// CPlusPlus language option.
|
||||
let Spellings = [Clang<"require_constant_initialization", 0>];
|
||||
let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
|
||||
let Documentation = [RequireConstantInitDocs];
|
||||
let LangOpts = [CPlusPlus];
|
||||
}
|
||||
|
||||
def WorkGroupSizeHint : InheritableAttr {
|
||||
// Does not have a [[]] spelling because it is an OpenCL-related attribute.
|
||||
let Spellings = [GNU<"work_group_size_hint">];
|
||||
@ -2002,6 +2020,14 @@ def PragmaClangRodataSection : InheritableAttr {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def PragmaClangRelroSection : InheritableAttr {
|
||||
// This attribute has no spellings as it is only ever created implicitly.
|
||||
let Spellings = [];
|
||||
let Args = [StringArgument<"Name">];
|
||||
let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def PragmaClangTextSection : InheritableAttr {
|
||||
// This attribute has no spellings as it is only ever created implicitly.
|
||||
let Spellings = [];
|
||||
@ -2335,11 +2361,19 @@ def WarnUnused : InheritableAttr {
|
||||
}
|
||||
|
||||
def WarnUnusedResult : InheritableAttr {
|
||||
let Spellings = [CXX11<"", "nodiscard", 201603>, C2x<"", "nodiscard">,
|
||||
let Spellings = [CXX11<"", "nodiscard", 201907>, C2x<"", "nodiscard">,
|
||||
CXX11<"clang", "warn_unused_result">,
|
||||
GCC<"warn_unused_result">];
|
||||
let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike]>;
|
||||
let Args = [StringArgument<"Message", 1>];
|
||||
let Documentation = [WarnUnusedResultsDocs];
|
||||
let AdditionalMembers = [{
|
||||
// Check whether this the C++11 nodiscard version, even in non C++11
|
||||
// spellings.
|
||||
bool IsCXX11NoDiscard() const {
|
||||
return this->getSemanticSpelling() == CXX11_nodiscard;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def Weak : InheritableAttr {
|
||||
@ -2428,6 +2462,12 @@ def NoSanitizeSpecific : InheritableAttr {
|
||||
let ASTNode = 0;
|
||||
}
|
||||
|
||||
def CFICanonicalJumpTable : InheritableAttr {
|
||||
let Spellings = [Clang<"cfi_canonical_jump_table">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
let Documentation = [CFICanonicalJumpTableDocs];
|
||||
}
|
||||
|
||||
// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
|
||||
// Not all of these attributes will be given a [[]] spelling. The attributes
|
||||
// which require access to function parameter names cannot use the [[]] spelling
|
||||
@ -2788,6 +2828,20 @@ def TypeTagForDatatype : InheritableAttr {
|
||||
let Documentation = [TypeTagForDatatypeDocs];
|
||||
}
|
||||
|
||||
def Owner : InheritableAttr {
|
||||
let Spellings = [CXX11<"gsl", "Owner">];
|
||||
let Subjects = SubjectList<[Struct]>;
|
||||
let Args = [TypeArgument<"DerefType", /*opt=*/1>];
|
||||
let Documentation = [LifetimeOwnerDocs];
|
||||
}
|
||||
|
||||
def Pointer : InheritableAttr {
|
||||
let Spellings = [CXX11<"gsl", "Pointer">];
|
||||
let Subjects = SubjectList<[Struct]>;
|
||||
let Args = [TypeArgument<"DerefType", /*opt=*/1>];
|
||||
let Documentation = [LifetimePointerDocs];
|
||||
}
|
||||
|
||||
// Microsoft-related attributes
|
||||
|
||||
def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
|
||||
@ -2981,10 +3035,12 @@ def LoopHint : Attr {
|
||||
let Args = [EnumArgument<"Option", "OptionType",
|
||||
["vectorize", "vectorize_width", "interleave", "interleave_count",
|
||||
"unroll", "unroll_count", "unroll_and_jam", "unroll_and_jam_count",
|
||||
"pipeline", "pipeline_initiation_interval", "distribute"],
|
||||
"pipeline", "pipeline_initiation_interval", "distribute",
|
||||
"vectorize_predicate"],
|
||||
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
|
||||
"Unroll", "UnrollCount", "UnrollAndJam", "UnrollAndJamCount",
|
||||
"PipelineDisabled", "PipelineInitiationInterval", "Distribute"]>,
|
||||
"PipelineDisabled", "PipelineInitiationInterval", "Distribute",
|
||||
"VectorizePredicate"]>,
|
||||
EnumArgument<"State", "LoopHintState",
|
||||
["enable", "disable", "numeric", "assume_safety", "full"],
|
||||
["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>,
|
||||
@ -3004,12 +3060,13 @@ def LoopHint : Attr {
|
||||
case PipelineDisabled: return "pipeline";
|
||||
case PipelineInitiationInterval: return "pipeline_initiation_interval";
|
||||
case Distribute: return "distribute";
|
||||
case VectorizePredicate: return "vectorize_predicate";
|
||||
}
|
||||
llvm_unreachable("Unhandled LoopHint option.");
|
||||
}
|
||||
|
||||
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
|
||||
unsigned SpellingIndex = getSpellingListIndex();
|
||||
unsigned SpellingIndex = getAttributeSpellingListIndex();
|
||||
// For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
|
||||
// "nounroll" is already emitted as the pragma name.
|
||||
if (SpellingIndex == Pragma_nounroll || SpellingIndex == Pragma_nounroll_and_jam)
|
||||
@ -3045,7 +3102,7 @@ def LoopHint : Attr {
|
||||
|
||||
// Return a string suitable for identifying this attribute in diagnostics.
|
||||
std::string getDiagnosticName(const PrintingPolicy &Policy) const {
|
||||
unsigned SpellingIndex = getSpellingListIndex();
|
||||
unsigned SpellingIndex = getAttributeSpellingListIndex();
|
||||
if (SpellingIndex == Pragma_nounroll)
|
||||
return "#pragma nounroll";
|
||||
else if (SpellingIndex == Pragma_unroll)
|
||||
@ -3176,11 +3233,16 @@ def OMPDeclareTargetDecl : InheritableAttr {
|
||||
let Args = [
|
||||
EnumArgument<"MapType", "MapTypeTy",
|
||||
[ "to", "link" ],
|
||||
[ "MT_To", "MT_Link" ]>
|
||||
[ "MT_To", "MT_Link" ]>,
|
||||
EnumArgument<"DevType", "DevTypeTy",
|
||||
[ "host", "nohost", "any" ],
|
||||
[ "DT_Host", "DT_NoHost", "DT_Any" ]>
|
||||
];
|
||||
let AdditionalMembers = [{
|
||||
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
|
||||
// Use fake syntax because it is for testing and debugging purpose only.
|
||||
if (getDevType() != DT_Any)
|
||||
OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
|
||||
if (getMapType() != MT_To)
|
||||
OS << ' ' << ConvertMapTypeTyToStr(getMapType());
|
||||
}
|
||||
@ -3193,6 +3255,14 @@ def OMPDeclareTargetDecl : InheritableAttr {
|
||||
|
||||
return llvm::None;
|
||||
}
|
||||
static llvm::Optional<DevTypeTy> getDeviceType(const ValueDecl *VD) {
|
||||
if (!VD->hasAttrs())
|
||||
return llvm::None;
|
||||
if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
|
||||
return Attr->getDevType();
|
||||
|
||||
return llvm::None;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@ -3219,6 +3289,82 @@ def OMPAllocateDecl : InheritableAttr {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def OMPDeclareVariant : InheritableAttr {
|
||||
let Spellings = [Pragma<"omp", "declare variant">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let SemaHandler = 0;
|
||||
let HasCustomParsing = 1;
|
||||
let InheritEvenIfAlreadyPresent = 1;
|
||||
let Documentation = [OMPDeclareVariantDocs];
|
||||
let Args = [
|
||||
ExprArgument<"VariantFuncRef">,
|
||||
ExprArgument<"Score">,
|
||||
EnumArgument<"CtxSelectorSet", "CtxSelectorSetType",
|
||||
[ "", "implementation"
|
||||
],
|
||||
[
|
||||
"CtxSetUnknown", "CtxSetImplementation"
|
||||
]>,
|
||||
EnumArgument<"CtxScore", "ScoreType",
|
||||
[ "", "score"
|
||||
],
|
||||
[
|
||||
"ScoreUnknown", "ScoreSpecified"
|
||||
]>,
|
||||
EnumArgument<"CtxSelector", "CtxSelectorType",
|
||||
[ "", "vendor"
|
||||
],
|
||||
[
|
||||
"CtxUnknown", "CtxVendor"
|
||||
]>,
|
||||
VariadicStringArgument<"ImplVendors">
|
||||
];
|
||||
let AdditionalMembers = [{
|
||||
void printScore(raw_ostream & OS, const PrintingPolicy &Policy) const {
|
||||
if (const Expr *E = getScore()) {
|
||||
OS << "score(";
|
||||
E->printPretty(OS, nullptr, Policy);
|
||||
OS << "):";
|
||||
}
|
||||
}
|
||||
void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
|
||||
const {
|
||||
assert(getCtxSelectorSet() != CtxSetUnknown &&
|
||||
getCtxSelector() != CtxUnknown && "Unknown context selector.");
|
||||
if (const Expr *E = getVariantFuncRef()) {
|
||||
OS << "(";
|
||||
E->printPretty(OS, nullptr, Policy);
|
||||
OS << ")";
|
||||
}
|
||||
// TODO: add printing of real context selectors.
|
||||
OS << " match(";
|
||||
switch (getCtxSelectorSet()) {
|
||||
case CtxSetImplementation:
|
||||
OS << "implementation={";
|
||||
switch (getCtxSelector()) {
|
||||
case CtxVendor:
|
||||
OS << "vendor(";
|
||||
printScore(OS, Policy);
|
||||
if (implVendors_size() > 0) {
|
||||
OS << *implVendors(). begin();
|
||||
for (StringRef VendorName : llvm::drop_begin(implVendors(), 1))
|
||||
OS << ", " << VendorName;
|
||||
}
|
||||
OS << ")";
|
||||
break;
|
||||
case CtxUnknown:
|
||||
llvm_unreachable("Unknown context selector.");
|
||||
}
|
||||
OS << "}";
|
||||
break;
|
||||
case CtxSetUnknown:
|
||||
llvm_unreachable("Unknown context selector set.");
|
||||
}
|
||||
OS << ")";
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def InternalLinkage : InheritableAttr {
|
||||
let Spellings = [Clang<"internal_linkage">];
|
||||
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
|
||||
|
@ -1408,15 +1408,17 @@ all optional, but the attribute has to have at least one clause.
|
||||
}];
|
||||
}
|
||||
|
||||
def RequireConstantInitDocs : Documentation {
|
||||
def ConstInitDocs : Documentation {
|
||||
let Category = DocCatVariable;
|
||||
let Heading = "require_constant_initialization, constinit (C++20)";
|
||||
let Content = [{
|
||||
This attribute specifies that the variable to which it is attached is intended
|
||||
to have a `constant initializer <http://en.cppreference.com/w/cpp/language/constant_initialization>`_
|
||||
according to the rules of [basic.start.static]. The variable is required to
|
||||
have static or thread storage duration. If the initialization of the variable
|
||||
is not a constant initializer an error will be produced. This attribute may
|
||||
only be used in C++.
|
||||
only be used in C++; the ``constinit`` spelling is only accepted in C++20
|
||||
onwards.
|
||||
|
||||
Note that in C++03 strict constant expression checking is not done. Instead
|
||||
the attribute reports if Clang can emit the variable as a constant, even if it's
|
||||
@ -1431,6 +1433,12 @@ for constant initialization have been met. Since these requirements change
|
||||
between dialects and have subtle pitfalls it's important to fail fast instead
|
||||
of silently falling back on dynamic initialization.
|
||||
|
||||
The first use of the attribute on a variable must be part of, or precede, the
|
||||
initializing declaration of the variable. C++20 requires the ``constinit``
|
||||
spelling of the attribute to be present on the initializing declaration if it
|
||||
is used anywhere. The other spellings can be specified on a forward declaration
|
||||
and omitted on a later initializing declaration.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// -std=c++14
|
||||
@ -1482,6 +1490,13 @@ generated when a function or its return type is marked with ``[[nodiscard]]``
|
||||
potentially-evaluated discarded-value expression that is not explicitly cast to
|
||||
`void`.
|
||||
|
||||
A string literal may optionally be provided to the attribute, which will be
|
||||
reproduced in any resulting diagnostics. Redeclarations using different forms
|
||||
of the attribute (with or without the string literal or with different string
|
||||
literal contents) are allowed. If there are redeclarations of the entity with
|
||||
differing string literals, it is unspecified which one will be used by Clang
|
||||
in any resulting diagnostics.
|
||||
|
||||
.. code-block: c++
|
||||
struct [[nodiscard]] error_info { /*...*/ };
|
||||
error_info enable_missile_safety_mode();
|
||||
@ -1493,6 +1508,33 @@ potentially-evaluated discarded-value expression that is not explicitly cast to
|
||||
}
|
||||
error_info &foo();
|
||||
void f() { foo(); } // Does not diagnose, error_info is a reference.
|
||||
|
||||
Additionally, discarded temporaries resulting from a call to a constructor
|
||||
marked with ``[[nodiscard]]`` or a constructor of a type marked
|
||||
``[[nodiscard]]`` will also diagnose. This also applies to type conversions that
|
||||
use the annotated ``[[nodiscard]]`` constructor or result in an annotated type.
|
||||
|
||||
.. code-block: c++
|
||||
struct [[nodiscard]] marked_type {/*..*/ };
|
||||
struct marked_ctor {
|
||||
[[nodiscard]] marked_ctor();
|
||||
marked_ctor(int);
|
||||
};
|
||||
|
||||
struct S {
|
||||
operator marked_type() const;
|
||||
[[nodiscard]] operator int() const;
|
||||
};
|
||||
|
||||
void usages() {
|
||||
marked_type(); // diagnoses.
|
||||
marked_ctor(); // diagnoses.
|
||||
marked_ctor(3); // Does not diagnose, int constructor isn't marked nodiscard.
|
||||
|
||||
S s;
|
||||
static_cast<marked_type>(s); // diagnoses
|
||||
(int)s; // diagnoses
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@ -2187,6 +2229,18 @@ to avoid false positives in other places.
|
||||
}];
|
||||
}
|
||||
|
||||
def CFICanonicalJumpTableDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Heading = "cfi_canonical_jump_table";
|
||||
let Content = [{
|
||||
.. _langext-cfi_canonical_jump_table:
|
||||
|
||||
Use ``__attribute__((cfi_canonical_jump_table))`` on a function declaration to
|
||||
make the function's CFI jump table canonical. See :ref:`the CFI documentation
|
||||
<cfi-canonical-jump-tables>` for more details.
|
||||
}];
|
||||
}
|
||||
|
||||
def DocCatTypeSafety : DocumentationCategory<"Type Safety Checking"> {
|
||||
let Content = [{
|
||||
Clang supports additional attributes to enable checking type safety properties
|
||||
@ -2504,6 +2558,30 @@ manipulating bits of the enumerator when issuing warnings.
|
||||
}];
|
||||
}
|
||||
|
||||
def AsmLabelDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
This attribute can be used on a function or variable to specify its symbol name.
|
||||
|
||||
On some targets, all C symbols are prefixed by default with a single character, typically ``_``. This was done historically to distinguish them from symbols used by other languages. (This prefix is also added to the standard Itanium C++ ABI prefix on "mangled" symbol names, so that e.g. on such targets the true symbol name for a C++ variable declared as ``int cppvar;`` would be ``__Z6cppvar``; note the two underscores.) This prefix is *not* added to the symbol names specified by the ``asm`` attribute; programmers wishing to match a C symbol name must compensate for this.
|
||||
|
||||
For example, consider the following C code:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int var1 asm("altvar") = 1; // "altvar" in symbol table.
|
||||
int var2 = 1; // "_var2" in symbol table.
|
||||
|
||||
void func1(void) asm("altfunc");
|
||||
void func1(void) {} // "altfunc" in symbol table.
|
||||
void func2(void) {} // "_func2" in symbol table.
|
||||
|
||||
Clang's implementation of this attribute is compatible with GCC's, `documented here <https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html>`_.
|
||||
|
||||
While it is possible to use this attribute to name a special symbol used internally by the compiler, such as an LLVM intrinsic, this is neither recommended nor supported and may cause the compiler to crash or miscompile. Users who wish to gain access to intrinsic behavior are strongly encouraged to request new builtin functions.
|
||||
}];
|
||||
}
|
||||
|
||||
def EnumExtensibilityDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
@ -2583,7 +2661,7 @@ is retained by the return value of the annotated function
|
||||
It is only supported in C++.
|
||||
|
||||
This attribute provides an experimental implementation of the facility
|
||||
described in the C++ committee paper [http://wg21.link/p0936r0](P0936R0),
|
||||
described in the C++ committee paper `P0936R0 <http://wg21.link/p0936r0>`_,
|
||||
and is subject to change as the design of the corresponding functionality
|
||||
changes.
|
||||
}];
|
||||
@ -2709,9 +2787,10 @@ def LoopHintDocs : Documentation {
|
||||
let Content = [{
|
||||
The ``#pragma clang loop`` directive allows loop optimization hints to be
|
||||
specified for the subsequent loop. The directive allows pipelining to be
|
||||
disabled, or vectorization, interleaving, and unrolling to be enabled or disabled.
|
||||
Vector width, interleave count, unrolling count, and the initiation interval
|
||||
for pipelining can be explicitly specified. See `language extensions
|
||||
disabled, or vectorization, vector predication, interleaving, and unrolling to
|
||||
be enabled or disabled. Vector width, vector predication, interleave count,
|
||||
unrolling count, and the initiation interval for pipelining can be explicitly
|
||||
specified. See `language extensions
|
||||
<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
|
||||
for details.
|
||||
}];
|
||||
@ -3129,6 +3208,55 @@ The syntax of the declare target directive is as follows:
|
||||
#pragma omp declare target new-line
|
||||
declarations-definition-seq
|
||||
#pragma omp end declare target new-line
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#pragma omp declare target (extended-list) new-line
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#pragma omp declare target clause[ [,] clause ... ] new-line
|
||||
|
||||
where clause is one of the following:
|
||||
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
to(extended-list)
|
||||
link(list)
|
||||
device_type(host | nohost | any)
|
||||
}];
|
||||
}
|
||||
|
||||
def OMPDeclareVariantDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Heading = "#pragma omp declare variant";
|
||||
let Content = [{
|
||||
The `declare variant` directive declares a specialized variant of a base
|
||||
function and specifies the context in which that specialized variant is used.
|
||||
The declare variant directive is a declarative directive.
|
||||
The syntax of the `declare variant` construct is as follows:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
#pragma omp declare variant(variant-func-id) clause new-line
|
||||
[#pragma omp declare variant(variant-func-id) clause new-line]
|
||||
[...]
|
||||
function definition or declaration
|
||||
|
||||
where clause is one of the following:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
match(context-selector-specification)
|
||||
|
||||
and where `variant-func-id` is the name of a function variant that is either a
|
||||
base language identifier or, for C++, a template-id.
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
@ -4194,4 +4322,72 @@ be accessed on both device side and host side. It has external linkage and is
|
||||
not initialized on device side. It has internal linkage and is initialized by
|
||||
the initializer on host side.
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
def LifetimeOwnerDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
.. Note:: This attribute is experimental and its effect on analysis is subject to change in
|
||||
a future version of clang.
|
||||
|
||||
The attribute ``[[gsl::Owner(T)]]`` applies to structs and classes that own an
|
||||
object of type ``T``:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
class [[gsl::Owner(int)]] IntOwner {
|
||||
private:
|
||||
int value;
|
||||
public:
|
||||
int *getInt() { return &value; }
|
||||
};
|
||||
|
||||
The argument ``T`` is optional and is ignored.
|
||||
This attribute may be used by analysis tools and has no effect on code
|
||||
generation.
|
||||
|
||||
See Pointer_ for an example.
|
||||
}];
|
||||
}
|
||||
|
||||
def LifetimePointerDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
.. Note:: This attribute is experimental and its effect on analysis is subject to change in
|
||||
a future version of clang.
|
||||
|
||||
The attribute ``[[gsl::Pointer(T)]]`` applies to structs and classes that behave
|
||||
like pointers to an object of type ``T``:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
class [[gsl::Pointer(int)]] IntPointer {
|
||||
private:
|
||||
int *valuePointer;
|
||||
public:
|
||||
int *getInt() { return &valuePointer; }
|
||||
};
|
||||
|
||||
The argument ``T`` is optional and is ignored.
|
||||
This attribute may be used by analysis tools and has no effect on code
|
||||
generation.
|
||||
|
||||
Example:
|
||||
When constructing an instance of a class annotated like this (a Pointer) from
|
||||
an instance of a class annotated with ``[[gsl::Owner]]`` (an Owner),
|
||||
then the analysis will consider the Pointer to point inside the Owner.
|
||||
When the Owner's lifetime ends, it will consider the Pointer to be dangling.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
int f() {
|
||||
IntPointer P;
|
||||
if (true) {
|
||||
IntOwner O(7);
|
||||
P = IntPointer(O); // P "points into" O
|
||||
} // P is dangling
|
||||
return P.get(); // error: Using a dangling Pointer.
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
|
190
include/clang/Basic/AttributeCommonInfo.h
Normal file
190
include/clang/Basic/AttributeCommonInfo.h
Normal file
@ -0,0 +1,190 @@
|
||||
//======- AttributeCommonInfo.h - Base info about Attributes-----*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the AttributeCommonInfo type, which is the base for a
|
||||
// ParsedAttr and is used by Attr as a way to share info between the two.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
|
||||
#define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
|
||||
namespace clang {
|
||||
class IdentifierInfo;
|
||||
class ASTRecordWriter;
|
||||
|
||||
class AttributeCommonInfo {
|
||||
public:
|
||||
/// The style used to specify an attribute.
|
||||
enum Syntax {
|
||||
/// __attribute__((...))
|
||||
AS_GNU,
|
||||
|
||||
/// [[...]]
|
||||
AS_CXX11,
|
||||
|
||||
/// [[...]]
|
||||
AS_C2x,
|
||||
|
||||
/// __declspec(...)
|
||||
AS_Declspec,
|
||||
|
||||
/// [uuid("...")] class Foo
|
||||
AS_Microsoft,
|
||||
|
||||
/// __ptr16, alignas(...), etc.
|
||||
AS_Keyword,
|
||||
|
||||
/// #pragma ...
|
||||
AS_Pragma,
|
||||
|
||||
// Note TableGen depends on the order above. Do not add or change the order
|
||||
// without adding related code to TableGen/ClangAttrEmitter.cpp.
|
||||
/// Context-sensitive version of a keyword attribute.
|
||||
AS_ContextSensitiveKeyword,
|
||||
};
|
||||
enum Kind {
|
||||
#define PARSED_ATTR(NAME) AT_##NAME,
|
||||
#include "clang/Sema/AttrParsedAttrList.inc"
|
||||
#undef PARSED_ATTR
|
||||
NoSemaHandlerAttribute,
|
||||
IgnoredAttribute,
|
||||
UnknownAttribute,
|
||||
};
|
||||
|
||||
private:
|
||||
const IdentifierInfo *AttrName = nullptr;
|
||||
const IdentifierInfo *ScopeName = nullptr;
|
||||
SourceRange AttrRange;
|
||||
const SourceLocation ScopeLoc;
|
||||
// Corresponds to the Kind enum.
|
||||
unsigned AttrKind : 16;
|
||||
/// Corresponds to the Syntax enum.
|
||||
unsigned SyntaxUsed : 3;
|
||||
unsigned SpellingIndex : 4;
|
||||
|
||||
protected:
|
||||
static constexpr unsigned SpellingNotCalculated = 0xf;
|
||||
|
||||
public:
|
||||
AttributeCommonInfo(SourceRange AttrRange)
|
||||
: AttrRange(AttrRange), ScopeLoc(), AttrKind(0), SyntaxUsed(0),
|
||||
SpellingIndex(SpellingNotCalculated) {}
|
||||
|
||||
AttributeCommonInfo(SourceLocation AttrLoc)
|
||||
: AttrRange(AttrLoc), ScopeLoc(), AttrKind(0), SyntaxUsed(0),
|
||||
SpellingIndex(SpellingNotCalculated) {}
|
||||
|
||||
AttributeCommonInfo(const IdentifierInfo *AttrName,
|
||||
const IdentifierInfo *ScopeName, SourceRange AttrRange,
|
||||
SourceLocation ScopeLoc, Syntax SyntaxUsed)
|
||||
: AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
|
||||
ScopeLoc(ScopeLoc),
|
||||
AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)),
|
||||
SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {}
|
||||
|
||||
AttributeCommonInfo(const IdentifierInfo *AttrName,
|
||||
const IdentifierInfo *ScopeName, SourceRange AttrRange,
|
||||
SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed)
|
||||
: AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
|
||||
ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed),
|
||||
SpellingIndex(SpellingNotCalculated) {}
|
||||
|
||||
AttributeCommonInfo(const IdentifierInfo *AttrName,
|
||||
const IdentifierInfo *ScopeName, SourceRange AttrRange,
|
||||
SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed,
|
||||
unsigned Spelling)
|
||||
: AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
|
||||
ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed),
|
||||
SpellingIndex(Spelling) {}
|
||||
|
||||
AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange,
|
||||
Syntax SyntaxUsed)
|
||||
: AttrName(AttrName), ScopeName(nullptr), AttrRange(AttrRange),
|
||||
ScopeLoc(), AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)),
|
||||
SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {}
|
||||
|
||||
AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed)
|
||||
: AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(),
|
||||
AttrKind(K), SyntaxUsed(SyntaxUsed),
|
||||
SpellingIndex(SpellingNotCalculated) {}
|
||||
|
||||
AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed,
|
||||
unsigned Spelling)
|
||||
: AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(),
|
||||
AttrKind(K), SyntaxUsed(SyntaxUsed), SpellingIndex(Spelling) {}
|
||||
|
||||
AttributeCommonInfo(AttributeCommonInfo &&) = default;
|
||||
AttributeCommonInfo(const AttributeCommonInfo &) = default;
|
||||
|
||||
Kind getParsedKind() const { return Kind(AttrKind); }
|
||||
Syntax getSyntax() const { return Syntax(SyntaxUsed); }
|
||||
const IdentifierInfo *getAttrName() const { return AttrName; }
|
||||
SourceLocation getLoc() const { return AttrRange.getBegin(); }
|
||||
SourceRange getRange() const { return AttrRange; }
|
||||
void setRange(SourceRange R) { AttrRange = R; }
|
||||
|
||||
bool hasScope() const { return ScopeName; }
|
||||
const IdentifierInfo *getScopeName() const { return ScopeName; }
|
||||
SourceLocation getScopeLoc() const { return ScopeLoc; }
|
||||
|
||||
bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
|
||||
bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
|
||||
|
||||
bool isGNUScope() const;
|
||||
|
||||
bool isAlignasAttribute() const {
|
||||
// FIXME: Use a better mechanism to determine this.
|
||||
return getParsedKind() == AT_Aligned && isKeywordAttribute();
|
||||
}
|
||||
|
||||
bool isCXX11Attribute() const {
|
||||
return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
|
||||
}
|
||||
|
||||
bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; }
|
||||
|
||||
bool isKeywordAttribute() const {
|
||||
return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
|
||||
}
|
||||
|
||||
bool isContextSensitiveKeywordAttribute() const {
|
||||
return SyntaxUsed == AS_ContextSensitiveKeyword;
|
||||
}
|
||||
|
||||
unsigned getAttributeSpellingListIndex() const {
|
||||
assert((isAttributeSpellingListCalculated() || AttrName) &&
|
||||
"Spelling cannot be found");
|
||||
return isAttributeSpellingListCalculated()
|
||||
? SpellingIndex
|
||||
: calculateAttributeSpellingListIndex();
|
||||
}
|
||||
void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; }
|
||||
|
||||
static Kind getParsedKind(const IdentifierInfo *Name,
|
||||
const IdentifierInfo *Scope, Syntax SyntaxUsed);
|
||||
|
||||
private:
|
||||
/// Get an index into the attribute spelling list
|
||||
/// defined in Attr.td. This index is used by an attribute
|
||||
/// to pretty print itself.
|
||||
unsigned calculateAttributeSpellingListIndex() const;
|
||||
|
||||
friend class clang::ASTRecordWriter;
|
||||
// Used exclusively by ASTDeclWriter to get the raw spelling list state.
|
||||
unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; }
|
||||
|
||||
protected:
|
||||
bool isAttributeSpellingListCalculated() const {
|
||||
return SpellingIndex != SpellingNotCalculated;
|
||||
}
|
||||
};
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
|
@ -113,14 +113,17 @@ BUILTIN(__builtin_atan2l, "LdLdLd", "Fne")
|
||||
BUILTIN(__builtin_abs , "ii" , "ncF")
|
||||
BUILTIN(__builtin_copysign, "ddd", "ncF")
|
||||
BUILTIN(__builtin_copysignf, "fff", "ncF")
|
||||
BUILTIN(__builtin_copysignf16, "hhh", "ncF")
|
||||
BUILTIN(__builtin_copysignl, "LdLdLd", "ncF")
|
||||
BUILTIN(__builtin_copysignf128, "LLdLLdLLd", "ncF")
|
||||
BUILTIN(__builtin_fabs , "dd" , "ncF")
|
||||
BUILTIN(__builtin_fabsf, "ff" , "ncF")
|
||||
BUILTIN(__builtin_fabsl, "LdLd", "ncF")
|
||||
BUILTIN(__builtin_fabsf16, "hh" , "ncF")
|
||||
BUILTIN(__builtin_fabsf128, "LLdLLd", "ncF")
|
||||
BUILTIN(__builtin_fmod , "ddd" , "Fne")
|
||||
BUILTIN(__builtin_fmodf, "fff" , "Fne")
|
||||
BUILTIN(__builtin_fmodf16, "hhh" , "Fne")
|
||||
BUILTIN(__builtin_fmodl, "LdLdLd", "Fne")
|
||||
BUILTIN(__builtin_frexp , "ddi*" , "Fn")
|
||||
BUILTIN(__builtin_frexpf, "ffi*" , "Fn")
|
||||
@ -154,6 +157,7 @@ BUILTIN(__builtin_powif, "ffi" , "Fnc")
|
||||
BUILTIN(__builtin_powil, "LdLdi", "Fnc")
|
||||
BUILTIN(__builtin_pow , "ddd" , "Fne")
|
||||
BUILTIN(__builtin_powf, "fff" , "Fne")
|
||||
BUILTIN(__builtin_powf16, "hhh" , "Fne")
|
||||
BUILTIN(__builtin_powl, "LdLdLd", "Fne")
|
||||
|
||||
// Standard unary libc/libm functions with double/float/long double variants:
|
||||
@ -180,9 +184,11 @@ BUILTIN(__builtin_cbrtf, "ff", "Fnc")
|
||||
BUILTIN(__builtin_cbrtl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_ceil , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_ceilf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_ceilf16, "hh" , "Fnc")
|
||||
BUILTIN(__builtin_ceill, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_cos , "dd" , "Fne")
|
||||
BUILTIN(__builtin_cosf, "ff" , "Fne")
|
||||
BUILTIN(__builtin_cosf16, "hh" , "Fne")
|
||||
BUILTIN(__builtin_cosh , "dd" , "Fne")
|
||||
BUILTIN(__builtin_coshf, "ff" , "Fne")
|
||||
BUILTIN(__builtin_coshl, "LdLd", "Fne")
|
||||
@ -195,9 +201,11 @@ BUILTIN(__builtin_erfcf, "ff", "Fne")
|
||||
BUILTIN(__builtin_erfcl, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_exp , "dd" , "Fne")
|
||||
BUILTIN(__builtin_expf, "ff" , "Fne")
|
||||
BUILTIN(__builtin_expf16, "hh" , "Fne")
|
||||
BUILTIN(__builtin_expl, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_exp2 , "dd" , "Fne")
|
||||
BUILTIN(__builtin_exp2f, "ff" , "Fne")
|
||||
BUILTIN(__builtin_exp2f16, "hh" , "Fne")
|
||||
BUILTIN(__builtin_exp2l, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_expm1 , "dd", "Fne")
|
||||
BUILTIN(__builtin_expm1f, "ff", "Fne")
|
||||
@ -207,15 +215,19 @@ BUILTIN(__builtin_fdimf, "fff", "Fne")
|
||||
BUILTIN(__builtin_fdiml, "LdLdLd", "Fne")
|
||||
BUILTIN(__builtin_floor , "dd" , "Fnc")
|
||||
BUILTIN(__builtin_floorf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_floorf16, "hh" , "Fnc")
|
||||
BUILTIN(__builtin_floorl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_fma, "dddd", "Fne")
|
||||
BUILTIN(__builtin_fmaf, "ffff", "Fne")
|
||||
BUILTIN(__builtin_fmaf16, "hhhh", "Fne")
|
||||
BUILTIN(__builtin_fmal, "LdLdLdLd", "Fne")
|
||||
BUILTIN(__builtin_fmax, "ddd", "Fnc")
|
||||
BUILTIN(__builtin_fmaxf, "fff", "Fnc")
|
||||
BUILTIN(__builtin_fmaxf16, "hhh", "Fnc")
|
||||
BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc")
|
||||
BUILTIN(__builtin_fmin, "ddd", "Fnc")
|
||||
BUILTIN(__builtin_fminf, "fff", "Fnc")
|
||||
BUILTIN(__builtin_fminf16, "hhh", "Fnc")
|
||||
BUILTIN(__builtin_fminl, "LdLdLd", "Fnc")
|
||||
BUILTIN(__builtin_hypot , "ddd" , "Fne")
|
||||
BUILTIN(__builtin_hypotf, "fff" , "Fne")
|
||||
@ -235,17 +247,20 @@ BUILTIN(__builtin_llroundl, "LLiLd", "Fne")
|
||||
BUILTIN(__builtin_log , "dd" , "Fne")
|
||||
BUILTIN(__builtin_log10 , "dd" , "Fne")
|
||||
BUILTIN(__builtin_log10f, "ff" , "Fne")
|
||||
BUILTIN(__builtin_log10f16, "hh" , "Fne")
|
||||
BUILTIN(__builtin_log10l, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_log1p , "dd" , "Fne")
|
||||
BUILTIN(__builtin_log1pf, "ff" , "Fne")
|
||||
BUILTIN(__builtin_log1pl, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_log2, "dd" , "Fne")
|
||||
BUILTIN(__builtin_log2f, "ff" , "Fne")
|
||||
BUILTIN(__builtin_log2f16, "hh" , "Fne")
|
||||
BUILTIN(__builtin_log2l, "LdLd" , "Fne")
|
||||
BUILTIN(__builtin_logb , "dd", "Fne")
|
||||
BUILTIN(__builtin_logbf, "ff", "Fne")
|
||||
BUILTIN(__builtin_logbl, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_logf, "ff" , "Fne")
|
||||
BUILTIN(__builtin_logf16, "hh" , "Fne")
|
||||
BUILTIN(__builtin_logl, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_lrint , "Lid", "Fne")
|
||||
BUILTIN(__builtin_lrintf, "Lif", "Fne")
|
||||
@ -270,9 +285,11 @@ BUILTIN(__builtin_remquof, "fffi*", "Fn")
|
||||
BUILTIN(__builtin_remquol, "LdLdLdi*", "Fn")
|
||||
BUILTIN(__builtin_rint , "dd", "Fnc")
|
||||
BUILTIN(__builtin_rintf, "ff", "Fnc")
|
||||
BUILTIN(__builtin_rintf16, "hh", "Fnc")
|
||||
BUILTIN(__builtin_rintl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_round, "dd" , "Fnc")
|
||||
BUILTIN(__builtin_roundf, "ff" , "Fnc")
|
||||
BUILTIN(__builtin_roundf16, "hh" , "Fnc")
|
||||
BUILTIN(__builtin_roundl, "LdLd" , "Fnc")
|
||||
BUILTIN(__builtin_scalbln , "ddLi", "Fne")
|
||||
BUILTIN(__builtin_scalblnf, "ffLi", "Fne")
|
||||
@ -282,12 +299,14 @@ BUILTIN(__builtin_scalbnf, "ffi", "Fne")
|
||||
BUILTIN(__builtin_scalbnl, "LdLdi", "Fne")
|
||||
BUILTIN(__builtin_sin , "dd" , "Fne")
|
||||
BUILTIN(__builtin_sinf, "ff" , "Fne")
|
||||
BUILTIN(__builtin_sinf16, "hh" , "Fne")
|
||||
BUILTIN(__builtin_sinh , "dd" , "Fne")
|
||||
BUILTIN(__builtin_sinhf, "ff" , "Fne")
|
||||
BUILTIN(__builtin_sinhl, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_sinl, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_sqrt , "dd" , "Fne")
|
||||
BUILTIN(__builtin_sqrtf, "ff" , "Fne")
|
||||
BUILTIN(__builtin_sqrtf16, "hh" , "Fne")
|
||||
BUILTIN(__builtin_sqrtl, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_tan , "dd" , "Fne")
|
||||
BUILTIN(__builtin_tanf, "ff" , "Fne")
|
||||
@ -301,6 +320,7 @@ BUILTIN(__builtin_tgammal, "LdLd", "Fne")
|
||||
BUILTIN(__builtin_trunc , "dd", "Fnc")
|
||||
BUILTIN(__builtin_truncf, "ff", "Fnc")
|
||||
BUILTIN(__builtin_truncl, "LdLd", "Fnc")
|
||||
BUILTIN(__builtin_truncf16, "hh", "Fnc")
|
||||
|
||||
// C99 complex builtins
|
||||
BUILTIN(__builtin_cabs, "dXd", "Fne")
|
||||
@ -394,6 +414,7 @@ BUILTIN(__builtin_signbitl, "iLd", "Fnc")
|
||||
// Special FP builtins.
|
||||
BUILTIN(__builtin_canonicalize, "dd", "nc")
|
||||
BUILTIN(__builtin_canonicalizef, "ff", "nc")
|
||||
BUILTIN(__builtin_canonicalizef16, "hh", "nc")
|
||||
BUILTIN(__builtin_canonicalizel, "LdLd", "nc")
|
||||
|
||||
// Builtins for arithmetic.
|
||||
@ -440,7 +461,7 @@ BUILTIN(__builtin_rotateleft64, "UWiUWiUWi", "nc")
|
||||
BUILTIN(__builtin_rotateright8, "UcUcUc", "nc")
|
||||
BUILTIN(__builtin_rotateright16, "UsUsUs", "nc")
|
||||
BUILTIN(__builtin_rotateright32, "UZiUZiUZi", "nc")
|
||||
BUILTIN(__builtin_rotateright64, "UWiUWiWi", "nc")
|
||||
BUILTIN(__builtin_rotateright64, "UWiUWiUWi", "nc")
|
||||
|
||||
// Random GCC builtins
|
||||
BUILTIN(__builtin_constant_p, "i.", "nctu")
|
||||
@ -984,9 +1005,7 @@ LIBBUILTIN(pthread_create, "", "fC<2,3>", "pthread.h", ALL_GNU_LANGUAGES)
|
||||
LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(__sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(getcontext, "iK*", "fj", "setjmp.h", ALL_LANGUAGES)
|
||||
|
||||
LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h", ALL_GNU_LANGUAGES)
|
||||
@ -1449,7 +1468,7 @@ BUILTIN(__builtin_operator_new, "v*z", "tc")
|
||||
BUILTIN(__builtin_operator_delete, "vv*", "tn")
|
||||
BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
|
||||
BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
|
||||
BUILTIN(__builtin_preserve_access_index, "vC*vC*", "nU")
|
||||
BUILTIN(__builtin_preserve_access_index, "v.", "t")
|
||||
|
||||
// Safestack builtins
|
||||
BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
|
||||
|
@ -91,12 +91,18 @@ LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
|
||||
// Misc
|
||||
BUILTIN(__builtin_sponentry, "v*", "c")
|
||||
|
||||
// Transactional Memory Extension
|
||||
BUILTIN(__builtin_arm_tstart, "WUi", "nj")
|
||||
BUILTIN(__builtin_arm_tcommit, "v", "n")
|
||||
BUILTIN(__builtin_arm_tcancel, "vWUIi", "n")
|
||||
BUILTIN(__builtin_arm_ttest, "WUi", "nc")
|
||||
|
||||
TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAdd, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAdd, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -106,9 +112,9 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h"
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -125,9 +131,9 @@ TARGET_HEADER_BUILTIN(_InterlockedExchange8_rel, "ccD*c", "nh", "intrin.h
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -138,9 +144,9 @@ TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_rel, "ccD*cc", "nh",
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_acq, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_nf, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_rel, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_acq, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_nf, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_rel, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -151,9 +157,9 @@ TARGET_HEADER_BUILTIN(_InterlockedOr8_rel, "ccD*c", "nh", "intrin.h", ALL
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -164,9 +170,9 @@ TARGET_HEADER_BUILTIN(_InterlockedXor8_rel, "ccD*c", "nh", "intrin.h", AL
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -177,9 +183,9 @@ TARGET_HEADER_BUILTIN(_InterlockedAnd8_rel, "ccD*c", "nh", "intrin.h", AL
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -187,9 +193,9 @@ TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", AL
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -197,9 +203,9 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h",
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
@ -118,6 +118,13 @@ BUILTIN(__builtin_amdgcn_cvt_pknorm_u16, "E2Usff", "nc")
|
||||
BUILTIN(__builtin_amdgcn_cvt_pk_i16, "E2sii", "nc")
|
||||
BUILTIN(__builtin_amdgcn_cvt_pk_u16, "E2UsUiUi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_cvt_pk_u8_f32, "UifUiUi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_sad_u8, "UiUiUiUi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_msad_u8, "UiUiUiUi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_sad_hi_u8, "UiUiUiUi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_sad_u16, "UiUiUiUi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_qsad_pk_u16_u8, "LUiLUiUiLUi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_mqsad_pk_u16_u8, "LUiLUiUiLUi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_mqsad_u32_u8, "V4UiLUiUiV4Ui", "nc")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CI+ only builtins.
|
||||
@ -125,6 +132,8 @@ BUILTIN(__builtin_amdgcn_cvt_pk_u8_f32, "UifUiUi", "nc")
|
||||
TARGET_BUILTIN(__builtin_amdgcn_s_dcache_inv_vol, "v", "n", "ci-insts")
|
||||
TARGET_BUILTIN(__builtin_amdgcn_buffer_wbinvl1_vol, "v", "n", "ci-insts")
|
||||
TARGET_BUILTIN(__builtin_amdgcn_ds_gws_sema_release_all, "vUi", "n", "ci-insts")
|
||||
TARGET_BUILTIN(__builtin_amdgcn_is_shared, "bvC*0", "nc", "flat-address-space")
|
||||
TARGET_BUILTIN(__builtin_amdgcn_is_private, "bvC*0", "nc", "flat-address-space")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Interpolation builtins.
|
||||
|
@ -221,9 +221,9 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h"
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -240,9 +240,9 @@ TARGET_HEADER_BUILTIN(_InterlockedExchange8_rel, "ccD*c", "nh", "intrin.h
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -253,9 +253,9 @@ TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_rel, "ccD*cc", "nh",
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_acq, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_nf, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_rel, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_acq, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_nf, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_rel, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -266,9 +266,9 @@ TARGET_HEADER_BUILTIN(_InterlockedOr8_rel, "ccD*c", "nh", "intrin.h", ALL
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedOr64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -279,9 +279,9 @@ TARGET_HEADER_BUILTIN(_InterlockedXor8_rel, "ccD*c", "nh", "intrin.h", AL
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedXor64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -292,9 +292,9 @@ TARGET_HEADER_BUILTIN(_InterlockedAnd8_rel, "ccD*c", "nh", "intrin.h", AL
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -302,9 +302,9 @@ TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", AL
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -312,9 +312,9 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h",
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
24
include/clang/Basic/BuiltinsBPF.def
Normal file
24
include/clang/Basic/BuiltinsBPF.def
Normal file
@ -0,0 +1,24 @@
|
||||
//===--- BuiltinsBPF.def - BPF Builtin function database --------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the BPF-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.
|
||||
|
||||
#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
|
||||
# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
|
||||
#endif
|
||||
|
||||
// Get record field information.
|
||||
TARGET_BUILTIN(__builtin_preserve_field_info, "Ui.", "t", "")
|
||||
|
||||
#undef BUILTIN
|
||||
#undef TARGET_BUILTIN
|
@ -50,17 +50,17 @@ BUILTIN(__builtin_altivec_vavguw, "V4UiV4UiV4Ui", "")
|
||||
|
||||
BUILTIN(__builtin_altivec_vrfip, "V4fV4f", "")
|
||||
|
||||
BUILTIN(__builtin_altivec_vcfsx, "V4fV4iIi", "")
|
||||
BUILTIN(__builtin_altivec_vcfux, "V4fV4iIi", "")
|
||||
BUILTIN(__builtin_altivec_vcfsx, "V4fV4SiIi", "")
|
||||
BUILTIN(__builtin_altivec_vcfux, "V4fV4UiIi", "")
|
||||
BUILTIN(__builtin_altivec_vctsxs, "V4SiV4fIi", "")
|
||||
BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fIi", "")
|
||||
|
||||
BUILTIN(__builtin_altivec_dss, "vUi", "")
|
||||
BUILTIN(__builtin_altivec_dss, "vUIi", "")
|
||||
BUILTIN(__builtin_altivec_dssall, "v", "")
|
||||
BUILTIN(__builtin_altivec_dst, "vvC*iUi", "")
|
||||
BUILTIN(__builtin_altivec_dstt, "vvC*iUi", "")
|
||||
BUILTIN(__builtin_altivec_dstst, "vvC*iUi", "")
|
||||
BUILTIN(__builtin_altivec_dststt, "vvC*iUi", "")
|
||||
BUILTIN(__builtin_altivec_dst, "vvC*iUIi", "")
|
||||
BUILTIN(__builtin_altivec_dstt, "vvC*iUIi", "")
|
||||
BUILTIN(__builtin_altivec_dstst, "vvC*iUIi", "")
|
||||
BUILTIN(__builtin_altivec_dststt, "vvC*iUIi", "")
|
||||
|
||||
BUILTIN(__builtin_altivec_vexptefp, "V4fV4f", "")
|
||||
|
||||
|
@ -31,6 +31,8 @@ TARGET_BUILTIN(__builtin_wasm_data_drop, "vIUi", "", "bulk-memory")
|
||||
|
||||
// Thread-local storage
|
||||
TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
|
||||
TARGET_BUILTIN(__builtin_wasm_tls_align, "z", "nc", "bulk-memory")
|
||||
TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "nU", "bulk-memory")
|
||||
|
||||
// Floating point min/max
|
||||
BUILTIN(__builtin_wasm_min_f32, "fff", "nc")
|
||||
@ -47,6 +49,16 @@ BUILTIN(__builtin_wasm_atomic_wait_i32, "ii*iLLi", "n")
|
||||
BUILTIN(__builtin_wasm_atomic_wait_i64, "iLLi*LLiLLi", "n")
|
||||
BUILTIN(__builtin_wasm_atomic_notify, "Uii*Ui", "n")
|
||||
|
||||
// Trapping fp-to-int conversions
|
||||
BUILTIN(__builtin_wasm_trunc_s_i32_f32, "if", "nc")
|
||||
BUILTIN(__builtin_wasm_trunc_u_i32_f32, "if", "nc")
|
||||
BUILTIN(__builtin_wasm_trunc_s_i32_f64, "id", "nc")
|
||||
BUILTIN(__builtin_wasm_trunc_u_i32_f64, "id", "nc")
|
||||
BUILTIN(__builtin_wasm_trunc_s_i64_f32, "LLif", "nc")
|
||||
BUILTIN(__builtin_wasm_trunc_u_i64_f32, "LLif", "nc")
|
||||
BUILTIN(__builtin_wasm_trunc_s_i64_f64, "LLid", "nc")
|
||||
BUILTIN(__builtin_wasm_trunc_u_i64_f64, "LLid", "nc")
|
||||
|
||||
// Saturating fp-to-int conversions
|
||||
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32_f32, "if", "nc", "nontrapping-fptoint")
|
||||
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32_f32, "if", "nc", "nontrapping-fptoint")
|
||||
@ -58,6 +70,8 @@ TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64_f64, "LLid", "nc", "nontrappi
|
||||
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64_f64, "LLid", "nc", "nontrapping-fptoint")
|
||||
|
||||
// SIMD builtins
|
||||
TARGET_BUILTIN(__builtin_wasm_swizzle_v8x16, "V16cV16cV16c", "nc", "unimplemented-simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_extract_lane_s_i8x16, "iV16cIi", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_extract_lane_u_i8x16, "iV16cIi", "nc", "unimplemented-simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_extract_lane_s_i16x8, "iV8sIi", "nc", "simd128")
|
||||
@ -106,10 +120,29 @@ TARGET_BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd1
|
||||
TARGET_BUILTIN(__builtin_wasm_sqrt_f32x4, "V4fV4f", "nc", "unimplemented-simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_sqrt_f64x2, "V2dV2d", "nc", "unimplemented-simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_qfma_f32x4, "V4fV4fV4fV4f", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_qfms_f32x4, "V4fV4fV4fV4f", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_qfma_f64x2, "V2dV2dV2dV2d", "nc", "unimplemented-simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_qfms_f64x2, "V2dV2dV2dV2d", "nc", "unimplemented-simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32x4_f32x4, "V4iV4f", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32x4_f32x4, "V4iV4f", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64x2_f64x2, "V2LLiV2d", "nc", "unimplemented-simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64x2_f64x2, "V2LLiV2d", "nc", "unimplemented-simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_narrow_s_i8x16_i16x8, "V16cV8sV8s", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_narrow_u_i8x16_i16x8, "V16cV8sV8s", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_narrow_s_i16x8_i32x4, "V8sV4iV4i", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_narrow_u_i16x8_i32x4, "V8sV4iV4i", "nc", "simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_widen_low_s_i16x8_i8x16, "V8sV16c", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_widen_high_s_i16x8_i8x16, "V8sV16c", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_widen_low_u_i16x8_i8x16, "V8sV16c", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_widen_high_u_i16x8_i8x16, "V8sV16c", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_widen_low_s_i32x4_i16x8, "V4iV8s", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_widen_high_s_i32x4_i16x8, "V4iV8s", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_widen_low_u_i32x4_i16x8, "V4iV8s", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_widen_high_u_i32x4_i16x8, "V4iV8s", "nc", "simd128")
|
||||
|
||||
#undef BUILTIN
|
||||
#undef TARGET_BUILTIN
|
||||
|
@ -751,8 +751,8 @@ TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "nc", "tbm")
|
||||
// LWP
|
||||
TARGET_BUILTIN(__builtin_ia32_llwpcb, "vv*", "n", "lwp")
|
||||
TARGET_BUILTIN(__builtin_ia32_slwpcb, "v*", "n", "lwp")
|
||||
TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiUi", "n", "lwp")
|
||||
TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiUi", "n", "lwp")
|
||||
TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiIUi", "n", "lwp")
|
||||
TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiIUi", "n", "lwp")
|
||||
|
||||
// SHA
|
||||
TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "ncV:128:", "sha")
|
||||
|
@ -86,8 +86,8 @@ TARGET_BUILTIN(__builtin_ia32_bzhi_di, "UOiUOiUOi", "nc", "bmi2")
|
||||
TARGET_BUILTIN(__builtin_ia32_pdep_di, "UOiUOiUOi", "nc", "bmi2")
|
||||
TARGET_BUILTIN(__builtin_ia32_pext_di, "UOiUOiUOi", "nc", "bmi2")
|
||||
TARGET_BUILTIN(__builtin_ia32_bextri_u64, "UOiUOiIUOi", "nc", "tbm")
|
||||
TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcUOiUiUi", "n", "lwp")
|
||||
TARGET_BUILTIN(__builtin_ia32_lwpval64, "vUOiUiUi", "n", "lwp")
|
||||
TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcUOiUiIUi", "n", "lwp")
|
||||
TARGET_BUILTIN(__builtin_ia32_lwpval64, "vUOiUiIUi", "n", "lwp")
|
||||
TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "OiV2dIi", "ncV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "UOiV2dIi", "ncV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "OiV4fIi", "ncV:128:", "avx512f")
|
||||
|
@ -47,7 +47,8 @@ CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker
|
||||
///< aliases to base ctors when possible.
|
||||
CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled.
|
||||
CODEGENOPT(UniqueSectionNames, 1, 1) ///< Set for -funique-section-names.
|
||||
CODEGENOPT(DisableFPElim , 1, 0) ///< Set when -fomit-frame-pointer is enabled.
|
||||
ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none
|
||||
|
||||
CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory.
|
||||
CODEGENOPT(DiscardValueNames , 1, 0) ///< Discard Value Names from the IR (LLVMContext flag)
|
||||
CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing.
|
||||
@ -132,6 +133,7 @@ CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is
|
||||
CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled.
|
||||
CODEGENOPT(FatalWarnings , 1, 0) ///< Set when -Wa,--fatal-warnings is
|
||||
///< enabled.
|
||||
CODEGENOPT(NoWarn , 1, 0) ///< Set when -Wa,--no-warn is enabled.
|
||||
CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
|
||||
CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled.
|
||||
CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf.
|
||||
@ -155,8 +157,6 @@ CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
|
||||
ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
|
||||
/// Replace certain message sends with calls to ObjC runtime entrypoints
|
||||
CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1)
|
||||
CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
|
||||
///< enabled.
|
||||
|
||||
VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
|
||||
VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
|
||||
@ -195,6 +195,8 @@ CODEGENOPT(SanitizeMinimalRuntime, 1, 0) ///< Use "_minimal" sanitizer runtime f
|
||||
///< diagnostics.
|
||||
CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0) ///< Generalize pointer types in
|
||||
///< CFI icall function signatures
|
||||
CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical
|
||||
///< instead of creating a local jump table.
|
||||
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
|
||||
///< instrumentation.
|
||||
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage
|
||||
@ -226,6 +228,8 @@ CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definiti
|
||||
CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers
|
||||
CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled.
|
||||
CODEGENOPT(TimeTrace , 1, 0) ///< Set when -ftime-trace is enabled.
|
||||
VALUE_CODEGENOPT(TimeTraceGranularity, 32, 500) ///< Minimum time granularity (in microseconds),
|
||||
///< traced by time profiler
|
||||
CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled.
|
||||
CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled.
|
||||
CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled.
|
||||
@ -274,6 +278,10 @@ CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
|
||||
CODEGENOPT(WholeProgramVTables, 1, 0) ///< Whether to apply whole-program
|
||||
/// vtable optimization.
|
||||
|
||||
CODEGENOPT(VirtualFunctionElimination, 1, 0) ///< Whether to apply the dead
|
||||
/// virtual function elimination
|
||||
/// optimization.
|
||||
|
||||
/// Whether to use public LTO visibility for entities in std and stdext
|
||||
/// namespaces. This is enabled by clang-cl's /MT and /MTd flags.
|
||||
CODEGENOPT(LTOVisibilityPublicStd, 1, 0)
|
||||
|
@ -117,6 +117,12 @@ class CodeGenOptions : public CodeGenOptionsBase {
|
||||
|
||||
enum SignReturnAddressKeyValue { AKey, BKey };
|
||||
|
||||
enum class FramePointerKind {
|
||||
None, // Omit all frame pointers.
|
||||
NonLeaf, // Keep non-leaf frame pointers.
|
||||
All, // Keep all frame pointers.
|
||||
};
|
||||
|
||||
/// The code model to use (-mcmodel).
|
||||
std::string CodeModel;
|
||||
|
||||
|
@ -632,24 +632,22 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
|
||||
/// Suppress all diagnostics, to silence the front end when we
|
||||
/// know that we don't want any more diagnostics to be passed along to the
|
||||
/// client
|
||||
void setSuppressAllDiagnostics(bool Val = true) {
|
||||
SuppressAllDiagnostics = Val;
|
||||
}
|
||||
void setSuppressAllDiagnostics(bool Val) { SuppressAllDiagnostics = Val; }
|
||||
bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
|
||||
|
||||
/// Set type eliding, to skip outputting same types occurring in
|
||||
/// template types.
|
||||
void setElideType(bool Val = true) { ElideType = Val; }
|
||||
void setElideType(bool Val) { ElideType = Val; }
|
||||
bool getElideType() { return ElideType; }
|
||||
|
||||
/// Set tree printing, to outputting the template difference in a
|
||||
/// tree format.
|
||||
void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; }
|
||||
void setPrintTemplateTree(bool Val) { PrintTemplateTree = Val; }
|
||||
bool getPrintTemplateTree() { return PrintTemplateTree; }
|
||||
|
||||
/// Set color printing, so the type diffing will inject color markers
|
||||
/// into the output.
|
||||
void setShowColors(bool Val = false) { ShowColors = Val; }
|
||||
void setShowColors(bool Val) { ShowColors = Val; }
|
||||
bool getShowColors() { return ShowColors; }
|
||||
|
||||
/// Specify which overload candidates to show when overload resolution
|
||||
@ -667,7 +665,7 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
|
||||
/// the middle of another diagnostic.
|
||||
///
|
||||
/// This can be used by clients who suppress diagnostics themselves.
|
||||
void setLastDiagnosticIgnored(bool Ignored = true) {
|
||||
void setLastDiagnosticIgnored(bool Ignored) {
|
||||
if (LastDiagLevel == DiagnosticIDs::Fatal)
|
||||
FatalErrorOccurred = true;
|
||||
LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning;
|
||||
@ -1127,11 +1125,6 @@ class DiagnosticBuilder {
|
||||
Emit();
|
||||
}
|
||||
|
||||
/// Retrieve an empty diagnostic builder.
|
||||
static DiagnosticBuilder getEmpty() {
|
||||
return {};
|
||||
}
|
||||
|
||||
/// Forces the diagnostic to be emitted.
|
||||
const DiagnosticBuilder &setForceEmit() const {
|
||||
IsForceEmit = true;
|
||||
|
@ -37,8 +37,9 @@ def note_constexpr_virtual_call : Note<
|
||||
def note_constexpr_pure_virtual_call : Note<
|
||||
"pure virtual function %q0 called">;
|
||||
def note_constexpr_polymorphic_unknown_dynamic_type : Note<
|
||||
"%select{||||virtual function called on|dynamic_cast applied to|"
|
||||
"typeid applied to}0 object '%1' whose dynamic type is not constant">;
|
||||
"%select{|||||virtual function called on|dynamic_cast applied to|"
|
||||
"typeid applied to|construction of|destruction of}0 object '%1' "
|
||||
"whose dynamic type is not constant">;
|
||||
def note_constexpr_dynamic_cast_to_reference_failed : Note<
|
||||
"reference dynamic_cast failed: %select{"
|
||||
"static type %1 of operand is a non-public base class of dynamic type %2|"
|
||||
@ -53,6 +54,9 @@ def note_constexpr_nonliteral : Note<
|
||||
def note_constexpr_non_global : Note<
|
||||
"%select{pointer|reference}0 to %select{|subobject of }1"
|
||||
"%select{temporary|%3}2 is not a constant expression">;
|
||||
def note_constexpr_dynamic_alloc : Note<
|
||||
"%select{pointer|reference}0 to %select{|subobject of }1"
|
||||
"heap-allocated object is not a constant expression">;
|
||||
def note_constexpr_uninitialized : Note<
|
||||
"%select{|sub}0object of type %1 is not initialized">;
|
||||
def note_constexpr_subobject_declared_here : Note<
|
||||
@ -100,6 +104,7 @@ def note_constexpr_typeid_polymorphic : Note<
|
||||
def note_constexpr_void_comparison : Note<
|
||||
"comparison between unequal pointers to void has unspecified result">;
|
||||
def note_constexpr_temporary_here : Note<"temporary created here">;
|
||||
def note_constexpr_dynamic_alloc_here : Note<"heap allocation performed here">;
|
||||
def note_constexpr_conditional_never_const : Note<
|
||||
"both arms of conditional operator are unable to produce a "
|
||||
"constant expression">;
|
||||
@ -109,16 +114,20 @@ def note_constexpr_call_limit_exceeded : Note<
|
||||
"constexpr evaluation hit maximum call limit">;
|
||||
def note_constexpr_step_limit_exceeded : Note<
|
||||
"constexpr evaluation hit maximum step limit; possible infinite loop?">;
|
||||
def note_constexpr_heap_alloc_limit_exceeded : Note<
|
||||
"constexpr evaluation hit maximum heap allocation limit">;
|
||||
def note_constexpr_this : Note<
|
||||
"%select{|implicit }0use of 'this' pointer is only allowed within the "
|
||||
"evaluation of a call to a 'constexpr' member function">;
|
||||
def note_constexpr_lifetime_ended : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"%select{temporary|variable}1 whose lifetime has ended">;
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|construction of|"
|
||||
"destruction of}0 %select{temporary|variable}1 whose "
|
||||
"%plural{8:storage duration|:lifetime}0 has ended">;
|
||||
def note_constexpr_access_uninit : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|"
|
||||
"construction of subobject of|destruction of}0 "
|
||||
"%select{object outside its lifetime|uninitialized object}1 "
|
||||
"is not allowed in a constant expression">;
|
||||
def note_constexpr_use_uninit_reference : Note<
|
||||
@ -128,16 +137,21 @@ def note_constexpr_modify_const_type : Note<
|
||||
"modification of object of const-qualified type %0 is not allowed "
|
||||
"in a constant expression">;
|
||||
def note_constexpr_access_volatile_type : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|<ERROR>|<ERROR>}0 "
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"<ERROR>|<ERROR>|<ERROR>|<ERROR>}0 "
|
||||
"volatile-qualified type %1 is not allowed in a constant expression">;
|
||||
def note_constexpr_access_volatile_obj : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|<ERROR>|<ERROR>}0 "
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"<ERROR>|<ERROR>|<ERROR>|<ERROR>}0 "
|
||||
"volatile %select{temporary|object %2|member %2}1 is not allowed in "
|
||||
"a constant expression">;
|
||||
def note_constexpr_volatile_here : Note<
|
||||
"volatile %select{temporary created|object declared|member declared}0 here">;
|
||||
def note_constexpr_ltor_mutable : Note<
|
||||
"read of mutable member %0 is not allowed in a constant expression">;
|
||||
def note_constexpr_access_mutable : Note<
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|construction of|"
|
||||
"destruction of}0 "
|
||||
"mutable member %1 is not allowed in a constant expression">;
|
||||
def note_constexpr_ltor_non_const_int : Note<
|
||||
"read of non-const variable %0 is not allowed in a constant expression">;
|
||||
def note_constexpr_ltor_non_constexpr : Note<
|
||||
@ -145,31 +159,44 @@ def note_constexpr_ltor_non_constexpr : Note<
|
||||
def note_constexpr_ltor_incomplete_type : Note<
|
||||
"read of incomplete type %0 is not allowed in a constant expression">;
|
||||
def note_constexpr_access_null : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|construction of|"
|
||||
"destruction of}0 "
|
||||
"dereferenced null pointer is not allowed in a constant expression">;
|
||||
def note_constexpr_access_past_end : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"dereferenced one-past-the-end pointer is not allowed in a constant expression">;
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|construction of|"
|
||||
"destruction of}0 "
|
||||
"dereferenced one-past-the-end pointer is not allowed "
|
||||
"in a constant expression">;
|
||||
def note_constexpr_access_unsized_array : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|construction of|"
|
||||
"destruction of}0 "
|
||||
"element of array without known bound "
|
||||
"is not allowed in a constant expression">;
|
||||
def note_constexpr_access_inactive_union_member : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|"
|
||||
"construction of subobject of|destruction of}0 "
|
||||
"member %1 of union with %select{active member %3|no active member}2 "
|
||||
"is not allowed in a constant expression">;
|
||||
def note_constexpr_access_static_temporary : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of|typeid applied to}0 temporary "
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|reconstruction of|"
|
||||
"destruction of}0 temporary "
|
||||
"is not allowed in a constant expression outside the expression that "
|
||||
"created the temporary">;
|
||||
def note_constexpr_access_unreadable_object : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of|typeid applied to}0 object '%1' whose value is not known">;
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|construction of|"
|
||||
"destruction of}0 "
|
||||
"object '%1' whose value is not known">;
|
||||
def note_constexpr_access_deleted_object : Note<
|
||||
"%select{read of|read of|assignment to|increment of|decrement of|"
|
||||
"member call on|dynamic_cast of|typeid applied to|construction of|"
|
||||
"destruction of}0 "
|
||||
"heap allocated object that has been deleted">;
|
||||
def note_constexpr_modify_global : Note<
|
||||
"a constant expression cannot modify an object that is visible outside "
|
||||
"that expression">;
|
||||
@ -189,6 +216,13 @@ def note_constexpr_baa_insufficient_alignment : Note<
|
||||
def note_constexpr_baa_value_insufficient_alignment : Note<
|
||||
"value of the aligned pointer (%0) is not a multiple of the asserted %1 "
|
||||
"%plural{1:byte|:bytes}1">;
|
||||
def note_constexpr_destroy_out_of_lifetime : Note<
|
||||
"destroying object '%0' whose lifetime has already ended">;
|
||||
def note_constexpr_unsupported_destruction : Note<
|
||||
"non-trivial destruction of type %0 in a constant expression is not supported">;
|
||||
def note_constexpr_unsupported_tempoarary_nontrivial_dtor : Note<
|
||||
"non-trivial destruction of lifetime-extended temporary with type %0 "
|
||||
"used in the result of a constant expression is not yet supported">;
|
||||
def note_constexpr_unsupported_unsized_array : Note<
|
||||
"array-to-pointer decay of array member without known bound is not supported">;
|
||||
def note_constexpr_unsized_array_indexed : Note<
|
||||
@ -228,6 +262,62 @@ def note_constexpr_bit_cast_invalid_subtype : Note<
|
||||
def note_constexpr_bit_cast_indet_dest : Note<
|
||||
"indeterminate value can only initialize an object of type 'unsigned char'"
|
||||
"%select{, 'char',|}1 or 'std::byte'; %0 is invalid">;
|
||||
def note_constexpr_pseudo_destructor : Note<
|
||||
"pseudo-destructor call is not permitted in constant expressions "
|
||||
"until C++20">;
|
||||
def note_constexpr_construct_complex_elem : Note<
|
||||
"construction of individual component of complex number is not yet supported "
|
||||
"in constant expressions">;
|
||||
def note_constexpr_destroy_complex_elem : Note<
|
||||
"destruction of individual component of complex number is not yet supported "
|
||||
"in constant expressions">;
|
||||
def note_constexpr_new : Note<
|
||||
"dynamic memory allocation is not permitted in constant expressions "
|
||||
"until C++20">;
|
||||
def note_constexpr_new_non_replaceable : Note<
|
||||
"call to %select{placement|class-specific}0 %1">;
|
||||
def note_constexpr_new_placement : Note<
|
||||
"this placement new expression is not yet supported in constant expressions">;
|
||||
def note_constexpr_placement_new_wrong_type : Note<
|
||||
"placement new would change type of storage from %0 to %1">;
|
||||
def note_constexpr_new_negative : Note<
|
||||
"cannot allocate array; evaluated array bound %0 is negative">;
|
||||
def note_constexpr_new_too_large : Note<
|
||||
"cannot allocate array; evaluated array bound %0 is too large">;
|
||||
def note_constexpr_new_too_small : Note<
|
||||
"cannot allocate array; evaluated array bound %0 is too small to hold "
|
||||
"%1 explicitly initialized elements">;
|
||||
def note_constexpr_new_untyped : Note<
|
||||
"cannot allocate untyped memory in a constant expression; "
|
||||
"use 'std::allocator<T>::allocate' to allocate memory of type 'T'">;
|
||||
def note_constexpr_new_not_complete_object_type : Note<
|
||||
"cannot allocate memory of %select{incomplete|function}0 type %1">;
|
||||
def note_constexpr_operator_new_bad_size : Note<
|
||||
"allocated size %0 is not a multiple of size %1 of element type %2">;
|
||||
def note_constexpr_delete_not_heap_alloc : Note<
|
||||
"delete of pointer '%0' that does not point to a heap-allocated object">;
|
||||
def note_constexpr_double_delete : Note<
|
||||
"delete of pointer that has already been deleted">;
|
||||
def note_constexpr_double_destroy : Note<
|
||||
"destruction of object that is already being destroyed">;
|
||||
def note_constexpr_new_delete_mismatch : Note<
|
||||
"%plural{2:'delete' used to delete pointer to object "
|
||||
"allocated with 'std::allocator<...>::allocate'|"
|
||||
":%select{non-array delete|array delete|'std::allocator<...>::deallocate'}0 "
|
||||
"used to delete pointer to "
|
||||
"%select{array object of type %2|non-array object of type %2|"
|
||||
"object allocated with 'new'}0}1">;
|
||||
def note_constexpr_delete_subobject : Note<
|
||||
"delete of pointer%select{ to subobject|}1 '%0' "
|
||||
"%select{|that does not point to complete object}1">;
|
||||
def note_constexpr_delete_base_nonvirt_dtor : Note<
|
||||
"delete of object with dynamic type %1 through pointer to "
|
||||
"base class type %0 with non-virtual destructor">;
|
||||
def note_constexpr_memory_leak : Note<
|
||||
"allocation performed here was not deallocated"
|
||||
"%plural{0:|: (along with %0 other memory leak%s0)}0">;
|
||||
def err_experimental_clang_interp_failed : Error<
|
||||
"the experimental clang interpreter failed to evaluate an expression">;
|
||||
|
||||
def warn_integer_constant_overflow : Warning<
|
||||
"overflow in expression; result is %0 with type %1">,
|
||||
@ -277,7 +367,6 @@ def warn_odr_variable_multiple_def : Warning<
|
||||
"external variable %0 defined in multiple translation units">,
|
||||
InGroup<ODR>;
|
||||
def note_odr_value_here : Note<"declared here with type %0">;
|
||||
def note_odr_defined_here : Note<"also defined here">;
|
||||
def err_odr_function_type_inconsistent : Error<
|
||||
"external function %0 declared with incompatible types in different "
|
||||
"translation units (%1 vs. %2)">;
|
||||
|
@ -153,6 +153,12 @@ def warn_doc_deprecated_not_sync : Warning<
|
||||
def note_add_deprecation_attr : Note<
|
||||
"add a deprecation attribute to the declaration to silence this warning">;
|
||||
|
||||
// inline contents commands
|
||||
|
||||
def warn_doc_inline_contents_no_argument : Warning<
|
||||
"'%select{\\|@}0%1' command does not have a valid word argument">,
|
||||
InGroup<Documentation>, DefaultIgnore;
|
||||
|
||||
// verbatim block commands
|
||||
|
||||
def warn_verbatim_block_end_without_start : Warning<
|
||||
|
@ -12,11 +12,21 @@
|
||||
|
||||
let Component = "Common" in {
|
||||
|
||||
// Substitutions.
|
||||
|
||||
def select_constexpr_spec_kind : TextSubstitution<
|
||||
"%select{<ERROR>|constexpr|consteval|constinit}0">;
|
||||
|
||||
// Basic.
|
||||
|
||||
def fatal_too_many_errors
|
||||
: Error<"too many errors emitted, stopping now">, DefaultFatal;
|
||||
|
||||
def warn_stack_exhausted : Warning<
|
||||
"stack nearly exhausted; compilation time may suffer, and "
|
||||
"crashes due to stack overflow are likely">,
|
||||
InGroup<DiagGroup<"stack-exhausted">>, NoSFINAE;
|
||||
|
||||
def note_declared_at : Note<"declared here">;
|
||||
def note_previous_definition : Note<"previous definition is here">;
|
||||
def note_previous_declaration : Note<"previous declaration is here">;
|
||||
@ -107,6 +117,10 @@ def err_attribute_not_type_attr : Error<
|
||||
"%0 attribute cannot be applied to types">;
|
||||
def err_enum_template : Error<"enumeration cannot be a template">;
|
||||
|
||||
def warn_cxx20_compat_consteval : Warning<
|
||||
"'consteval' specifier is incompatible with C++ standards before C++20">,
|
||||
InGroup<CXX2aCompat>, DefaultIgnore;
|
||||
|
||||
}
|
||||
|
||||
let CategoryName = "Nullability Issue" in {
|
||||
@ -172,9 +186,6 @@ def ext_cxx11_longlong : Extension<
|
||||
def warn_cxx98_compat_longlong : Warning<
|
||||
"'long long' is incompatible with C++98">,
|
||||
InGroup<CXX98CompatPedantic>, DefaultIgnore;
|
||||
def warn_cxx20_compat_consteval : Warning<
|
||||
"consteval is incompatible with C++ standards before C++20">,
|
||||
InGroup<CXX2aCompat>, DefaultIgnore;
|
||||
def err_integer_literal_too_large : Error<
|
||||
"integer literal is too large to be represented in any %select{signed |}0"
|
||||
"integer type">;
|
||||
@ -259,8 +270,6 @@ def err_target_unsupported_mcmse : Error<
|
||||
"-mcmse is not supported for %0">;
|
||||
def err_opt_not_valid_with_opt : Error<
|
||||
"option '%0' cannot be specified with '%1'">;
|
||||
def err_opt_not_valid_without_opt : Error<
|
||||
"option '%0' cannot be specified without '%1'">;
|
||||
def err_opt_not_valid_on_target : Error<
|
||||
"option '%0' cannot be specified on this target">;
|
||||
|
||||
@ -300,8 +309,13 @@ 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">;
|
||||
|
||||
// Static Analyzer Core
|
||||
def err_unknown_analyzer_checker : Error<
|
||||
def err_unknown_analyzer_checker_or_package : Error<
|
||||
"no analyzer checkers or packages are associated with '%0'">;
|
||||
def note_suggest_disabling_all_checkers : Note<
|
||||
"use -analyzer-disable-all-checks to disable all static analyzer checkers">;
|
||||
|
||||
// Poison system directories.
|
||||
def warn_poison_system_directories : Warning <
|
||||
"include location '%0' is unsafe for cross-compilation">,
|
||||
InGroup<DiagGroup<"poison-system-directories">>, DefaultIgnore;
|
||||
}
|
||||
|
@ -184,9 +184,6 @@ def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning<
|
||||
def warn_drv_ycyu_different_arg_clang_cl : Warning<
|
||||
"support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored">,
|
||||
InGroup<ClangClPch>;
|
||||
def warn_drv_ycyu_no_fi_arg_clang_cl : Warning<
|
||||
"support for '%0' without a corresponding /FI flag not implemented yet; flag ignored">,
|
||||
InGroup<ClangClPch>;
|
||||
def warn_drv_yc_multiple_inputs_clang_cl : Warning<
|
||||
"support for '/Yc' with more than one source file not implemented yet; flag ignored">,
|
||||
InGroup<ClangClPch>;
|
||||
@ -368,6 +365,9 @@ def err_drv_ropi_rwpi_incompatible_with_pic : Error<
|
||||
def err_drv_ropi_incompatible_with_cxx : Error<
|
||||
"ROPI is not compatible with c++">;
|
||||
|
||||
def err_stack_tagging_requires_hardware_feature : Error<
|
||||
"'-fsanitize=memtag' requires hardware support (+memtag)">;
|
||||
|
||||
def warn_target_unsupported_nan2008 : Warning<
|
||||
"ignoring '-mnan=2008' option because the '%0' architecture does not support it">,
|
||||
InGroup<UnsupportedNan>;
|
||||
@ -383,6 +383,9 @@ def warn_target_unsupported_abs2008 : Warning<
|
||||
def warn_target_unsupported_compact_branches : Warning<
|
||||
"ignoring '-mcompact-branches=' option because the '%0' architecture does not"
|
||||
" support it">, InGroup<UnsupportedCB>;
|
||||
def warn_target_unsupported_extension : Warning<
|
||||
"ignoring extension '%0' because the '%1' architecture does not support it">,
|
||||
InGroup<InvalidCommandLineArgument>;
|
||||
def warn_drv_unsupported_gpopt : Warning<
|
||||
"ignoring '-mgpopt' option as it cannot be used with %select{|the implicit"
|
||||
" usage of }0-mabicalls">,
|
||||
|
@ -64,8 +64,6 @@ def err_fe_backend_unsupported : Error<"%0">, BackendInfo;
|
||||
|
||||
def err_fe_invalid_code_complete_file : Error<
|
||||
"cannot locate code-completion file %0">, DefaultFatal;
|
||||
def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
|
||||
DefaultFatal;
|
||||
def err_fe_dependency_file_requires_MT : Error<
|
||||
"-dependency-file requires at least one -MT or -MQ option">;
|
||||
def err_fe_invalid_plugin_name : Error<
|
||||
@ -217,10 +215,6 @@ def err_modules_embed_file_not_found :
|
||||
DefaultFatal;
|
||||
def err_module_header_file_not_found :
|
||||
Error<"module header file '%0' not found">, DefaultFatal;
|
||||
def err_module_header_file_invalid :
|
||||
Error<"unexpected module header file input '%0'">, DefaultFatal;
|
||||
|
||||
def err_interface_stubs : Error<"clang-ifs (-emit-iterface-stubs): %0">;
|
||||
|
||||
def err_test_module_file_extension_version : Error<
|
||||
"test module file extension '%0' has different version (%1.%2) than expected "
|
||||
@ -275,7 +269,12 @@ def warn_profile_data_missing : Warning<
|
||||
def warn_profile_data_unprofiled : Warning<
|
||||
"no profile data available for file \"%0\"">,
|
||||
InGroup<ProfileInstrUnprofiled>;
|
||||
|
||||
def warn_profile_data_misexpect : Warning<
|
||||
"Potential performance regression from use of __builtin_expect(): "
|
||||
"Annotation was correct on %0 of profiled executions.">,
|
||||
BackendInfo,
|
||||
InGroup<MisExpect>,
|
||||
DefaultIgnore;
|
||||
} // end of instrumentation issue category
|
||||
|
||||
}
|
||||
|
@ -61,8 +61,16 @@ def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
|
||||
UndefinedBoolConversion]>;
|
||||
def IntConversion : DiagGroup<"int-conversion">;
|
||||
def EnumConversion : DiagGroup<"enum-conversion">;
|
||||
def ImplicitIntConversion : DiagGroup<"implicit-int-conversion">;
|
||||
def ImplicitFloatConversion : DiagGroup<"implicit-float-conversion">;
|
||||
def ObjCSignedCharBoolImplicitIntConversion :
|
||||
DiagGroup<"objc-signed-char-bool-implicit-int-conversion">;
|
||||
def ImplicitIntConversion : DiagGroup<"implicit-int-conversion",
|
||||
[ObjCSignedCharBoolImplicitIntConversion]>;
|
||||
def ImplicitIntFloatConversion : DiagGroup<"implicit-int-float-conversion">;
|
||||
def ObjCSignedCharBoolImplicitFloatConversion :
|
||||
DiagGroup<"objc-signed-char-bool-implicit-float-conversion">;
|
||||
def ImplicitFloatConversion : DiagGroup<"implicit-float-conversion",
|
||||
[ImplicitIntFloatConversion,
|
||||
ObjCSignedCharBoolImplicitFloatConversion]>;
|
||||
def ImplicitFixedPointConversion : DiagGroup<"implicit-fixed-point-conversion">;
|
||||
|
||||
def FloatOverflowConversion : DiagGroup<"float-overflow-conversion">;
|
||||
@ -99,7 +107,6 @@ def GNUComplexInteger : DiagGroup<"gnu-complex-integer">;
|
||||
def GNUConditionalOmittedOperand : DiagGroup<"gnu-conditional-omitted-operand">;
|
||||
def ConfigMacros : DiagGroup<"config-macros">;
|
||||
def : DiagGroup<"ctor-dtor-privacy">;
|
||||
def GNUDesignator : DiagGroup<"gnu-designator">;
|
||||
def GNUStringLiteralOperatorTemplate :
|
||||
DiagGroup<"gnu-string-literal-operator-template">;
|
||||
def UndefinedVarTemplate : DiagGroup<"undefined-var-template">;
|
||||
@ -113,11 +120,13 @@ def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor",
|
||||
[DeleteNonAbstractNonVirtualDtor,
|
||||
DeleteAbstractNonVirtualDtor]>;
|
||||
def AbstractFinalClass : DiagGroup<"abstract-final-class">;
|
||||
def FinalDtorNonFinalClass : DiagGroup<"final-dtor-non-final-class">;
|
||||
|
||||
def CXX11CompatDeprecatedWritableStr :
|
||||
DiagGroup<"c++11-compat-deprecated-writable-strings">;
|
||||
|
||||
def DeprecatedAttributes : DiagGroup<"deprecated-attributes">;
|
||||
def DeprecatedCommaSubscript : DiagGroup<"deprecated-comma-subscript">;
|
||||
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
|
||||
def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
|
||||
def UnguardedAvailabilityNew : DiagGroup<"unguarded-availability-new">;
|
||||
@ -131,18 +140,27 @@ def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
|
||||
def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
|
||||
def DeprecatedRegister : DiagGroup<"deprecated-register">;
|
||||
def DeprecatedThisCapture : DiagGroup<"deprecated-this-capture">;
|
||||
def DeprecatedVolatile : DiagGroup<"deprecated-volatile">;
|
||||
def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
|
||||
[CXX11CompatDeprecatedWritableStr]>;
|
||||
// FIXME: Why is DeprecatedImplementations not in this group?
|
||||
def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
|
||||
DeprecatedCommaSubscript,
|
||||
DeprecatedDeclarations,
|
||||
DeprecatedDynamicExceptionSpec,
|
||||
DeprecatedIncrementBool,
|
||||
DeprecatedRegister,
|
||||
DeprecatedThisCapture,
|
||||
DeprecatedVolatile,
|
||||
DeprecatedWritableStr]>,
|
||||
DiagCategory<"Deprecations">;
|
||||
|
||||
def CXX2aDesignator : DiagGroup<"c++2a-designator">;
|
||||
// Allow -Wno-c99-designator to be used to turn off all warnings on valid C99
|
||||
// designators (including the warning controlled by -Wc++2a-designator).
|
||||
def C99Designator : DiagGroup<"c99-designator", [CXX2aDesignator]>;
|
||||
def GNUDesignator : DiagGroup<"gnu-designator">;
|
||||
|
||||
def DynamicExceptionSpec
|
||||
: DiagGroup<"dynamic-exception-spec", [DeprecatedDynamicExceptionSpec]>;
|
||||
|
||||
@ -278,6 +296,7 @@ def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
|
||||
def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;
|
||||
def FourByteMultiChar : DiagGroup<"four-char-constants">;
|
||||
def GlobalConstructors : DiagGroup<"global-constructors">;
|
||||
def BitwiseConditionalParentheses: DiagGroup<"bitwise-conditional-parentheses">;
|
||||
def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">;
|
||||
def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
|
||||
def LogicalNotParentheses: DiagGroup<"logical-not-parentheses">;
|
||||
@ -286,9 +305,11 @@ def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
|
||||
def DanglingElse: DiagGroup<"dangling-else">;
|
||||
def DanglingField : DiagGroup<"dangling-field">;
|
||||
def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
|
||||
def DanglingGsl : DiagGroup<"dangling-gsl">;
|
||||
def ReturnStackAddress : DiagGroup<"return-stack-address">;
|
||||
def Dangling : DiagGroup<"dangling", [DanglingField,
|
||||
DanglingInitializerList,
|
||||
DanglingGsl,
|
||||
ReturnStackAddress]>;
|
||||
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
|
||||
def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
|
||||
@ -481,6 +502,7 @@ def StringCompare : DiagGroup<"string-compare">;
|
||||
def StringPlusInt : DiagGroup<"string-plus-int">;
|
||||
def StringPlusChar : DiagGroup<"string-plus-char">;
|
||||
def StrncatSize : DiagGroup<"strncat-size">;
|
||||
def IntInBoolContext : DiagGroup<"int-in-bool-context">;
|
||||
def TautologicalTypeLimitCompare : DiagGroup<"tautological-type-limit-compare">;
|
||||
def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">;
|
||||
def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">;
|
||||
@ -495,12 +517,14 @@ def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare",
|
||||
[TautologicalOutOfRangeCompare]>;
|
||||
def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">;
|
||||
def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">;
|
||||
def TautologicalBitwiseCompare : DiagGroup<"tautological-bitwise-compare">;
|
||||
def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">;
|
||||
def TautologicalObjCBoolCompare : DiagGroup<"tautological-objc-bool-compare">;
|
||||
def TautologicalCompare : DiagGroup<"tautological-compare",
|
||||
[TautologicalConstantCompare,
|
||||
TautologicalPointerCompare,
|
||||
TautologicalOverlapCompare,
|
||||
TautologicalBitwiseCompare,
|
||||
TautologicalUndefinedCompare,
|
||||
TautologicalObjCBoolCompare]>;
|
||||
def HeaderHygiene : DiagGroup<"header-hygiene">;
|
||||
@ -509,6 +533,7 @@ def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
|
||||
def GNUUnionCast : DiagGroup<"gnu-union-cast">;
|
||||
def GNUVariableSizedTypeNotAtEnd : DiagGroup<"gnu-variable-sized-type-not-at-end">;
|
||||
def Varargs : DiagGroup<"varargs">;
|
||||
def XorUsedAsPow : DiagGroup<"xor-used-as-pow">;
|
||||
|
||||
def Unsequenced : DiagGroup<"unsequenced">;
|
||||
// GCC name for -Wunsequenced
|
||||
@ -543,6 +568,7 @@ def CoveredSwitchDefault : DiagGroup<"covered-switch-default">;
|
||||
def SwitchBool : DiagGroup<"switch-bool">;
|
||||
def SwitchEnum : DiagGroup<"switch-enum">;
|
||||
def Switch : DiagGroup<"switch">;
|
||||
def EnumCompareConditional : DiagGroup<"enum-compare-conditional">;
|
||||
def EnumCompareSwitch : DiagGroup<"enum-compare-switch">;
|
||||
def EnumCompare : DiagGroup<"enum-compare", [EnumCompareSwitch]>;
|
||||
def ImplicitFallthroughPerFunction :
|
||||
@ -620,7 +646,9 @@ def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">;
|
||||
def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
|
||||
def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
|
||||
def UserDefinedWarnings : DiagGroup<"user-defined-warnings">;
|
||||
def Reorder : DiagGroup<"reorder">;
|
||||
def ReorderCtor : DiagGroup<"reorder-ctor">;
|
||||
def ReorderInitList : DiagGroup<"reorder-init-list">;
|
||||
def Reorder : DiagGroup<"reorder", [ReorderCtor, ReorderInitList]>;
|
||||
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
|
||||
def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">;
|
||||
def CustomAtomic : DiagGroup<"custom-atomic-properties">;
|
||||
@ -710,6 +738,7 @@ def ParenthesesOnEquality : DiagGroup<"parentheses-equality">;
|
||||
def Parentheses : DiagGroup<"parentheses",
|
||||
[LogicalOpParentheses,
|
||||
LogicalNotParentheses,
|
||||
BitwiseConditionalParentheses,
|
||||
BitwiseOpParentheses,
|
||||
ShiftOpParentheses,
|
||||
OverloadedShiftOpParentheses,
|
||||
@ -757,6 +786,7 @@ def FormatSecurity : DiagGroup<"format-security">;
|
||||
def FormatNonStandard : DiagGroup<"format-non-iso">;
|
||||
def FormatY2K : DiagGroup<"format-y2k">;
|
||||
def FormatPedantic : DiagGroup<"format-pedantic">;
|
||||
def FormatTypeConfusion : DiagGroup<"format-type-confusion">;
|
||||
def Format : DiagGroup<"format",
|
||||
[FormatExtraArgs, FormatZeroLength, NonNull,
|
||||
FormatSecurity, FormatY2K, FormatInvalidSpecifier]>,
|
||||
@ -800,6 +830,7 @@ def Most : DiagGroup<"most", [
|
||||
Format,
|
||||
Implicit,
|
||||
InfiniteRecursion,
|
||||
IntInBoolContext,
|
||||
MismatchedTags,
|
||||
MissingBraces,
|
||||
Move,
|
||||
@ -890,7 +921,7 @@ def CXX17 : DiagGroup<"c++17-extensions">;
|
||||
|
||||
// A warning group for warnings about using C++2a features as extensions in
|
||||
// earlier C++ versions.
|
||||
def CXX2a : DiagGroup<"c++2a-extensions">;
|
||||
def CXX2a : DiagGroup<"c++2a-extensions", [CXX2aDesignator]>;
|
||||
|
||||
def : DiagGroup<"c++0x-extensions", [CXX11]>;
|
||||
def : DiagGroup<"c++1y-extensions", [CXX14]>;
|
||||
@ -903,7 +934,7 @@ def DelegatingCtorCycles :
|
||||
def C11 : DiagGroup<"c11-extensions">;
|
||||
|
||||
// A warning group for warnings about using C99 features as extensions.
|
||||
def C99 : DiagGroup<"c99-extensions">;
|
||||
def C99 : DiagGroup<"c99-extensions", [C99Designator]>;
|
||||
|
||||
// A warning group for warnings about GCC extensions.
|
||||
def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
|
||||
@ -1001,6 +1032,12 @@ def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
|
||||
ObjCStringComparison
|
||||
]>;
|
||||
|
||||
def ObjCSignedCharBool : DiagGroup<"objc-signed-char-bool",
|
||||
[ObjCSignedCharBoolImplicitIntConversion,
|
||||
ObjCSignedCharBoolImplicitFloatConversion,
|
||||
ObjCBoolConstantConversion,
|
||||
TautologicalObjCBoolCompare]>;
|
||||
|
||||
// Inline ASM warnings.
|
||||
def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
|
||||
def ASMIgnoredQualifier : DiagGroup<"asm-ignored-qualifier">;
|
||||
@ -1028,6 +1065,7 @@ def BackendOptimizationFailure : DiagGroup<"pass-failed">;
|
||||
def ProfileInstrMissing : DiagGroup<"profile-instr-missing">;
|
||||
def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
|
||||
def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">;
|
||||
def MisExpect : DiagGroup<"misexpect">;
|
||||
|
||||
// AddressSanitizer frontend instrumentation remarks.
|
||||
def SanitizeAddressRemarks : DiagGroup<"sanitize-address">;
|
||||
|
@ -49,6 +49,7 @@ DIAGOPT(Pedantic, 1, 0) /// -pedantic
|
||||
DIAGOPT(PedanticErrors, 1, 0) /// -pedantic-errors
|
||||
DIAGOPT(ShowColumn, 1, 1) /// Show column number on diagnostics.
|
||||
DIAGOPT(ShowLocation, 1, 1) /// Show source location information.
|
||||
DIAGOPT(ShowLevel, 1, 1) /// Show diagnostic level.
|
||||
DIAGOPT(AbsolutePath, 1, 0) /// Use absolute paths.
|
||||
DIAGOPT(ShowCarets, 1, 1) /// Show carets in diagnostics.
|
||||
DIAGOPT(ShowFixits, 1, 1) /// Show fixit information.
|
||||
|
@ -119,18 +119,16 @@ def warn_microsoft_qualifiers_ignored : Warning<
|
||||
"qualifiers after comma in declarator list are ignored">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
|
||||
def ext_c11_generic_selection : Extension<
|
||||
"generic selections are a C11-specific feature">, InGroup<C11>;
|
||||
def err_duplicate_default_assoc : Error<
|
||||
"duplicate default generic association">;
|
||||
def note_previous_default_assoc : Note<
|
||||
"previous default generic association is here">;
|
||||
|
||||
def ext_c11_alignment : Extension<
|
||||
"%0 is a C11-specific feature">, InGroup<C11>;
|
||||
def ext_c99_feature : Extension<
|
||||
"'%0' is a C99 extension">, InGroup<C99>;
|
||||
def ext_c11_feature : Extension<
|
||||
"'%0' is a C11 extension">, InGroup<C11>;
|
||||
|
||||
def ext_c11_noreturn : Extension<
|
||||
"_Noreturn functions are a C11-specific feature">, InGroup<C11>;
|
||||
def err_c11_noreturn_misplaced : Error<
|
||||
"'_Noreturn' keyword must precede function declarator">;
|
||||
|
||||
@ -203,6 +201,7 @@ def err_invalid_token_after_declarator_suggest_equal : Error<
|
||||
"invalid %0 at end of declaration; did you mean '='?">;
|
||||
def err_expected_statement : Error<"expected statement">;
|
||||
def err_expected_lparen_after : Error<"expected '(' after '%0'">;
|
||||
def err_expected_lbrace_after : Error<"expected '{' after '%0'">;
|
||||
def err_expected_rparen_after : Error<"expected ')' after '%0'">;
|
||||
def err_expected_punc : Error<"expected ')' or ',' after '%0'">;
|
||||
def err_expected_less_after : Error<"expected '<' after '%0'">;
|
||||
@ -360,7 +359,8 @@ def err_typename_invalid_storageclass : Error<
|
||||
def err_typename_invalid_functionspec : Error<
|
||||
"type name does not allow function specifier to be specified">;
|
||||
def err_typename_invalid_constexpr : Error<
|
||||
"type name does not allow %select{constexpr|consteval}0 specifier to be specified">;
|
||||
"type name does not allow %sub{select_constexpr_spec_kind}0 specifier "
|
||||
"to be specified">;
|
||||
def err_typename_identifiers_only : Error<
|
||||
"typename is allowed for identifiers only">;
|
||||
|
||||
@ -374,8 +374,6 @@ def err_unexpected_token_in_nested_name_spec : Error<
|
||||
"'%0' cannot be a part of nested name specifier; did you mean ':'?">;
|
||||
def err_bool_redeclaration : Error<
|
||||
"redeclaration of C++ built-in type 'bool'">;
|
||||
def ext_c11_static_assert : Extension<
|
||||
"_Static_assert is a C11-specific feature">, InGroup<C11>;
|
||||
def warn_cxx98_compat_static_assert : Warning<
|
||||
"static_assert declarations are incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
@ -436,8 +434,6 @@ def err_objc_property_requires_field_name : Error<
|
||||
"property requires fields to be named">;
|
||||
def err_objc_property_bitfield : Error<"property name cannot be a bit-field">;
|
||||
def err_objc_expected_property_attr : Error<"unknown property attribute %0">;
|
||||
def err_objc_properties_require_objc2 : Error<
|
||||
"properties are an Objective-C 2 feature">;
|
||||
def err_objc_unexpected_attr : Error<
|
||||
"prefix attribute must be followed by an interface, protocol, or implementation">;
|
||||
def err_objc_postfix_attribute : Error <
|
||||
@ -976,11 +972,13 @@ def warn_pragma_missing_argument : Warning<
|
||||
def warn_pragma_invalid_argument : Warning<
|
||||
"unexpected argument '%0' to '#pragma %1'%select{|; expected %3}2">, InGroup<IgnoredPragmas>;
|
||||
|
||||
def err_pragma_misplaced_in_decl : Error<"this pragma cannot appear in %0 declaration">;
|
||||
|
||||
// '#pragma clang section' related errors
|
||||
def err_pragma_expected_clang_section_name : Error<
|
||||
"expected one of [bss|data|rodata|text] section kind in '#pragma %0'">;
|
||||
"expected one of [bss|data|rodata|text|relro] section kind in '#pragma %0'">;
|
||||
def err_pragma_clang_section_expected_equal : Error<
|
||||
"expected '=' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
|
||||
"expected '=' following '#pragma clang section %select{invalid|bss|data|rodata|text|relro}0'">;
|
||||
def warn_pragma_expected_section_name : Warning<
|
||||
"expected a string literal for the section name in '#pragma %0' - ignored">,
|
||||
InGroup<IgnoredPragmas>;
|
||||
@ -1180,8 +1178,8 @@ def err_omp_expected_identifier_for_critical : Error<
|
||||
"expected identifier specifying the name of the 'omp critical' directive">;
|
||||
def err_omp_expected_reduction_identifier : Error<
|
||||
"expected identifier or one of the following operators: '+', '-', '*', '&', '|', '^', '&&', or '||'">;
|
||||
def err_omp_decl_in_declare_simd : Error<
|
||||
"function declaration is expected after 'declare simd' directive">;
|
||||
def err_omp_decl_in_declare_simd_variant : Error<
|
||||
"function declaration is expected after 'declare %select{simd|variant}0' 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<
|
||||
@ -1195,13 +1193,36 @@ def err_omp_declare_simd_inbranch_notinbranch : Error<
|
||||
def err_expected_end_declare_target : Error<
|
||||
"expected '#pragma omp end declare target'">;
|
||||
def err_omp_declare_target_unexpected_clause: Error<
|
||||
"unexpected '%0' clause, only 'to' or 'link' clauses expected">;
|
||||
"unexpected '%0' clause, only %select{'to' or 'link'|'to', 'link' or 'device_type'}1 clauses expected">;
|
||||
def err_omp_expected_clause: Error<
|
||||
"expected at least one clause on '#pragma omp %0' directive">;
|
||||
def err_omp_mapper_illegal_identifier : Error<
|
||||
"illegal OpenMP user-defined mapper identifier">;
|
||||
def err_omp_mapper_expected_declarator : Error<
|
||||
"expected declarator on 'omp declare mapper' directive">;
|
||||
def err_omp_declare_variant_wrong_clause : Error<
|
||||
"expected '%0' clause on 'omp declare variant' directive">;
|
||||
def err_omp_declare_variant_no_ctx_selector : Error<
|
||||
"expected context selector in '%0' clause on 'omp declare variant' directive">;
|
||||
def err_omp_declare_variant_equal_expected : Error<
|
||||
"expected '=' after '%0' context selector set name on 'omp declare variant' directive">;
|
||||
def warn_omp_declare_variant_cs_name_expected : Warning<
|
||||
"unknown context selector in '%0' context selector set of 'omp declare variant' directive, ignored">,
|
||||
InGroup<OpenMPClauses>;
|
||||
def err_omp_declare_variant_item_expected : Error<
|
||||
"expected %0 in '%1' context selector of '%2' selector set of 'omp declare variant' directive">;
|
||||
def err_omp_declare_variant_ctx_set_mutiple_use : Error<
|
||||
"context selector set '%0' is used already in the same 'omp declare variant' directive">;
|
||||
def note_omp_declare_variant_ctx_set_used_here : Note<
|
||||
"previously context selector set '%0' used here">;
|
||||
def err_omp_expected_comma_brace : Error<"expected '}' or ',' after '%0'">;
|
||||
def err_omp_declare_variant_ctx_mutiple_use : Error<
|
||||
"context trait selector '%0' is used already in the same '%1' context selector set of 'omp declare variant' directive">;
|
||||
def note_omp_declare_variant_ctx_used_here : Note<
|
||||
"previously context trait selector '%0' used here">;
|
||||
def warn_omp_more_one_device_type_clause : Warning<
|
||||
"more than one 'device_type' clause is specified">,
|
||||
InGroup<OpenMPClauses>;
|
||||
|
||||
// Pragma loop support.
|
||||
def err_pragma_loop_missing_argument : Error<
|
||||
@ -1210,7 +1231,7 @@ def err_pragma_loop_missing_argument : Error<
|
||||
def err_pragma_loop_invalid_option : Error<
|
||||
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
|
||||
"vectorize_width, interleave, interleave_count, unroll, unroll_count, "
|
||||
"pipeline, pipeline_initiation_interval, or distribute">;
|
||||
"pipeline, pipeline_initiation_interval, vectorize_predicate, or distribute">;
|
||||
|
||||
def err_pragma_fp_invalid_option : Error<
|
||||
"%select{invalid|missing}0 option%select{ %1|}0; expected contract">;
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
let Component = "Sema" in {
|
||||
let CategoryName = "Semantic Issue" in {
|
||||
|
||||
def note_previous_decl : Note<"%0 declared here">;
|
||||
def note_entity_declared_at : Note<"%0 declared here">;
|
||||
def note_callee_decl : Note<"%0 declared here">;
|
||||
@ -155,7 +154,7 @@ def err_variably_modified_new_type : Error<
|
||||
|
||||
// C99 Designated Initializers
|
||||
def ext_designated_init : Extension<
|
||||
"designated initializers are a C99 feature">, InGroup<C99>;
|
||||
"designated initializers are a C99 feature">, InGroup<C99Designator>;
|
||||
def err_array_designator_negative : Error<
|
||||
"array designator value '%0' is negative">;
|
||||
def err_array_designator_empty_range : Error<
|
||||
@ -174,15 +173,17 @@ def err_field_designator_nonfield : Error<
|
||||
def note_field_designator_found : Note<"field designator refers here">;
|
||||
def err_designator_for_scalar_init : Error<
|
||||
"designator in initializer for scalar type %0">;
|
||||
def warn_subobject_initializer_overrides : Warning<
|
||||
"subobject initialization overrides initialization of other fields "
|
||||
"within its enclosing subobject">, InGroup<InitializerOverrides>;
|
||||
def warn_initializer_overrides : Warning<
|
||||
"initializer overrides prior initialization of this subobject">,
|
||||
InGroup<InitializerOverrides>;
|
||||
"initializer %select{partially |}0overrides prior initialization of "
|
||||
"this subobject">, InGroup<InitializerOverrides>;
|
||||
def ext_initializer_overrides : ExtWarn<warn_initializer_overrides.Text>,
|
||||
InGroup<InitializerOverrides>, SFINAEFailure;
|
||||
def err_initializer_overrides_destructed : Error<
|
||||
"initializer would partially override prior initialization of object of "
|
||||
"type %1 with non-trivial destruction">;
|
||||
def note_previous_initializer : Note<
|
||||
"previous initialization %select{|with side effects }0is here"
|
||||
"%select{| (side effects may not occur at run time)}0">;
|
||||
"%select{| (side effects will not occur at run time)}0">;
|
||||
def err_designator_into_flexible_array_member : Error<
|
||||
"designator into flexible array member subobject">;
|
||||
def note_flexible_array_member : Note<
|
||||
@ -190,6 +191,28 @@ def note_flexible_array_member : Note<
|
||||
def ext_flexible_array_init : Extension<
|
||||
"flexible array initialization is a GNU extension">, InGroup<GNUFlexibleArrayInitializer>;
|
||||
|
||||
// C++20 designated initializers
|
||||
def ext_cxx_designated_init : Extension<
|
||||
"designated initializers are a C++20 extension">, InGroup<CXX2aDesignator>;
|
||||
def warn_cxx17_compat_designated_init : Warning<
|
||||
"designated initializers are incompatible with C++ standards before C++20">,
|
||||
InGroup<CXXPre2aCompatPedantic>, DefaultIgnore;
|
||||
def ext_designated_init_mixed : ExtWarn<
|
||||
"mixture of designated and non-designated initializers in the same "
|
||||
"initializer list is a C99 extension">, InGroup<C99Designator>;
|
||||
def note_designated_init_mixed : Note<
|
||||
"first non-designated initializer is here">;
|
||||
def ext_designated_init_array : ExtWarn<
|
||||
"array designators are a C99 extension">, InGroup<C99Designator>;
|
||||
def ext_designated_init_nested : ExtWarn<
|
||||
"nested designators are a C99 extension">, InGroup<C99Designator>;
|
||||
def ext_designated_init_reordered : ExtWarn<
|
||||
"ISO C++ requires field designators to be specified in declaration order; "
|
||||
"field %1 will be initialized after field %0">, InGroup<ReorderInitList>,
|
||||
SFINAEFailure;
|
||||
def note_previous_field_init : Note<
|
||||
"previous initialization for field %0 is here">;
|
||||
|
||||
// Declarations.
|
||||
def ext_plain_complex : ExtWarn<
|
||||
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
|
||||
@ -598,6 +621,10 @@ def ext_implicit_lib_function_decl : ExtWarn<
|
||||
def note_include_header_or_declare : Note<
|
||||
"include the header <%0> or explicitly provide a declaration for '%1'">;
|
||||
def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">;
|
||||
def warn_implicit_decl_no_jmp_buf
|
||||
: Warning<"declaration of built-in function '%0' requires the declaration"
|
||||
" of the 'jmp_buf' type, commonly provided in the header <setjmp.h>.">,
|
||||
InGroup<DiagGroup<"incomplete-setjmp-declaration">>;
|
||||
def warn_implicit_decl_requires_sysheader : Warning<
|
||||
"declaration of built-in function '%1' requires inclusion of the header <%0>">,
|
||||
InGroup<BuiltinRequiresHeader>;
|
||||
@ -2212,6 +2239,11 @@ def err_class_marked_final_used_as_base : Error<
|
||||
"base %0 is marked '%select{final|sealed}1'">;
|
||||
def warn_abstract_final_class : Warning<
|
||||
"abstract class is marked '%select{final|sealed}0'">, InGroup<AbstractFinalClass>;
|
||||
def warn_final_dtor_non_final_class : Warning<
|
||||
"class with destructor marked '%select{final|sealed}0' cannot be inherited from">,
|
||||
InGroup<FinalDtorNonFinalClass>;
|
||||
def note_final_dtor_non_final_class_silence : Note<
|
||||
"mark %0 as '%select{final|sealed}1' to silence this warning">;
|
||||
|
||||
// C++11 attributes
|
||||
def err_repeat_attribute : Error<"%0 attribute cannot be repeated">;
|
||||
@ -2326,18 +2358,24 @@ def warn_cxx14_compat_constexpr_not_const : Warning<
|
||||
"in C++14; add 'const' to avoid a change in behavior">,
|
||||
InGroup<DiagGroup<"constexpr-not-const">>;
|
||||
def err_invalid_constexpr : Error<
|
||||
"%select{function parameter|typedef|non-static data member}0 "
|
||||
"cannot be %select{constexpr|consteval}1">;
|
||||
"%select{function parameter|typedef}0 "
|
||||
"cannot be %sub{select_constexpr_spec_kind}1">;
|
||||
def err_invalid_constexpr_member : Error<"non-static data member cannot be "
|
||||
"constexpr%select{; did you intend to make it %select{const|static}0?|}1">;
|
||||
def err_constexpr_tag : Error<
|
||||
"%select{class|struct|interface|union|enum}0 "
|
||||
"cannot be marked %select{constexpr|consteval}1">;
|
||||
"cannot be marked %sub{select_constexpr_spec_kind}1">;
|
||||
def err_constexpr_dtor : Error<
|
||||
"destructor cannot be marked %select{constexpr|consteval}0">;
|
||||
"destructor cannot be declared %sub{select_constexpr_spec_kind}0">;
|
||||
def err_constexpr_dtor_subobject : Error<
|
||||
"destructor cannot be declared %sub{select_constexpr_spec_kind}0 because "
|
||||
"%select{data member %2|base class %3}1 does not have a "
|
||||
"constexpr destructor">;
|
||||
def note_constexpr_dtor_subobject : Note<
|
||||
"%select{data member %1|base class %2}0 declared here">;
|
||||
def err_constexpr_wrong_decl_kind : Error<
|
||||
"%select{constexpr|consteval}0 can only be used "
|
||||
"in %select{variable and |}0function declarations">;
|
||||
"%sub{select_constexpr_spec_kind}0 can only be used "
|
||||
"in %select{|variable and function|function|variable}0 declarations">;
|
||||
def err_invalid_constexpr_var_decl : Error<
|
||||
"constexpr variable declaration must be a definition">;
|
||||
def err_constexpr_static_mem_var_requires_init : Error<
|
||||
@ -2346,6 +2384,8 @@ def err_constexpr_var_non_literal : Error<
|
||||
"constexpr variable cannot have non-literal type %0">;
|
||||
def err_constexpr_var_requires_const_init : Error<
|
||||
"constexpr variable %0 must be initialized by a constant expression">;
|
||||
def err_constexpr_var_requires_const_destruction : Error<
|
||||
"constexpr variable %0 must have constant destruction">;
|
||||
def err_constexpr_redecl_mismatch : Error<
|
||||
"%select{non-constexpr|constexpr|consteval}1 declaration of %0"
|
||||
" follows %select{non-constexpr|constexpr|consteval}2 declaration">;
|
||||
@ -2406,9 +2446,13 @@ def err_constexpr_local_var_static : Error<
|
||||
def err_constexpr_local_var_non_literal_type : Error<
|
||||
"variable of non-literal type %1 cannot be defined in a constexpr "
|
||||
"%select{function|constructor}0">;
|
||||
def err_constexpr_local_var_no_init : Error<
|
||||
"variables defined in a constexpr %select{function|constructor}0 must be "
|
||||
"initialized">;
|
||||
def ext_constexpr_local_var_no_init : ExtWarn<
|
||||
"uninitialized variable in a constexpr %select{function|constructor}0 "
|
||||
"is a C++20 extension">, InGroup<CXX2a>;
|
||||
def warn_cxx17_compat_constexpr_local_var_no_init : Warning<
|
||||
"uninitialized variable in a constexpr %select{function|constructor}0 "
|
||||
"is incompatible with C++ standards before C++20">,
|
||||
InGroup<CXXPre2aCompat>, DefaultIgnore;
|
||||
def ext_constexpr_function_never_constant_expr : ExtWarn<
|
||||
"constexpr %select{function|constructor}0 never produces a "
|
||||
"constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
|
||||
@ -2433,10 +2477,8 @@ def warn_cxx11_compat_constexpr_body_multiple_return : Warning<
|
||||
InGroup<CXXPre14Compat>, DefaultIgnore;
|
||||
def note_constexpr_body_previous_return : Note<
|
||||
"previous return statement is here">;
|
||||
def err_constexpr_function_try_block : Error<
|
||||
"function try block not allowed in constexpr %select{function|constructor}0">;
|
||||
|
||||
// c++2a function try blocks in constexpr
|
||||
// C++2a function try blocks in constexpr
|
||||
def ext_constexpr_function_try_block_cxx2a : ExtWarn<
|
||||
"function try block in constexpr %select{function|constructor}0 is "
|
||||
"a C++2a extension">, InGroup<CXX2a>;
|
||||
@ -2445,10 +2487,20 @@ def warn_cxx17_compat_constexpr_function_try_block : Warning<
|
||||
"incompatible with C++ standards before C++2a">,
|
||||
InGroup<CXXPre2aCompat>, DefaultIgnore;
|
||||
|
||||
def err_constexpr_union_ctor_no_init : Error<
|
||||
"constexpr union constructor does not initialize any member">;
|
||||
def err_constexpr_ctor_missing_init : Error<
|
||||
"constexpr constructor must initialize all members">;
|
||||
def ext_constexpr_union_ctor_no_init : ExtWarn<
|
||||
"constexpr union constructor that does not initialize any member "
|
||||
"is a C++20 extension">, InGroup<CXX2a>;
|
||||
def warn_cxx17_compat_constexpr_union_ctor_no_init : Warning<
|
||||
"constexpr union constructor that does not initialize any member "
|
||||
"is incompatible with C++ standards before C++20">,
|
||||
InGroup<CXXPre2aCompat>, DefaultIgnore;
|
||||
def ext_constexpr_ctor_missing_init : ExtWarn<
|
||||
"constexpr constructor that does not initialize all members "
|
||||
"is a C++20 extension">, InGroup<CXX2a>;
|
||||
def warn_cxx17_compat_constexpr_ctor_missing_init : Warning<
|
||||
"constexpr constructor that does not initialize all members "
|
||||
"is incompatible with C++ standards before C++20">,
|
||||
InGroup<CXXPre2aCompat>, DefaultIgnore;
|
||||
def note_constexpr_ctor_missing_init : Note<
|
||||
"member not initialized by constructor">;
|
||||
def note_non_literal_no_constexpr_ctors : Note<
|
||||
@ -2463,6 +2515,8 @@ def note_non_literal_user_provided_dtor : Note<
|
||||
"%0 is not literal because it has a user-provided destructor">;
|
||||
def note_non_literal_nontrivial_dtor : Note<
|
||||
"%0 is not literal because it has a non-trivial destructor">;
|
||||
def note_non_literal_non_constexpr_dtor : Note<
|
||||
"%0 is not literal because its destructor is not constexpr">;
|
||||
def note_non_literal_lambda : Note<
|
||||
"lambda closure types are non-literal types before C++17">;
|
||||
def warn_private_extern : Warning<
|
||||
@ -2472,8 +2526,6 @@ def note_private_extern : Note<
|
||||
"use __attribute__((visibility(\"hidden\"))) attribute instead">;
|
||||
|
||||
// C++ Concepts
|
||||
def err_concept_initialized_with_non_bool_type : Error<
|
||||
"constraint expression must be of type 'bool' but is of type %0">;
|
||||
def err_concept_decls_may_only_appear_in_global_namespace_scope : Error<
|
||||
"concept declarations may only appear in global or namespace scope">;
|
||||
def err_concept_no_parameters : Error<
|
||||
@ -2485,9 +2537,14 @@ def err_concept_no_associated_constraints : Error<
|
||||
"concept cannot have associated constraints">;
|
||||
def err_concept_not_implemented : Error<
|
||||
"sorry, unimplemented concepts feature %0 used">;
|
||||
def err_non_constant_constraint_expression : Error<
|
||||
"substitution into constraint expression resulted in a non-constant "
|
||||
"expression">;
|
||||
def err_non_bool_atomic_constraint : Error<
|
||||
"atomic constraint must be of type 'bool' (found %0)">;
|
||||
|
||||
def err_template_different_associated_constraints : Error<
|
||||
"associated constraints differ in template redeclaration">;
|
||||
def err_template_different_requires_clause : Error<
|
||||
"requires clause differs in template redeclaration">;
|
||||
|
||||
// C++11 char16_t/char32_t
|
||||
def warn_cxx98_compat_unicode_type : Warning<
|
||||
@ -2519,6 +2576,9 @@ def err_nsobject_attribute : Error<
|
||||
"'NSObject' attribute is for pointer types only">;
|
||||
def err_attributes_are_not_compatible : Error<
|
||||
"%0 and %1 attributes are not compatible">;
|
||||
def err_attribute_invalid_argument : Error<
|
||||
"%select{'void'|a reference type|an array type|a non-vector or "
|
||||
"non-vectorizable scalar type}0 is an invalid argument to attribute %1">;
|
||||
def err_attribute_wrong_number_arguments : Error<
|
||||
"%0 attribute %plural{0:takes no arguments|1:takes one argument|"
|
||||
":requires exactly %1 arguments}1">;
|
||||
@ -2567,8 +2627,6 @@ def err_attribute_argument_out_of_range : Error<
|
||||
def err_init_priority_object_attr : Error<
|
||||
"can only use 'init_priority' attribute on file-scope definitions "
|
||||
"of objects of class type">;
|
||||
def err_attribute_argument_vec_type_hint : Error<
|
||||
"invalid attribute argument %0 - expecting a vector or vectorizable scalar type">;
|
||||
def err_attribute_argument_out_of_bounds : Error<
|
||||
"%0 attribute parameter %1 is out of bounds">;
|
||||
def err_attribute_only_once_per_parameter : Error<
|
||||
@ -2778,6 +2836,11 @@ def err_no_accessor_for_property : Error<
|
||||
def err_cannot_find_suitable_accessor : Error<
|
||||
"cannot find suitable %select{getter|setter}0 for property %1">;
|
||||
|
||||
def warn_alloca : Warning<
|
||||
"use of function %0 is discouraged; there is no way to check for failure but "
|
||||
"failure may still occur, resulting in a possibly exploitable security vulnerability">,
|
||||
InGroup<DiagGroup<"alloca">>, DefaultIgnore;
|
||||
|
||||
def warn_alloca_align_alignof : Warning<
|
||||
"second argument to __builtin_alloca_with_align is supposed to be in bits">,
|
||||
InGroup<DiagGroup<"alloca-with-align-alignof">>;
|
||||
@ -2793,6 +2856,10 @@ def err_alignment_dependent_typedef_name : Error<
|
||||
|
||||
def err_attribute_aligned_too_great : Error<
|
||||
"requested alignment must be %0 bytes or smaller">;
|
||||
def warn_assume_aligned_too_great
|
||||
: Warning<"requested alignment must be %0 bytes or smaller; maximum "
|
||||
"alignment assumed">,
|
||||
InGroup<DiagGroup<"builtin-assume-aligned-alignment">>;
|
||||
def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
|
||||
"%q0 redeclared without %1 attribute: previous %1 ignored">,
|
||||
InGroup<MicrosoftInconsistentDllImport>;
|
||||
@ -2950,6 +3017,10 @@ def warn_gnu_inline_attribute_requires_inline : Warning<
|
||||
"'gnu_inline' attribute requires function to be marked 'inline',"
|
||||
" attribute ignored">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
def warn_gnu_inline_cplusplus_without_extern : Warning<
|
||||
"'gnu_inline' attribute without 'extern' in C++ treated as externally"
|
||||
" available, this changed in Clang 10">,
|
||||
InGroup<DiagGroup<"gnu-inline-cpp-without-extern">>;
|
||||
def err_attribute_vecreturn_only_vector_member : Error<
|
||||
"the vecreturn attribute can only be used on a class or structure with one member, which must be a vector">;
|
||||
def err_attribute_vecreturn_only_pod_record : Error<
|
||||
@ -2966,6 +3037,7 @@ def warn_cconv_unsupported : Warning<
|
||||
"|on builtin function"
|
||||
"}1">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
def error_cconv_unsupported : Error<warn_cconv_unsupported.Text>;
|
||||
def err_cconv_knr : Error<
|
||||
"function with no prototype cannot use the %0 calling convention">;
|
||||
def warn_cconv_knr : Warning<
|
||||
@ -3251,9 +3323,9 @@ def warn_impcast_integer_precision_constant : Warning<
|
||||
def warn_impcast_bitfield_precision_constant : Warning<
|
||||
"implicit truncation from %2 to bit-field changes value from %0 to %1">,
|
||||
InGroup<BitFieldConstantConversion>;
|
||||
def warn_impcast_constant_int_to_objc_bool : Warning<
|
||||
"implicit conversion from constant value %0 to BOOL; "
|
||||
"the only well defined values for BOOL are YES and NO">,
|
||||
def warn_impcast_constant_value_to_objc_bool : Warning<
|
||||
"implicit conversion from constant value %0 to 'BOOL'; "
|
||||
"the only well defined values for 'BOOL' are YES and NO">,
|
||||
InGroup<ObjCBoolConstantConversion>;
|
||||
|
||||
def warn_impcast_fixed_point_range : Warning<
|
||||
@ -3269,6 +3341,20 @@ def warn_impcast_literal_float_to_integer_out_of_range : Warning<
|
||||
def warn_impcast_float_integer : Warning<
|
||||
"implicit conversion turns floating-point number into integer: %0 to %1">,
|
||||
InGroup<FloatConversion>, DefaultIgnore;
|
||||
def warn_impcast_float_to_objc_signed_char_bool : Warning<
|
||||
"implicit conversion from floating-point type %0 to 'BOOL'">,
|
||||
InGroup<ObjCSignedCharBoolImplicitFloatConversion>;
|
||||
def warn_impcast_int_to_objc_signed_char_bool : Warning<
|
||||
"implicit conversion from integral type %0 to 'BOOL'">,
|
||||
InGroup<ObjCSignedCharBoolImplicitIntConversion>, DefaultIgnore;
|
||||
|
||||
// Implicit int -> float conversion precision loss warnings.
|
||||
def warn_impcast_integer_float_precision : Warning<
|
||||
"implicit conversion from %0 to %1 may lose precision">,
|
||||
InGroup<ImplicitIntFloatConversion>, DefaultIgnore;
|
||||
def warn_impcast_integer_float_precision_constant : Warning<
|
||||
"implicit conversion from %2 to %3 changes value from %0 to %1">,
|
||||
InGroup<ImplicitIntFloatConversion>;
|
||||
|
||||
def warn_impcast_float_to_integer : Warning<
|
||||
"implicit conversion from %0 to %1 changes value from %2 to %3">,
|
||||
@ -3292,6 +3378,10 @@ def warn_impcast_bool_to_null_pointer : Warning<
|
||||
def warn_non_literal_null_pointer : Warning<
|
||||
"expression which evaluates to zero treated as a null pointer constant of "
|
||||
"type %0">, InGroup<NonLiteralNullConversion>;
|
||||
def warn_pointer_compare : Warning<
|
||||
"comparing a pointer to a null character constant; did you mean "
|
||||
"to compare to %select{NULL|(void *)0}0?">,
|
||||
InGroup<DiagGroup<"pointer-compare">>;
|
||||
def warn_impcast_null_pointer_to_integer : Warning<
|
||||
"implicit conversion of %select{NULL|nullptr}0 constant to %1">,
|
||||
InGroup<NullConversion>;
|
||||
@ -3318,6 +3408,18 @@ def warn_address_of_reference_bool_conversion : Warning<
|
||||
"code; pointer may be assumed to always convert to true">,
|
||||
InGroup<UndefinedBoolConversion>;
|
||||
|
||||
def warn_xor_used_as_pow : Warning<
|
||||
"result of '%0' is %1; did you mean exponentiation?">,
|
||||
InGroup<XorUsedAsPow>;
|
||||
def warn_xor_used_as_pow_base_extra : Warning<
|
||||
"result of '%0' is %1; did you mean '%2' (%3)?">,
|
||||
InGroup<XorUsedAsPow>;
|
||||
def warn_xor_used_as_pow_base : Warning<
|
||||
"result of '%0' is %1; did you mean '%2'?">,
|
||||
InGroup<XorUsedAsPow>;
|
||||
def note_xor_used_as_pow_silence : Note<
|
||||
"replace expression with '%0' %select{|or use 'xor' instead of '^' }1to silence this warning">;
|
||||
|
||||
def warn_null_pointer_compare : Warning<
|
||||
"comparison of %select{address of|function|array}0 '%1' %select{not |}2"
|
||||
"equal to a null pointer is always %select{true|false}2">,
|
||||
@ -3338,9 +3440,15 @@ def warn_address_of_reference_null_compare : Warning<
|
||||
InGroup<TautologicalUndefinedCompare>;
|
||||
def note_reference_is_return_value : Note<"%0 returns a reference">;
|
||||
|
||||
def note_pointer_declared_here : Note<
|
||||
"pointer %0 declared here">;
|
||||
def warn_division_sizeof_ptr : Warning<
|
||||
"'%0' will return the size of the pointer, not the array itself">,
|
||||
InGroup<DiagGroup<"sizeof-pointer-div">>;
|
||||
def warn_division_sizeof_array : Warning<
|
||||
"expression does not compute the number of elements in this array; element "
|
||||
"type is %0, not %1">,
|
||||
InGroup<DiagGroup<"sizeof-array-div">>;
|
||||
|
||||
def note_function_warning_silence : Note<
|
||||
"prefix with the address-of operator to silence this warning">;
|
||||
@ -3661,7 +3769,8 @@ def note_ovl_too_many_candidates : Note<
|
||||
"pass -fshow-overloads=all to show them">;
|
||||
|
||||
def select_ovl_candidate_kind : TextSubstitution<
|
||||
"%select{function|function|constructor|"
|
||||
"%select{function|function|function (with reversed parameter order)|"
|
||||
"constructor|"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
@ -3855,10 +3964,7 @@ def note_implicit_member_target_infer_collision : Note<
|
||||
|
||||
def note_ambiguous_type_conversion: Note<
|
||||
"because of ambiguity in conversion %diff{of $ to $|between types}0,1">;
|
||||
def note_ovl_builtin_binary_candidate : Note<
|
||||
"built-in candidate %0">;
|
||||
def note_ovl_builtin_unary_candidate : Note<
|
||||
"built-in candidate %0">;
|
||||
def note_ovl_builtin_candidate : Note<"built-in candidate %0">;
|
||||
def err_ovl_no_viable_function_in_init : Error<
|
||||
"no matching constructor for initialization of %0">;
|
||||
def err_ovl_no_conversion_in_cast : Error<
|
||||
@ -3885,6 +3991,13 @@ def err_ovl_ambiguous_oper_unary : Error<
|
||||
"use of overloaded operator '%0' is ambiguous (operand type %1)">;
|
||||
def err_ovl_ambiguous_oper_binary : Error<
|
||||
"use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">;
|
||||
def ext_ovl_ambiguous_oper_binary_reversed : ExtWarn<
|
||||
"ISO C++20 considers use of overloaded operator '%0' (with operand types %1 "
|
||||
"and %2) to be ambiguous despite there being a unique best viable function">,
|
||||
InGroup<DiagGroup<"ambiguous-reversed-operator">>, SFINAEFailure;
|
||||
def note_ovl_ambiguous_oper_binary_reversed_candidate : Note<
|
||||
"ambiguity is between a regular call to this operator and a call with the "
|
||||
"argument order reversed">;
|
||||
def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">;
|
||||
def note_assign_lhs_incomplete : Note<"type %0 is incomplete">;
|
||||
def err_ovl_deleted_oper : Error<
|
||||
@ -3892,6 +4005,9 @@ def err_ovl_deleted_oper : Error<
|
||||
def err_ovl_deleted_special_oper : Error<
|
||||
"object of type %0 cannot be %select{constructed|copied|moved|assigned|"
|
||||
"assigned|destroyed}1 because its %sub{select_special_member_kind}1 is implicitly deleted">;
|
||||
def err_ovl_rewrite_equalequal_not_bool : Error<
|
||||
"return type %0 of selected 'operator==' function for rewritten "
|
||||
"'%1' comparison is not 'bool'">;
|
||||
def err_ovl_no_viable_subscript :
|
||||
Error<"no viable overloaded operator[] for type %0">;
|
||||
def err_ovl_no_oper :
|
||||
@ -3934,6 +4050,8 @@ def err_ovl_no_viable_literal_operator : Error<
|
||||
// C++ Template Declarations
|
||||
def err_template_param_shadow : Error<
|
||||
"declaration of %0 shadows template parameter">;
|
||||
def ext_template_param_shadow : ExtWarn<
|
||||
err_template_param_shadow.Text>, InGroup<MicrosoftTemplate>;
|
||||
def note_template_param_here : Note<"template parameter is declared here">;
|
||||
def warn_template_export_unsupported : Warning<
|
||||
"exported templates are unsupported">;
|
||||
@ -4392,6 +4510,10 @@ def note_prior_template_arg_substitution : Note<
|
||||
" template parameter%1 %2">;
|
||||
def note_template_default_arg_checking : Note<
|
||||
"while checking a default template argument used here">;
|
||||
def note_concept_specialization_here : Note<
|
||||
"while checking the satisfaction of concept '%0' requested here">;
|
||||
def note_constraint_substitution_here : Note<
|
||||
"while substituting template arguments into constraint expression here">;
|
||||
def note_instantiation_contexts_suppressed : Note<
|
||||
"(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to "
|
||||
"see all)">;
|
||||
@ -5334,9 +5456,6 @@ def err_arc_mismatched_cast : Error<
|
||||
" to %3 is disallowed with ARC">;
|
||||
def err_arc_nolifetime_behavior : Error<
|
||||
"explicit ownership qualifier on cast result has no effect">;
|
||||
def err_arc_objc_object_in_tag : Error<
|
||||
"ARC forbids %select{Objective-C objects|blocks}0 in "
|
||||
"%select{struct|interface|union|<<ERROR>>|enum}1">;
|
||||
def err_arc_objc_property_default_assign_on_object : Error<
|
||||
"ARC forbids synthesizing a property of an Objective-C object "
|
||||
"with unspecified ownership or storage attribute">;
|
||||
@ -5626,9 +5745,18 @@ def note_precedence_silence : Note<
|
||||
def warn_precedence_conditional : Warning<
|
||||
"operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">,
|
||||
InGroup<Parentheses>;
|
||||
def warn_precedence_bitwise_conditional : Warning<
|
||||
"operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">,
|
||||
InGroup<BitwiseConditionalParentheses>;
|
||||
def note_precedence_conditional_first : Note<
|
||||
"place parentheses around the '?:' expression to evaluate it first">;
|
||||
|
||||
def warn_enum_constant_in_bool_context : Warning<
|
||||
"converting the enum constant to a boolean">,
|
||||
InGroup<IntInBoolContext>, DefaultIgnore;
|
||||
def warn_left_shift_in_bool_context : Warning<
|
||||
"converting the result of '<<' to a boolean; did you mean '(%0) != 0'?">,
|
||||
InGroup<IntInBoolContext>, DefaultIgnore;
|
||||
def warn_logical_instead_of_bitwise : Warning<
|
||||
"use of logical '%0' with constant operand">,
|
||||
InGroup<DiagGroup<"constant-logical-operand">>;
|
||||
@ -5638,10 +5766,10 @@ def note_logical_instead_of_bitwise_remove_constant : Note<
|
||||
"remove constant to silence this warning">;
|
||||
|
||||
def warn_bitwise_op_in_bitwise_op : Warning<
|
||||
"'%0' within '%1'">, InGroup<BitwiseOpParentheses>;
|
||||
"'%0' within '%1'">, InGroup<BitwiseOpParentheses>, DefaultIgnore;
|
||||
|
||||
def warn_logical_and_in_logical_or : Warning<
|
||||
"'&&' within '||'">, InGroup<LogicalOpParentheses>;
|
||||
"'&&' within '||'">, InGroup<LogicalOpParentheses>, DefaultIgnore;
|
||||
|
||||
def warn_overloaded_shift_in_comparison :Warning<
|
||||
"overloaded operator %select{>>|<<}0 has higher precedence than "
|
||||
@ -5718,6 +5846,9 @@ def err_arithmetic_nonfragile_interface : Error<
|
||||
"arithmetic on pointer to interface %0, which is not a constant size for "
|
||||
"this architecture and platform">;
|
||||
|
||||
def warn_deprecated_comma_subscript : Warning<
|
||||
"top-level comma expression in array subscript is deprecated">,
|
||||
InGroup<DeprecatedCommaSubscript>;
|
||||
|
||||
def ext_subscript_non_lvalue : Extension<
|
||||
"ISO C90 does not allow subscripting non-lvalue array">;
|
||||
@ -6038,8 +6169,8 @@ def warn_tautological_constant_compare : Warning<
|
||||
"%select{%1|%3}0 is always %4">,
|
||||
InGroup<TautologicalTypeLimitCompare>, DefaultIgnore;
|
||||
def warn_tautological_compare_objc_bool : Warning<
|
||||
"result of comparison of constant %0 with expression of type BOOL"
|
||||
" is always %1, as the only well defined values for BOOL are YES and NO">,
|
||||
"result of comparison of constant %0 with expression of type 'BOOL'"
|
||||
" is always %1, as the only well defined values for 'BOOL' are YES and NO">,
|
||||
InGroup<TautologicalObjCBoolCompare>;
|
||||
|
||||
def warn_mixed_sign_comparison : Warning<
|
||||
@ -6051,10 +6182,22 @@ def warn_out_of_range_compare : Warning<
|
||||
InGroup<TautologicalOutOfRangeCompare>;
|
||||
def warn_tautological_bool_compare : Warning<warn_out_of_range_compare.Text>,
|
||||
InGroup<TautologicalConstantCompare>;
|
||||
def warn_integer_constants_in_conditional_always_true : Warning<
|
||||
"converting the result of '?:' with integer constants to a boolean always "
|
||||
"evaluates to 'true'">,
|
||||
InGroup<TautologicalConstantCompare>;
|
||||
def warn_left_shift_always : Warning<
|
||||
"converting the result of '<<' to a boolean always evaluates "
|
||||
"to %select{false|true}0">,
|
||||
InGroup<TautologicalConstantCompare>;
|
||||
def warn_comparison_of_mixed_enum_types : Warning<
|
||||
"comparison of two values with different enumeration types"
|
||||
"%diff{ ($ and $)|}0,1">,
|
||||
InGroup<EnumCompare>;
|
||||
def warn_conditional_mixed_enum_types : Warning<
|
||||
"enumeration type mismatch in conditional expression"
|
||||
"%diff{ ($ and $)|}0,1">,
|
||||
InGroup<EnumCompareConditional>, DefaultIgnore;
|
||||
def warn_comparison_of_mixed_enum_types_switch : Warning<
|
||||
"comparison of two values with different enumeration types in switch statement"
|
||||
"%diff{ ($ and $)|}0,1">,
|
||||
@ -6093,6 +6236,8 @@ def err_invalid_qualified_function_type : Error<
|
||||
def err_compound_qualified_function_type : Error<
|
||||
"%select{block pointer|pointer|reference}0 to function type %select{%2 |}1"
|
||||
"cannot have '%3' qualifier">;
|
||||
def err_qualified_function_typeid : Error<
|
||||
"type operand %0 of 'typeid' cannot have '%1' qualifier">;
|
||||
|
||||
def err_ref_qualifier_overload : Error<
|
||||
"cannot overload a member function %select{without a ref-qualifier|with "
|
||||
@ -6517,6 +6662,10 @@ def note_member_declared_here : Note<
|
||||
"member %0 declared here">;
|
||||
def note_member_first_declared_here : Note<
|
||||
"member %0 first declared here">;
|
||||
def warn_bitwise_negation_bool : Warning<
|
||||
"bitwise negation of a boolean expression%select{;| always evaluates to 'true';}0 "
|
||||
"did you mean logical negation?">,
|
||||
InGroup<DiagGroup<"bool-operation">>;
|
||||
def err_decrement_bool : Error<"cannot decrement expression of type bool">;
|
||||
def warn_increment_bool : Warning<
|
||||
"incrementing expression of type bool is deprecated and "
|
||||
@ -6526,6 +6675,26 @@ def ext_increment_bool : ExtWarn<
|
||||
DefaultError, InGroup<IncrementBool>;
|
||||
def err_increment_decrement_enum : Error<
|
||||
"cannot %select{decrement|increment}0 expression of enum type %1">;
|
||||
|
||||
def warn_deprecated_increment_decrement_volatile : Warning<
|
||||
"%select{decrement|increment}0 of object of volatile-qualified type %1 "
|
||||
"is deprecated">, InGroup<DeprecatedVolatile>;
|
||||
def warn_deprecated_simple_assign_volatile : Warning<
|
||||
"use of result of assignment to object of volatile-qualified type %0 "
|
||||
"is deprecated">, InGroup<DeprecatedVolatile>;
|
||||
def warn_deprecated_compound_assign_volatile : Warning<
|
||||
"compound assignment to object of volatile-qualified type %0 is deprecated">,
|
||||
InGroup<DeprecatedVolatile>;
|
||||
def warn_deprecated_volatile_return : Warning<
|
||||
"volatile-qualified return type %0 is deprecated">,
|
||||
InGroup<DeprecatedVolatile>;
|
||||
def warn_deprecated_volatile_param : Warning<
|
||||
"volatile-qualified parameter type %0 is deprecated">,
|
||||
InGroup<DeprecatedVolatile>;
|
||||
def warn_deprecated_volatile_structured_binding : Warning<
|
||||
"volatile qualifier in structured binding declaration is deprecated">,
|
||||
InGroup<DeprecatedVolatile>;
|
||||
|
||||
def err_catch_incomplete_ptr : Error<
|
||||
"cannot catch pointer to incomplete type %0">;
|
||||
def err_catch_incomplete_ref : Error<
|
||||
@ -7426,6 +7595,12 @@ def warn_unused_container_subscript_expr : Warning<
|
||||
def warn_unused_call : Warning<
|
||||
"ignoring return value of function declared with %0 attribute">,
|
||||
InGroup<UnusedValue>;
|
||||
def warn_unused_constructor : Warning<
|
||||
"ignoring temporary created by a constructor declared with %0 attribute">,
|
||||
InGroup<UnusedValue>;
|
||||
def warn_unused_constructor_msg : Warning<
|
||||
"ignoring temporary created by a constructor declared with %0 attribute: %1">,
|
||||
InGroup<UnusedValue>;
|
||||
def warn_side_effects_unevaluated_context : Warning<
|
||||
"expression with side effects has no effect in an unevaluated context">,
|
||||
InGroup<UnevaluatedExpression>;
|
||||
@ -7435,6 +7610,9 @@ def warn_side_effects_typeid : Warning<
|
||||
def warn_unused_result : Warning<
|
||||
"ignoring return value of function declared with %0 attribute">,
|
||||
InGroup<UnusedResult>;
|
||||
def warn_unused_result_msg : Warning<
|
||||
"ignoring return value of function declared with %0 attribute: %1">,
|
||||
InGroup<UnusedResult>;
|
||||
def warn_unused_volatile : Warning<
|
||||
"expression result unused; assign into a variable to force a volatile load">,
|
||||
InGroup<DiagGroup<"unused-volatile-lvalue">>;
|
||||
@ -7443,6 +7621,8 @@ def ext_cxx14_attr : Extension<
|
||||
"use of the %0 attribute is a C++14 extension">, InGroup<CXX14>;
|
||||
def ext_cxx17_attr : Extension<
|
||||
"use of the %0 attribute is a C++17 extension">, InGroup<CXX17>;
|
||||
def ext_cxx2a_attr : Extension<
|
||||
"use of the %0 attribute is a C++2a extension">, InGroup<CXX2a>;
|
||||
|
||||
def warn_unused_comparison : Warning<
|
||||
"%select{equality|inequality|relational|three-way}0 comparison result unused">,
|
||||
@ -7453,10 +7633,30 @@ def note_inequality_comparison_to_or_assign : Note<
|
||||
def err_incomplete_type_used_in_type_trait_expr : Error<
|
||||
"incomplete type %0 used in type trait expression">;
|
||||
|
||||
// C++20 constinit and require_constant_initialization attribute
|
||||
def warn_cxx20_compat_constinit : Warning<
|
||||
"'constinit' specifier is incompatible with C++ standards before C++20">,
|
||||
InGroup<CXX2aCompat>, DefaultIgnore;
|
||||
def err_constinit_local_variable : Error<
|
||||
"local variable cannot be declared 'constinit'">;
|
||||
def err_require_constant_init_failed : Error<
|
||||
"variable does not have a constant initializer">;
|
||||
def note_declared_required_constant_init_here : Note<
|
||||
"required by 'require_constant_initialization' attribute here">;
|
||||
"required by %select{'require_constant_initialization' attribute|"
|
||||
"'constinit' specifier}0 here">;
|
||||
def ext_constinit_missing : ExtWarn<
|
||||
"'constinit' specifier missing on initializing declaration of %0">,
|
||||
InGroup<DiagGroup<"missing-constinit">>;
|
||||
def note_constinit_specified_here : Note<"variable declared constinit here">;
|
||||
def err_constinit_added_too_late : Error<
|
||||
"'constinit' specifier added after initialization of variable">;
|
||||
def warn_require_const_init_added_too_late : Warning<
|
||||
"'require_constant_initialization' attribute added after initialization "
|
||||
"of variable">, InGroup<IgnoredAttributes>;
|
||||
def note_constinit_missing_here : Note<
|
||||
"add the "
|
||||
"%select{'require_constant_initialization' attribute|'constinit' specifier}0 "
|
||||
"to the initializing declaration here">;
|
||||
|
||||
def err_dimension_expr_not_constant_integer : Error<
|
||||
"dimension expression does not evaluate to a constant unsigned int">;
|
||||
@ -7493,8 +7693,6 @@ let CategoryName = "Inline Assembly Issue" in {
|
||||
"invalid lvalue in asm input for constraint '%0'">;
|
||||
def err_asm_invalid_input_constraint : Error<
|
||||
"invalid input constraint '%0' in asm">;
|
||||
def err_asm_immediate_expected : Error<"constraint '%0' expects "
|
||||
"an integer constant expression">;
|
||||
def err_asm_tying_incompatible_types : Error<
|
||||
"unsupported inline asm: input with type "
|
||||
"%diff{$ matching output with type $|}0,1">;
|
||||
@ -7583,7 +7781,7 @@ def err_mem_init_not_member_or_class : Error<
|
||||
def warn_initializer_out_of_order : Warning<
|
||||
"%select{field|base class}0 %1 will be initialized after "
|
||||
"%select{field|base}2 %3">,
|
||||
InGroup<Reorder>, DefaultIgnore;
|
||||
InGroup<ReorderCtor>, DefaultIgnore;
|
||||
def warn_abstract_vbase_init_ignored : Warning<
|
||||
"initializer for virtual base class %0 of abstract class %1 "
|
||||
"will never be used">,
|
||||
@ -7919,7 +8117,7 @@ def warn_array_index_precedes_bounds : Warning<
|
||||
def warn_array_index_exceeds_bounds : Warning<
|
||||
"array index %0 is past the end of the array (which contains %1 "
|
||||
"element%s2)">, InGroup<ArrayBounds>;
|
||||
def note_array_index_out_of_bounds : Note<
|
||||
def note_array_declared_here : Note<
|
||||
"array %0 declared here">;
|
||||
|
||||
def warn_printf_insufficient_data_args : Warning<
|
||||
@ -7940,16 +8138,17 @@ def warn_format_conversion_argument_type_mismatch : Warning<
|
||||
"%select{type|underlying type}2 %1">,
|
||||
InGroup<Format>;
|
||||
def warn_format_conversion_argument_type_mismatch_pedantic : Extension<
|
||||
"format specifies type %0 but the argument has "
|
||||
"%select{type|underlying type}2 %1">,
|
||||
warn_format_conversion_argument_type_mismatch.Text>,
|
||||
InGroup<FormatPedantic>;
|
||||
def warn_format_conversion_argument_type_mismatch_confusion : Warning<
|
||||
warn_format_conversion_argument_type_mismatch.Text>,
|
||||
InGroup<FormatTypeConfusion>, DefaultIgnore;
|
||||
def warn_format_argument_needs_cast : Warning<
|
||||
"%select{values of type|enum values with underlying type}2 '%0' should not "
|
||||
"be used as format arguments; add an explicit cast to %1 instead">,
|
||||
InGroup<Format>;
|
||||
def warn_format_argument_needs_cast_pedantic : Warning<
|
||||
"%select{values of type|enum values with underlying type}2 '%0' should not "
|
||||
"be used as format arguments; add an explicit cast to %1 instead">,
|
||||
warn_format_argument_needs_cast.Text>,
|
||||
InGroup<FormatPedantic>, DefaultIgnore;
|
||||
def warn_printf_positional_arg_exceeds_data_args : Warning <
|
||||
"data argument position '%0' exceeds the number of data arguments (%1)">,
|
||||
@ -8023,6 +8222,9 @@ def warn_printf_invalid_objc_flag: Warning<
|
||||
def warn_scanf_scanlist_incomplete : Warning<
|
||||
"no closing ']' for '%%[' in scanf format string">,
|
||||
InGroup<Format>;
|
||||
def warn_format_bool_as_character : Warning<
|
||||
"using '%0' format specifier, but argument has boolean value">,
|
||||
InGroup<Format>;
|
||||
def note_format_string_defined : Note<"format string is defined here">;
|
||||
def note_format_fix_specifier : Note<"did you mean to use '%0'?">;
|
||||
def note_printf_c_str: Note<"did you mean to call the %0 method?">;
|
||||
@ -8085,6 +8287,10 @@ def warn_dangling_member : Warning<
|
||||
"%select{binds to|is}2 a temporary object "
|
||||
"whose lifetime is shorter than the lifetime of the constructed object">,
|
||||
InGroup<DanglingField>;
|
||||
def warn_dangling_lifetime_pointer_member : Warning<
|
||||
"initializing pointer member %0 to point to a temporary object "
|
||||
"whose lifetime is shorter than the lifetime of the constructed object">,
|
||||
InGroup<DanglingGsl>;
|
||||
def note_lifetime_extending_member_declared_here : Note<
|
||||
"%select{%select{reference|'std::initializer_list'}0 member|"
|
||||
"member with %select{reference|'std::initializer_list'}0 subobject}1 "
|
||||
@ -8103,6 +8309,10 @@ def warn_new_dangling_reference : Warning<
|
||||
"temporary bound to reference member of allocated object "
|
||||
"will be destroyed at the end of the full-expression">,
|
||||
InGroup<DanglingField>;
|
||||
def warn_dangling_lifetime_pointer : Warning<
|
||||
"object backing the pointer "
|
||||
"will be destroyed at the end of the full-expression">,
|
||||
InGroup<DanglingGsl>;
|
||||
def warn_new_dangling_initializer_list : Warning<
|
||||
"array backing "
|
||||
"%select{initializer list subobject of the allocated object|"
|
||||
@ -8120,11 +8330,15 @@ def warn_unsupported_lifetime_extension : Warning<
|
||||
// should result in a warning, since these always evaluate to a constant.
|
||||
// Array comparisons have similar warnings
|
||||
def warn_comparison_always : Warning<
|
||||
"%select{self-|array }0comparison always evaluates to %select{a constant|%2}1">,
|
||||
"%select{self-|array }0comparison always evaluates to "
|
||||
"%select{a constant|true|false|'std::strong_ordering::equal'}1">,
|
||||
InGroup<TautologicalCompare>;
|
||||
def warn_comparison_bitwise_always : Warning<
|
||||
"bitwise comparison always evaluates to %select{false|true}0">,
|
||||
InGroup<TautologicalCompare>;
|
||||
InGroup<TautologicalBitwiseCompare>, DefaultIgnore;
|
||||
def warn_comparison_bitwise_or : Warning<
|
||||
"bitwise or with non-zero value always evaluates to true">,
|
||||
InGroup<TautologicalBitwiseCompare>, DefaultIgnore;
|
||||
def warn_tautological_overlap_comparison : Warning<
|
||||
"overlapping comparisons always evaluate to %select{false|true}0">,
|
||||
InGroup<TautologicalOverlapCompare>, DefaultIgnore;
|
||||
@ -8503,10 +8717,11 @@ def warn_sync_fetch_and_nand_semantics_change : Warning<
|
||||
InGroup<DiagGroup<"sync-fetch-and-nand-semantics-changed">>;
|
||||
|
||||
// Type
|
||||
def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">;
|
||||
def ext_wchar_t_sign_spec : ExtWarn<"'%0' cannot be signed or unsigned">,
|
||||
InGroup<DiagGroup<"signed-unsigned-wchar">>, DefaultError;
|
||||
def warn_receiver_forward_class : Warning<
|
||||
"receiver %0 is a forward class and corresponding @interface may not exist">,
|
||||
InGroup<ForwardClassReceiver>;
|
||||
"receiver %0 is a forward class and corresponding @interface may not exist">,
|
||||
InGroup<ForwardClassReceiver>;
|
||||
def note_method_sent_forward_class : Note<"method %0 is used for the forward class">;
|
||||
def ext_missing_declspec : ExtWarn<
|
||||
"declaration specifier missing, defaulting to 'int'">;
|
||||
@ -8984,7 +9199,7 @@ def ext_omp_loop_not_canonical_init : ExtWarn<
|
||||
"('var = init' or 'T var = init')">, InGroup<OpenMPLoopForm>;
|
||||
def err_omp_loop_not_canonical_cond : Error<
|
||||
"condition of OpenMP for loop must be a relational comparison "
|
||||
"('<', '<=', '>', or '>=') of loop variable %0">;
|
||||
"('<', '<=', '>', %select{or '>='|'>=', or '!='}0) of loop variable %1">;
|
||||
def err_omp_loop_not_canonical_incr : Error<
|
||||
"increment clause of OpenMP for loop must perform simple addition "
|
||||
"or subtraction on loop variable %0">;
|
||||
@ -9101,10 +9316,10 @@ def err_omp_single_copyprivate_with_nowait : Error<
|
||||
"the 'copyprivate' clause must not be used with the 'nowait' clause">;
|
||||
def note_omp_nowait_clause_here : Note<
|
||||
"'nowait' clause is here">;
|
||||
def err_omp_single_decl_in_declare_simd : Error<
|
||||
"single declaration is expected after 'declare simd' directive">;
|
||||
def err_omp_single_decl_in_declare_simd_variant : Error<
|
||||
"single declaration is expected after 'declare %select{simd|variant}0' directive">;
|
||||
def err_omp_function_expected : Error<
|
||||
"'#pragma omp declare simd' can only be applied to functions">;
|
||||
"'#pragma omp declare %select{simd|variant}0' can only be applied to functions">;
|
||||
def err_omp_wrong_cancel_region : Error<
|
||||
"one of 'for', 'parallel', 'sections' or 'taskgroup' is expected">;
|
||||
def err_omp_parent_cancel_region_nowait : Error<
|
||||
@ -9286,6 +9501,44 @@ def err_omp_wrong_dependency_iterator_type : Error<
|
||||
"expected an integer or a pointer type of the outer loop counter '%0' for non-rectangular nests">;
|
||||
def err_omp_unsupported_type : Error <
|
||||
"host requires %0 bit size %1 type support, but device '%2' does not support it">;
|
||||
def err_omp_lambda_capture_in_declare_target_not_to : Error<
|
||||
"variable captured in declare target region must appear in a to clause">;
|
||||
def err_omp_device_type_mismatch : Error<
|
||||
"'device_type(%0)' does not match previously specified 'device_type(%1)' for the same declaration">;
|
||||
def err_omp_wrong_device_function_call : Error<
|
||||
"function with 'device_type(%0)' is not available on %select{device|host}1">;
|
||||
def note_omp_marked_device_type_here : Note<"marked as 'device_type(%0)' here">;
|
||||
def warn_omp_declare_target_after_first_use : Warning<
|
||||
"declaration marked as declare target after first use, it may lead to incorrect results">,
|
||||
InGroup<OpenMPTarget>;
|
||||
def err_omp_declare_variant_incompat_attributes : Error<
|
||||
"'#pragma omp declare variant' is not compatible with any target-specific attributes">;
|
||||
def warn_omp_declare_variant_after_used : Warning<
|
||||
"'#pragma omp declare variant' cannot be applied for function after first "
|
||||
"usage; the original function might be used">, InGroup<SourceUsesOpenMP>;
|
||||
def warn_omp_declare_variant_after_emitted : Warning<
|
||||
"'#pragma omp declare variant' cannot be applied to the function that was defined already;"
|
||||
" the original function might be used">, InGroup<SourceUsesOpenMP>;
|
||||
def err_omp_declare_variant_noproto : Error<
|
||||
"function with '#pragma omp declare variant' must have a prototype">;
|
||||
def note_omp_declare_variant_specified_here : Note<
|
||||
"'#pragma omp declare variant' for function specified here">;
|
||||
def err_omp_declare_variant_doesnt_support : Error<
|
||||
"'#pragma omp declare variant' does not "
|
||||
"support %select{function templates|virtual functions|"
|
||||
"deduced return types|constructors|destructors|deleted functions|"
|
||||
"defaulted functions|constexpr functions|consteval function}0">;
|
||||
def err_omp_declare_variant_diff : Error<
|
||||
"function with '#pragma omp declare variant' has a different %select{calling convention"
|
||||
"|return type|constexpr specification|inline specification|storage class|"
|
||||
"linkage}0">;
|
||||
def err_omp_declare_variant_incompat_types : Error<
|
||||
"variant in '#pragma omp declare variant' with type %0 is incompatible with type %1"
|
||||
>;
|
||||
def warn_omp_declare_variant_marked_as_declare_variant : Warning<
|
||||
"variant function in '#pragma omp declare variant' is itself marked as '#pragma omp declare variant'"
|
||||
>, InGroup<SourceUsesOpenMP>;
|
||||
def note_omp_marked_declare_variant_here : Note<"marked as 'declare variant' here">;
|
||||
} // end of OpenMP category
|
||||
|
||||
let CategoryName = "Related Result Type Issue" in {
|
||||
@ -9725,6 +9978,8 @@ def err_std_compare_type_not_supported : Error<
|
||||
"member '%2' is missing|"
|
||||
"the type is not trivially copyable|"
|
||||
"the type does not have the expected form}1">;
|
||||
def note_rewriting_operator_as_spaceship : Note<
|
||||
"while rewriting comparison as call to 'operator<=>' declared here">;
|
||||
|
||||
// Memory Tagging Extensions (MTE) diagnostics
|
||||
def err_memtag_arg_null_or_pointer : Error<
|
||||
@ -9735,8 +9990,6 @@ def err_memtag_arg_must_be_pointer : Error<
|
||||
"%0 argument of MTE builtin function must be a pointer (%1 invalid)">;
|
||||
def err_memtag_arg_must_be_integer : Error<
|
||||
"%0 argument of MTE builtin function must be an integer type (%1 invalid)">;
|
||||
def err_memtag_arg_must_be_unsigned : Error<
|
||||
"%0 argument of MTE builtin function must be an unsigned integer type (%1 invalid)">;
|
||||
|
||||
def warn_dereference_of_noderef_type : Warning<
|
||||
"dereferencing %0; was declared with a 'noderef' type">, InGroup<NoDeref>;
|
||||
@ -9751,6 +10004,11 @@ def err_builtin_launder_invalid_arg : Error<
|
||||
"%select{non-pointer|function pointer|void pointer}0 argument to "
|
||||
"'__builtin_launder' is not allowed">;
|
||||
|
||||
def err_preserve_field_info_not_field : Error<
|
||||
"__builtin_preserve_field_info argument %0 not a field access">;
|
||||
def err_preserve_field_info_not_const: Error<
|
||||
"__builtin_preserve_field_info argument %0 not a constant">;
|
||||
|
||||
def err_bit_cast_non_trivially_copyable : Error<
|
||||
"__builtin_bit_cast %select{source|destination}0 type must be trivially copyable">;
|
||||
def err_bit_cast_type_size_mismatch : Error<
|
||||
|
@ -18,13 +18,16 @@ def err_fe_pch_malformed : Error<
|
||||
def err_fe_pch_malformed_block : Error<
|
||||
"malformed block record in PCH file: '%0'">, DefaultFatal;
|
||||
def err_fe_pch_file_modified : Error<
|
||||
"file '%0' has been modified since the precompiled header '%1' was built">,
|
||||
"file '%0' has been modified since the precompiled header '%1' was built"
|
||||
": %select{size|mtime|content}2 changed">,
|
||||
DefaultFatal;
|
||||
def err_fe_module_file_modified : Error<
|
||||
"file '%0' has been modified since the module file '%1' was built">,
|
||||
"file '%0' has been modified since the module file '%1' was built"
|
||||
": %select{size|mtime|content}2 changed">,
|
||||
DefaultFatal;
|
||||
def err_fe_ast_file_modified : Error<
|
||||
"file '%0' has been modified since the AST file '%1' was built">,
|
||||
"file '%0' has been modified since the AST file '%1' was built"
|
||||
": %select{size|mtime|content}2 changed">,
|
||||
DefaultFatal;
|
||||
def err_fe_pch_file_overridden : Error<
|
||||
"file '%0' from the precompiled header has been overridden">;
|
||||
@ -77,13 +80,13 @@ def remark_module_import : Remark<
|
||||
InGroup<ModuleImport>;
|
||||
|
||||
def err_imported_module_not_found : Error<
|
||||
"module '%0' in AST file '%1' (imported by AST file '%2') "
|
||||
"module '%0' in AST file '%1' %select{(imported by AST file '%2') |}4"
|
||||
"is not defined in any loaded module map file; "
|
||||
"maybe you need to load '%3'?">, DefaultFatal;
|
||||
def note_imported_by_pch_module_not_found : Note<
|
||||
"consider adding '%0' to the header search path">;
|
||||
def err_imported_module_modmap_changed : Error<
|
||||
"module '%0' imported by AST file '%1' found in a different module map file"
|
||||
"module '%0' %select{in|imported by}4 AST file '%1' found in a different module map file"
|
||||
" (%2) than when the importing AST file was built (%3)">, DefaultFatal;
|
||||
def err_imported_module_relocated : Error<
|
||||
"module '%0' was built in directory '%1' but now resides in "
|
||||
@ -399,6 +402,8 @@ def warn_module_uses_date_time : Warning<
|
||||
def err_module_no_size_mtime_for_header : Error<
|
||||
"cannot emit module %0: %select{size|mtime}1 must be explicitly specified "
|
||||
"for missing header file \"%2\"">;
|
||||
def err_module_unable_to_hash_content : Error<
|
||||
"failed to hash content for '%0' because memory buffer cannot be retrieved">;
|
||||
} // let CategoryName
|
||||
} // let Component
|
||||
|
||||
|
@ -39,6 +39,8 @@
|
||||
FEATURE(address_sanitizer,
|
||||
LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
|
||||
SanitizerKind::KernelAddress))
|
||||
FEATURE(leak_sanitizer,
|
||||
LangOpts.Sanitize.has(SanitizerKind::Leak))
|
||||
FEATURE(hwaddress_sanitizer,
|
||||
LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress |
|
||||
SanitizerKind::KernelHWAddress))
|
||||
@ -187,7 +189,7 @@ FEATURE(cxx_variable_templates, LangOpts.CPlusPlus14)
|
||||
// FEATURE(raw_invocation_type, LangOpts.CPlusPlus)
|
||||
// Type traits
|
||||
// N.B. Additional type traits should not be added to the following list.
|
||||
// Instead, they should be detected by has_extension.
|
||||
// Instead, they should be detected by has_builtin.
|
||||
FEATURE(has_nothrow_assign, LangOpts.CPlusPlus)
|
||||
FEATURE(has_nothrow_copy, LangOpts.CPlusPlus)
|
||||
FEATURE(has_nothrow_constructor, LangOpts.CPlusPlus)
|
||||
|
@ -45,12 +45,31 @@ class FileSystemStatCache;
|
||||
class DirectoryEntry {
|
||||
friend class FileManager;
|
||||
|
||||
// FIXME: We should not be storing a directory entry name here.
|
||||
StringRef Name; // Name of the directory.
|
||||
|
||||
public:
|
||||
StringRef getName() const { return Name; }
|
||||
};
|
||||
|
||||
/// A reference to a \c DirectoryEntry that includes the name of the directory
|
||||
/// as it was accessed by the FileManager's client.
|
||||
class DirectoryEntryRef {
|
||||
public:
|
||||
const DirectoryEntry &getDirEntry() const { return *Entry->getValue(); }
|
||||
|
||||
StringRef getName() const { return Entry->getKey(); }
|
||||
|
||||
private:
|
||||
friend class FileManager;
|
||||
|
||||
DirectoryEntryRef(
|
||||
llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>> *Entry)
|
||||
: Entry(Entry) {}
|
||||
|
||||
const llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>> *Entry;
|
||||
};
|
||||
|
||||
/// Cached information about one file (either on disk
|
||||
/// or in the virtual file system).
|
||||
///
|
||||
@ -64,8 +83,8 @@ class FileEntry {
|
||||
off_t Size; // File size in bytes.
|
||||
time_t ModTime; // Modification time of file.
|
||||
const DirectoryEntry *Dir; // Directory file lives in.
|
||||
unsigned UID; // A unique (small) ID for the file.
|
||||
llvm::sys::fs::UniqueID UniqueID;
|
||||
unsigned UID; // A unique (small) ID for the file.
|
||||
bool IsNamedPipe;
|
||||
bool IsValid; // Is this \c FileEntry initialized and valid?
|
||||
|
||||
@ -106,6 +125,42 @@ class FileEntry {
|
||||
bool isOpenForTests() const { return File != nullptr; }
|
||||
};
|
||||
|
||||
/// A reference to a \c FileEntry that includes the name of the file as it was
|
||||
/// accessed by the FileManager's client.
|
||||
class FileEntryRef {
|
||||
public:
|
||||
FileEntryRef() = delete;
|
||||
FileEntryRef(StringRef Name, const FileEntry &Entry)
|
||||
: Name(Name), Entry(&Entry) {}
|
||||
|
||||
const StringRef getName() const { return Name; }
|
||||
|
||||
bool isValid() const { return Entry->isValid(); }
|
||||
|
||||
const FileEntry &getFileEntry() const { return *Entry; }
|
||||
|
||||
off_t getSize() const { return Entry->getSize(); }
|
||||
|
||||
unsigned getUID() const { return Entry->getUID(); }
|
||||
|
||||
const llvm::sys::fs::UniqueID &getUniqueID() const {
|
||||
return Entry->getUniqueID();
|
||||
}
|
||||
|
||||
time_t getModificationTime() const { return Entry->getModificationTime(); }
|
||||
|
||||
friend bool operator==(const FileEntryRef &LHS, const FileEntryRef &RHS) {
|
||||
return LHS.Entry == RHS.Entry && LHS.Name == RHS.Name;
|
||||
}
|
||||
friend bool operator!=(const FileEntryRef &LHS, const FileEntryRef &RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
private:
|
||||
StringRef Name;
|
||||
const FileEntry *Entry;
|
||||
};
|
||||
|
||||
/// Implements support for file system lookup, file system caching,
|
||||
/// and directory search management.
|
||||
///
|
||||
@ -131,21 +186,41 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
/// The virtual files that we have allocated.
|
||||
SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
|
||||
|
||||
/// A set of files that bypass the maps and uniquing. They can have
|
||||
/// conflicting filenames.
|
||||
SmallVector<std::unique_ptr<FileEntry>, 0> BypassFileEntries;
|
||||
|
||||
/// A cache that maps paths to directory entries (either real or
|
||||
/// virtual) we have looked up
|
||||
/// virtual) we have looked up, or an error that occurred when we looked up
|
||||
/// the directory.
|
||||
///
|
||||
/// The actual Entries for real directories/files are
|
||||
/// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
|
||||
/// for virtual directories/files are owned by
|
||||
/// VirtualDirectoryEntries/VirtualFileEntries above.
|
||||
///
|
||||
llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries;
|
||||
llvm::StringMap<llvm::ErrorOr<DirectoryEntry &>, llvm::BumpPtrAllocator>
|
||||
SeenDirEntries;
|
||||
|
||||
/// A reference to the file entry that is associated with a particular
|
||||
/// filename, or a reference to another filename that should be looked up
|
||||
/// instead of the accessed filename.
|
||||
///
|
||||
/// The reference to another filename is specifically useful for Redirecting
|
||||
/// VFSs that use external names. In that case, the \c FileEntryRef returned
|
||||
/// by the \c FileManager will have the external name, and not the name that
|
||||
/// was used to lookup the file.
|
||||
using SeenFileEntryOrRedirect =
|
||||
llvm::PointerUnion<FileEntry *, const StringRef *>;
|
||||
|
||||
/// A cache that maps paths to file entries (either real or
|
||||
/// virtual) we have looked up.
|
||||
/// virtual) we have looked up, or an error that occurred when we looked up
|
||||
/// the file.
|
||||
///
|
||||
/// \see SeenDirEntries
|
||||
llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
|
||||
llvm::StringMap<llvm::ErrorOr<SeenFileEntryOrRedirect>,
|
||||
llvm::BumpPtrAllocator>
|
||||
SeenFileEntries;
|
||||
|
||||
/// The canonical names of directories.
|
||||
llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames;
|
||||
@ -157,15 +232,12 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
///
|
||||
unsigned NextFileUID;
|
||||
|
||||
// Statistics.
|
||||
unsigned NumDirLookups, NumFileLookups;
|
||||
unsigned NumDirCacheMisses, NumFileCacheMisses;
|
||||
|
||||
// Caching.
|
||||
std::unique_ptr<FileSystemStatCache> StatCache;
|
||||
|
||||
bool getStatValue(StringRef Path, llvm::vfs::Status &Status, bool isFile,
|
||||
std::unique_ptr<llvm::vfs::File> *F);
|
||||
std::error_code getStatValue(StringRef Path, llvm::vfs::Status &Status,
|
||||
bool isFile,
|
||||
std::unique_ptr<llvm::vfs::File> *F);
|
||||
|
||||
/// Add all ancestors of the given path (pointing to either a file
|
||||
/// or a directory) as virtual directories.
|
||||
@ -195,27 +267,86 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
/// Removes the FileSystemStatCache object from the manager.
|
||||
void clearStatCache();
|
||||
|
||||
/// Returns the number of unique real file entries cached by the file manager.
|
||||
size_t getNumUniqueRealFiles() const { return UniqueRealFiles.size(); }
|
||||
|
||||
/// Lookup, cache, and verify the specified directory (real or
|
||||
/// virtual).
|
||||
///
|
||||
/// This returns NULL if the directory doesn't exist.
|
||||
/// This returns a \c std::error_code if there was an error reading the
|
||||
/// directory. On success, returns the reference to the directory entry
|
||||
/// together with the exact path that was used to access a file by a
|
||||
/// particular call to getDirectoryRef.
|
||||
///
|
||||
/// \param CacheFailure If true and the file does not exist, we'll cache
|
||||
/// the failure to find this file.
|
||||
const DirectoryEntry *getDirectory(StringRef DirName,
|
||||
bool CacheFailure = true);
|
||||
llvm::Expected<DirectoryEntryRef> getDirectoryRef(StringRef DirName,
|
||||
bool CacheFailure = true);
|
||||
|
||||
/// Get a \c DirectoryEntryRef if it exists, without doing anything on error.
|
||||
llvm::Optional<DirectoryEntryRef>
|
||||
getOptionalDirectoryRef(StringRef DirName, bool CacheFailure = true) {
|
||||
return llvm::expectedToOptional(getDirectoryRef(DirName, CacheFailure));
|
||||
}
|
||||
|
||||
/// Lookup, cache, and verify the specified directory (real or
|
||||
/// virtual).
|
||||
///
|
||||
/// This function is deprecated and will be removed at some point in the
|
||||
/// future, new clients should use
|
||||
/// \c getDirectoryRef.
|
||||
///
|
||||
/// This returns a \c std::error_code if there was an error reading the
|
||||
/// directory. If there is no error, the DirectoryEntry is guaranteed to be
|
||||
/// non-NULL.
|
||||
///
|
||||
/// \param CacheFailure If true and the file does not exist, we'll cache
|
||||
/// the failure to find this file.
|
||||
llvm::ErrorOr<const DirectoryEntry *>
|
||||
getDirectory(StringRef DirName, bool CacheFailure = true);
|
||||
|
||||
/// Lookup, cache, and verify the specified file (real or
|
||||
/// virtual).
|
||||
///
|
||||
/// This returns NULL if the file doesn't exist.
|
||||
/// This function is deprecated and will be removed at some point in the
|
||||
/// future, new clients should use
|
||||
/// \c getFileRef.
|
||||
///
|
||||
/// This returns a \c std::error_code if there was an error loading the file.
|
||||
/// If there is no error, the FileEntry is guaranteed to be non-NULL.
|
||||
///
|
||||
/// \param OpenFile if true and the file exists, it will be opened.
|
||||
///
|
||||
/// \param CacheFailure If true and the file does not exist, we'll cache
|
||||
/// the failure to find this file.
|
||||
const FileEntry *getFile(StringRef Filename, bool OpenFile = false,
|
||||
bool CacheFailure = true);
|
||||
llvm::ErrorOr<const FileEntry *>
|
||||
getFile(StringRef Filename, bool OpenFile = false, bool CacheFailure = true);
|
||||
|
||||
/// Lookup, cache, and verify the specified file (real or virtual). Return the
|
||||
/// reference to the file entry together with the exact path that was used to
|
||||
/// access a file by a particular call to getFileRef. If the underlying VFS is
|
||||
/// a redirecting VFS that uses external file names, the returned FileEntryRef
|
||||
/// will use the external name instead of the filename that was passed to this
|
||||
/// method.
|
||||
///
|
||||
/// This returns a \c std::error_code if there was an error loading the file,
|
||||
/// or a \c FileEntryRef otherwise.
|
||||
///
|
||||
/// \param OpenFile if true and the file exists, it will be opened.
|
||||
///
|
||||
/// \param CacheFailure If true and the file does not exist, we'll cache
|
||||
/// the failure to find this file.
|
||||
llvm::Expected<FileEntryRef> getFileRef(StringRef Filename,
|
||||
bool OpenFile = false,
|
||||
bool CacheFailure = true);
|
||||
|
||||
/// Get a FileEntryRef if it exists, without doing anything on error.
|
||||
llvm::Optional<FileEntryRef> getOptionalFileRef(StringRef Filename,
|
||||
bool OpenFile = false,
|
||||
bool CacheFailure = true) {
|
||||
return llvm::expectedToOptional(
|
||||
getFileRef(Filename, OpenFile, CacheFailure));
|
||||
}
|
||||
|
||||
/// Returns the current file system options
|
||||
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
|
||||
@ -223,6 +354,10 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
|
||||
llvm::vfs::FileSystem &getVirtualFileSystem() const { return *FS; }
|
||||
|
||||
void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
|
||||
this->FS = std::move(FS);
|
||||
}
|
||||
|
||||
/// Retrieve a file entry for a "virtual" file that acts as
|
||||
/// if there were a file with the given name on disk.
|
||||
///
|
||||
@ -230,24 +365,38 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
const FileEntry *getVirtualFile(StringRef Filename, off_t Size,
|
||||
time_t ModificationTime);
|
||||
|
||||
/// Retrieve a FileEntry that bypasses VFE, which is expected to be a virtual
|
||||
/// file entry, to access the real file. The returned FileEntry will have
|
||||
/// the same filename as FE but a different identity and its own stat.
|
||||
///
|
||||
/// This should be used only for rare error recovery paths because it
|
||||
/// bypasses all mapping and uniquing, blindly creating a new FileEntry.
|
||||
/// There is no attempt to deduplicate these; if you bypass the same file
|
||||
/// twice, you get two new file entries.
|
||||
llvm::Optional<FileEntryRef> getBypassFile(FileEntryRef VFE);
|
||||
|
||||
/// Open the specified file as a MemoryBuffer, returning a new
|
||||
/// MemoryBuffer if successful, otherwise returning null.
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
|
||||
getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
|
||||
bool ShouldCloseOpenFile = true);
|
||||
getBufferForFile(const FileEntry *Entry, bool isVolatile = false);
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
|
||||
getBufferForFile(StringRef Filename, bool isVolatile = false);
|
||||
getBufferForFile(StringRef Filename, bool isVolatile = false) {
|
||||
return getBufferForFileImpl(Filename, /*FileSize=*/-1, isVolatile);
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
|
||||
getBufferForFileImpl(StringRef Filename, int64_t FileSize, bool isVolatile);
|
||||
|
||||
public:
|
||||
/// Get the 'stat' information for the given \p Path.
|
||||
///
|
||||
/// If the path is relative, it will be resolved against the WorkingDir of the
|
||||
/// FileManager's FileSystemOptions.
|
||||
///
|
||||
/// \returns false on success, true on error.
|
||||
bool getNoncachedStatValue(StringRef Path, llvm::vfs::Status &Result);
|
||||
|
||||
/// Remove the real file \p Entry from the cache.
|
||||
void invalidateCache(const FileEntry *Entry);
|
||||
/// \returns a \c std::error_code describing an error, if there was one
|
||||
std::error_code getNoncachedStatValue(StringRef Path,
|
||||
llvm::vfs::Status &Result);
|
||||
|
||||
/// If path is not absolute and FileSystemOptions set the working
|
||||
/// directory, the path is modified to be relative to the given
|
||||
@ -265,11 +414,6 @@ class FileManager : public RefCountedBase<FileManager> {
|
||||
void GetUniqueIDMapping(
|
||||
SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
|
||||
|
||||
/// Modifies the size and modification time of a previously created
|
||||
/// FileEntry. Use with caution.
|
||||
static void modifyFileEntry(FileEntry *File, off_t Size,
|
||||
time_t ModificationTime);
|
||||
|
||||
/// Retrieve the canonical name for a given directory.
|
||||
///
|
||||
/// This is a very expensive operation, despite its results being cached,
|
||||
|
@ -750,6 +750,12 @@ class Selector {
|
||||
return getIdentifierInfoFlag() == ZeroArg;
|
||||
}
|
||||
|
||||
/// If this selector is the specific keyword selector described by Names.
|
||||
bool isKeywordSelector(ArrayRef<StringRef> Names) const;
|
||||
|
||||
/// If this selector is the specific unary selector described by Name.
|
||||
bool isUnarySelector(StringRef Name) const;
|
||||
|
||||
unsigned getNumArgs() const;
|
||||
|
||||
/// Retrieve the identifier at a given position in the selector.
|
||||
|
@ -111,6 +111,7 @@ BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers")
|
||||
BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode")
|
||||
LANGOPT(GNUMode , 1, 1, "GNU extensions")
|
||||
LANGOPT(GNUKeywords , 1, 1, "GNU keywords")
|
||||
VALUE_LANGOPT(GNUCVersion , 32, 0, "GNU C compatibility version")
|
||||
BENIGN_LANGOPT(ImplicitInt, 1, !C99 && !CPlusPlus, "C89 implicit 'int'")
|
||||
LANGOPT(Digraphs , 1, 0, "digraphs")
|
||||
BENIGN_LANGOPT(HexFloats , 1, C99, "C99 hexadecimal float constants")
|
||||
@ -119,7 +120,8 @@ LANGOPT(AppleKext , 1, 0, "Apple kext support")
|
||||
BENIGN_LANGOPT(PascalStrings, 1, 0, "Pascal string support")
|
||||
LANGOPT(WritableStrings , 1, 0, "writable string support")
|
||||
LANGOPT(ConstStrings , 1, 0, "const-qualified string support")
|
||||
LANGOPT(LaxVectorConversions , 1, 1, "lax vector conversions")
|
||||
ENUM_LANGOPT(LaxVectorConversions, LaxVectorConversionKind, 2,
|
||||
LaxVectorConversionKind::All, "lax vector conversions")
|
||||
LANGOPT(AltiVec , 1, 0, "AltiVec-style vector initializers")
|
||||
LANGOPT(ZVector , 1, 0, "System z vector extensions")
|
||||
LANGOPT(Exceptions , 1, 0, "exception handling")
|
||||
@ -128,6 +130,7 @@ LANGOPT(CXXExceptions , 1, 0, "C++ exceptions")
|
||||
LANGOPT(DWARFExceptions , 1, 0, "dwarf exception handling")
|
||||
LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling")
|
||||
LANGOPT(SEHExceptions , 1, 0, "SEH .xdata exception handling")
|
||||
LANGOPT(WasmExceptions , 1, 0, "WebAssembly exception handling")
|
||||
LANGOPT(ExternCNoUnwind , 1, 0, "Assume extern C functions don't unwind")
|
||||
LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation")
|
||||
LANGOPT(RTTI , 1, 1, "run-time type information")
|
||||
@ -224,6 +227,8 @@ LANGOPT(GPURelocatableDeviceCode, 1, 0, "generate relocatable device code")
|
||||
|
||||
LANGOPT(SYCLIsDevice , 1, 0, "Generate code for SYCL device")
|
||||
|
||||
LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP")
|
||||
|
||||
LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
|
||||
LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
|
||||
LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are unavailable")
|
||||
@ -288,6 +293,10 @@ BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
|
||||
"maximum constexpr call depth")
|
||||
BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576,
|
||||
"maximum constexpr evaluation steps")
|
||||
BENIGN_LANGOPT(EnableNewConstInterp, 1, 0,
|
||||
"enable the experimental new constant interpreter")
|
||||
BENIGN_LANGOPT(ForceNewConstInterp, 1, 0,
|
||||
"force the use of the experimental new constant interpreter")
|
||||
BENIGN_LANGOPT(BracketDepth, 32, 256,
|
||||
"maximum bracket nesting depth")
|
||||
BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0,
|
||||
|
@ -138,6 +138,12 @@ class LangOptions : public LangOptionsBase {
|
||||
/// rather than returning the required alignment.
|
||||
Ver7,
|
||||
|
||||
/// Attempt to be ABI-compatible with code generated by Clang 9.0.x
|
||||
/// (SVN r351319). This causes vectors of __int128 to be passed in memory
|
||||
/// instead of passing in multiple scalar registers on x86_64 on Linux and
|
||||
/// NetBSD.
|
||||
Ver9,
|
||||
|
||||
/// Conform to the underlying platform's C and C++ ABIs as closely
|
||||
/// as we can.
|
||||
Latest
|
||||
@ -178,6 +184,16 @@ class LangOptions : public LangOptionsBase {
|
||||
FEA_On
|
||||
};
|
||||
|
||||
enum class LaxVectorConversionKind {
|
||||
/// Permit no implicit vector bitcasts.
|
||||
None,
|
||||
/// Permit vector bitcasts between integer vectors with different numbers
|
||||
/// of elements but the same total bit-width.
|
||||
Integer,
|
||||
/// Permit vector bitcasts between all vectors with the same total
|
||||
/// bit-width.
|
||||
All,
|
||||
};
|
||||
|
||||
public:
|
||||
/// Set of enabled sanitizers.
|
||||
|
@ -6,16 +6,37 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_FRONTEND_LANGSTANDARD_H
|
||||
#define LLVM_CLANG_FRONTEND_LANGSTANDARD_H
|
||||
#ifndef LLVM_CLANG_BASIC_LANGSTANDARD_H
|
||||
#define LLVM_CLANG_BASIC_LANGSTANDARD_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Frontend/FrontendOptions.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace frontend {
|
||||
/// The language for the input, used to select and validate the language
|
||||
/// standard and possible actions.
|
||||
enum class Language : uint8_t {
|
||||
Unknown,
|
||||
|
||||
/// Assembly: we accept this only so that we can preprocess it.
|
||||
Asm,
|
||||
|
||||
/// LLVM IR: we accept this so that we can run the optimizer on it,
|
||||
/// and compile it to assembly or object code.
|
||||
LLVM_IR,
|
||||
|
||||
///@{ Languages that the frontend can parse and compile.
|
||||
C,
|
||||
CXX,
|
||||
ObjC,
|
||||
ObjCXX,
|
||||
OpenCL,
|
||||
CUDA,
|
||||
RenderScript,
|
||||
HIP,
|
||||
///@}
|
||||
};
|
||||
|
||||
enum LangFeatures {
|
||||
LineComment = (1 << 0),
|
||||
@ -35,22 +56,20 @@ enum LangFeatures {
|
||||
OpenCL = (1 << 14)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// LangStandard - Information about the properties of a particular language
|
||||
/// standard.
|
||||
struct LangStandard {
|
||||
enum Kind {
|
||||
#define LANGSTANDARD(id, name, lang, desc, features) \
|
||||
lang_##id,
|
||||
#include "clang/Frontend/LangStandards.def"
|
||||
#include "clang/Basic/LangStandards.def"
|
||||
lang_unspecified
|
||||
};
|
||||
|
||||
const char *ShortName;
|
||||
const char *Description;
|
||||
unsigned Flags;
|
||||
InputKind::Language Language;
|
||||
clang::Language Language;
|
||||
|
||||
public:
|
||||
/// getName - Get the name of this standard.
|
||||
@ -60,54 +79,54 @@ struct LangStandard {
|
||||
const char *getDescription() const { return Description; }
|
||||
|
||||
/// Get the language that this standard describes.
|
||||
InputKind::Language getLanguage() const { return Language; }
|
||||
clang::Language getLanguage() const { return Language; }
|
||||
|
||||
/// Language supports '//' comments.
|
||||
bool hasLineComments() const { return Flags & frontend::LineComment; }
|
||||
bool hasLineComments() const { return Flags & LineComment; }
|
||||
|
||||
/// isC99 - Language is a superset of C99.
|
||||
bool isC99() const { return Flags & frontend::C99; }
|
||||
bool isC99() const { return Flags & C99; }
|
||||
|
||||
/// isC11 - Language is a superset of C11.
|
||||
bool isC11() const { return Flags & frontend::C11; }
|
||||
bool isC11() const { return Flags & C11; }
|
||||
|
||||
/// isC17 - Language is a superset of C17.
|
||||
bool isC17() const { return Flags & frontend::C17; }
|
||||
bool isC17() const { return Flags & C17; }
|
||||
|
||||
/// isC2x - Language is a superset of C2x.
|
||||
bool isC2x() const { return Flags & frontend::C2x; }
|
||||
bool isC2x() const { return Flags & C2x; }
|
||||
|
||||
/// isCPlusPlus - Language is a C++ variant.
|
||||
bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; }
|
||||
bool isCPlusPlus() const { return Flags & CPlusPlus; }
|
||||
|
||||
/// isCPlusPlus11 - Language is a C++11 variant (or later).
|
||||
bool isCPlusPlus11() const { return Flags & frontend::CPlusPlus11; }
|
||||
bool isCPlusPlus11() const { return Flags & CPlusPlus11; }
|
||||
|
||||
/// isCPlusPlus14 - Language is a C++14 variant (or later).
|
||||
bool isCPlusPlus14() const { return Flags & frontend::CPlusPlus14; }
|
||||
bool isCPlusPlus14() const { return Flags & CPlusPlus14; }
|
||||
|
||||
/// isCPlusPlus17 - Language is a C++17 variant (or later).
|
||||
bool isCPlusPlus17() const { return Flags & frontend::CPlusPlus17; }
|
||||
bool isCPlusPlus17() const { return Flags & CPlusPlus17; }
|
||||
|
||||
/// isCPlusPlus2a - Language is a post-C++17 variant (or later).
|
||||
bool isCPlusPlus2a() const { return Flags & frontend::CPlusPlus2a; }
|
||||
|
||||
bool isCPlusPlus2a() const { return Flags & CPlusPlus2a; }
|
||||
|
||||
/// hasDigraphs - Language supports digraphs.
|
||||
bool hasDigraphs() const { return Flags & frontend::Digraphs; }
|
||||
bool hasDigraphs() const { return Flags & Digraphs; }
|
||||
|
||||
/// isGNUMode - Language includes GNU extensions.
|
||||
bool isGNUMode() const { return Flags & frontend::GNUMode; }
|
||||
bool isGNUMode() const { return Flags & GNUMode; }
|
||||
|
||||
/// hasHexFloats - Language supports hexadecimal float constants.
|
||||
bool hasHexFloats() const { return Flags & frontend::HexFloat; }
|
||||
bool hasHexFloats() const { return Flags & HexFloat; }
|
||||
|
||||
/// hasImplicitInt - Language allows variables to be typed as int implicitly.
|
||||
bool hasImplicitInt() const { return Flags & frontend::ImplicitInt; }
|
||||
bool hasImplicitInt() const { return Flags & ImplicitInt; }
|
||||
|
||||
/// isOpenCL - Language is a OpenCL variant.
|
||||
bool isOpenCL() const { return Flags & frontend::OpenCL; }
|
||||
bool isOpenCL() const { return Flags & OpenCL; }
|
||||
|
||||
static Kind getLangKind(StringRef Name);
|
||||
static const LangStandard &getLangStandardForKind(Kind K);
|
||||
static const LangStandard *getLangStandardForName(StringRef Name);
|
||||
};
|
@ -14,7 +14,7 @@
|
||||
///
|
||||
/// \param IDENT - The name of the standard as a C++ identifier.
|
||||
/// \param NAME - The name of the standard.
|
||||
/// \param LANG - The InputKind::Language for which this is a standard.
|
||||
/// \param LANG - The Language for which this is a standard.
|
||||
/// \param DESC - A short description of the standard.
|
||||
/// \param FEATURES - The standard features as flags, these are enums from the
|
||||
/// clang::frontend namespace, which is assumed to be be available.
|
||||
@ -165,7 +165,7 @@ LANGSTANDARD(opencl12, "cl1.2",
|
||||
LANGSTANDARD(opencl20, "cl2.0",
|
||||
OpenCL, "OpenCL 2.0",
|
||||
LineComment | C99 | Digraphs | HexFloat | OpenCL)
|
||||
LANGSTANDARD(openclcpp, "c++",
|
||||
LANGSTANDARD(openclcpp, "clc++",
|
||||
OpenCL, "C++ for OpenCL",
|
||||
LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
|
||||
Digraphs | HexFloat | OpenCL)
|
||||
@ -174,6 +174,7 @@ LANGSTANDARD_ALIAS_DEPR(opencl10, "CL")
|
||||
LANGSTANDARD_ALIAS_DEPR(opencl11, "CL1.1")
|
||||
LANGSTANDARD_ALIAS_DEPR(opencl12, "CL1.2")
|
||||
LANGSTANDARD_ALIAS_DEPR(opencl20, "CL2.0")
|
||||
LANGSTANDARD_ALIAS_DEPR(openclcpp, "CLC++")
|
||||
|
||||
// CUDA
|
||||
LANGSTANDARD(cuda, "cuda", CUDA, "NVIDIA CUDA(tm)",
|
@ -82,6 +82,12 @@ inline bool isDiscardableGVALinkage(GVALinkage L) {
|
||||
return L <= GVA_DiscardableODR;
|
||||
}
|
||||
|
||||
/// Do we know that this will be the only definition of this symbol (excluding
|
||||
/// inlining-only definitions)?
|
||||
inline bool isUniqueGVALinkage(GVALinkage L) {
|
||||
return L == GVA_Internal || L == GVA_StrongExternal;
|
||||
}
|
||||
|
||||
inline bool isExternallyVisible(Linkage L) {
|
||||
return L >= VisibleNoLinkage;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class OpenCLOptions {
|
||||
|
||||
// Is supported as either an extension or an (optional) core feature for
|
||||
// OpenCL version \p CLVer.
|
||||
bool isSupported(llvm::StringRef Ext, LangOptions LO) const {
|
||||
bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const {
|
||||
// In C++ mode all extensions should work at least as in v2.0.
|
||||
auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
|
||||
auto I = OptMap.find(Ext)->getValue();
|
||||
@ -51,7 +51,7 @@ class OpenCLOptions {
|
||||
|
||||
// Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
|
||||
// For supported extension, return false.
|
||||
bool isSupportedCore(llvm::StringRef Ext, LangOptions LO) const {
|
||||
bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const {
|
||||
// In C++ mode all extensions should work at least as in v2.0.
|
||||
auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
|
||||
auto I = OptMap.find(Ext)->getValue();
|
||||
@ -60,7 +60,7 @@ class OpenCLOptions {
|
||||
|
||||
// Is supported OpenCL extension for OpenCL version \p CLVer.
|
||||
// For supported (optional) core feature, return false.
|
||||
bool isSupportedExtension(llvm::StringRef Ext, LangOptions LO) const {
|
||||
bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const {
|
||||
// In C++ mode all extensions should work at least as in v2.0.
|
||||
auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
|
||||
auto I = OptMap.find(Ext)->getValue();
|
||||
|
@ -92,6 +92,15 @@
|
||||
#ifndef OPENMP_TASKLOOP_SIMD_CLAUSE
|
||||
# define OPENMP_TASKLOOP_SIMD_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_MASTER_TASKLOOP_CLAUSE
|
||||
# define OPENMP_MASTER_TASKLOOP_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE
|
||||
# define OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE
|
||||
# define OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_CRITICAL_CLAUSE
|
||||
# define OPENMP_CRITICAL_CLAUSE(Name)
|
||||
#endif
|
||||
@ -191,6 +200,15 @@
|
||||
#ifndef OPENMP_ALLOCATE_CLAUSE
|
||||
# define OPENMP_ALLOCATE_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DEVICE_TYPE_KIND
|
||||
#define OPENMP_DEVICE_TYPE_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DECLARE_VARIANT_CLAUSE
|
||||
#define OPENMP_DECLARE_VARIANT_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_MATCH_KIND
|
||||
#define OPENMP_MATCH_KIND(Name)
|
||||
#endif
|
||||
|
||||
// OpenMP directives.
|
||||
OPENMP_DIRECTIVE(threadprivate)
|
||||
@ -248,6 +266,10 @@ OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for, "target teams distrib
|
||||
OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for_simd, "target teams distribute parallel for simd")
|
||||
OPENMP_DIRECTIVE_EXT(target_teams_distribute_simd, "target teams distribute simd")
|
||||
OPENMP_DIRECTIVE(allocate)
|
||||
OPENMP_DIRECTIVE_EXT(declare_variant, "declare variant")
|
||||
OPENMP_DIRECTIVE_EXT(master_taskloop, "master taskloop")
|
||||
OPENMP_DIRECTIVE_EXT(parallel_master_taskloop, "parallel master taskloop")
|
||||
OPENMP_DIRECTIVE_EXT(master_taskloop_simd, "master taskloop simd")
|
||||
|
||||
// OpenMP clauses.
|
||||
OPENMP_CLAUSE(allocator, OMPAllocatorClause)
|
||||
@ -656,6 +678,69 @@ OPENMP_TASKLOOP_SIMD_CLAUSE(reduction)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(in_reduction)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(allocate)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'master taskloop'.
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(if)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(shared)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(private)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(firstprivate)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(lastprivate)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(default)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(collapse)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(final)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(untied)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(mergeable)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(priority)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(grainsize)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(nogroup)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(num_tasks)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(reduction)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(in_reduction)
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(allocate)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'master taskloop simd'.
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(if)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(shared)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(private)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(firstprivate)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(lastprivate)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(default)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(collapse)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(final)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(untied)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(mergeable)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(priority)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(linear)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(aligned)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(safelen)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(grainsize)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(nogroup)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(num_tasks)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(reduction)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(in_reduction)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(allocate)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel master taskloop'.
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(if)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(shared)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(private)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(firstprivate)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(lastprivate)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(default)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(collapse)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(final)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(untied)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(mergeable)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(priority)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(grainsize)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(nogroup)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(num_tasks)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(reduction)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(allocate)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(num_threads)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(proc_bind)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(copyin)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'critical'.
|
||||
OPENMP_CRITICAL_CLAUSE(hint)
|
||||
|
||||
@ -950,9 +1035,27 @@ OPENMP_TASKGROUP_CLAUSE(allocate)
|
||||
// Clauses allowed for OpenMP directive 'declare mapper'.
|
||||
OPENMP_DECLARE_MAPPER_CLAUSE(map)
|
||||
|
||||
// Device types for 'device_type' clause.
|
||||
OPENMP_DEVICE_TYPE_KIND(host)
|
||||
OPENMP_DEVICE_TYPE_KIND(nohost)
|
||||
OPENMP_DEVICE_TYPE_KIND(any)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'declare variant'.
|
||||
OPENMP_DECLARE_VARIANT_CLAUSE(match)
|
||||
|
||||
// Context selectors for 'match' clause.
|
||||
// TODO: add other context selectors.
|
||||
OPENMP_MATCH_KIND(implementation)
|
||||
|
||||
#undef OPENMP_MATCH_KIND
|
||||
#undef OPENMP_DECLARE_VARIANT_CLAUSE
|
||||
#undef OPENMP_DEVICE_TYPE_KIND
|
||||
#undef OPENMP_ALLOCATE_CLAUSE
|
||||
#undef OPENMP_DECLARE_MAPPER_CLAUSE
|
||||
#undef OPENMP_TASKGROUP_CLAUSE
|
||||
#undef OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE
|
||||
#undef OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE
|
||||
#undef OPENMP_MASTER_TASKLOOP_CLAUSE
|
||||
#undef OPENMP_TASKLOOP_SIMD_CLAUSE
|
||||
#undef OPENMP_TASKLOOP_CLAUSE
|
||||
#undef OPENMP_LINEAR_KIND
|
||||
|
@ -35,6 +35,8 @@ enum OpenMPClauseKind {
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_threadprivate,
|
||||
OMPC_uniform,
|
||||
OMPC_device_type,
|
||||
OMPC_match,
|
||||
OMPC_unknown
|
||||
};
|
||||
|
||||
@ -152,6 +154,14 @@ enum OpenMPAtomicDefaultMemOrderClauseKind {
|
||||
OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
|
||||
};
|
||||
|
||||
/// OpenMP device type for 'device_type' clause.
|
||||
enum OpenMPDeviceType {
|
||||
#define OPENMP_DEVICE_TYPE_KIND(Name) \
|
||||
OMPC_DEVICE_TYPE_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_DEVICE_TYPE_unknown
|
||||
};
|
||||
|
||||
/// Scheduling data for loop-based OpenMP directives.
|
||||
struct OpenMPScheduleTy final {
|
||||
OpenMPScheduleClauseKind Schedule = OMPC_SCHEDULE_unknown;
|
||||
@ -259,7 +269,8 @@ bool isOpenMPPrivate(OpenMPClauseKind Kind);
|
||||
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind);
|
||||
|
||||
/// Checks if the specified directive kind is one of tasking directives - task,
|
||||
/// taskloop or taksloop simd.
|
||||
/// taskloop, taksloop simd, master taskloop, parallel master taskloop or master
|
||||
/// taskloop simd.
|
||||
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind);
|
||||
|
||||
/// Checks if the specified directive kind is one of the composite or combined
|
||||
|
@ -30,6 +30,25 @@ enum OverloadedOperatorKind : int {
|
||||
/// the preceding "operator" keyword.
|
||||
const char *getOperatorSpelling(OverloadedOperatorKind Operator);
|
||||
|
||||
/// Get the other overloaded operator that the given operator can be rewritten
|
||||
/// into, if any such operator exists.
|
||||
inline OverloadedOperatorKind
|
||||
getRewrittenOverloadedOperator(OverloadedOperatorKind Kind) {
|
||||
switch (Kind) {
|
||||
case OO_Less:
|
||||
case OO_LessEqual:
|
||||
case OO_Greater:
|
||||
case OO_GreaterEqual:
|
||||
return OO_Spaceship;
|
||||
|
||||
case OO_ExclaimEqual:
|
||||
return OO_EqualEqual;
|
||||
|
||||
default:
|
||||
return OO_None;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
@ -140,9 +140,9 @@ namespace SrcMgr {
|
||||
/// exist.
|
||||
unsigned BufferOverridden : 1;
|
||||
|
||||
/// True if this content cache was initially created for a source
|
||||
/// file considered as a system one.
|
||||
unsigned IsSystemFile : 1;
|
||||
/// True if this content cache was initially created for a source file
|
||||
/// considered to be volatile (likely to change between stat and open).
|
||||
unsigned IsFileVolatile : 1;
|
||||
|
||||
/// 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,
|
||||
@ -152,15 +152,15 @@ namespace SrcMgr {
|
||||
ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {}
|
||||
|
||||
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
|
||||
: Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
|
||||
BufferOverridden(false), IsSystemFile(false), IsTransient(false) {}
|
||||
: Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
|
||||
BufferOverridden(false), IsFileVolatile(false), IsTransient(false) {}
|
||||
|
||||
/// The copy ctor does not allow copies where source object has either
|
||||
/// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
|
||||
/// is not transferred, so this is a logical error.
|
||||
ContentCache(const ContentCache &RHS)
|
||||
: Buffer(nullptr, false), BufferOverridden(false), IsSystemFile(false),
|
||||
IsTransient(false) {
|
||||
: Buffer(nullptr, false), BufferOverridden(false),
|
||||
IsFileVolatile(false), IsTransient(false) {
|
||||
OrigEntry = RHS.OrigEntry;
|
||||
ContentsEntry = RHS.ContentsEntry;
|
||||
|
||||
@ -185,7 +185,7 @@ namespace SrcMgr {
|
||||
///
|
||||
/// \param Invalid If non-NULL, will be set \c true if an error occurred.
|
||||
const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag,
|
||||
const SourceManager &SM,
|
||||
FileManager &FM,
|
||||
SourceLocation Loc = SourceLocation(),
|
||||
bool *Invalid = nullptr) const;
|
||||
|
||||
@ -265,16 +265,21 @@ namespace SrcMgr {
|
||||
llvm::PointerIntPair<const ContentCache*, 3, CharacteristicKind>
|
||||
ContentAndKind;
|
||||
|
||||
/// The filename that is used to access the file entry represented by the
|
||||
/// content cache.
|
||||
StringRef Filename;
|
||||
|
||||
public:
|
||||
/// Return a FileInfo object.
|
||||
static FileInfo get(SourceLocation IL, const ContentCache *Con,
|
||||
CharacteristicKind FileCharacter) {
|
||||
CharacteristicKind FileCharacter, StringRef Filename) {
|
||||
FileInfo X;
|
||||
X.IncludeLoc = IL.getRawEncoding();
|
||||
X.NumCreatedFIDs = 0;
|
||||
X.HasLineDirectives = false;
|
||||
X.ContentAndKind.setPointer(Con);
|
||||
X.ContentAndKind.setInt(FileCharacter);
|
||||
X.Filename = Filename;
|
||||
return X;
|
||||
}
|
||||
|
||||
@ -299,6 +304,10 @@ namespace SrcMgr {
|
||||
void setHasLineDirectives() {
|
||||
HasLineDirectives = true;
|
||||
}
|
||||
|
||||
/// Returns the name of the file that was used when the file was loaded from
|
||||
/// the underlying file system.
|
||||
StringRef getName() const { return Filename; }
|
||||
};
|
||||
|
||||
/// Each ExpansionInfo encodes the expansion location - where
|
||||
@ -821,7 +830,18 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
const SrcMgr::ContentCache *IR =
|
||||
getOrCreateContentCache(SourceFile, isSystem(FileCharacter));
|
||||
assert(IR && "getOrCreateContentCache() cannot return NULL");
|
||||
return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset);
|
||||
return createFileID(IR, SourceFile->getName(), IncludePos, FileCharacter,
|
||||
LoadedID, LoadedOffset);
|
||||
}
|
||||
|
||||
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos,
|
||||
SrcMgr::CharacteristicKind FileCharacter,
|
||||
int LoadedID = 0, unsigned LoadedOffset = 0) {
|
||||
const SrcMgr::ContentCache *IR = getOrCreateContentCache(
|
||||
&SourceFile.getFileEntry(), isSystem(FileCharacter));
|
||||
assert(IR && "getOrCreateContentCache() cannot return NULL");
|
||||
return createFileID(IR, SourceFile.getName(), IncludePos, FileCharacter,
|
||||
LoadedID, LoadedOffset);
|
||||
}
|
||||
|
||||
/// Create a new FileID that represents the specified memory buffer.
|
||||
@ -832,9 +852,10 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
|
||||
int LoadedID = 0, unsigned LoadedOffset = 0,
|
||||
SourceLocation IncludeLoc = SourceLocation()) {
|
||||
StringRef Name = Buffer->getBufferIdentifier();
|
||||
return createFileID(
|
||||
createMemBufferContentCache(Buffer.release(), /*DoNotFree*/ false),
|
||||
IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
|
||||
Name, IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
|
||||
}
|
||||
|
||||
enum UnownedTag { Unowned };
|
||||
@ -847,8 +868,9 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
|
||||
int LoadedID = 0, unsigned LoadedOffset = 0,
|
||||
SourceLocation IncludeLoc = SourceLocation()) {
|
||||
return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/true),
|
||||
IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
|
||||
return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/ true),
|
||||
Buffer->getBufferIdentifier(), IncludeLoc,
|
||||
FileCharacter, LoadedID, LoadedOffset);
|
||||
}
|
||||
|
||||
/// Get the FileID for \p SourceFile if it exists. Otherwise, create a
|
||||
@ -930,11 +952,12 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Disable overridding the contents of a file, previously enabled
|
||||
/// with #overrideFileContents.
|
||||
/// Bypass the overridden contents of a file. This creates a new FileEntry
|
||||
/// and initializes the content cache for it. Returns nullptr if there is no
|
||||
/// such file in the filesystem.
|
||||
///
|
||||
/// This should be called before parsing has begun.
|
||||
void disableFileContentsOverride(const FileEntry *File);
|
||||
const FileEntry *bypassFileContentsOverride(const FileEntry &File);
|
||||
|
||||
/// Specify that a file is transient.
|
||||
void setFileIsTransient(const FileEntry *SourceFile);
|
||||
@ -964,8 +987,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
return getFakeBufferForRecovery();
|
||||
}
|
||||
|
||||
return Entry.getFile().getContentCache()->getBuffer(Diag, *this, Loc,
|
||||
Invalid);
|
||||
return Entry.getFile().getContentCache()->getBuffer(Diag, getFileManager(),
|
||||
Loc, Invalid);
|
||||
}
|
||||
|
||||
const llvm::MemoryBuffer *getBuffer(FileID FID,
|
||||
@ -979,9 +1002,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
return getFakeBufferForRecovery();
|
||||
}
|
||||
|
||||
return Entry.getFile().getContentCache()->getBuffer(Diag, *this,
|
||||
SourceLocation(),
|
||||
Invalid);
|
||||
return Entry.getFile().getContentCache()->getBuffer(
|
||||
Diag, getFileManager(), SourceLocation(), Invalid);
|
||||
}
|
||||
|
||||
/// Returns the FileEntry record for the provided FileID.
|
||||
@ -997,6 +1019,19 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
return Content->OrigEntry;
|
||||
}
|
||||
|
||||
/// Returns the FileEntryRef for the provided FileID.
|
||||
Optional<FileEntryRef> getFileEntryRefForID(FileID FID) const {
|
||||
bool Invalid = false;
|
||||
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
|
||||
if (Invalid || !Entry.isFile())
|
||||
return None;
|
||||
|
||||
const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache();
|
||||
if (!Content || !Content->OrigEntry)
|
||||
return None;
|
||||
return FileEntryRef(Entry.getFile().getName(), *Content->OrigEntry);
|
||||
}
|
||||
|
||||
/// Returns the FileEntry record for the provided SLocEntry.
|
||||
const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const
|
||||
{
|
||||
@ -1785,10 +1820,10 @@ class SourceManager : public RefCountedBase<SourceManager> {
|
||||
///
|
||||
/// This works regardless of whether the ContentCache corresponds to a
|
||||
/// file or some other input source.
|
||||
FileID createFileID(const SrcMgr::ContentCache* File,
|
||||
FileID createFileID(const SrcMgr::ContentCache *File, StringRef Filename,
|
||||
SourceLocation IncludePos,
|
||||
SrcMgr::CharacteristicKind DirCharacter,
|
||||
int LoadedID, unsigned LoadedOffset);
|
||||
SrcMgr::CharacteristicKind DirCharacter, int LoadedID,
|
||||
unsigned LoadedOffset);
|
||||
|
||||
const SrcMgr::ContentCache *
|
||||
getOrCreateContentCache(const FileEntry *SourceFile,
|
||||
|
@ -32,7 +32,8 @@ namespace clang {
|
||||
enum ConstexprSpecKind {
|
||||
CSK_unspecified,
|
||||
CSK_constexpr,
|
||||
CSK_consteval
|
||||
CSK_consteval,
|
||||
CSK_constinit
|
||||
};
|
||||
|
||||
/// Specifies the width of a type, e.g., short, long, or long long.
|
||||
|
@ -16,11 +16,40 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace clang {
|
||||
/// The amount of stack space that Clang would like to be provided with.
|
||||
/// If less than this much is available, we may be unable to reach our
|
||||
/// template instantiation depth limit and other similar limits.
|
||||
constexpr size_t DesiredStackSize = 8 << 20;
|
||||
|
||||
/// Call this once on each thread, as soon after starting the thread as
|
||||
/// feasible, to note the approximate address of the bottom of the stack.
|
||||
void noteBottomOfStack();
|
||||
|
||||
/// Determine whether the stack is nearly exhausted.
|
||||
bool isStackNearlyExhausted();
|
||||
|
||||
void runWithSufficientStackSpaceSlow(llvm::function_ref<void()> Diag,
|
||||
llvm::function_ref<void()> Fn);
|
||||
|
||||
/// Run a given function on a stack with "sufficient" space. If stack space
|
||||
/// is insufficient, calls Diag to emit a diagnostic before calling Fn.
|
||||
inline void runWithSufficientStackSpace(llvm::function_ref<void()> Diag,
|
||||
llvm::function_ref<void()> Fn) {
|
||||
#ifdef LLVM_ENABLE_THREADS
|
||||
if (LLVM_UNLIKELY(isStackNearlyExhausted()))
|
||||
runWithSufficientStackSpaceSlow(Diag, Fn);
|
||||
else
|
||||
Fn();
|
||||
#else
|
||||
if (LLVM_UNLIKELY(isStackNearlyExhausted()))
|
||||
Diag();
|
||||
Fn();
|
||||
#endif
|
||||
}
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_STACK_H
|
||||
|
@ -114,6 +114,7 @@ def GNUNullExpr : DStmt<Expr>;
|
||||
// C++ Expressions.
|
||||
def CXXOperatorCallExpr : DStmt<CallExpr>;
|
||||
def CXXMemberCallExpr : DStmt<CallExpr>;
|
||||
def CXXRewrittenBinaryOperator : DStmt<Expr>;
|
||||
def CXXNamedCastExpr : DStmt<ExplicitCastExpr, 1>;
|
||||
def CXXStaticCastExpr : DStmt<CXXNamedCastExpr>;
|
||||
def CXXDynamicCastExpr : DStmt<CXXNamedCastExpr>;
|
||||
@ -163,6 +164,9 @@ def CoawaitExpr : DStmt<CoroutineSuspendExpr>;
|
||||
def DependentCoawaitExpr : DStmt<Expr>;
|
||||
def CoyieldExpr : DStmt<CoroutineSuspendExpr>;
|
||||
|
||||
// C++2a Concepts expressions
|
||||
def ConceptSpecializationExpr : DStmt<Expr>;
|
||||
|
||||
// Obj-C Expressions.
|
||||
def ObjCStringLiteral : DStmt<Expr>;
|
||||
def ObjCBoxedExpr : DStmt<Expr>;
|
||||
@ -242,6 +246,9 @@ def OMPCancellationPointDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPCancelDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTaskLoopDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTaskLoopSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPMasterTaskLoopDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPMasterTaskLoopSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPParallelMasterTaskLoopDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPDistributeDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPDistributeParallelForDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPDistributeParallelForSimdDirective : DStmt<OMPLoopDirective>;
|
||||
|
@ -144,7 +144,7 @@ AtomicScopeModel::create(AtomicScopeModelKind K) {
|
||||
case AtomicScopeModelKind::None:
|
||||
return std::unique_ptr<AtomicScopeModel>{};
|
||||
case AtomicScopeModelKind::OpenCL:
|
||||
return llvm::make_unique<AtomicScopeOpenCLModel>();
|
||||
return std::make_unique<AtomicScopeOpenCLModel>();
|
||||
}
|
||||
llvm_unreachable("Invalid atomic scope model kind");
|
||||
}
|
||||
|
@ -52,6 +52,16 @@ namespace clang {
|
||||
};
|
||||
}
|
||||
|
||||
/// BPF builtins
|
||||
namespace BPF {
|
||||
enum {
|
||||
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
|
||||
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
|
||||
#include "clang/Basic/BuiltinsBPF.def"
|
||||
LastTSBuiltin
|
||||
};
|
||||
}
|
||||
|
||||
/// PPC builtins
|
||||
namespace PPC {
|
||||
enum {
|
||||
|
@ -19,14 +19,15 @@
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Basic/TargetCXXABI.h"
|
||||
#include "clang/Basic/TargetOptions.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/VersionTuple.h"
|
||||
#include <cassert>
|
||||
@ -35,6 +36,7 @@
|
||||
|
||||
namespace llvm {
|
||||
struct fltSemantics;
|
||||
class DataLayout;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
@ -193,12 +195,12 @@ class TargetInfo : public virtual TransferrableTargetInfo,
|
||||
|
||||
unsigned IsRenderScriptTarget : 1;
|
||||
|
||||
unsigned HasAArch64SVETypes : 1;
|
||||
|
||||
// TargetInfo Constructor. Default initializes all fields.
|
||||
TargetInfo(const llvm::Triple &T);
|
||||
|
||||
void resetDataLayout(StringRef DL) {
|
||||
DataLayout.reset(new llvm::DataLayout(DL));
|
||||
}
|
||||
void resetDataLayout(StringRef DL);
|
||||
|
||||
public:
|
||||
/// Construct a target for the given options.
|
||||
@ -789,6 +791,10 @@ class TargetInfo : public virtual TransferrableTargetInfo,
|
||||
/// Returns true for RenderScript.
|
||||
bool isRenderScriptTarget() const { return IsRenderScriptTarget; }
|
||||
|
||||
/// Returns whether or not the AArch64 SVE built-in types are
|
||||
/// available on this target.
|
||||
bool hasAArch64SVETypes() const { return HasAArch64SVETypes; }
|
||||
|
||||
/// Returns whether the passed in string is a valid clobber in an
|
||||
/// inline asm statement.
|
||||
///
|
||||
@ -1249,15 +1255,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
|
||||
bool isBigEndian() const { return BigEndian; }
|
||||
bool isLittleEndian() const { return !BigEndian; }
|
||||
|
||||
enum CallingConvMethodType {
|
||||
CCMT_Unknown,
|
||||
CCMT_Member,
|
||||
CCMT_NonMember
|
||||
};
|
||||
|
||||
/// Gets the default calling convention for the given target and
|
||||
/// declaration context.
|
||||
virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const {
|
||||
virtual CallingConv getDefaultCallingConv() const {
|
||||
// Not all targets will specify an explicit calling convention that we can
|
||||
// express. This will always do the right thing, even though it's not
|
||||
// an explicit calling convention.
|
||||
@ -1268,6 +1268,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
|
||||
CCCR_OK,
|
||||
CCCR_Warning,
|
||||
CCCR_Ignore,
|
||||
CCCR_Error,
|
||||
};
|
||||
|
||||
/// Determines whether a given calling convention is valid for the
|
||||
|
@ -68,6 +68,9 @@
|
||||
#ifndef ANNOTATION
|
||||
#define ANNOTATION(X) TOK(annot_ ## X)
|
||||
#endif
|
||||
#ifndef PRAGMA_ANNOTATION
|
||||
#define PRAGMA_ANNOTATION(X) ANNOTATION(X)
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Preprocessor keywords.
|
||||
@ -386,6 +389,7 @@ MODULES_KEYWORD(import)
|
||||
// C++20 keywords.
|
||||
CXX2A_KEYWORD(char8_t , CHAR8SUPPORT)
|
||||
CXX2A_KEYWORD(consteval , 0)
|
||||
CXX2A_KEYWORD(constinit , 0)
|
||||
|
||||
// C11 Extension
|
||||
KEYWORD(_Float16 , KEYALL)
|
||||
@ -446,16 +450,18 @@ TYPE_TRAIT_N(__is_nothrow_constructible, IsNothrowConstructible, KEYCXX)
|
||||
// MSVC14.0 / VS2015 Type Traits
|
||||
TYPE_TRAIT_2(__is_assignable, IsAssignable, KEYCXX)
|
||||
|
||||
// MSVC Type Traits of unknown vintage
|
||||
TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX)
|
||||
|
||||
// GNU and MS Type Traits
|
||||
TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_nothrow_copy, HasNothrowCopy, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_nothrow_constructor, HasNothrowConstructor, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_trivial_assign, HasTrivialAssign, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_trivial_copy, HasTrivialCopy, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_trivial_constructor, HasTrivialDefaultConstructor, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX)
|
||||
@ -472,17 +478,18 @@ TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX)
|
||||
ALIAS("__is_literal_type", __is_literal, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_pod, IsPOD, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_polymorphic, IsPolymorphic, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_standard_layout, IsStandardLayout, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_trivial, IsTrivial, KEYCXX)
|
||||
TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX)
|
||||
TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_unique_object_representations,
|
||||
HasUniqueObjectRepresentations, KEYCXX)
|
||||
KEYWORD(__underlying_type , KEYCXX)
|
||||
|
||||
// Clang-only C++ Type Traits
|
||||
TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
|
||||
TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX)
|
||||
TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
|
||||
KEYWORD(__underlying_type , KEYCXX)
|
||||
|
||||
// Embarcadero Expression Traits
|
||||
KEYWORD(__is_lvalue_expr , KEYCXX)
|
||||
@ -509,7 +516,6 @@ TYPE_TRAIT_1(__is_member_function_pointer, IsMemberFunctionPointer, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_member_pointer, IsMemberPointer, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_const, IsConst, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_volatile, IsVolatile, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_standard_layout, IsStandardLayout, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_signed, IsSigned, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX)
|
||||
|
||||
@ -722,6 +728,11 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly
|
||||
ANNOTATION(template_id) // annotation for a C++ template-id that names a
|
||||
// function template specialization (not a type),
|
||||
// e.g., "std::swap<int>"
|
||||
ANNOTATION(non_type) // annotation for a single non-type declaration
|
||||
ANNOTATION(non_type_undeclared) // annotation for an undeclared identifier that
|
||||
// was assumed to be an ADL-only function name
|
||||
ANNOTATION(non_type_dependent) // annotation for an assumed non-type member of
|
||||
// a dependent base class
|
||||
ANNOTATION(primary_expr) // annotation for a primary expression
|
||||
ANNOTATION(decltype) // annotation for a decltype expression,
|
||||
// e.g., "decltype(foo.bar())"
|
||||
@ -729,103 +740,103 @@ ANNOTATION(decltype) // annotation for a decltype expression,
|
||||
// Annotation for #pragma unused(...)
|
||||
// For each argument inside the parentheses the pragma handler will produce
|
||||
// one 'pragma_unused' annotation token followed by the argument token.
|
||||
ANNOTATION(pragma_unused)
|
||||
PRAGMA_ANNOTATION(pragma_unused)
|
||||
|
||||
// Annotation for #pragma GCC visibility...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_vis)
|
||||
PRAGMA_ANNOTATION(pragma_vis)
|
||||
|
||||
// Annotation for #pragma pack...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_pack)
|
||||
PRAGMA_ANNOTATION(pragma_pack)
|
||||
|
||||
// Annotation for #pragma clang __debug parser_crash...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_parser_crash)
|
||||
PRAGMA_ANNOTATION(pragma_parser_crash)
|
||||
|
||||
// Annotation for #pragma clang __debug captured...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_captured)
|
||||
PRAGMA_ANNOTATION(pragma_captured)
|
||||
|
||||
// Annotation for #pragma clang __debug dump...
|
||||
// The lexer produces these so that the parser and semantic analysis can
|
||||
// look up and dump the operand.
|
||||
ANNOTATION(pragma_dump)
|
||||
PRAGMA_ANNOTATION(pragma_dump)
|
||||
|
||||
// Annotation for #pragma ms_struct...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_msstruct)
|
||||
PRAGMA_ANNOTATION(pragma_msstruct)
|
||||
|
||||
// Annotation for #pragma align...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_align)
|
||||
PRAGMA_ANNOTATION(pragma_align)
|
||||
|
||||
// Annotation for #pragma weak id
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_weak)
|
||||
PRAGMA_ANNOTATION(pragma_weak)
|
||||
|
||||
// Annotation for #pragma weak id = id
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_weakalias)
|
||||
PRAGMA_ANNOTATION(pragma_weakalias)
|
||||
|
||||
// Annotation for #pragma redefine_extname...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_redefine_extname)
|
||||
PRAGMA_ANNOTATION(pragma_redefine_extname)
|
||||
|
||||
// Annotation for #pragma STDC FP_CONTRACT...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_fp_contract)
|
||||
PRAGMA_ANNOTATION(pragma_fp_contract)
|
||||
|
||||
// Annotation for #pragma STDC FENV_ACCESS
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_fenv_access)
|
||||
PRAGMA_ANNOTATION(pragma_fenv_access)
|
||||
|
||||
// Annotation for #pragma pointers_to_members...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_ms_pointers_to_members)
|
||||
PRAGMA_ANNOTATION(pragma_ms_pointers_to_members)
|
||||
|
||||
// Annotation for #pragma vtordisp...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_ms_vtordisp)
|
||||
PRAGMA_ANNOTATION(pragma_ms_vtordisp)
|
||||
|
||||
// Annotation for all microsoft #pragmas...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_ms_pragma)
|
||||
PRAGMA_ANNOTATION(pragma_ms_pragma)
|
||||
|
||||
// Annotation for #pragma OPENCL EXTENSION...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
ANNOTATION(pragma_opencl_extension)
|
||||
PRAGMA_ANNOTATION(pragma_opencl_extension)
|
||||
|
||||
// Annotations for OpenMP pragma directives - #pragma omp ...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles #pragma omp ... directives.
|
||||
ANNOTATION(pragma_openmp)
|
||||
ANNOTATION(pragma_openmp_end)
|
||||
PRAGMA_ANNOTATION(pragma_openmp)
|
||||
PRAGMA_ANNOTATION(pragma_openmp_end)
|
||||
|
||||
// Annotations for loop pragma directives #pragma clang loop ...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles #pragma loop ... directives.
|
||||
ANNOTATION(pragma_loop_hint)
|
||||
PRAGMA_ANNOTATION(pragma_loop_hint)
|
||||
|
||||
ANNOTATION(pragma_fp)
|
||||
PRAGMA_ANNOTATION(pragma_fp)
|
||||
|
||||
// Annotation for the attribute pragma directives - #pragma clang attribute ...
|
||||
ANNOTATION(pragma_attribute)
|
||||
PRAGMA_ANNOTATION(pragma_attribute)
|
||||
|
||||
// Annotations for module import translated from #include etc.
|
||||
ANNOTATION(module_include)
|
||||
@ -836,6 +847,7 @@ ANNOTATION(module_end)
|
||||
// into the name of a header unit.
|
||||
ANNOTATION(header_unit)
|
||||
|
||||
#undef PRAGMA_ANNOTATION
|
||||
#undef ANNOTATION
|
||||
#undef TESTING_KEYWORD
|
||||
#undef OBJC_AT_KEYWORD
|
||||
|
@ -90,13 +90,10 @@ inline bool isLiteral(TokenKind K) {
|
||||
}
|
||||
|
||||
/// Return true if this is any of tok::annot_* kinds.
|
||||
inline bool isAnnotation(TokenKind K) {
|
||||
#define ANNOTATION(NAME) \
|
||||
if (K == tok::annot_##NAME) \
|
||||
return true;
|
||||
#include "clang/Basic/TokenKinds.def"
|
||||
return false;
|
||||
}
|
||||
bool isAnnotation(TokenKind K);
|
||||
|
||||
/// Return true if this is an annotation token representing a pragma.
|
||||
bool isPragmaAnnotation(TokenKind K);
|
||||
|
||||
} // end namespace tok
|
||||
} // end namespace clang
|
||||
|
106
include/clang/Basic/TypeNodes.td
Normal file
106
include/clang/Basic/TypeNodes.td
Normal file
@ -0,0 +1,106 @@
|
||||
class Type<bit abstract = 0> {
|
||||
bit Abstract = abstract;
|
||||
}
|
||||
|
||||
class DerivedType<Type base, bit abstract = 0> : Type<abstract> {
|
||||
Type Base = base;
|
||||
}
|
||||
|
||||
/// A type node that is only used to represent dependent types in C++. For
|
||||
/// example, DependentTemplateSpecializationType is used to represent types
|
||||
/// where the base template-id is dependent (such as `T::foo<U>`). Code
|
||||
/// that only works with non-dependent types can ignore these type nodes.
|
||||
class AlwaysDependent {}
|
||||
|
||||
/// A type node that is never used to represent a canonical type, which is to
|
||||
/// say that it always represents some sort of type "sugar" which can
|
||||
/// (supposedly) be erased without affecting the formal behavior of the
|
||||
/// language. For example, in standard C/C++, typedefs do not introduce new
|
||||
/// types and do not affect the semantics of the program. Code that only
|
||||
/// works with canonical types can ignore these type nodes.
|
||||
///
|
||||
/// Note that this simple story about non-canonical types is not the whole
|
||||
/// truth. Languages and extensions often have formation rules which differ
|
||||
/// based on how a type is spelled and which therefore are not consistent
|
||||
/// with immediately stipping away type sugar. More critically, attributes on
|
||||
/// typedefs can have semantic impacts in ways that are only reflected in our
|
||||
/// AST by preserving the typedef sugar; for example, we do not otherwise
|
||||
/// represent the alignment attribute on typedefs, and so it is necessary to
|
||||
/// preserve typedef structure into most parts of IR generation.
|
||||
class NeverCanonical {}
|
||||
|
||||
/// A type node that only represents a canonical type in some dependent cases.
|
||||
/// For example, `std::vector<int>` (a TemplateSpecializationType) is
|
||||
/// considered to be a non-canonical representation for the RecordType
|
||||
/// referencing the concrete ClassTemplateSpecializationDecl; but
|
||||
/// `std::vector<T>` cannot be resolved to a concrete specialization
|
||||
/// and so remains canonical. Code which only works with non-dependent
|
||||
/// canonical types can ignore these nodes.
|
||||
class NeverCanonicalUnlessDependent {}
|
||||
|
||||
/// A type node which never has component type structure. Some code may be
|
||||
/// able to operate on leaf types faster than they can on non-leaf types.
|
||||
///
|
||||
/// For example, the function type `void (int)` is not a leaf type because it
|
||||
/// is structurally composed of component types (`void` and `int`).
|
||||
///
|
||||
/// A struct type is a leaf type because its field types are not part of its
|
||||
/// type-expression.
|
||||
///
|
||||
/// Nodes like `TypedefType` which are syntactically leaves but can desugar
|
||||
/// to types that may not be leaves should not declare this.
|
||||
class LeafType {}
|
||||
|
||||
def BuiltinType : Type, LeafType;
|
||||
def ComplexType : Type;
|
||||
def PointerType : Type;
|
||||
def BlockPointerType : Type;
|
||||
def ReferenceType : Type<1>;
|
||||
def LValueReferenceType : DerivedType<ReferenceType>;
|
||||
def RValueReferenceType : DerivedType<ReferenceType>;
|
||||
def MemberPointerType : Type;
|
||||
def ArrayType : Type<1>;
|
||||
def ConstantArrayType : DerivedType<ArrayType>;
|
||||
def IncompleteArrayType : DerivedType<ArrayType>;
|
||||
def VariableArrayType : DerivedType<ArrayType>;
|
||||
def DependentSizedArrayType : DerivedType<ArrayType>, AlwaysDependent;
|
||||
def DependentSizedExtVectorType : Type, AlwaysDependent;
|
||||
def DependentAddressSpaceType : Type, AlwaysDependent;
|
||||
def VectorType : Type;
|
||||
def DependentVectorType : Type, AlwaysDependent;
|
||||
def ExtVectorType : DerivedType<VectorType>;
|
||||
def FunctionType : Type<1>;
|
||||
def FunctionProtoType : DerivedType<FunctionType>;
|
||||
def FunctionNoProtoType : DerivedType<FunctionType>;
|
||||
def UnresolvedUsingType : Type, AlwaysDependent;
|
||||
def ParenType : Type, NeverCanonical;
|
||||
def TypedefType : Type, NeverCanonical;
|
||||
def MacroQualifiedType : Type, NeverCanonical;
|
||||
def AdjustedType : Type, NeverCanonical;
|
||||
def DecayedType : DerivedType<AdjustedType>, NeverCanonical;
|
||||
def TypeOfExprType : Type, NeverCanonicalUnlessDependent;
|
||||
def TypeOfType : Type, NeverCanonicalUnlessDependent;
|
||||
def DecltypeType : Type, NeverCanonicalUnlessDependent;
|
||||
def UnaryTransformType : Type, NeverCanonicalUnlessDependent;
|
||||
def TagType : Type<1>;
|
||||
def RecordType : DerivedType<TagType>, LeafType;
|
||||
def EnumType : DerivedType<TagType>, LeafType;
|
||||
def ElaboratedType : Type, NeverCanonical;
|
||||
def AttributedType : Type, NeverCanonical;
|
||||
def TemplateTypeParmType : Type, AlwaysDependent, LeafType;
|
||||
def SubstTemplateTypeParmType : Type, NeverCanonical;
|
||||
def SubstTemplateTypeParmPackType : Type, AlwaysDependent;
|
||||
def TemplateSpecializationType : Type, NeverCanonicalUnlessDependent;
|
||||
def DeducedType : Type<1>;
|
||||
def AutoType : DerivedType<DeducedType>;
|
||||
def DeducedTemplateSpecializationType : DerivedType<DeducedType>;
|
||||
def InjectedClassNameType : Type, AlwaysDependent, LeafType;
|
||||
def DependentNameType : Type, AlwaysDependent;
|
||||
def DependentTemplateSpecializationType : Type, AlwaysDependent;
|
||||
def PackExpansionType : Type, NeverCanonicalUnlessDependent;
|
||||
def ObjCTypeParamType : Type, NeverCanonical;
|
||||
def ObjCObjectType : Type;
|
||||
def ObjCInterfaceType : DerivedType<ObjCObjectType>, LeafType;
|
||||
def ObjCObjectPointerType : Type;
|
||||
def PipeType : Type;
|
||||
def AtomicType : Type;
|
@ -173,6 +173,10 @@ PROC(IcelakeClient, "icelake-client", PROC_64_BIT)
|
||||
/// Icelake server microarchitecture based processors.
|
||||
PROC(IcelakeServer, "icelake-server", PROC_64_BIT)
|
||||
|
||||
/// \name Tigerlake
|
||||
/// Tigerlake microarchitecture based processors.
|
||||
PROC(Tigerlake, "tigerlake", PROC_64_BIT)
|
||||
|
||||
/// \name Knights Landing
|
||||
/// Knights Landing processor.
|
||||
PROC_WITH_FEAT(KNL, "knl", PROC_64_BIT, FEATURE_AVX512F)
|
||||
@ -297,6 +301,7 @@ FEATURE(FEATURE_VPCLMULQDQ)
|
||||
FEATURE(FEATURE_AVX512VNNI)
|
||||
FEATURE(FEATURE_AVX512BITALG)
|
||||
FEATURE(FEATURE_AVX512BF16)
|
||||
FEATURE(FEATURE_AVX512VP2INTERSECT)
|
||||
|
||||
|
||||
// FIXME: When commented out features are supported in LLVM, enable them here.
|
||||
|
@ -1651,10 +1651,10 @@ let ArchGuard = "defined(__ARM_FEATURE_DOTPROD) && defined(__aarch64__)" in {
|
||||
|
||||
// v8.2-A FP16 fused multiply-add long instructions.
|
||||
let ArchGuard = "defined(__ARM_FEATURE_FP16FML) && defined(__aarch64__)" in {
|
||||
def VFMLAL_LOW : SInst<"vfmlal_low", "ffHH", "hQh">;
|
||||
def VFMLSL_LOW : SInst<"vfmlsl_low", "ffHH", "hQh">;
|
||||
def VFMLAL_HIGH : SInst<"vfmlal_high", "ffHH", "hQh">;
|
||||
def VFMLSL_HIGH : SInst<"vfmlsl_high", "ffHH", "hQh">;
|
||||
def VFMLAL_LOW : SInst<"vfmlal_low", "nndd", "hQh">;
|
||||
def VFMLSL_LOW : SInst<"vfmlsl_low", "nndd", "hQh">;
|
||||
def VFMLAL_HIGH : SInst<"vfmlal_high", "nndd", "hQh">;
|
||||
def VFMLSL_HIGH : SInst<"vfmlsl_high", "nndd", "hQh">;
|
||||
|
||||
def VFMLAL_LANE_LOW : SOpInst<"vfmlal_lane_low", "ffH0i", "hQh", OP_FMLAL_LN>;
|
||||
def VFMLSL_LANE_LOW : SOpInst<"vfmlsl_lane_low", "ffH0i", "hQh", OP_FMLSL_LN>;
|
||||
|
@ -109,14 +109,12 @@ class ABIArgInfo {
|
||||
UnpaddedCoerceAndExpandType = T;
|
||||
}
|
||||
|
||||
ABIArgInfo(Kind K)
|
||||
: TheKind(K), PaddingInReg(false), InReg(false) {
|
||||
}
|
||||
|
||||
public:
|
||||
ABIArgInfo()
|
||||
ABIArgInfo(Kind K = Direct)
|
||||
: TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
|
||||
TheKind(Direct), PaddingInReg(false), InReg(false) {}
|
||||
TheKind(K), PaddingInReg(false), InAllocaSRet(false),
|
||||
IndirectByVal(false), IndirectRealign(false), SRetAfterThis(false),
|
||||
InReg(false), CanBeFlattened(false), SignExt(false) {}
|
||||
|
||||
static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
|
||||
llvm::Type *Padding = nullptr,
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "clang/AST/ASTImporterSharedState.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
@ -153,18 +154,34 @@ class CrossTranslationUnitContext {
|
||||
/// was passed to the constructor.
|
||||
///
|
||||
/// \return Returns the resulting definition or an error.
|
||||
llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD);
|
||||
llvm::Expected<const VarDecl *> importDefinition(const VarDecl *VD);
|
||||
llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD,
|
||||
ASTUnit *Unit);
|
||||
llvm::Expected<const VarDecl *> importDefinition(const VarDecl *VD,
|
||||
ASTUnit *Unit);
|
||||
|
||||
/// Get a name to identify a named decl.
|
||||
static std::string getLookupName(const NamedDecl *ND);
|
||||
static llvm::Optional<std::string> getLookupName(const NamedDecl *ND);
|
||||
|
||||
/// Emit diagnostics for the user for potential configuration errors.
|
||||
void emitCrossTUDiagnostics(const IndexError &IE);
|
||||
|
||||
/// Determine the original source location in the original TU for an
|
||||
/// imported source location.
|
||||
/// \p ToLoc Source location in the imported-to AST.
|
||||
/// \return Source location in the imported-from AST and the corresponding
|
||||
/// ASTUnit object (the AST was loaded from a file using an internal ASTUnit
|
||||
/// object that is returned here).
|
||||
/// If any error happens (ToLoc is a non-imported source location) empty is
|
||||
/// returned.
|
||||
llvm::Optional<std::pair<SourceLocation /*FromLoc*/, ASTUnit *>>
|
||||
getImportedFromSourceLocation(const clang::SourceLocation &ToLoc) const;
|
||||
|
||||
private:
|
||||
using ImportedFileIDMap =
|
||||
llvm::DenseMap<FileID, std::pair<FileID, ASTUnit *>>;
|
||||
|
||||
void lazyInitImporterSharedSt(TranslationUnitDecl *ToTU);
|
||||
ASTImporter &getOrCreateASTImporter(ASTContext &From);
|
||||
ASTImporter &getOrCreateASTImporter(ASTUnit *Unit);
|
||||
template <typename T>
|
||||
llvm::Expected<const T *> getCrossTUDefinitionImpl(const T *D,
|
||||
StringRef CrossTUDir,
|
||||
@ -174,20 +191,114 @@ class CrossTranslationUnitContext {
|
||||
const T *findDefInDeclContext(const DeclContext *DC,
|
||||
StringRef LookupName);
|
||||
template <typename T>
|
||||
llvm::Expected<const T *> importDefinitionImpl(const T *D);
|
||||
llvm::Expected<const T *> importDefinitionImpl(const T *D, ASTUnit *Unit);
|
||||
|
||||
using ImporterMapTy =
|
||||
llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>>;
|
||||
|
||||
ImporterMapTy ASTUnitImporterMap;
|
||||
|
||||
llvm::StringMap<std::unique_ptr<clang::ASTUnit>> FileASTUnitMap;
|
||||
llvm::StringMap<clang::ASTUnit *> NameASTUnitMap;
|
||||
llvm::StringMap<std::string> NameFileMap;
|
||||
llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>>
|
||||
ASTUnitImporterMap;
|
||||
CompilerInstance &CI;
|
||||
ASTContext &Context;
|
||||
std::shared_ptr<ASTImporterSharedState> ImporterSharedSt;
|
||||
/// \p CTULoadTreshold should serve as an upper limit to the number of TUs
|
||||
/// imported in order to reduce the memory footprint of CTU analysis.
|
||||
const unsigned CTULoadThreshold;
|
||||
unsigned NumASTLoaded{0u};
|
||||
/// Map of imported FileID's (in "To" context) to FileID in "From" context
|
||||
/// and the ASTUnit for the From context.
|
||||
/// This map is used by getImportedFromSourceLocation to lookup a FileID and
|
||||
/// its Preprocessor when knowing only the FileID in the 'To' context. The
|
||||
/// FileID could be imported by any of multiple 'From' ASTImporter objects.
|
||||
/// we do not want to loop over all ASTImporter's to find the one that
|
||||
/// imported the FileID.
|
||||
ImportedFileIDMap ImportedFileIDs;
|
||||
|
||||
/// Functor for loading ASTUnits from AST-dump files.
|
||||
class ASTFileLoader {
|
||||
public:
|
||||
ASTFileLoader(const CompilerInstance &CI);
|
||||
std::unique_ptr<ASTUnit> operator()(StringRef ASTFilePath);
|
||||
|
||||
private:
|
||||
const CompilerInstance &CI;
|
||||
};
|
||||
|
||||
/// Maintain number of AST loads and check for reaching the load limit.
|
||||
class ASTLoadGuard {
|
||||
public:
|
||||
ASTLoadGuard(unsigned Limit) : Limit(Limit) {}
|
||||
|
||||
/// Indicates, whether a new load operation is permitted, it is within the
|
||||
/// threshold.
|
||||
operator bool() const { return Count < Limit; }
|
||||
|
||||
/// Tell that a new AST was loaded successfully.
|
||||
void indicateLoadSuccess() { ++Count; }
|
||||
|
||||
private:
|
||||
/// The number of ASTs actually imported.
|
||||
unsigned Count{0u};
|
||||
/// The limit (threshold) value for number of loaded ASTs.
|
||||
const unsigned Limit;
|
||||
};
|
||||
|
||||
/// Storage and load of ASTUnits, cached access, and providing searchability
|
||||
/// are the concerns of ASTUnitStorage class.
|
||||
class ASTUnitStorage {
|
||||
public:
|
||||
ASTUnitStorage(const CompilerInstance &CI);
|
||||
/// Loads an ASTUnit for a function.
|
||||
///
|
||||
/// \param FunctionName USR name of the function.
|
||||
/// \param CrossTUDir Path to the directory used to store CTU related files.
|
||||
/// \param IndexName Name of the file inside \p CrossTUDir which maps
|
||||
/// function USR names to file paths. These files contain the corresponding
|
||||
/// AST-dumps.
|
||||
/// \param DisplayCTUProgress Display a message about loading new ASTs.
|
||||
///
|
||||
/// \return An Expected instance which contains the ASTUnit pointer or the
|
||||
/// error occured during the load.
|
||||
llvm::Expected<ASTUnit *> getASTUnitForFunction(StringRef FunctionName,
|
||||
StringRef CrossTUDir,
|
||||
StringRef IndexName,
|
||||
bool DisplayCTUProgress);
|
||||
/// Identifies the path of the file which can be used to load the ASTUnit
|
||||
/// for a given function.
|
||||
///
|
||||
/// \param FunctionName USR name of the function.
|
||||
/// \param CrossTUDir Path to the directory used to store CTU related files.
|
||||
/// \param IndexName Name of the file inside \p CrossTUDir which maps
|
||||
/// function USR names to file paths. These files contain the corresponding
|
||||
/// AST-dumps.
|
||||
///
|
||||
/// \return An Expected instance containing the filepath.
|
||||
llvm::Expected<std::string> getFileForFunction(StringRef FunctionName,
|
||||
StringRef CrossTUDir,
|
||||
StringRef IndexName);
|
||||
|
||||
private:
|
||||
llvm::Error ensureCTUIndexLoaded(StringRef CrossTUDir, StringRef IndexName);
|
||||
llvm::Expected<ASTUnit *> getASTUnitForFile(StringRef FileName,
|
||||
bool DisplayCTUProgress);
|
||||
|
||||
template <typename... T> using BaseMapTy = llvm::StringMap<T...>;
|
||||
using OwningMapTy = BaseMapTy<std::unique_ptr<clang::ASTUnit>>;
|
||||
using NonOwningMapTy = BaseMapTy<clang::ASTUnit *>;
|
||||
|
||||
OwningMapTy FileASTUnitMap;
|
||||
NonOwningMapTy NameASTUnitMap;
|
||||
|
||||
using IndexMapTy = BaseMapTy<std::string>;
|
||||
IndexMapTy NameFileMap;
|
||||
|
||||
ASTFileLoader FileAccessor;
|
||||
|
||||
/// Limit the number of loaded ASTs. Used to limit the memory usage of the
|
||||
/// CrossTranslationUnitContext.
|
||||
/// The ASTUnitStorage has the knowledge about if the AST to load is
|
||||
/// actually loaded or returned from cache. This information is needed to
|
||||
/// maintain the counter.
|
||||
ASTLoadGuard LoadGuard;
|
||||
};
|
||||
|
||||
ASTUnitStorage ASTStorage;
|
||||
|
||||
};
|
||||
|
||||
} // namespace cross_tu
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -98,10 +99,11 @@ class DirectoryWatcher {
|
||||
: Kind(Kind), Filename(Filename) {}
|
||||
};
|
||||
|
||||
/// Returns nullptr if \param Path doesn't exist or isn't a directory.
|
||||
/// Returns nullptr if OS kernel API told us we can't start watching. In such
|
||||
/// case it's unclear whether just retrying has any chance to succeeed.
|
||||
static std::unique_ptr<DirectoryWatcher>
|
||||
/// llvm fatal_error if \param Path doesn't exist or isn't a directory.
|
||||
/// Returns llvm::Expected Error if OS kernel API told us we can't start
|
||||
/// watching. In such case it's unclear whether just retrying has any chance
|
||||
/// to succeed.
|
||||
static llvm::Expected<std::unique_ptr<DirectoryWatcher>>
|
||||
create(llvm::StringRef Path,
|
||||
std::function<void(llvm::ArrayRef<DirectoryWatcher::Event> Events,
|
||||
bool IsInitial)>
|
||||
|
@ -65,15 +65,17 @@ class Action {
|
||||
BackendJobClass,
|
||||
AssembleJobClass,
|
||||
LinkJobClass,
|
||||
IfsMergeJobClass,
|
||||
LipoJobClass,
|
||||
DsymutilJobClass,
|
||||
VerifyDebugInfoJobClass,
|
||||
VerifyPCHJobClass,
|
||||
OffloadBundlingJobClass,
|
||||
OffloadUnbundlingJobClass,
|
||||
OffloadWrapperJobClass,
|
||||
|
||||
JobClassFirst = PreprocessJobClass,
|
||||
JobClassLast = OffloadUnbundlingJobClass
|
||||
JobClassLast = OffloadWrapperJobClass
|
||||
};
|
||||
|
||||
// The offloading kind determines if this action is binded to a particular
|
||||
@ -485,6 +487,17 @@ class AssembleJobAction : public JobAction {
|
||||
}
|
||||
};
|
||||
|
||||
class IfsMergeJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
IfsMergeJobAction(ActionList &Inputs, types::ID Type);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == IfsMergeJobClass;
|
||||
}
|
||||
};
|
||||
|
||||
class LinkJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
|
||||
@ -613,6 +626,17 @@ class OffloadUnbundlingJobAction final : public JobAction {
|
||||
}
|
||||
};
|
||||
|
||||
class OffloadWrapperJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
OffloadWrapperJobAction(ActionList &Inputs, types::ID Type);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == OffloadWrapperJobClass;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace driver
|
||||
} // namespace clang
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user