mirror of
https://github.com/opnsense/src.git
synced 2026-06-04 14:26:03 -04:00
Vendor import of llvm-project master e26a78e70, the last commit before
the llvmorg-11-init tag, from which release/10.x was branched.
This commit is contained in:
parent
7cc9cf2bf0
commit
706b4fc47b
3297 changed files with 150294 additions and 74513 deletions
|
|
@ -14,13 +14,12 @@
|
|||
#ifndef LLVM_CLANG_C_BUILDSYSTEM_H
|
||||
#define LLVM_CLANG_C_BUILDSYSTEM_H
|
||||
|
||||
#include "clang-c/Platform.h"
|
||||
#include "clang-c/CXErrorCode.h"
|
||||
#include "clang-c/CXString.h"
|
||||
#include "clang-c/ExternC.h"
|
||||
#include "clang-c/Platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_BEGIN
|
||||
|
||||
/**
|
||||
* \defgroup BUILD_SYSTEM Build system utilities
|
||||
|
|
@ -148,9 +147,7 @@ CINDEX_LINKAGE void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor);
|
|||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_END
|
||||
|
||||
#endif /* CLANG_C_BUILD_SYSTEM_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -15,12 +15,11 @@
|
|||
#ifndef LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
|
||||
#define LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
|
||||
|
||||
#include "clang-c/Platform.h"
|
||||
#include "clang-c/CXString.h"
|
||||
#include "clang-c/ExternC.h"
|
||||
#include "clang-c/Platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_BEGIN
|
||||
|
||||
/** \defgroup COMPILATIONDB CompilationDatabase functions
|
||||
* \ingroup CINDEX
|
||||
|
|
@ -169,8 +168,7 @@ clang_CompileCommand_getMappedSourceContent(CXCompileCommand, unsigned I);
|
|||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,10 @@
|
|||
#ifndef LLVM_CLANG_C_CXERRORCODE_H
|
||||
#define LLVM_CLANG_C_CXERRORCODE_H
|
||||
|
||||
#include "clang-c/ExternC.h"
|
||||
#include "clang-c/Platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_BEGIN
|
||||
|
||||
/**
|
||||
* Error codes returned by libclang routines.
|
||||
|
|
@ -57,8 +56,7 @@ enum CXErrorCode {
|
|||
CXError_ASTReadError = 4
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,10 @@
|
|||
#ifndef LLVM_CLANG_C_CXSTRING_H
|
||||
#define LLVM_CLANG_C_CXSTRING_H
|
||||
|
||||
#include "clang-c/ExternC.h"
|
||||
#include "clang-c/Platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_BEGIN
|
||||
|
||||
/**
|
||||
* \defgroup CINDEX_STRING String manipulation routines
|
||||
|
|
@ -64,8 +63,7 @@ CINDEX_LINKAGE void clang_disposeStringSet(CXStringSet *set);
|
|||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,10 @@
|
|||
#ifndef LLVM_CLANG_C_DOCUMENTATION_H
|
||||
#define LLVM_CLANG_C_DOCUMENTATION_H
|
||||
|
||||
#include "clang-c/ExternC.h"
|
||||
#include "clang-c/Index.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_BEGIN
|
||||
|
||||
/**
|
||||
* \defgroup CINDEX_COMMENT Comment introspection
|
||||
|
|
@ -182,7 +181,12 @@ enum CXCommentInlineCommandRenderKind {
|
|||
* Command argument should be rendered emphasized (typically italic
|
||||
* font).
|
||||
*/
|
||||
CXCommentInlineCommandRenderKind_Emphasized
|
||||
CXCommentInlineCommandRenderKind_Emphasized,
|
||||
|
||||
/**
|
||||
* Command argument should not be rendered (since it only defines an anchor).
|
||||
*/
|
||||
CXCommentInlineCommandRenderKind_Anchor
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -545,10 +549,7 @@ CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment);
|
|||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_END
|
||||
|
||||
#endif /* CLANG_C_DOCUMENTATION_H */
|
||||
|
||||
|
|
|
|||
39
clang/include/clang-c/ExternC.h
Normal file
39
clang/include/clang-c/ExternC.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*===- clang-c/ExternC.h - Wrapper for 'extern "C"' ---------------*- 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 an 'extern "C"' wrapper. *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#ifndef LLVM_CLANG_C_EXTERN_C_H
|
||||
#define LLVM_CLANG_C_EXTERN_C_H
|
||||
|
||||
#ifdef __clang__
|
||||
#define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic error \"-Wstrict-prototypes\"")
|
||||
#define LLVM_CLANG_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop")
|
||||
#else
|
||||
#define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN
|
||||
#define LLVM_CLANG_C_STRICT_PROTOTYPES_END
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define LLVM_CLANG_C_EXTERN_C_BEGIN \
|
||||
extern "C" { \
|
||||
LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN
|
||||
#define LLVM_CLANG_C_EXTERN_C_END \
|
||||
LLVM_CLANG_C_STRICT_PROTOTYPES_END \
|
||||
}
|
||||
#else
|
||||
#define LLVM_CLANG_C_EXTERN_C_BEGIN LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN
|
||||
#define LLVM_CLANG_C_EXTERN_C_END LLVM_CLANG_C_STRICT_PROTOTYPES_END
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -10,9 +10,9 @@
|
|||
#ifndef LLVM_CLANG_C_FATAL_ERROR_HANDLER_H
|
||||
#define LLVM_CLANG_C_FATAL_ERROR_HANDLER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "clang-c/ExternC.h"
|
||||
|
||||
LLVM_CLANG_C_EXTERN_C_BEGIN
|
||||
|
||||
/**
|
||||
* Installs error handler that prints error message to stderr and calls abort().
|
||||
|
|
@ -27,7 +27,6 @@ void clang_install_aborting_llvm_fatal_error_handler(void);
|
|||
*/
|
||||
void clang_uninstall_llvm_fatal_error_handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,10 +18,11 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
#include "clang-c/Platform.h"
|
||||
#include "clang-c/BuildSystem.h"
|
||||
#include "clang-c/CXErrorCode.h"
|
||||
#include "clang-c/CXString.h"
|
||||
#include "clang-c/BuildSystem.h"
|
||||
#include "clang-c/ExternC.h"
|
||||
#include "clang-c/Platform.h"
|
||||
|
||||
/**
|
||||
* The version constants for the libclang API.
|
||||
|
|
@ -51,9 +52,7 @@
|
|||
CINDEX_VERSION_MAJOR, \
|
||||
CINDEX_VERSION_MINOR)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_BEGIN
|
||||
|
||||
/** \defgroup CINDEX libclang: C Interface to Clang
|
||||
*
|
||||
|
|
@ -2567,8 +2566,15 @@ enum CXCursorKind {
|
|||
*/
|
||||
CXCursor_OMPMasterTaskLoopSimdDirective = 283,
|
||||
|
||||
/** OpenMP parallel master taskloop simd directive.
|
||||
*/
|
||||
CXCursor_OMPParallelMasterTaskLoopSimdDirective = 284,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OMPMasterTaskLoopSimdDirective,
|
||||
/** OpenMP parallel master directive.
|
||||
*/
|
||||
CXCursor_OMPParallelMasterDirective = 285,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OMPParallelMasterDirective,
|
||||
|
||||
/**
|
||||
* Cursor that represents the translation unit itself.
|
||||
|
|
@ -6771,7 +6777,6 @@ CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T,
|
|||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@
|
|||
#ifndef LLVM_CLANG_C_PLATFORM_H
|
||||
#define LLVM_CLANG_C_PLATFORM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "clang-c/ExternC.h"
|
||||
|
||||
LLVM_CLANG_C_EXTERN_C_BEGIN
|
||||
|
||||
/* MSVC DLL import/export. */
|
||||
#ifdef _MSC_VER
|
||||
|
|
@ -39,7 +39,6 @@ extern "C" {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
LLVM_CLANG_C_EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
177
clang/include/clang/AST/ASTConcept.h
Normal file
177
clang/include/clang/AST/ASTConcept.h
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
//===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// \brief This file provides AST data structures related to concepts.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_ASTCONCEPT_H
|
||||
#define LLVM_CLANG_AST_ASTCONCEPT_H
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <string>
|
||||
#include <utility>
|
||||
namespace clang {
|
||||
class ConceptDecl;
|
||||
|
||||
/// \brief The result of a constraint satisfaction check, containing the
|
||||
/// necessary information to diagnose an unsatisfied constraint.
|
||||
struct ConstraintSatisfaction {
|
||||
using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
|
||||
using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
|
||||
|
||||
bool IsSatisfied = false;
|
||||
|
||||
/// \brief Pairs of unsatisfied atomic constraint expressions along with the
|
||||
/// substituted constraint expr, if the template arguments could be
|
||||
/// substituted into them, or a diagnostic if substitution resulted in an
|
||||
/// invalid expression.
|
||||
llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details;
|
||||
|
||||
// This can leak if used in an AST node, use ASTConstraintSatisfaction
|
||||
// instead.
|
||||
void *operator new(size_t bytes, ASTContext &C) = delete;
|
||||
};
|
||||
|
||||
/// Pairs of unsatisfied atomic constraint expressions along with the
|
||||
/// substituted constraint expr, if the template arguments could be
|
||||
/// substituted into them, or a diagnostic if substitution resulted in
|
||||
/// an invalid expression.
|
||||
using UnsatisfiedConstraintRecord =
|
||||
std::pair<const Expr *,
|
||||
llvm::PointerUnion<Expr *,
|
||||
std::pair<SourceLocation, StringRef> *>>;
|
||||
|
||||
/// \brief The result of a constraint satisfaction check, containing the
|
||||
/// necessary information to diagnose an unsatisfied constraint.
|
||||
///
|
||||
/// This is safe to store in an AST node, as opposed to ConstraintSatisfaction.
|
||||
struct ASTConstraintSatisfaction final :
|
||||
llvm::TrailingObjects<ASTConstraintSatisfaction,
|
||||
UnsatisfiedConstraintRecord> {
|
||||
std::size_t NumRecords;
|
||||
bool IsSatisfied : 1;
|
||||
|
||||
const UnsatisfiedConstraintRecord *begin() const {
|
||||
return getTrailingObjects<UnsatisfiedConstraintRecord>();
|
||||
}
|
||||
|
||||
const UnsatisfiedConstraintRecord *end() const {
|
||||
return getTrailingObjects<UnsatisfiedConstraintRecord>() + NumRecords;
|
||||
}
|
||||
|
||||
ASTConstraintSatisfaction(const ASTContext &C,
|
||||
const ConstraintSatisfaction &Satisfaction);
|
||||
|
||||
static ASTConstraintSatisfaction *
|
||||
Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
|
||||
};
|
||||
|
||||
/// \brief Common data class for constructs that reference concepts with
|
||||
/// template arguments.
|
||||
class ConceptReference {
|
||||
protected:
|
||||
// \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 concept name used.
|
||||
DeclarationNameInfo ConceptName;
|
||||
|
||||
/// \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.
|
||||
ConceptDecl *NamedConcept;
|
||||
|
||||
/// \brief The template argument list source info used to specialize the
|
||||
/// concept.
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten;
|
||||
|
||||
public:
|
||||
|
||||
ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
|
||||
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
|
||||
ConceptDecl *NamedConcept,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten) :
|
||||
NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
|
||||
ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
|
||||
NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {}
|
||||
|
||||
ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(),
|
||||
FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {}
|
||||
|
||||
const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
|
||||
return NestedNameSpec;
|
||||
}
|
||||
|
||||
const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; }
|
||||
|
||||
SourceLocation getConceptNameLoc() const {
|
||||
return getConceptNameInfo().getLoc();
|
||||
}
|
||||
|
||||
SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
|
||||
|
||||
NamedDecl *getFoundDecl() const {
|
||||
return FoundDecl;
|
||||
}
|
||||
|
||||
ConceptDecl *getNamedConcept() const {
|
||||
return NamedConcept;
|
||||
}
|
||||
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
return ArgsAsWritten;
|
||||
}
|
||||
|
||||
/// \brief Whether or not template arguments were explicitly specified in the
|
||||
/// concept reference (they might not be in type constraints, for example)
|
||||
bool hasExplicitTemplateArgs() const {
|
||||
return ArgsAsWritten != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class TypeConstraint : public ConceptReference {
|
||||
/// \brief The immediately-declared constraint expression introduced by this
|
||||
/// type-constraint.
|
||||
Expr *ImmediatelyDeclaredConstraint = nullptr;
|
||||
|
||||
public:
|
||||
TypeConstraint(NestedNameSpecifierLoc NNS,
|
||||
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
|
||||
ConceptDecl *NamedConcept,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
Expr *ImmediatelyDeclaredConstraint) :
|
||||
ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo,
|
||||
FoundDecl, NamedConcept, ArgsAsWritten),
|
||||
ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {}
|
||||
|
||||
/// \brief Get the immediately-declared constraint expression introduced by
|
||||
/// this type-constraint, that is - the constraint expression that is added to
|
||||
/// the associated constraints of the enclosing declaration in practice.
|
||||
Expr *getImmediatelyDeclaredConstraint() const {
|
||||
return ImmediatelyDeclaredConstraint;
|
||||
}
|
||||
|
||||
void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const;
|
||||
};
|
||||
|
||||
} // clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_ASTCONCEPT_H
|
||||
|
|
@ -102,6 +102,11 @@ public:
|
|||
/// modified by the introduction of an implicit zero initializer.
|
||||
virtual void CompleteTentativeDefinition(VarDecl *D) {}
|
||||
|
||||
/// CompleteExternalDeclaration - Callback invoked at the end of a translation
|
||||
/// unit to notify the consumer that the given external declaration should be
|
||||
/// completed.
|
||||
virtual void CompleteExternalDeclaration(VarDecl *D) {}
|
||||
|
||||
/// Callback invoked when an MSInheritanceAttr has been attached to a
|
||||
/// CXXRecordDecl.
|
||||
virtual void AssignInheritanceModel(CXXRecordDecl *RD) {}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExternalASTSource.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
|
|
@ -96,6 +95,7 @@ class CXXRecordDecl;
|
|||
class DiagnosticsEngine;
|
||||
class Expr;
|
||||
class FixedPointSemantics;
|
||||
class GlobalDecl;
|
||||
class MangleContext;
|
||||
class MangleNumberingContext;
|
||||
class MaterializeTemporaryExpr;
|
||||
|
|
@ -113,9 +113,11 @@ class ObjCPropertyDecl;
|
|||
class ObjCPropertyImplDecl;
|
||||
class ObjCProtocolDecl;
|
||||
class ObjCTypeParamDecl;
|
||||
struct ParsedTargetAttr;
|
||||
class Preprocessor;
|
||||
class Stmt;
|
||||
class StoredDeclsMap;
|
||||
class TargetAttr;
|
||||
class TemplateDecl;
|
||||
class TemplateParameterList;
|
||||
class TemplateTemplateParmDecl;
|
||||
|
|
@ -124,6 +126,7 @@ class UnresolvedSetIterator;
|
|||
class UsingShadowDecl;
|
||||
class VarTemplateDecl;
|
||||
class VTableContextBase;
|
||||
struct BlockVarCopyInit;
|
||||
|
||||
namespace Builtin {
|
||||
|
||||
|
|
@ -145,6 +148,10 @@ class Context;
|
|||
|
||||
} // namespace interp
|
||||
|
||||
namespace serialization {
|
||||
template <class> class AbstractTypeReader;
|
||||
} // namespace serialization
|
||||
|
||||
struct TypeInfo {
|
||||
uint64_t Width = 0;
|
||||
unsigned Align = 0;
|
||||
|
|
@ -158,22 +165,6 @@ struct TypeInfo {
|
|||
/// Holds long-lived AST nodes (such as types and decls) that can be
|
||||
/// referred to throughout the semantic analysis of a file.
|
||||
class ASTContext : public RefCountedBase<ASTContext> {
|
||||
public:
|
||||
/// Copy initialization expr of a __block variable and a boolean flag that
|
||||
/// indicates whether the expression can throw.
|
||||
struct BlockVarCopyInit {
|
||||
BlockVarCopyInit() = default;
|
||||
BlockVarCopyInit(Expr *CopyExpr, bool CanThrow)
|
||||
: ExprAndFlag(CopyExpr, CanThrow) {}
|
||||
void setExprAndFlag(Expr *CopyExpr, bool CanThrow) {
|
||||
ExprAndFlag.setPointerAndInt(CopyExpr, CanThrow);
|
||||
}
|
||||
Expr *getCopyExpr() const { return ExprAndFlag.getPointer(); }
|
||||
bool canThrow() const { return ExprAndFlag.getInt(); }
|
||||
llvm::PointerIntPair<Expr *, 1, bool> ExprAndFlag;
|
||||
};
|
||||
|
||||
private:
|
||||
friend class NestedNameSpecifier;
|
||||
|
||||
mutable SmallVector<Type *, 0> Types;
|
||||
|
|
@ -272,12 +263,6 @@ private:
|
|||
/// Mapping from __block VarDecls to BlockVarCopyInit.
|
||||
llvm::DenseMap<const VarDecl *, BlockVarCopyInit> BlockVarCopyInits;
|
||||
|
||||
/// Mapping from materialized temporaries with static storage duration
|
||||
/// that appear in constant initializers to their evaluated values. These are
|
||||
/// allocated in a std::map because their address must be stable.
|
||||
llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *>
|
||||
MaterializedTemporaryValues;
|
||||
|
||||
/// Used to cleanups APValues stored in the AST.
|
||||
mutable llvm::SmallVector<APValue *, 0> APValueCleanups;
|
||||
|
||||
|
|
@ -298,12 +283,16 @@ private:
|
|||
|
||||
TemplateTemplateParmDecl *getParam() const { return Parm; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Parm); }
|
||||
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
|
||||
Profile(ID, C, Parm);
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
const ASTContext &C,
|
||||
TemplateTemplateParmDecl *Parm);
|
||||
};
|
||||
mutable llvm::FoldingSet<CanonicalTemplateTemplateParm>
|
||||
mutable llvm::ContextualFoldingSet<CanonicalTemplateTemplateParm,
|
||||
const ASTContext&>
|
||||
CanonTemplateTemplateParms;
|
||||
|
||||
TemplateTemplateParmDecl *
|
||||
|
|
@ -435,6 +424,7 @@ private:
|
|||
friend class ASTDeclReader;
|
||||
friend class ASTReader;
|
||||
friend class ASTWriter;
|
||||
template <class> friend class serialization::AbstractTypeReader;
|
||||
friend class CXXRecordDecl;
|
||||
|
||||
/// A mapping to contain the template or declaration that
|
||||
|
|
@ -575,7 +565,17 @@ private:
|
|||
clang::PrintingPolicy PrintingPolicy;
|
||||
std::unique_ptr<interp::Context> InterpContext;
|
||||
|
||||
ast_type_traits::TraversalKind Traversal = ast_type_traits::TK_AsIs;
|
||||
|
||||
public:
|
||||
ast_type_traits::TraversalKind getTraversalKind() const { return Traversal; }
|
||||
void setTraversalKind(ast_type_traits::TraversalKind TK) { Traversal = TK; }
|
||||
|
||||
const Expr *traverseIgnored(const Expr *E) const;
|
||||
Expr *traverseIgnored(Expr *E) const;
|
||||
ast_type_traits::DynTypedNode
|
||||
traverseIgnored(const ast_type_traits::DynTypedNode &N) const;
|
||||
|
||||
IdentifierTable &Idents;
|
||||
SelectorTable &Selectors;
|
||||
Builtin::Context &BuiltinInfo;
|
||||
|
|
@ -1162,6 +1162,10 @@ public:
|
|||
/// attribute.
|
||||
QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr) const;
|
||||
|
||||
/// Remove the existing address space on the type if it is a pointer size
|
||||
/// address space and return the type with qualifiers intact.
|
||||
QualType removePtrSizeAddrSpace(QualType T) const;
|
||||
|
||||
/// Return the uniqued reference to the type for a \c restrict
|
||||
/// qualified type.
|
||||
///
|
||||
|
|
@ -1216,6 +1220,15 @@ public:
|
|||
const FunctionProtoType::ExceptionSpecInfo &ESI,
|
||||
bool AsWritten = false);
|
||||
|
||||
/// Get a function type and produce the equivalent function type where
|
||||
/// pointer size address spaces in the return type and parameter tyeps are
|
||||
/// replaced with the default address space.
|
||||
QualType getFunctionTypeWithoutPtrSizes(QualType T);
|
||||
|
||||
/// Determine whether two function types are the same, ignoring pointer sizes
|
||||
/// in the return type and parameter types.
|
||||
bool hasSameFunctionTypeIgnoringPtrSizes(QualType T, QualType U);
|
||||
|
||||
/// Return the uniqued reference to the type for a complex
|
||||
/// number with the specified element type.
|
||||
QualType getComplexType(QualType T) const;
|
||||
|
|
@ -2827,16 +2840,20 @@ public:
|
|||
/// index of the parameter when it exceeds the size of the normal bitfield.
|
||||
unsigned getParameterIndex(const ParmVarDecl *D) const;
|
||||
|
||||
/// Get the storage for the constant value of a materialized temporary
|
||||
/// of static storage duration.
|
||||
APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E,
|
||||
bool MayCreate);
|
||||
|
||||
/// Return a string representing the human readable name for the specified
|
||||
/// function declaration or file name. Used by SourceLocExpr and
|
||||
/// PredefinedExpr to cache evaluated results.
|
||||
StringLiteral *getPredefinedStringLiteralFromCache(StringRef Key) const;
|
||||
|
||||
/// Parses the target attributes passed in, and returns only the ones that are
|
||||
/// valid feature names.
|
||||
ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const;
|
||||
|
||||
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
|
||||
const FunctionDecl *) const;
|
||||
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
|
||||
GlobalDecl GD) const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Statistics
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
@ -3007,7 +3024,7 @@ private:
|
|||
|
||||
std::vector<Decl *> TraversalScope;
|
||||
class ParentMap;
|
||||
std::unique_ptr<ParentMap> Parents;
|
||||
std::map<ast_type_traits::TraversalKind, std::unique_ptr<ParentMap>> Parents;
|
||||
|
||||
std::unique_ptr<VTableContextBase> VTContext;
|
||||
|
||||
|
|
@ -3051,6 +3068,22 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
|
|||
return Ctx.Selectors.getSelector(1, &II);
|
||||
}
|
||||
|
||||
class TraversalKindScope {
|
||||
ASTContext &Ctx;
|
||||
ast_type_traits::TraversalKind TK = ast_type_traits::TK_AsIs;
|
||||
|
||||
public:
|
||||
TraversalKindScope(ASTContext &Ctx,
|
||||
llvm::Optional<ast_type_traits::TraversalKind> ScopeTK)
|
||||
: Ctx(Ctx) {
|
||||
TK = Ctx.getTraversalKind();
|
||||
if (ScopeTK)
|
||||
Ctx.setTraversalKind(*ScopeTK);
|
||||
}
|
||||
|
||||
~TraversalKindScope() { Ctx.setTraversalKind(TK); }
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
// operator new and delete aren't allowed inside namespaces.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ class Type;
|
|||
#define TYPE(DERIVED, BASE) class DERIVED##Type;
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
class CXXCtorInitializer;
|
||||
class OMPClause;
|
||||
#define OPENMP_CLAUSE(KIND, CLASSNAME) class CLASSNAME;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
|
|
|||
|
|
@ -60,8 +60,12 @@ class TypeSourceInfo;
|
|||
|
||||
static char ID;
|
||||
|
||||
ImportError() : Error(Unknown) { }
|
||||
ImportError(const ImportError &Other) : Error(Other.Error) { }
|
||||
ImportError() : Error(Unknown) {}
|
||||
ImportError(const ImportError &Other) : Error(Other.Error) {}
|
||||
ImportError &operator=(const ImportError &Other) {
|
||||
Error = Other.Error;
|
||||
return *this;
|
||||
}
|
||||
ImportError(ErrorKind Error) : Error(Error) { }
|
||||
|
||||
std::string toString() const;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,17 @@ inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) {
|
|||
dyn_cast<CXXMethodDecl>(DC));
|
||||
}
|
||||
|
||||
inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization(
|
||||
DeclContext *DC) {
|
||||
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC);
|
||||
if (!MD) return false;
|
||||
const CXXRecordDecl *LambdaClass = MD->getParent();
|
||||
if (LambdaClass && LambdaClass->isGenericLambda())
|
||||
return (isLambdaCallOperator(MD) || MD->isLambdaStaticInvoker()) &&
|
||||
MD->isFunctionTemplateSpecialization();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// This returns the parent DeclContext ensuring that the correct
|
||||
// parent DeclContext is returned for Lambdas
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ class ASTNodeTraverser
|
|||
/// not already been loaded.
|
||||
bool Deserialize = false;
|
||||
|
||||
ast_type_traits::TraversalKind Traversal =
|
||||
ast_type_traits::TraversalKind::TK_AsIs;
|
||||
|
||||
NodeDelegateType &getNodeDelegate() {
|
||||
return getDerived().doGetNodeDelegate();
|
||||
}
|
||||
|
|
@ -74,6 +77,8 @@ public:
|
|||
void setDeserialize(bool D) { Deserialize = D; }
|
||||
bool getDeserialize() const { return Deserialize; }
|
||||
|
||||
void SetTraversalKind(ast_type_traits::TraversalKind TK) { Traversal = TK; }
|
||||
|
||||
void Visit(const Decl *D) {
|
||||
getNodeDelegate().AddChild([=] {
|
||||
getNodeDelegate().Visit(D);
|
||||
|
|
@ -97,8 +102,23 @@ public:
|
|||
});
|
||||
}
|
||||
|
||||
void Visit(const Stmt *S, StringRef Label = {}) {
|
||||
void Visit(const Stmt *Node, StringRef Label = {}) {
|
||||
getNodeDelegate().AddChild(Label, [=] {
|
||||
const Stmt *S = Node;
|
||||
|
||||
if (auto *E = dyn_cast_or_null<Expr>(S)) {
|
||||
switch (Traversal) {
|
||||
case ast_type_traits::TK_AsIs:
|
||||
break;
|
||||
case ast_type_traits::TK_IgnoreImplicitCastsAndParentheses:
|
||||
S = E->IgnoreParenImpCasts();
|
||||
break;
|
||||
case ast_type_traits::TK_IgnoreUnlessSpelledInSource:
|
||||
S = E->IgnoreUnlessSpelledInSource();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
getNodeDelegate().Visit(S);
|
||||
|
||||
if (!S) {
|
||||
|
|
@ -108,9 +128,12 @@ public:
|
|||
ConstStmtVisitor<Derived>::Visit(S);
|
||||
|
||||
// Some statements have custom mechanisms for dumping their children.
|
||||
if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S)) {
|
||||
if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S))
|
||||
return;
|
||||
|
||||
if (isa<LambdaExpr>(S) &&
|
||||
Traversal == ast_type_traits::TK_IgnoreUnlessSpelledInSource)
|
||||
return;
|
||||
}
|
||||
|
||||
for (const Stmt *SubStmt : S->children())
|
||||
Visit(SubStmt);
|
||||
|
|
@ -361,6 +384,9 @@ public:
|
|||
for (const auto *Parameter : D->parameters())
|
||||
Visit(Parameter);
|
||||
|
||||
if (const Expr *TRC = D->getTrailingRequiresClause())
|
||||
Visit(TRC);
|
||||
|
||||
if (const auto *C = dyn_cast<CXXConstructorDecl>(D))
|
||||
for (const auto *I : C->inits())
|
||||
Visit(I);
|
||||
|
|
@ -511,6 +537,10 @@ public:
|
|||
}
|
||||
|
||||
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
|
||||
if (const auto *TC = D->getTypeConstraint())
|
||||
if (TC->hasExplicitTemplateArgs())
|
||||
for (const auto &ArgLoc : TC->getTemplateArgsAsWritten()->arguments())
|
||||
dumpTemplateArgumentLoc(ArgLoc);
|
||||
if (D->hasDefaultArgument())
|
||||
Visit(D->getDefaultArgument(), SourceRange(),
|
||||
D->getDefaultArgStorage().getInheritedFrom(),
|
||||
|
|
@ -518,6 +548,8 @@ public:
|
|||
}
|
||||
|
||||
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
|
||||
if (const auto *TC = D->getPlaceholderTypeConstraint())
|
||||
Visit(TC->getImmediatelyDeclaredConstraint());
|
||||
if (D->hasDefaultArgument())
|
||||
Visit(D->getDefaultArgument(), SourceRange(),
|
||||
D->getDefaultArgStorage().getInheritedFrom(),
|
||||
|
|
@ -620,13 +652,29 @@ public:
|
|||
Visit(E->getControllingExpr());
|
||||
Visit(E->getControllingExpr()->getType()); // FIXME: remove
|
||||
|
||||
for (const auto &Assoc : E->associations()) {
|
||||
for (const auto Assoc : E->associations()) {
|
||||
Visit(Assoc);
|
||||
}
|
||||
}
|
||||
|
||||
void VisitLambdaExpr(const LambdaExpr *Node) {
|
||||
Visit(Node->getLambdaClass());
|
||||
if (Traversal == ast_type_traits::TK_IgnoreUnlessSpelledInSource) {
|
||||
for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
|
||||
const auto *C = Node->capture_begin() + I;
|
||||
if (!C->isExplicit())
|
||||
continue;
|
||||
if (Node->isInitCapture(C))
|
||||
Visit(C->getCapturedVar());
|
||||
else
|
||||
Visit(Node->capture_init_begin()[I]);
|
||||
}
|
||||
dumpTemplateParameters(Node->getTemplateParameterList());
|
||||
for (const auto *P : Node->getCallOperator()->parameters())
|
||||
Visit(P);
|
||||
Visit(Node->getBody());
|
||||
} else {
|
||||
return Visit(Node->getLambdaClass());
|
||||
}
|
||||
}
|
||||
|
||||
void VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
|
||||
|
|
|
|||
|
|
@ -16,10 +16,7 @@
|
|||
#define LLVM_CLANG_AST_ASTTYPETRAITS_H
|
||||
|
||||
#include "clang/AST/ASTFwd.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/OpenMPClause.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
|
|
@ -46,7 +43,10 @@ enum TraversalKind {
|
|||
|
||||
/// Will not traverse implicit casts and parentheses.
|
||||
/// Corresponds to Expr::IgnoreParenImpCasts()
|
||||
TK_IgnoreImplicitCastsAndParentheses
|
||||
TK_IgnoreImplicitCastsAndParentheses,
|
||||
|
||||
/// Ignore AST nodes not written in the source
|
||||
TK_IgnoreUnlessSpelledInSource
|
||||
};
|
||||
|
||||
/// Kind identifier.
|
||||
|
|
|
|||
263
clang/include/clang/AST/AbstractBasicReader.h
Normal file
263
clang/include/clang/AST/AbstractBasicReader.h
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
//==--- AbstractBasiceReader.h - Abstract basic value deserialization -----===//
|
||||
//
|
||||
// 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 CLANG_AST_ABSTRACTBASICREADER_H
|
||||
#define CLANG_AST_ABSTRACTBASICREADER_H
|
||||
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialization {
|
||||
|
||||
template <class T>
|
||||
inline T makeNullableFromOptional(const Optional<T> &value) {
|
||||
return (value ? *value : T());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T *makePointerFromOptional(Optional<T *> value) {
|
||||
return (value ? *value : nullptr);
|
||||
}
|
||||
|
||||
// PropertyReader is a class concept that requires the following method:
|
||||
// BasicReader find(llvm::StringRef propertyName);
|
||||
// where BasicReader is some class conforming to the BasicReader concept.
|
||||
// An abstract AST-node reader is created with a PropertyReader and
|
||||
// performs a sequence of calls like so:
|
||||
// propertyReader.find(propertyName).read##TypeName()
|
||||
// to read the properties of the node it is deserializing.
|
||||
|
||||
// BasicReader is a class concept that requires methods like:
|
||||
// ValueType read##TypeName();
|
||||
// where TypeName is the name of a PropertyType node from PropertiesBase.td
|
||||
// and ValueType is the corresponding C++ type name. The read method may
|
||||
// require one or more buffer arguments.
|
||||
//
|
||||
// In addition to the concrete type names, BasicReader is expected to
|
||||
// implement these methods:
|
||||
//
|
||||
// template <class EnumType>
|
||||
// void writeEnum(T value);
|
||||
//
|
||||
// Reads an enum value from the current property. EnumType will always
|
||||
// be an enum type. Only necessary if the BasicReader doesn't provide
|
||||
// type-specific readers for all the enum types.
|
||||
//
|
||||
// template <class ValueType>
|
||||
// Optional<ValueType> writeOptional();
|
||||
//
|
||||
// Reads an optional value from the current property.
|
||||
//
|
||||
// template <class ValueType>
|
||||
// ArrayRef<ValueType> readArray(llvm::SmallVectorImpl<ValueType> &buffer);
|
||||
//
|
||||
// Reads an array of values from the current property.
|
||||
//
|
||||
// PropertyReader readObject();
|
||||
//
|
||||
// Reads an object from the current property; the returned property
|
||||
// reader will be subjected to a sequence of property reads and then
|
||||
// discarded before any other properties are reader from the "outer"
|
||||
// property reader (which need not be the same type). The sub-reader
|
||||
// will be used as if with the following code:
|
||||
//
|
||||
// {
|
||||
// auto &&widget = W.find("widget").readObject();
|
||||
// auto kind = widget.find("kind").readWidgetKind();
|
||||
// auto declaration = widget.find("declaration").readDeclRef();
|
||||
// return Widget(kind, declaration);
|
||||
// }
|
||||
|
||||
// ReadDispatcher does type-based forwarding to one of the read methods
|
||||
// on the BasicReader passed in:
|
||||
//
|
||||
// template <class ValueType>
|
||||
// struct ReadDispatcher {
|
||||
// template <class BasicReader, class... BufferTypes>
|
||||
// static ValueType read(BasicReader &R, BufferTypes &&...);
|
||||
// };
|
||||
|
||||
// BasicReaderBase provides convenience implementations of the read methods
|
||||
// for EnumPropertyType and SubclassPropertyType types that just defer to
|
||||
// the "underlying" implementations (for UInt32 and the base class,
|
||||
// respectively).
|
||||
//
|
||||
// template <class Impl>
|
||||
// class BasicReaderBase {
|
||||
// protected:
|
||||
// BasicReaderBase(ASTContext &ctx);
|
||||
// Impl &asImpl();
|
||||
// public:
|
||||
// ASTContext &getASTContext();
|
||||
// ...
|
||||
// };
|
||||
|
||||
// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
|
||||
#include "clang/AST/AbstractBasicReader.inc"
|
||||
|
||||
/// DataStreamBasicReader provides convenience implementations for many
|
||||
/// BasicReader methods based on the assumption that the
|
||||
/// ultimate reader implementation is based on a variable-length stream
|
||||
/// of unstructured data (like Clang's module files). It is designed
|
||||
/// to pair with DataStreamBasicWriter.
|
||||
///
|
||||
/// This class can also act as a PropertyReader, implementing find("...")
|
||||
/// by simply forwarding to itself.
|
||||
///
|
||||
/// Unimplemented methods:
|
||||
/// readBool
|
||||
/// readUInt32
|
||||
/// readUInt64
|
||||
/// readIdentifier
|
||||
/// readSelector
|
||||
/// readSourceLocation
|
||||
/// readQualType
|
||||
/// readStmtRef
|
||||
/// readDeclRef
|
||||
template <class Impl>
|
||||
class DataStreamBasicReader : public BasicReaderBase<Impl> {
|
||||
protected:
|
||||
using BasicReaderBase<Impl>::asImpl;
|
||||
DataStreamBasicReader(ASTContext &ctx) : BasicReaderBase<Impl>(ctx) {}
|
||||
|
||||
public:
|
||||
using BasicReaderBase<Impl>::getASTContext;
|
||||
|
||||
/// Implement property-find by ignoring it. We rely on properties being
|
||||
/// serialized and deserialized in a reliable order instead.
|
||||
Impl &find(const char *propertyName) {
|
||||
return asImpl();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T readEnum() {
|
||||
return T(asImpl().readUInt32());
|
||||
}
|
||||
|
||||
// Implement object reading by forwarding to this, collapsing the
|
||||
// structure into a single data stream.
|
||||
Impl &readObject() { return asImpl(); }
|
||||
|
||||
template <class T>
|
||||
llvm::ArrayRef<T> readArray(llvm::SmallVectorImpl<T> &buffer) {
|
||||
assert(buffer.empty());
|
||||
|
||||
uint32_t size = asImpl().readUInt32();
|
||||
buffer.reserve(size);
|
||||
|
||||
for (uint32_t i = 0; i != size; ++i) {
|
||||
buffer.push_back(ReadDispatcher<T>::read(asImpl()));
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
llvm::Optional<T> readOptional(Args &&...args) {
|
||||
return UnpackOptionalValue<T>::unpack(
|
||||
ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
llvm::APSInt readAPSInt() {
|
||||
bool isUnsigned = asImpl().readBool();
|
||||
llvm::APInt value = asImpl().readAPInt();
|
||||
return llvm::APSInt(std::move(value), isUnsigned);
|
||||
}
|
||||
|
||||
llvm::APInt readAPInt() {
|
||||
unsigned bitWidth = asImpl().readUInt32();
|
||||
unsigned numWords = llvm::APInt::getNumWords(bitWidth);
|
||||
llvm::SmallVector<uint64_t, 4> data;
|
||||
for (uint32_t i = 0; i != numWords; ++i)
|
||||
data.push_back(asImpl().readUInt64());
|
||||
return llvm::APInt(bitWidth, numWords, &data[0]);
|
||||
}
|
||||
|
||||
Qualifiers readQualifiers() {
|
||||
static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
|
||||
"update this if the value size changes");
|
||||
uint32_t value = asImpl().readUInt32();
|
||||
return Qualifiers::fromOpaqueValue(value);
|
||||
}
|
||||
|
||||
FunctionProtoType::ExceptionSpecInfo
|
||||
readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> &buffer) {
|
||||
FunctionProtoType::ExceptionSpecInfo esi;
|
||||
esi.Type = ExceptionSpecificationType(asImpl().readUInt32());
|
||||
if (esi.Type == EST_Dynamic) {
|
||||
esi.Exceptions = asImpl().template readArray<QualType>(buffer);
|
||||
} else if (isComputedNoexcept(esi.Type)) {
|
||||
esi.NoexceptExpr = asImpl().readExprRef();
|
||||
} else if (esi.Type == EST_Uninstantiated) {
|
||||
esi.SourceDecl = asImpl().readFunctionDeclRef();
|
||||
esi.SourceTemplate = asImpl().readFunctionDeclRef();
|
||||
} else if (esi.Type == EST_Unevaluated) {
|
||||
esi.SourceDecl = asImpl().readFunctionDeclRef();
|
||||
}
|
||||
return esi;
|
||||
}
|
||||
|
||||
FunctionProtoType::ExtParameterInfo readExtParameterInfo() {
|
||||
static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue())
|
||||
<= sizeof(uint32_t),
|
||||
"opaque value doesn't fit into uint32_t");
|
||||
uint32_t value = asImpl().readUInt32();
|
||||
return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
|
||||
}
|
||||
|
||||
NestedNameSpecifier *readNestedNameSpecifier() {
|
||||
auto &ctx = getASTContext();
|
||||
|
||||
// We build this up iteratively.
|
||||
NestedNameSpecifier *cur = nullptr;
|
||||
|
||||
uint32_t depth = asImpl().readUInt32();
|
||||
for (uint32_t i = 0; i != depth; ++i) {
|
||||
auto kind = asImpl().readNestedNameSpecifierKind();
|
||||
switch (kind) {
|
||||
case NestedNameSpecifier::Identifier:
|
||||
cur = NestedNameSpecifier::Create(ctx, cur,
|
||||
asImpl().readIdentifier());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Namespace:
|
||||
cur = NestedNameSpecifier::Create(ctx, cur,
|
||||
asImpl().readNamespaceDeclRef());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::NamespaceAlias:
|
||||
cur = NestedNameSpecifier::Create(ctx, cur,
|
||||
asImpl().readNamespaceAliasDeclRef());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
cur = NestedNameSpecifier::Create(ctx, cur,
|
||||
kind == NestedNameSpecifier::TypeSpecWithTemplate,
|
||||
asImpl().readQualType().getTypePtr());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Global:
|
||||
cur = NestedNameSpecifier::GlobalSpecifier(ctx);
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Super:
|
||||
cur = NestedNameSpecifier::SuperSpecifier(ctx,
|
||||
asImpl().readCXXRecordDeclRef());
|
||||
continue;
|
||||
}
|
||||
llvm_unreachable("bad nested name specifier kind");
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace serialization
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
243
clang/include/clang/AST/AbstractBasicWriter.h
Normal file
243
clang/include/clang/AST/AbstractBasicWriter.h
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
//==--- AbstractBasicWriter.h - Abstract basic value serialization --------===//
|
||||
//
|
||||
// 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 CLANG_AST_ABSTRACTBASICWRITER_H
|
||||
#define CLANG_AST_ABSTRACTBASICWRITER_H
|
||||
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialization {
|
||||
|
||||
template <class T>
|
||||
inline llvm::Optional<T> makeOptionalFromNullable(const T &value) {
|
||||
return (value.isNull()
|
||||
? llvm::Optional<T>()
|
||||
: llvm::Optional<T>(value));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline llvm::Optional<T*> makeOptionalFromPointer(T *value) {
|
||||
return (value ? llvm::Optional<T*>(value) : llvm::Optional<T*>());
|
||||
}
|
||||
|
||||
// PropertyWriter is a class concept that requires the following method:
|
||||
// BasicWriter find(llvm::StringRef propertyName);
|
||||
// where BasicWriter is some class conforming to the BasicWriter concept.
|
||||
// An abstract AST-node writer is created with a PropertyWriter and
|
||||
// performs a sequence of calls like so:
|
||||
// propertyWriter.find(propertyName).write##TypeName(value)
|
||||
// to write the properties of the node it is serializing.
|
||||
|
||||
// BasicWriter is a class concept that requires methods like:
|
||||
// void write##TypeName(ValueType value);
|
||||
// where TypeName is the name of a PropertyType node from PropertiesBase.td
|
||||
// and ValueType is the corresponding C++ type name.
|
||||
//
|
||||
// In addition to the concrete property types, BasicWriter is expected
|
||||
// to implement these methods:
|
||||
//
|
||||
// template <class EnumType>
|
||||
// void writeEnum(T value);
|
||||
//
|
||||
// Writes an enum value as the current property. EnumType will always
|
||||
// be an enum type. Only necessary if the BasicWriter doesn't provide
|
||||
// type-specific writers for all the enum types.
|
||||
//
|
||||
// template <class ValueType>
|
||||
// void writeOptional(Optional<ValueType> value);
|
||||
//
|
||||
// Writes an optional value as the current property.
|
||||
//
|
||||
// template <class ValueType>
|
||||
// void writeArray(ArrayRef<ValueType> value);
|
||||
//
|
||||
// Writes an array of values as the current property.
|
||||
//
|
||||
// PropertyWriter writeObject();
|
||||
//
|
||||
// Writes an object as the current property; the returned property
|
||||
// writer will be subjected to a sequence of property writes and then
|
||||
// discarded before any other properties are written to the "outer"
|
||||
// property writer (which need not be the same type). The sub-writer
|
||||
// will be used as if with the following code:
|
||||
//
|
||||
// {
|
||||
// auto &&widget = W.find("widget").writeObject();
|
||||
// widget.find("kind").writeWidgetKind(...);
|
||||
// widget.find("declaration").writeDeclRef(...);
|
||||
// }
|
||||
|
||||
// WriteDispatcher is a template which does type-based forwarding to one
|
||||
// of the write methods of the BasicWriter passed in:
|
||||
//
|
||||
// template <class ValueType>
|
||||
// struct WriteDispatcher {
|
||||
// template <class BasicWriter>
|
||||
// static void write(BasicWriter &W, ValueType value);
|
||||
// };
|
||||
|
||||
// BasicWriterBase provides convenience implementations of the write
|
||||
// methods for EnumPropertyType and SubclassPropertyType types that just
|
||||
// defer to the "underlying" implementations (for UInt32 and the base class,
|
||||
// respectively).
|
||||
//
|
||||
// template <class Impl>
|
||||
// class BasicWriterBase {
|
||||
// protected:
|
||||
// Impl &asImpl();
|
||||
// public:
|
||||
// ...
|
||||
// };
|
||||
|
||||
// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
|
||||
#include "clang/AST/AbstractBasicWriter.inc"
|
||||
|
||||
/// DataStreamBasicWriter provides convenience implementations for many
|
||||
/// BasicWriter methods based on the assumption that the
|
||||
/// ultimate writer implementation is based on a variable-length stream
|
||||
/// of unstructured data (like Clang's module files). It is designed
|
||||
/// to pair with DataStreamBasicReader.
|
||||
///
|
||||
/// This class can also act as a PropertyWriter, implementing find("...")
|
||||
/// by simply forwarding to itself.
|
||||
///
|
||||
/// Unimplemented methods:
|
||||
/// writeBool
|
||||
/// writeUInt32
|
||||
/// writeUInt64
|
||||
/// writeIdentifier
|
||||
/// writeSelector
|
||||
/// writeSourceLocation
|
||||
/// writeQualType
|
||||
/// writeStmtRef
|
||||
/// writeDeclRef
|
||||
template <class Impl>
|
||||
class DataStreamBasicWriter : public BasicWriterBase<Impl> {
|
||||
protected:
|
||||
using BasicWriterBase<Impl>::asImpl;
|
||||
|
||||
public:
|
||||
/// Implement property-find by ignoring it. We rely on properties being
|
||||
/// serialized and deserialized in a reliable order instead.
|
||||
Impl &find(const char *propertyName) {
|
||||
return asImpl();
|
||||
}
|
||||
|
||||
// Implement object writing by forwarding to this, collapsing the
|
||||
// structure into a single data stream.
|
||||
Impl &writeObject() { return asImpl(); }
|
||||
|
||||
template <class T>
|
||||
void writeEnum(T value) {
|
||||
asImpl().writeUInt32(uint32_t(value));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void writeArray(llvm::ArrayRef<T> array) {
|
||||
asImpl().writeUInt32(array.size());
|
||||
for (const T &elt : array) {
|
||||
WriteDispatcher<T>::write(asImpl(), elt);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void writeOptional(llvm::Optional<T> value) {
|
||||
WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
|
||||
}
|
||||
|
||||
void writeAPSInt(const llvm::APSInt &value) {
|
||||
asImpl().writeBool(value.isUnsigned());
|
||||
asImpl().writeAPInt(value);
|
||||
}
|
||||
|
||||
void writeAPInt(const llvm::APInt &value) {
|
||||
asImpl().writeUInt32(value.getBitWidth());
|
||||
const uint64_t *words = value.getRawData();
|
||||
for (size_t i = 0, e = value.getNumWords(); i != e; ++i)
|
||||
asImpl().writeUInt64(words[i]);
|
||||
}
|
||||
|
||||
void writeQualifiers(Qualifiers value) {
|
||||
static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),
|
||||
"update this if the value size changes");
|
||||
asImpl().writeUInt32(value.getAsOpaqueValue());
|
||||
}
|
||||
|
||||
void writeExceptionSpecInfo(
|
||||
const FunctionProtoType::ExceptionSpecInfo &esi) {
|
||||
asImpl().writeUInt32(uint32_t(esi.Type));
|
||||
if (esi.Type == EST_Dynamic) {
|
||||
asImpl().writeArray(esi.Exceptions);
|
||||
} else if (isComputedNoexcept(esi.Type)) {
|
||||
asImpl().writeExprRef(esi.NoexceptExpr);
|
||||
} else if (esi.Type == EST_Uninstantiated) {
|
||||
asImpl().writeDeclRef(esi.SourceDecl);
|
||||
asImpl().writeDeclRef(esi.SourceTemplate);
|
||||
} else if (esi.Type == EST_Unevaluated) {
|
||||
asImpl().writeDeclRef(esi.SourceDecl);
|
||||
}
|
||||
}
|
||||
|
||||
void writeExtParameterInfo(FunctionProtoType::ExtParameterInfo epi) {
|
||||
static_assert(sizeof(epi.getOpaqueValue()) <= sizeof(uint32_t),
|
||||
"opaque value doesn't fit into uint32_t");
|
||||
asImpl().writeUInt32(epi.getOpaqueValue());
|
||||
}
|
||||
|
||||
void writeNestedNameSpecifier(NestedNameSpecifier *NNS) {
|
||||
// Nested name specifiers usually aren't too long. I think that 8 would
|
||||
// typically accommodate the vast majority.
|
||||
SmallVector<NestedNameSpecifier *, 8> nestedNames;
|
||||
|
||||
// Push each of the NNS's onto a stack for serialization in reverse order.
|
||||
while (NNS) {
|
||||
nestedNames.push_back(NNS);
|
||||
NNS = NNS->getPrefix();
|
||||
}
|
||||
|
||||
asImpl().writeUInt32(nestedNames.size());
|
||||
while (!nestedNames.empty()) {
|
||||
NNS = nestedNames.pop_back_val();
|
||||
NestedNameSpecifier::SpecifierKind kind = NNS->getKind();
|
||||
asImpl().writeNestedNameSpecifierKind(kind);
|
||||
switch (kind) {
|
||||
case NestedNameSpecifier::Identifier:
|
||||
asImpl().writeIdentifier(NNS->getAsIdentifier());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Namespace:
|
||||
asImpl().writeNamespaceDeclRef(NNS->getAsNamespace());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::NamespaceAlias:
|
||||
asImpl().writeNamespaceAliasDeclRef(NNS->getAsNamespaceAlias());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
asImpl().writeQualType(QualType(NNS->getAsType(), 0));
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Global:
|
||||
// Don't need to write an associated value.
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Super:
|
||||
asImpl().writeDeclRef(NNS->getAsRecordDecl());
|
||||
continue;
|
||||
}
|
||||
llvm_unreachable("bad nested name specifier kind");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace serialization
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
31
clang/include/clang/AST/AbstractTypeReader.h
Normal file
31
clang/include/clang/AST/AbstractTypeReader.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
//==--- AbstractTypeReader.h - Abstract deserialization for types ---------===//
|
||||
//
|
||||
// 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 CLANG_AST_ABSTRACTTYPEREADER_H
|
||||
#define CLANG_AST_ABSTRACTTYPEREADER_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/AbstractBasicReader.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialization {
|
||||
|
||||
// template <class PropertyReader>
|
||||
// class AbstractTypeReader {
|
||||
// public:
|
||||
// AbstractTypeReader(PropertyReader &W);
|
||||
// QualType read(Type::TypeClass kind);
|
||||
// };
|
||||
//
|
||||
// The actual class is auto-generated; see ClangASTPropertiesEmitter.cpp.
|
||||
#include "clang/AST/AbstractTypeReader.inc"
|
||||
|
||||
} // end namespace serialization
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
32
clang/include/clang/AST/AbstractTypeWriter.h
Normal file
32
clang/include/clang/AST/AbstractTypeWriter.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//==--- AbstractTypeWriter.h - Abstract serialization for types -----------===//
|
||||
//
|
||||
// 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 CLANG_AST_ABSTRACTTYPEWRITER_H
|
||||
#define CLANG_AST_ABSTRACTTYPEWRITER_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/AbstractBasicWriter.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialization {
|
||||
|
||||
// template <class PropertyWriter>
|
||||
// class AbstractTypeWriter {
|
||||
// public:
|
||||
// AbstractTypeWriter(PropertyWriter &W);
|
||||
// void write(QualType type);
|
||||
// };
|
||||
//
|
||||
// The actual class is auto-generated; see ClangASTPropertiesEmitter.cpp.
|
||||
#include "clang/AST/AbstractTypeWriter.inc"
|
||||
|
||||
} // end namespace serialization
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
@ -32,83 +32,83 @@
|
|||
#include <cassert>
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class AttributeCommonInfo;
|
||||
class IdentifierInfo;
|
||||
class ObjCInterfaceDecl;
|
||||
class Expr;
|
||||
class QualType;
|
||||
class FunctionDecl;
|
||||
class TypeSourceInfo;
|
||||
class ASTContext;
|
||||
class AttributeCommonInfo;
|
||||
class IdentifierInfo;
|
||||
class ObjCInterfaceDecl;
|
||||
class Expr;
|
||||
class QualType;
|
||||
class FunctionDecl;
|
||||
class TypeSourceInfo;
|
||||
|
||||
/// Attr - This represents one attribute.
|
||||
class Attr : public AttributeCommonInfo {
|
||||
private:
|
||||
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 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(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
|
||||
attr::Kind AK, bool IsLateParsed)
|
||||
: AttributeCommonInfo(CommonInfo), AttrKind(AK), 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:
|
||||
attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); }
|
||||
public:
|
||||
attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); }
|
||||
|
||||
unsigned getSpellingListIndex() const {
|
||||
return getAttributeSpellingListIndex();
|
||||
}
|
||||
const char *getSpelling() const;
|
||||
unsigned getSpellingListIndex() const {
|
||||
return getAttributeSpellingListIndex();
|
||||
}
|
||||
const char *getSpelling() const;
|
||||
|
||||
SourceLocation getLocation() const { return getRange().getBegin(); }
|
||||
SourceLocation getLocation() const { return getRange().getBegin(); }
|
||||
|
||||
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:
|
||||
|
|
@ -329,6 +329,18 @@ public:
|
|||
static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType),
|
||||
"ParamIdx does not fit its serialization type");
|
||||
|
||||
/// Contains information gathered from parsing the contents of TargetAttr.
|
||||
struct ParsedTargetAttr {
|
||||
std::vector<std::string> Features;
|
||||
StringRef Architecture;
|
||||
StringRef BranchProtection;
|
||||
bool DuplicateArchitecture = false;
|
||||
bool operator ==(const ParsedTargetAttr &Other) const {
|
||||
return DuplicateArchitecture == Other.DuplicateArchitecture &&
|
||||
Architecture == Other.Architecture && Features == Other.Features;
|
||||
}
|
||||
};
|
||||
|
||||
#include "clang/AST/Attrs.inc"
|
||||
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
|
|
|
|||
|
|
@ -372,6 +372,30 @@ class CXXFinalOverriderMap
|
|||
class CXXIndirectPrimaryBaseSet
|
||||
: public llvm::SmallSet<const CXXRecordDecl*, 32> {};
|
||||
|
||||
inline bool
|
||||
inheritanceModelHasVBPtrOffsetField(MSInheritanceModel Inheritance) {
|
||||
return Inheritance == MSInheritanceModel::Unspecified;
|
||||
}
|
||||
|
||||
// Only member pointers to functions need a this adjustment, since it can be
|
||||
// combined with the field offset for data pointers.
|
||||
inline bool inheritanceModelHasNVOffsetField(bool IsMemberFunction,
|
||||
MSInheritanceModel Inheritance) {
|
||||
return IsMemberFunction && Inheritance >= MSInheritanceModel::Multiple;
|
||||
}
|
||||
|
||||
inline bool
|
||||
inheritanceModelHasVBTableOffsetField(MSInheritanceModel Inheritance) {
|
||||
return Inheritance >= MSInheritanceModel::Virtual;
|
||||
}
|
||||
|
||||
inline bool inheritanceModelHasOnlyOneField(bool IsMemberFunction,
|
||||
MSInheritanceModel Inheritance) {
|
||||
if (IsMemberFunction)
|
||||
return Inheritance <= MSInheritanceModel::Single;
|
||||
return Inheritance <= MSInheritanceModel::Multiple;
|
||||
}
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_CXXINHERITANCE_H
|
||||
|
|
|
|||
|
|
@ -94,10 +94,11 @@ protected:
|
|||
|
||||
unsigned : NumInlineContentCommentBits;
|
||||
|
||||
unsigned RenderKind : 2;
|
||||
unsigned RenderKind : 3;
|
||||
|
||||
unsigned CommandID : CommandInfo::NumCommandIDBits;
|
||||
};
|
||||
enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 +
|
||||
enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 3 +
|
||||
CommandInfo::NumCommandIDBits };
|
||||
|
||||
class HTMLTagCommentBitfields {
|
||||
|
|
@ -310,7 +311,8 @@ public:
|
|||
RenderNormal,
|
||||
RenderBold,
|
||||
RenderMonospaced,
|
||||
RenderEmphasized
|
||||
RenderEmphasized,
|
||||
RenderAnchor
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -81,12 +81,13 @@ class RecordLikeDeclarationVerbatimLineCommand<string name> :
|
|||
// InlineCommand
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def B : InlineCommand<"b">;
|
||||
def C : InlineCommand<"c">;
|
||||
def P : InlineCommand<"p">;
|
||||
def A : InlineCommand<"a">;
|
||||
def E : InlineCommand<"e">;
|
||||
def Em : InlineCommand<"em">;
|
||||
def B : InlineCommand<"b">;
|
||||
def C : InlineCommand<"c">;
|
||||
def P : InlineCommand<"p">;
|
||||
def A : InlineCommand<"a">;
|
||||
def E : InlineCommand<"e">;
|
||||
def Em : InlineCommand<"em">;
|
||||
def Anchor : InlineCommand<"anchor">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BlockCommand
|
||||
|
|
|
|||
|
|
@ -41,23 +41,30 @@ class NamespaceDecl;
|
|||
/// partial_ordering, weak_ordering, and strong_ordering are collectively
|
||||
/// termed the comparison category types.
|
||||
enum class ComparisonCategoryType : unsigned char {
|
||||
WeakEquality,
|
||||
StrongEquality,
|
||||
PartialOrdering,
|
||||
WeakOrdering,
|
||||
StrongOrdering,
|
||||
First = WeakEquality,
|
||||
First = PartialOrdering,
|
||||
Last = StrongOrdering
|
||||
};
|
||||
|
||||
/// Determine the common comparison type, as defined in C++2a
|
||||
/// [class.spaceship]p4.
|
||||
inline ComparisonCategoryType commonComparisonType(ComparisonCategoryType A,
|
||||
ComparisonCategoryType B) {
|
||||
return A < B ? A : B;
|
||||
}
|
||||
|
||||
/// Get the comparison category that should be used when comparing values of
|
||||
/// type \c T.
|
||||
Optional<ComparisonCategoryType> getComparisonCategoryForBuiltinCmp(QualType T);
|
||||
|
||||
/// An enumeration representing the possible results of a three-way
|
||||
/// comparison. These values map onto instances of comparison category types
|
||||
/// defined in the standard library. e.g. 'std::strong_ordering::less'.
|
||||
enum class ComparisonCategoryResult : unsigned char {
|
||||
Equal,
|
||||
Equivalent,
|
||||
Nonequivalent,
|
||||
Nonequal,
|
||||
Less,
|
||||
Greater,
|
||||
Unordered,
|
||||
|
|
@ -125,21 +132,11 @@ public:
|
|||
return Info;
|
||||
}
|
||||
|
||||
/// True iff the comparison category is an equality comparison.
|
||||
bool isEquality() const { return !isOrdered(); }
|
||||
|
||||
/// True iff the comparison category is a relational comparison.
|
||||
bool isOrdered() const {
|
||||
using CCK = ComparisonCategoryType;
|
||||
return Kind == CCK::PartialOrdering || Kind == CCK::WeakOrdering ||
|
||||
Kind == CCK::StrongOrdering;
|
||||
}
|
||||
|
||||
/// True iff the comparison is "strong". i.e. it checks equality and
|
||||
/// not equivalence.
|
||||
bool isStrong() const {
|
||||
using CCK = ComparisonCategoryType;
|
||||
return Kind == CCK::StrongEquality || Kind == CCK::StrongOrdering;
|
||||
return Kind == CCK::StrongOrdering;
|
||||
}
|
||||
|
||||
/// True iff the comparison is not totally ordered.
|
||||
|
|
@ -153,28 +150,18 @@ public:
|
|||
/// weak equivalence if needed.
|
||||
ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const {
|
||||
using CCR = ComparisonCategoryResult;
|
||||
if (!isStrong()) {
|
||||
if (Res == CCR::Equal)
|
||||
return CCR::Equivalent;
|
||||
if (Res == CCR::Nonequal)
|
||||
return CCR::Nonequivalent;
|
||||
}
|
||||
if (!isStrong() && Res == CCR::Equal)
|
||||
return CCR::Equivalent;
|
||||
return Res;
|
||||
}
|
||||
|
||||
const ValueInfo *getEqualOrEquiv() const {
|
||||
return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal));
|
||||
}
|
||||
const ValueInfo *getNonequalOrNonequiv() const {
|
||||
assert(isEquality());
|
||||
return getValueInfo(makeWeakResult(ComparisonCategoryResult::Nonequal));
|
||||
}
|
||||
const ValueInfo *getLess() const {
|
||||
assert(isOrdered());
|
||||
return getValueInfo(ComparisonCategoryResult::Less);
|
||||
}
|
||||
const ValueInfo *getGreater() const {
|
||||
assert(isOrdered());
|
||||
return getValueInfo(ComparisonCategoryResult::Greater);
|
||||
}
|
||||
const ValueInfo *getUnordered() const {
|
||||
|
|
@ -221,7 +208,6 @@ public:
|
|||
return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
|
||||
}
|
||||
|
||||
private:
|
||||
const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "clang/AST/APValue.h"
|
||||
#include "clang/AST/ASTContextAllocate.h"
|
||||
#include "clang/AST/DeclAccessPair.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/ExternalASTSource.h"
|
||||
|
|
@ -59,6 +60,7 @@ class EnumDecl;
|
|||
class Expr;
|
||||
class FunctionTemplateDecl;
|
||||
class FunctionTemplateSpecializationInfo;
|
||||
class FunctionTypeLoc;
|
||||
class LabelStmt;
|
||||
class MemberSpecializationInfo;
|
||||
class Module;
|
||||
|
|
@ -76,33 +78,6 @@ class TypeLoc;
|
|||
class UnresolvedSetImpl;
|
||||
class VarTemplateDecl;
|
||||
|
||||
/// A container of type source information.
|
||||
///
|
||||
/// A client can read the relevant info using TypeLoc wrappers, e.g:
|
||||
/// @code
|
||||
/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
|
||||
/// TL.getBeginLoc().print(OS, SrcMgr);
|
||||
/// @endcode
|
||||
class alignas(8) TypeSourceInfo {
|
||||
// Contains a memory block after the class, used for type source information,
|
||||
// allocated by ASTContext.
|
||||
friend class ASTContext;
|
||||
|
||||
QualType Ty;
|
||||
|
||||
TypeSourceInfo(QualType ty) : Ty(ty) {}
|
||||
|
||||
public:
|
||||
/// Return the type wrapped by this type source info.
|
||||
QualType getType() const { return Ty; }
|
||||
|
||||
/// Return the TypeLoc wrapper for the type source info.
|
||||
TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
|
||||
|
||||
/// Override the type stored in this TypeSourceInfo. Use with caution!
|
||||
void overrideType(QualType T) { Ty = T; }
|
||||
};
|
||||
|
||||
/// The top declaration context.
|
||||
class TranslationUnitDecl : public Decl, public DeclContext {
|
||||
ASTContext &Ctx;
|
||||
|
|
@ -694,10 +669,12 @@ struct QualifierInfo {
|
|||
/// Represents a ValueDecl that came out of a declarator.
|
||||
/// Contains type source information through TypeSourceInfo.
|
||||
class DeclaratorDecl : public ValueDecl {
|
||||
// A struct representing both a TInfo and a syntactic qualifier,
|
||||
// to be used for the (uncommon) case of out-of-line declarations.
|
||||
// A struct representing a TInfo, a trailing requires-clause and a syntactic
|
||||
// qualifier, to be used for the (uncommon) case of out-of-line declarations
|
||||
// and constrained function decls.
|
||||
struct ExtInfo : public QualifierInfo {
|
||||
TypeSourceInfo *TInfo;
|
||||
Expr *TrailingRequiresClause = nullptr;
|
||||
};
|
||||
|
||||
llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo;
|
||||
|
|
@ -764,6 +741,21 @@ public:
|
|||
|
||||
void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);
|
||||
|
||||
/// \brief Get the constraint-expression introduced by the trailing
|
||||
/// requires-clause in the function/member declaration, or null if no
|
||||
/// requires-clause was provided.
|
||||
Expr *getTrailingRequiresClause() {
|
||||
return hasExtInfo() ? getExtInfo()->TrailingRequiresClause
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
const Expr *getTrailingRequiresClause() const {
|
||||
return hasExtInfo() ? getExtInfo()->TrailingRequiresClause
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void setTrailingRequiresClause(Expr *TrailingRequiresClause);
|
||||
|
||||
unsigned getNumTemplateParameterLists() const {
|
||||
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
|
||||
}
|
||||
|
|
@ -777,6 +769,7 @@ public:
|
|||
ArrayRef<TemplateParameterList *> TPLists);
|
||||
|
||||
SourceLocation getTypeSpecStartLoc() const;
|
||||
SourceLocation getTypeSpecEndLoc() const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
|
@ -898,6 +891,8 @@ protected:
|
|||
DAK_Normal
|
||||
};
|
||||
|
||||
enum { NumScopeDepthOrObjCQualsBits = 7 };
|
||||
|
||||
class ParmVarDeclBitfields {
|
||||
friend class ASTDeclReader;
|
||||
friend class ParmVarDecl;
|
||||
|
|
@ -924,7 +919,7 @@ protected:
|
|||
/// Otherwise, the number of function parameter scopes enclosing
|
||||
/// the function parameter scope in which this parameter was
|
||||
/// declared.
|
||||
unsigned ScopeDepthOrObjCQuals : 7;
|
||||
unsigned ScopeDepthOrObjCQuals : NumScopeDepthOrObjCQualsBits;
|
||||
|
||||
/// The number of parameters preceding this parameter in the
|
||||
/// function parameter scope in which it was declared.
|
||||
|
|
@ -1524,8 +1519,8 @@ public:
|
|||
/// 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?
|
||||
/// Would the destruction of this variable have any effect, and if so, what
|
||||
/// kind?
|
||||
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
|
|
@ -1649,6 +1644,10 @@ public:
|
|||
return ParmVarDeclBits.ScopeDepthOrObjCQuals;
|
||||
}
|
||||
|
||||
static constexpr unsigned getMaxFunctionScopeDepth() {
|
||||
return (1u << NumScopeDepthOrObjCQualsBits) - 1;
|
||||
}
|
||||
|
||||
/// Returns the index of this parameter in its prototype or method scope.
|
||||
unsigned getFunctionScopeIndex() const {
|
||||
return getParameterIndex();
|
||||
|
|
@ -1805,13 +1804,37 @@ public:
|
|||
TK_DependentFunctionTemplateSpecialization
|
||||
};
|
||||
|
||||
/// Stashed information about a defaulted function definition whose body has
|
||||
/// not yet been lazily generated.
|
||||
class DefaultedFunctionInfo final
|
||||
: llvm::TrailingObjects<DefaultedFunctionInfo, DeclAccessPair> {
|
||||
friend TrailingObjects;
|
||||
unsigned NumLookups;
|
||||
|
||||
public:
|
||||
static DefaultedFunctionInfo *Create(ASTContext &Context,
|
||||
ArrayRef<DeclAccessPair> Lookups);
|
||||
/// Get the unqualified lookup results that should be used in this
|
||||
/// defaulted function definition.
|
||||
ArrayRef<DeclAccessPair> getUnqualifiedLookups() const {
|
||||
return {getTrailingObjects<DeclAccessPair>(), NumLookups};
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
/// A new[]'d array of pointers to VarDecls for the formal
|
||||
/// parameters of this function. This is null if a prototype or if there are
|
||||
/// no formals.
|
||||
ParmVarDecl **ParamInfo = nullptr;
|
||||
|
||||
LazyDeclStmtPtr Body;
|
||||
/// The active member of this union is determined by
|
||||
/// FunctionDeclBits.HasDefaultedFunctionInfo.
|
||||
union {
|
||||
/// The body of the function.
|
||||
LazyDeclStmtPtr Body;
|
||||
/// Information about a future defaulted function definition.
|
||||
DefaultedFunctionInfo *DefaultedInfo;
|
||||
};
|
||||
|
||||
unsigned ODRHash;
|
||||
|
||||
|
|
@ -1836,10 +1859,10 @@ private:
|
|||
/// FunctionTemplateSpecializationInfo, which contains information about
|
||||
/// the template being specialized and the template arguments involved in
|
||||
/// that specialization.
|
||||
llvm::PointerUnion4<FunctionTemplateDecl *,
|
||||
MemberSpecializationInfo *,
|
||||
FunctionTemplateSpecializationInfo *,
|
||||
DependentFunctionTemplateSpecializationInfo *>
|
||||
llvm::PointerUnion<FunctionTemplateDecl *,
|
||||
MemberSpecializationInfo *,
|
||||
FunctionTemplateSpecializationInfo *,
|
||||
DependentFunctionTemplateSpecializationInfo *>
|
||||
TemplateOrSpecialization;
|
||||
|
||||
/// Provides source/type location info for the declaration name embedded in
|
||||
|
|
@ -1897,7 +1920,8 @@ protected:
|
|||
FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified,
|
||||
ConstexprSpecKind ConstexprKind);
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause = nullptr);
|
||||
|
||||
using redeclarable_base = Redeclarable<FunctionDecl>;
|
||||
|
||||
|
|
@ -1932,11 +1956,12 @@ public:
|
|||
SourceLocation NLoc, DeclarationName N, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified = false,
|
||||
bool hasWrittenPrototype = true,
|
||||
ConstexprSpecKind ConstexprKind = CSK_unspecified) {
|
||||
ConstexprSpecKind ConstexprKind = CSK_unspecified,
|
||||
Expr *TrailingRequiresClause = nullptr) {
|
||||
DeclarationNameInfo NameInfo(N, NLoc);
|
||||
return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, SC,
|
||||
isInlineSpecified, hasWrittenPrototype,
|
||||
ConstexprKind);
|
||||
ConstexprKind, TrailingRequiresClause);
|
||||
}
|
||||
|
||||
static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
|
|
@ -1944,7 +1969,8 @@ public:
|
|||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass SC,
|
||||
bool isInlineSpecified, bool hasWrittenPrototype,
|
||||
ConstexprSpecKind ConstexprKind);
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause);
|
||||
|
||||
static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
|
|
@ -1957,6 +1983,14 @@ public:
|
|||
|
||||
void setRangeEnd(SourceLocation E) { EndRangeLoc = E; }
|
||||
|
||||
/// Returns the location of the ellipsis of a variadic function.
|
||||
SourceLocation getEllipsisLoc() const {
|
||||
const auto *FPT = getType()->getAs<FunctionProtoType>();
|
||||
if (FPT && FPT->isVariadic())
|
||||
return FPT->getEllipsisLoc();
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
// Function definitions.
|
||||
|
|
@ -2030,18 +2064,30 @@ public:
|
|||
///
|
||||
/// This does not determine whether the function has been defined (e.g., in a
|
||||
/// previous definition); for that information, use isDefined.
|
||||
///
|
||||
/// Note: the function declaration does not become a definition until the
|
||||
/// parser reaches the definition, if called before, this function will return
|
||||
/// `false`.
|
||||
bool isThisDeclarationADefinition() const {
|
||||
return isDeletedAsWritten() || isDefaulted() || Body || hasSkippedBody() ||
|
||||
isLateTemplateParsed() || willHaveBody() || hasDefiningAttr();
|
||||
return isDeletedAsWritten() || isDefaulted() ||
|
||||
doesThisDeclarationHaveABody() || hasSkippedBody() ||
|
||||
willHaveBody() || hasDefiningAttr();
|
||||
}
|
||||
|
||||
/// Returns whether this specific declaration of the function has a body.
|
||||
bool doesThisDeclarationHaveABody() const {
|
||||
return Body || isLateTemplateParsed();
|
||||
return (!FunctionDeclBits.HasDefaultedFunctionInfo && Body) ||
|
||||
isLateTemplateParsed();
|
||||
}
|
||||
|
||||
void setBody(Stmt *B);
|
||||
void setLazyBody(uint64_t Offset) { Body = Offset; }
|
||||
void setLazyBody(uint64_t Offset) {
|
||||
FunctionDeclBits.HasDefaultedFunctionInfo = false;
|
||||
Body = LazyDeclStmtPtr(Offset);
|
||||
}
|
||||
|
||||
void setDefaultedFunctionInfo(DefaultedFunctionInfo *Info);
|
||||
DefaultedFunctionInfo *getDefaultedFunctionInfo() const;
|
||||
|
||||
/// Whether this function is variadic.
|
||||
bool isVariadic() const;
|
||||
|
|
@ -2096,6 +2142,16 @@ public:
|
|||
FunctionDeclBits.IsExplicitlyDefaulted = ED;
|
||||
}
|
||||
|
||||
/// True if this method is user-declared and was not
|
||||
/// deleted or defaulted on its first declaration.
|
||||
bool isUserProvided() const {
|
||||
auto *DeclAsWritten = this;
|
||||
if (FunctionDecl *Pattern = getTemplateInstantiationPattern())
|
||||
DeclAsWritten = Pattern;
|
||||
return !(DeclAsWritten->isDeleted() ||
|
||||
DeclAsWritten->getCanonicalDecl()->isDefaulted());
|
||||
}
|
||||
|
||||
/// Whether falling off this function implicitly returns null/zero.
|
||||
/// If a more specific implicit return value is required, front-ends
|
||||
/// should synthesize the appropriate return statements.
|
||||
|
|
@ -2177,6 +2233,10 @@ public:
|
|||
bool usesSEHTry() const { return FunctionDeclBits.UsesSEHTry; }
|
||||
void setUsesSEHTry(bool UST) { FunctionDeclBits.UsesSEHTry = UST; }
|
||||
|
||||
/// Indicates the function uses Floating Point constrained intrinsics
|
||||
bool usesFPIntrin() const { return FunctionDeclBits.UsesFPIntrin; }
|
||||
void setUsesFPIntrin(bool Val) { FunctionDeclBits.UsesFPIntrin = Val; }
|
||||
|
||||
/// Whether this function has been deleted.
|
||||
///
|
||||
/// A function that is "deleted" (via the C++0x "= delete" syntax)
|
||||
|
|
@ -2249,6 +2309,9 @@ public:
|
|||
/// true through IsAligned.
|
||||
bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;
|
||||
|
||||
/// Determine if this function provides an inline implementation of a builtin.
|
||||
bool isInlineBuiltinDeclaration() const;
|
||||
|
||||
/// Determine whether this is a destroying operator delete.
|
||||
bool isDestroyingOperatorDelete() const;
|
||||
|
||||
|
|
@ -2312,6 +2375,17 @@ public:
|
|||
/// the target functionality.
|
||||
bool isTargetMultiVersion() const;
|
||||
|
||||
/// \brief Get the associated-constraints of this function declaration.
|
||||
/// Currently, this will either be a vector of size 1 containing the
|
||||
/// trailing-requires-clause or an empty vector.
|
||||
///
|
||||
/// Use this instead of getTrailingRequiresClause for concepts APIs that
|
||||
/// accept an ArrayRef of constraint expressions.
|
||||
void getAssociatedConstraints(SmallVectorImpl<const Expr *> &AC) const {
|
||||
if (auto *TRC = getTrailingRequiresClause())
|
||||
AC.push_back(TRC);
|
||||
}
|
||||
|
||||
void setPreviousDeclaration(FunctionDecl * PrevDecl);
|
||||
|
||||
FunctionDecl *getCanonicalDecl() override;
|
||||
|
|
@ -2362,6 +2436,12 @@ public:
|
|||
/// parameters have default arguments (in C++).
|
||||
unsigned getMinRequiredArguments() const;
|
||||
|
||||
/// Find the source location information for how the type of this function
|
||||
/// was written. May be absent (for example if the function was declared via
|
||||
/// a typedef) and may contain a different type from that of the function
|
||||
/// (for example if the function type was adjusted by an attribute).
|
||||
FunctionTypeLoc getFunctionTypeLoc() const;
|
||||
|
||||
QualType getReturnType() const {
|
||||
return getType()->castAs<FunctionType>()->getReturnType();
|
||||
}
|
||||
|
|
@ -2371,6 +2451,12 @@ public:
|
|||
/// limited representation in the AST.
|
||||
SourceRange getReturnTypeSourceRange() const;
|
||||
|
||||
/// Attempt to compute an informative source range covering the
|
||||
/// function parameters, including the ellipsis of a variadic function.
|
||||
/// The source range excludes the parentheses, and is invalid if there are
|
||||
/// no parameters and no ellipsis.
|
||||
SourceRange getParametersSourceRange() const;
|
||||
|
||||
/// Get the declared return type, which may differ from the actual return
|
||||
/// type if the return type is deduced.
|
||||
QualType getDeclaredReturnType() const {
|
||||
|
|
|
|||
|
|
@ -1501,10 +1501,9 @@ class DeclContext {
|
|||
/// constructor or a destructor.
|
||||
uint64_t IsTrivialForCall : 1;
|
||||
|
||||
/// Used by CXXMethodDecl
|
||||
uint64_t IsDefaulted : 1;
|
||||
/// Used by CXXMethodDecl
|
||||
uint64_t IsExplicitlyDefaulted : 1;
|
||||
uint64_t HasDefaultedFunctionInfo : 1;
|
||||
uint64_t HasImplicitReturnZero : 1;
|
||||
uint64_t IsLateTemplateParsed : 1;
|
||||
|
||||
|
|
@ -1534,10 +1533,13 @@ class DeclContext {
|
|||
|
||||
/// Store the ODRHash after first calculation.
|
||||
uint64_t HasODRHash : 1;
|
||||
|
||||
/// Indicates if the function uses Floating Point Constrained Intrinsics
|
||||
uint64_t UsesFPIntrin : 1;
|
||||
};
|
||||
|
||||
/// Number of non-inherited bits in FunctionDeclBitfields.
|
||||
enum { NumFunctionDeclBits = 25 };
|
||||
enum { NumFunctionDeclBits = 27 };
|
||||
|
||||
/// Stores the bits used by CXXConstructorDecl. If modified
|
||||
/// NumCXXConstructorDeclBits and the accessor
|
||||
|
|
@ -1554,7 +1556,7 @@ class DeclContext {
|
|||
/// exactly 64 bits and thus the width of NumCtorInitializers
|
||||
/// will need to be shrunk if some bit is added to NumDeclContextBitfields,
|
||||
/// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
|
||||
uint64_t NumCtorInitializers : 23;
|
||||
uint64_t NumCtorInitializers : 21;
|
||||
uint64_t IsInheritingConstructor : 1;
|
||||
|
||||
/// Whether this constructor has a trail-allocated explicit specifier.
|
||||
|
|
@ -1590,6 +1592,9 @@ class DeclContext {
|
|||
/// True if this method is the getter or setter for an explicit property.
|
||||
uint64_t IsPropertyAccessor : 1;
|
||||
|
||||
/// True if this method is a synthesized property accessor stub.
|
||||
uint64_t IsSynthesizedAccessorStub : 1;
|
||||
|
||||
/// Method has a definition.
|
||||
uint64_t IsDefined : 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ASTUnresolvedSet.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
|
|
@ -42,7 +41,6 @@
|
|||
#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"
|
||||
|
|
@ -1048,7 +1046,8 @@ public:
|
|||
|
||||
/// Get all conversion functions visible in current class,
|
||||
/// including conversion function templates.
|
||||
llvm::iterator_range<conversion_iterator> getVisibleConversionFunctions();
|
||||
llvm::iterator_range<conversion_iterator>
|
||||
getVisibleConversionFunctions() const;
|
||||
|
||||
/// Determine whether this class is an aggregate (C++ [dcl.init.aggr]),
|
||||
/// which is a class with no user-declared constructors, no private
|
||||
|
|
@ -1737,10 +1736,10 @@ public:
|
|||
}
|
||||
|
||||
/// Returns the inheritance model used for this record.
|
||||
MSInheritanceAttr::Spelling getMSInheritanceModel() const;
|
||||
MSInheritanceModel getMSInheritanceModel() const;
|
||||
|
||||
/// Calculate what the inheritance model would be for this class.
|
||||
MSInheritanceAttr::Spelling calculateInheritanceModel() const;
|
||||
MSInheritanceModel calculateInheritanceModel() const;
|
||||
|
||||
/// In the Microsoft C++ ABI, use zero for the field offset of a null data
|
||||
/// member pointer if we can guarantee that zero is not a valid field offset,
|
||||
|
|
@ -1748,15 +1747,11 @@ public:
|
|||
/// vfptr at offset zero, so we can use zero for null. If there are multiple
|
||||
/// fields, we can use zero even if it is a valid field offset because
|
||||
/// null-ness testing will check the other fields.
|
||||
bool nullFieldOffsetIsZero() const {
|
||||
return !MSInheritanceAttr::hasOnlyOneField(/*IsMemberFunction=*/false,
|
||||
getMSInheritanceModel()) ||
|
||||
(hasDefinition() && isPolymorphic());
|
||||
}
|
||||
bool nullFieldOffsetIsZero() const;
|
||||
|
||||
/// Controls when vtordisps will be emitted if this record is used as a
|
||||
/// virtual base.
|
||||
MSVtorDispAttr::Mode getMSVtorDispMode() const;
|
||||
MSVtorDispMode getMSVtorDispMode() const;
|
||||
|
||||
/// Determine whether this lambda expression was known to be dependent
|
||||
/// at the time it was created, even if its context does not appear to be
|
||||
|
|
@ -1788,7 +1783,7 @@ public:
|
|||
};
|
||||
|
||||
/// Store information needed for an explicit specifier.
|
||||
/// used by CXXDeductionGuideDecl, CXXConstructorDecl and CXXConversionDecl.
|
||||
/// Used by CXXDeductionGuideDecl, CXXConstructorDecl and CXXConversionDecl.
|
||||
class ExplicitSpecifier {
|
||||
llvm::PointerIntPair<Expr *, 2, ExplicitSpecKind> ExplicitSpec{
|
||||
nullptr, ExplicitSpecKind::ResolvedFalse};
|
||||
|
|
@ -1801,20 +1796,22 @@ public:
|
|||
const Expr *getExpr() const { return ExplicitSpec.getPointer(); }
|
||||
Expr *getExpr() { return ExplicitSpec.getPointer(); }
|
||||
|
||||
/// Return true if the ExplicitSpecifier isn't defaulted.
|
||||
/// Determine if the declaration had an explicit specifier of any kind.
|
||||
bool isSpecified() const {
|
||||
return ExplicitSpec.getInt() != ExplicitSpecKind::ResolvedFalse ||
|
||||
ExplicitSpec.getPointer();
|
||||
}
|
||||
|
||||
/// Check for Equivalence of explicit specifiers.
|
||||
/// Return True if the explicit specifier are equivalent false otherwise.
|
||||
/// Check for equivalence of explicit specifiers.
|
||||
/// \return true if the explicit specifier are equivalent, false otherwise.
|
||||
bool isEquivalent(const ExplicitSpecifier Other) const;
|
||||
/// Return true if the explicit specifier is already resolved to be explicit.
|
||||
/// Determine whether this specifier is known to correspond to an explicit
|
||||
/// declaration. Returns false if the specifier is absent or has an
|
||||
/// expression that is value-dependent or evaluates to false.
|
||||
bool isExplicit() const {
|
||||
return ExplicitSpec.getInt() == ExplicitSpecKind::ResolvedTrue;
|
||||
}
|
||||
/// Return true if the ExplicitSpecifier isn't valid.
|
||||
/// Determine if the explicit specifier is invalid.
|
||||
/// This state occurs after a substitution failures.
|
||||
bool isInvalid() const {
|
||||
return ExplicitSpec.getInt() == ExplicitSpecKind::Unresolved &&
|
||||
|
|
@ -1822,9 +1819,7 @@ public:
|
|||
}
|
||||
void setKind(ExplicitSpecKind Kind) { ExplicitSpec.setInt(Kind); }
|
||||
void setExpr(Expr *E) { ExplicitSpec.setPointer(E); }
|
||||
// getFromDecl - retrieve the explicit specifier in the given declaration.
|
||||
// if the given declaration has no explicit. the returned explicit specifier
|
||||
// is defaulted. .isSpecified() will be false.
|
||||
// Retrieve the explicit specifier in the given declaration, if any.
|
||||
static ExplicitSpecifier getFromDecl(FunctionDecl *Function);
|
||||
static const ExplicitSpecifier getFromDecl(const FunctionDecl *Function) {
|
||||
return getFromDecl(const_cast<FunctionDecl *>(Function));
|
||||
|
|
@ -1910,9 +1905,10 @@ protected:
|
|||
SourceLocation StartLoc, const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo, StorageClass SC,
|
||||
bool isInline, ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation EndLocation)
|
||||
SourceLocation EndLocation,
|
||||
Expr *TrailingRequiresClause = nullptr)
|
||||
: FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, isInline,
|
||||
ConstexprKind) {
|
||||
ConstexprKind, TrailingRequiresClause) {
|
||||
if (EndLocation.isValid())
|
||||
setRangeEnd(EndLocation);
|
||||
}
|
||||
|
|
@ -1923,7 +1919,8 @@ public:
|
|||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass SC,
|
||||
bool isInline, ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation EndLocation);
|
||||
SourceLocation EndLocation,
|
||||
Expr *TrailingRequiresClause = nullptr);
|
||||
|
||||
static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
|
|
@ -2001,16 +1998,6 @@ public:
|
|||
return const_cast<CXXMethodDecl*>(this)->getMostRecentDecl();
|
||||
}
|
||||
|
||||
/// True if this method is user-declared and was not
|
||||
/// deleted or defaulted on its first declaration.
|
||||
bool isUserProvided() const {
|
||||
auto *DeclAsWritten = this;
|
||||
if (auto *Pattern = getTemplateInstantiationPattern())
|
||||
DeclAsWritten = cast<CXXMethodDecl>(Pattern);
|
||||
return !(DeclAsWritten->isDeleted() ||
|
||||
DeclAsWritten->getCanonicalDecl()->isDefaulted());
|
||||
}
|
||||
|
||||
void addOverriddenMethod(const CXXMethodDecl *MD);
|
||||
|
||||
using method_iterator = const CXXMethodDecl *const *;
|
||||
|
|
@ -2138,8 +2125,8 @@ class CXXCtorInitializer final {
|
|||
/// Either the base class name/delegating constructor type (stored as
|
||||
/// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field
|
||||
/// (IndirectFieldDecl*) being initialized.
|
||||
llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *>
|
||||
Initializee;
|
||||
llvm::PointerUnion<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *>
|
||||
Initializee;
|
||||
|
||||
/// The source location for the field name or, for a base initializer
|
||||
/// pack expansion, the location of the ellipsis.
|
||||
|
|
@ -2378,7 +2365,8 @@ class CXXConstructorDecl final
|
|||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline,
|
||||
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
|
||||
InheritedConstructor Inherited);
|
||||
InheritedConstructor Inherited,
|
||||
Expr *TrailingRequiresClause);
|
||||
|
||||
void anchor() override;
|
||||
|
||||
|
|
@ -2431,7 +2419,8 @@ public:
|
|||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared,
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
InheritedConstructor Inherited = InheritedConstructor());
|
||||
InheritedConstructor Inherited = InheritedConstructor(),
|
||||
Expr *TrailingRequiresClause = nullptr);
|
||||
|
||||
ExplicitSpecifier getExplicitSpecifier() {
|
||||
return getCanonicalDecl()->getExplicitSpecifierInternal();
|
||||
|
|
@ -2638,9 +2627,11 @@ class CXXDestructorDecl : public CXXMethodDecl {
|
|||
CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, bool isInline,
|
||||
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind)
|
||||
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause = nullptr)
|
||||
: CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, ConstexprKind, SourceLocation()) {
|
||||
SC_None, isInline, ConstexprKind, SourceLocation(),
|
||||
TrailingRequiresClause) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
}
|
||||
|
||||
|
|
@ -2652,7 +2643,8 @@ public:
|
|||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, bool isImplicitlyDeclared,
|
||||
ConstexprSpecKind ConstexprKind);
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause = nullptr);
|
||||
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
|
||||
|
||||
void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
|
||||
|
|
@ -2691,9 +2683,11 @@ class CXXConversionDecl : public CXXMethodDecl {
|
|||
CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, bool isInline, ExplicitSpecifier ES,
|
||||
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation)
|
||||
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
|
||||
Expr *TrailingRequiresClause = nullptr)
|
||||
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, ConstexprKind, EndLocation),
|
||||
SC_None, isInline, ConstexprKind, EndLocation,
|
||||
TrailingRequiresClause),
|
||||
ExplicitSpec(ES) {}
|
||||
void anchor() override;
|
||||
|
||||
|
|
@ -2709,7 +2703,7 @@ public:
|
|||
Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation EndLocation);
|
||||
SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr);
|
||||
static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
ExplicitSpecifier getExplicitSpecifier() {
|
||||
|
|
@ -2758,15 +2752,8 @@ public:
|
|||
/// Represents the language in a linkage specification.
|
||||
///
|
||||
/// The values are part of the serialization ABI for
|
||||
/// ASTs and cannot be changed without altering that ABI. To help
|
||||
/// ensure a stable ABI for this, we choose the DW_LANG_ encodings
|
||||
/// from the dwarf standard.
|
||||
enum LanguageIDs {
|
||||
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
|
||||
};
|
||||
/// ASTs and cannot be changed without altering that ABI.
|
||||
enum LanguageIDs { lang_c = 1, lang_cxx = 2 };
|
||||
|
||||
private:
|
||||
/// The source location for the extern keyword.
|
||||
|
|
@ -3052,6 +3039,82 @@ public:
|
|||
static bool classofKind(Kind K) { return K == NamespaceAlias; }
|
||||
};
|
||||
|
||||
/// Implicit declaration of a temporary that was materialized by
|
||||
/// a MaterializeTemporaryExpr and lifetime-extended by a declaration
|
||||
class LifetimeExtendedTemporaryDecl final
|
||||
: public Decl,
|
||||
public Mergeable<LifetimeExtendedTemporaryDecl> {
|
||||
friend class MaterializeTemporaryExpr;
|
||||
friend class ASTDeclReader;
|
||||
|
||||
Stmt *ExprWithTemporary = nullptr;
|
||||
|
||||
/// The declaration which lifetime-extended this reference, if any.
|
||||
/// Either a VarDecl, or (for a ctor-initializer) a FieldDecl.
|
||||
ValueDecl *ExtendingDecl = nullptr;
|
||||
unsigned ManglingNumber;
|
||||
|
||||
mutable APValue *Value = nullptr;
|
||||
|
||||
virtual void anchor();
|
||||
|
||||
LifetimeExtendedTemporaryDecl(Expr *Temp, ValueDecl *EDecl, unsigned Mangling)
|
||||
: Decl(Decl::LifetimeExtendedTemporary, EDecl->getDeclContext(),
|
||||
EDecl->getLocation()),
|
||||
ExprWithTemporary(Temp), ExtendingDecl(EDecl),
|
||||
ManglingNumber(Mangling) {}
|
||||
|
||||
LifetimeExtendedTemporaryDecl(EmptyShell)
|
||||
: Decl(Decl::LifetimeExtendedTemporary, EmptyShell{}) {}
|
||||
|
||||
public:
|
||||
static LifetimeExtendedTemporaryDecl *Create(Expr *Temp, ValueDecl *EDec,
|
||||
unsigned Mangling) {
|
||||
return new (EDec->getASTContext(), EDec->getDeclContext())
|
||||
LifetimeExtendedTemporaryDecl(Temp, EDec, Mangling);
|
||||
}
|
||||
static LifetimeExtendedTemporaryDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID) {
|
||||
return new (C, ID) LifetimeExtendedTemporaryDecl(EmptyShell{});
|
||||
}
|
||||
|
||||
ValueDecl *getExtendingDecl() { return ExtendingDecl; }
|
||||
const ValueDecl *getExtendingDecl() const { return ExtendingDecl; }
|
||||
|
||||
/// Retrieve the storage duration for the materialized temporary.
|
||||
StorageDuration getStorageDuration() const;
|
||||
|
||||
/// Retrieve the expression to which the temporary materialization conversion
|
||||
/// was applied. This isn't necessarily the initializer of the temporary due
|
||||
/// to the C++98 delayed materialization rules, but
|
||||
/// skipRValueSubobjectAdjustments can be used to find said initializer within
|
||||
/// the subexpression.
|
||||
Expr *getTemporaryExpr() { return cast<Expr>(ExprWithTemporary); }
|
||||
const Expr *getTemporaryExpr() const { return cast<Expr>(ExprWithTemporary); }
|
||||
|
||||
unsigned getManglingNumber() const { return ManglingNumber; }
|
||||
|
||||
/// Get the storage for the constant value of a materialized temporary
|
||||
/// of static storage duration.
|
||||
APValue *getOrCreateValue(bool MayCreate) const;
|
||||
|
||||
APValue *getValue() const { return Value; }
|
||||
|
||||
// Iterators
|
||||
Stmt::child_range childrenExpr() {
|
||||
return Stmt::child_range(&ExprWithTemporary, &ExprWithTemporary + 1);
|
||||
}
|
||||
|
||||
Stmt::const_child_range childrenExpr() const {
|
||||
return Stmt::const_child_range(&ExprWithTemporary, &ExprWithTemporary + 1);
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) {
|
||||
return K == Decl::LifetimeExtendedTemporary;
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents a shadow declaration introduced into a scope by a
|
||||
/// (resolved) using declaration.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ private:
|
|||
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
|
||||
DeclContext *contextDecl, bool isInstance = true,
|
||||
bool isVariadic = false, bool isPropertyAccessor = false,
|
||||
bool isSynthesizedAccessorStub = false,
|
||||
bool isImplicitlyDeclared = false, bool isDefined = false,
|
||||
ImplementationControl impControl = None,
|
||||
bool HasRelatedResultType = false);
|
||||
|
|
@ -232,6 +233,7 @@ public:
|
|||
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
|
||||
DeclContext *contextDecl, bool isInstance = true,
|
||||
bool isVariadic = false, bool isPropertyAccessor = false,
|
||||
bool isSynthesizedAccessorStub = false,
|
||||
bool isImplicitlyDeclared = false, bool isDefined = false,
|
||||
ImplementationControl impControl = None,
|
||||
bool HasRelatedResultType = false);
|
||||
|
|
@ -408,7 +410,7 @@ public:
|
|||
/// \return the type for \c self and set \arg selfIsPseudoStrong and
|
||||
/// \arg selfIsConsumed accordingly.
|
||||
QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID,
|
||||
bool &selfIsPseudoStrong, bool &selfIsConsumed);
|
||||
bool &selfIsPseudoStrong, bool &selfIsConsumed) const;
|
||||
|
||||
ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
|
||||
void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
|
||||
|
|
@ -436,6 +438,14 @@ public:
|
|||
ObjCMethodDeclBits.IsPropertyAccessor = isAccessor;
|
||||
}
|
||||
|
||||
bool isSynthesizedAccessorStub() const {
|
||||
return ObjCMethodDeclBits.IsSynthesizedAccessorStub;
|
||||
}
|
||||
|
||||
void setSynthesizedAccessorStub(bool isSynthesizedAccessorStub) {
|
||||
ObjCMethodDeclBits.IsSynthesizedAccessorStub = isSynthesizedAccessorStub;
|
||||
}
|
||||
|
||||
bool isDefined() const { return ObjCMethodDeclBits.IsDefined; }
|
||||
void setDefined(bool isDefined) { ObjCMethodDeclBits.IsDefined = isDefined; }
|
||||
|
||||
|
|
@ -466,6 +476,9 @@ public:
|
|||
ObjCMethodDeclBits.HasSkippedBody = Skipped;
|
||||
}
|
||||
|
||||
/// True if the method is tagged as objc_direct
|
||||
bool isDirectMethod() const;
|
||||
|
||||
/// Returns the property associated with this method's selector.
|
||||
///
|
||||
/// Note that even if this particular method is not marked as a property
|
||||
|
|
@ -747,13 +760,14 @@ public:
|
|||
/// property attribute rather than a type qualifier.
|
||||
OBJC_PR_nullability = 0x1000,
|
||||
OBJC_PR_null_resettable = 0x2000,
|
||||
OBJC_PR_class = 0x4000
|
||||
OBJC_PR_class = 0x4000,
|
||||
OBJC_PR_direct = 0x8000
|
||||
// Adding a property should change NumPropertyAttrsBits
|
||||
};
|
||||
|
||||
enum {
|
||||
/// Number of bits fitting all the property attributes.
|
||||
NumPropertyAttrsBits = 15
|
||||
NumPropertyAttrsBits = 16
|
||||
};
|
||||
|
||||
enum SetterKind { Assign, Retain, Copy, Weak };
|
||||
|
|
@ -876,6 +890,7 @@ public:
|
|||
|
||||
bool isInstanceProperty() const { return !isClassProperty(); }
|
||||
bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; }
|
||||
bool isDirectProperty() const { return PropertyAttributes & OBJC_PR_direct; }
|
||||
|
||||
ObjCPropertyQueryKind getQueryKind() const {
|
||||
return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class :
|
||||
|
|
@ -2779,6 +2794,11 @@ private:
|
|||
/// Null for \@dynamic. Required for \@synthesize.
|
||||
ObjCIvarDecl *PropertyIvarDecl;
|
||||
|
||||
/// The getter's definition, which has an empty body if synthesized.
|
||||
ObjCMethodDecl *GetterMethodDecl = nullptr;
|
||||
/// The getter's definition, which has an empty body if synthesized.
|
||||
ObjCMethodDecl *SetterMethodDecl = nullptr;
|
||||
|
||||
/// Null for \@dynamic. Non-null if property must be copy-constructed in
|
||||
/// getter.
|
||||
Expr *GetterCXXConstructor = nullptr;
|
||||
|
|
@ -2845,6 +2865,12 @@ public:
|
|||
return IvarLoc.isValid() && IvarLoc != getLocation();
|
||||
}
|
||||
|
||||
ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
|
||||
void setGetterMethodDecl(ObjCMethodDecl *MD) { GetterMethodDecl = MD; }
|
||||
|
||||
ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
|
||||
void setSetterMethodDecl(ObjCMethodDecl *MD) { SetterMethodDecl = MD; }
|
||||
|
||||
Expr *getGetterCXXConstructor() const {
|
||||
return GetterCXXConstructor;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H
|
||||
#define LLVM_CLANG_AST_DECLTEMPLATE_H
|
||||
|
||||
#include "clang/AST/ASTConcept.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
|
|
@ -51,14 +52,15 @@ class NonTypeTemplateParmDecl;
|
|||
class TemplateDecl;
|
||||
class TemplateTemplateParmDecl;
|
||||
class TemplateTypeParmDecl;
|
||||
class ConceptDecl;
|
||||
class UnresolvedSetImpl;
|
||||
class VarTemplateDecl;
|
||||
class VarTemplatePartialSpecializationDecl;
|
||||
|
||||
/// Stores a template parameter of any kind.
|
||||
using TemplateParameter =
|
||||
llvm::PointerUnion3<TemplateTypeParmDecl *, NonTypeTemplateParmDecl *,
|
||||
TemplateTemplateParmDecl *>;
|
||||
llvm::PointerUnion<TemplateTypeParmDecl *, NonTypeTemplateParmDecl *,
|
||||
TemplateTemplateParmDecl *>;
|
||||
|
||||
NamedDecl *getAsNamedDecl(TemplateParameter P);
|
||||
|
||||
|
|
@ -81,20 +83,24 @@ class TemplateParameterList final
|
|||
/// pack.
|
||||
unsigned ContainsUnexpandedParameterPack : 1;
|
||||
|
||||
/// Whether this template parameter list has an associated requires-clause
|
||||
/// Whether this template parameter list has a requires clause.
|
||||
unsigned HasRequiresClause : 1;
|
||||
|
||||
/// Whether any of the template parameters has constrained-parameter
|
||||
/// constraint-expression.
|
||||
unsigned HasConstrainedParameters : 1;
|
||||
|
||||
protected:
|
||||
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
|
||||
ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc,
|
||||
Expr *RequiresClause);
|
||||
TemplateParameterList(const ASTContext& C, SourceLocation TemplateLoc,
|
||||
SourceLocation LAngleLoc, ArrayRef<NamedDecl *> Params,
|
||||
SourceLocation RAngleLoc, Expr *RequiresClause);
|
||||
|
||||
size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
|
||||
return NumParams;
|
||||
}
|
||||
|
||||
size_t numTrailingObjects(OverloadToken<Expr *>) const {
|
||||
return HasRequiresClause;
|
||||
return HasRequiresClause ? 1 : 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -158,14 +164,22 @@ public:
|
|||
return ContainsUnexpandedParameterPack;
|
||||
}
|
||||
|
||||
/// Determine whether this template parameter list contains a parameter pack.
|
||||
bool hasParameterPack() const {
|
||||
for (const NamedDecl *P : asArray())
|
||||
if (P->isParameterPack())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// The constraint-expression of the associated requires-clause.
|
||||
Expr *getRequiresClause() {
|
||||
return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
|
||||
return HasRequiresClause ? getTrailingObjects<Expr *>()[0] : nullptr;
|
||||
}
|
||||
|
||||
/// The constraint-expression of the associated requires-clause.
|
||||
const Expr *getRequiresClause() const {
|
||||
return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
|
||||
return HasRequiresClause ? getTrailingObjects<Expr *>()[0] : nullptr;
|
||||
}
|
||||
|
||||
/// \brief All associated constraints derived from this template parameter
|
||||
|
|
@ -208,15 +222,16 @@ class FixedSizeTemplateParameterListStorage
|
|||
>::type storage;
|
||||
|
||||
public:
|
||||
FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc,
|
||||
FixedSizeTemplateParameterListStorage(const ASTContext &C,
|
||||
SourceLocation TemplateLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ArrayRef<NamedDecl *> Params,
|
||||
SourceLocation RAngleLoc,
|
||||
Expr *RequiresClause)
|
||||
: FixedSizeStorageOwner(
|
||||
(assert(N == Params.size()),
|
||||
assert(HasRequiresClause == static_cast<bool>(RequiresClause)),
|
||||
new (static_cast<void *>(&storage)) TemplateParameterList(
|
||||
assert(HasRequiresClause == (RequiresClause != nullptr)),
|
||||
new (static_cast<void *>(&storage)) TemplateParameterList(C,
|
||||
TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause))) {}
|
||||
};
|
||||
|
||||
|
|
@ -309,7 +324,7 @@ class DefaultArgStorage {
|
|||
static_assert(sizeof(Chain) == sizeof(void *) * 2,
|
||||
"non-pointer argument type?");
|
||||
|
||||
llvm::PointerUnion3<ArgType, ParmDecl*, Chain*> ValueOrInherited;
|
||||
llvm::PointerUnion<ArgType, ParmDecl*, Chain*> ValueOrInherited;
|
||||
|
||||
static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) {
|
||||
const DefaultArgStorage &Storage = Parm->getDefaultArgStorage();
|
||||
|
|
@ -793,9 +808,10 @@ protected:
|
|||
|
||||
void loadLazySpecializationsImpl() const;
|
||||
|
||||
template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
|
||||
template <class EntryType, typename ...ProfileArguments>
|
||||
typename SpecEntryTraits<EntryType>::DeclType*
|
||||
findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
|
||||
ArrayRef<TemplateArgument> Args, void *&InsertPos);
|
||||
void *&InsertPos, ProfileArguments &&...ProfileArgs);
|
||||
|
||||
template <class Derived, class EntryType>
|
||||
void addSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
|
||||
|
|
@ -1147,9 +1163,12 @@ public:
|
|||
/// \code
|
||||
/// template<typename T> class vector;
|
||||
/// \endcode
|
||||
class TemplateTypeParmDecl : public TypeDecl {
|
||||
class TemplateTypeParmDecl final : public TypeDecl,
|
||||
private llvm::TrailingObjects<TemplateTypeParmDecl, TypeConstraint> {
|
||||
/// Sema creates these on the stack during auto type deduction.
|
||||
friend class Sema;
|
||||
friend TrailingObjects;
|
||||
friend class ASTDeclReader;
|
||||
|
||||
/// Whether this template type parameter was declaration with
|
||||
/// the 'typename' keyword.
|
||||
|
|
@ -1157,6 +1176,22 @@ class TemplateTypeParmDecl : public TypeDecl {
|
|||
/// If false, it was declared with the 'class' keyword.
|
||||
bool Typename : 1;
|
||||
|
||||
/// Whether this template type parameter has a type-constraint construct.
|
||||
bool HasTypeConstraint : 1;
|
||||
|
||||
/// Whether the type constraint has been initialized. This can be false if the
|
||||
/// constraint was not initialized yet or if there was an error forming the
|
||||
/// type constriant.
|
||||
bool TypeConstraintInitialized : 1;
|
||||
|
||||
/// Whether this non-type template parameter is an "expanded"
|
||||
/// parameter pack, meaning that its type is a pack expansion and we
|
||||
/// already know the set of types that expansion expands to.
|
||||
bool ExpandedParameterPack : 1;
|
||||
|
||||
/// The number of type parameters in an expanded parameter pack.
|
||||
unsigned NumExpanded = 0;
|
||||
|
||||
/// The default template argument, if any.
|
||||
using DefArgStorage =
|
||||
DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>;
|
||||
|
|
@ -1164,8 +1199,12 @@ class TemplateTypeParmDecl : public TypeDecl {
|
|||
|
||||
TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
bool Typename)
|
||||
: TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename) {}
|
||||
bool Typename, bool HasTypeConstraint,
|
||||
Optional<unsigned> NumExpanded)
|
||||
: TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename),
|
||||
HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false),
|
||||
ExpandedParameterPack(NumExpanded),
|
||||
NumExpanded(NumExpanded ? *NumExpanded : 0) {}
|
||||
|
||||
public:
|
||||
static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
|
||||
|
|
@ -1173,15 +1212,24 @@ public:
|
|||
SourceLocation NameLoc,
|
||||
unsigned D, unsigned P,
|
||||
IdentifierInfo *Id, bool Typename,
|
||||
bool ParameterPack);
|
||||
bool ParameterPack,
|
||||
bool HasTypeConstraint = false,
|
||||
Optional<unsigned> NumExpanded = None);
|
||||
|
||||
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
|
||||
unsigned ID);
|
||||
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
|
||||
unsigned ID,
|
||||
bool HasTypeConstraint);
|
||||
|
||||
/// Whether this template type parameter was declared with
|
||||
/// the 'typename' keyword.
|
||||
///
|
||||
/// If not, it was declared with the 'class' keyword.
|
||||
bool wasDeclaredWithTypename() const { return Typename; }
|
||||
/// If not, it was either declared with the 'class' keyword or with a
|
||||
/// type-constraint (see hasTypeConstraint()).
|
||||
bool wasDeclaredWithTypename() const {
|
||||
return Typename && !HasTypeConstraint;
|
||||
}
|
||||
|
||||
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
|
||||
|
||||
|
|
@ -1238,6 +1286,78 @@ public:
|
|||
/// Returns whether this is a parameter pack.
|
||||
bool isParameterPack() const;
|
||||
|
||||
/// Whether this parameter pack is a pack expansion.
|
||||
///
|
||||
/// A template type template parameter pack can be a pack expansion if its
|
||||
/// type-constraint contains an unexpanded parameter pack.
|
||||
bool isPackExpansion() const {
|
||||
if (!isParameterPack())
|
||||
return false;
|
||||
if (const TypeConstraint *TC = getTypeConstraint())
|
||||
if (TC->hasExplicitTemplateArgs())
|
||||
for (const auto &ArgLoc : TC->getTemplateArgsAsWritten()->arguments())
|
||||
if (ArgLoc.getArgument().containsUnexpandedParameterPack())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Whether this parameter is a template type parameter pack that has a known
|
||||
/// list of different type-constraints at different positions.
|
||||
///
|
||||
/// A parameter pack is an expanded parameter pack when the original
|
||||
/// parameter pack's type-constraint was itself a pack expansion, and that
|
||||
/// expansion has already been expanded. For example, given:
|
||||
///
|
||||
/// \code
|
||||
/// template<typename ...Types>
|
||||
/// struct X {
|
||||
/// template<convertible_to<Types> ...Convertibles>
|
||||
/// struct Y { /* ... */ };
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// The parameter pack \c Convertibles has (convertible_to<Types> && ...) as
|
||||
/// its type-constraint. When \c Types is supplied with template arguments by
|
||||
/// instantiating \c X, the instantiation of \c Convertibles becomes an
|
||||
/// expanded parameter pack. For example, instantiating
|
||||
/// \c X<int, unsigned int> results in \c Convertibles being an expanded
|
||||
/// parameter pack of size 2 (use getNumExpansionTypes() to get this number).
|
||||
bool isExpandedParameterPack() const { return ExpandedParameterPack; }
|
||||
|
||||
/// Retrieves the number of parameters in an expanded parameter pack.
|
||||
unsigned getNumExpansionParameters() const {
|
||||
assert(ExpandedParameterPack && "Not an expansion parameter pack");
|
||||
return NumExpanded;
|
||||
}
|
||||
|
||||
/// Returns the type constraint associated with this template parameter (if
|
||||
/// any).
|
||||
const TypeConstraint *getTypeConstraint() const {
|
||||
return TypeConstraintInitialized ? getTrailingObjects<TypeConstraint>() :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
void setTypeConstraint(NestedNameSpecifierLoc NNS,
|
||||
DeclarationNameInfo NameInfo, NamedDecl *FoundDecl,
|
||||
ConceptDecl *CD,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
Expr *ImmediatelyDeclaredConstraint);
|
||||
|
||||
/// Determine whether this template parameter has a type-constraint.
|
||||
bool hasTypeConstraint() const {
|
||||
return HasTypeConstraint;
|
||||
}
|
||||
|
||||
/// \brief Get the associated-constraints of this template parameter.
|
||||
/// This will either be the immediately-introduced constraint or empty.
|
||||
///
|
||||
/// Use this instead of getConstraintExpression for concepts APIs that
|
||||
/// accept an ArrayRef of constraint expressions.
|
||||
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
||||
if (HasTypeConstraint)
|
||||
AC.push_back(getTypeConstraint()->getImmediatelyDeclaredConstraint());
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
|
|
@ -1423,6 +1543,33 @@ public:
|
|||
return TypesAndInfos[I].second;
|
||||
}
|
||||
|
||||
/// Return the type-constraint in the placeholder type of this non-type
|
||||
/// template parameter (if any).
|
||||
TypeConstraint *getPlaceholderTypeConstraint() const {
|
||||
// TODO: Concepts: Implement once we have actual placeholders with type
|
||||
// constraints.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Determine whether this non-type template parameter's type has a
|
||||
/// placeholder with a type-constraint.
|
||||
bool hasPlaceholderTypeConstraint() const {
|
||||
// TODO: Concepts: Implement once we have actual placeholders with type
|
||||
// constraints.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Get the associated-constraints of this template parameter.
|
||||
/// This will either be a vector of size 1 containing the immediately-declared
|
||||
/// constraint introduced by the placeholder type, or an empty vector.
|
||||
///
|
||||
/// Use this instead of getPlaceholderImmediatelyDeclaredConstraint for
|
||||
/// concepts APIs that accept an ArrayRef of constraint expressions.
|
||||
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
||||
if (TypeConstraint *TC = getPlaceholderTypeConstraint())
|
||||
AC.push_back(TC->getImmediatelyDeclaredConstraint());
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == NonTypeTemplateParm; }
|
||||
|
|
@ -1557,8 +1704,8 @@ public:
|
|||
|
||||
/// Retrieve the default argument, if any.
|
||||
const TemplateArgumentLoc &getDefaultArgument() const {
|
||||
static const TemplateArgumentLoc None;
|
||||
return DefaultArgument.isSet() ? *DefaultArgument.get() : None;
|
||||
static const TemplateArgumentLoc NoneLoc;
|
||||
return DefaultArgument.isSet() ? *DefaultArgument.get() : NoneLoc;
|
||||
}
|
||||
|
||||
/// Retrieve the location of the default argument, if any.
|
||||
|
|
@ -2056,7 +2203,14 @@ public:
|
|||
->getInjectedSpecializationType();
|
||||
}
|
||||
|
||||
// FIXME: Add Profile support!
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
|
||||
getASTContext());
|
||||
}
|
||||
|
||||
static void
|
||||
Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
|
||||
TemplateParameterList *TPL, ASTContext &Context);
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
||||
|
|
@ -2180,7 +2334,8 @@ public:
|
|||
/// Return the partial specialization with the provided arguments if it
|
||||
/// exists, otherwise return the insertion point.
|
||||
ClassTemplatePartialSpecializationDecl *
|
||||
findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
|
||||
findPartialSpecialization(ArrayRef<TemplateArgument> Args,
|
||||
TemplateParameterList *TPL, void *&InsertPos);
|
||||
|
||||
/// Insert the specified partial specialization knowing that it is not
|
||||
/// already in. InsertPos must be obtained from findPartialSpecialization.
|
||||
|
|
@ -2880,6 +3035,15 @@ public:
|
|||
return First->InstantiatedFromMember.setInt(true);
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
|
||||
getASTContext());
|
||||
}
|
||||
|
||||
static void
|
||||
Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
|
||||
TemplateParameterList *TPL, ASTContext &Context);
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
||||
static bool classofKind(Kind K) {
|
||||
|
|
@ -2998,7 +3162,8 @@ public:
|
|||
/// Return the partial specialization with the provided arguments if it
|
||||
/// exists, otherwise return the insertion point.
|
||||
VarTemplatePartialSpecializationDecl *
|
||||
findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
|
||||
findPartialSpecialization(ArrayRef<TemplateArgument> Args,
|
||||
TemplateParameterList *TPL, void *&InsertPos);
|
||||
|
||||
/// Insert the specified partial specialization knowing that it is not
|
||||
/// already in. InsertPos must be obtained from findPartialSpecialization.
|
||||
|
|
@ -3067,6 +3232,10 @@ public:
|
|||
ConstraintExpr->getEndLoc());
|
||||
}
|
||||
|
||||
bool isTypeConcept() const {
|
||||
return isa<TemplateTypeParmDecl>(getTemplateParameters()->getParam(0));
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == Concept; }
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ public:
|
|||
|
||||
static int compare(DeclarationName LHS, DeclarationName RHS);
|
||||
|
||||
void print(raw_ostream &OS, const PrintingPolicy &Policy);
|
||||
void print(raw_ostream &OS, const PrintingPolicy &Policy) const;
|
||||
|
||||
void dump() const;
|
||||
};
|
||||
|
|
@ -792,7 +792,7 @@ public:
|
|||
std::string getAsString() const;
|
||||
|
||||
/// printName - Print the human-readable name to a stream.
|
||||
void printName(raw_ostream &OS) const;
|
||||
void printName(raw_ostream &OS, PrintingPolicy Policy) const;
|
||||
|
||||
/// getBeginLoc - Retrieve the location of the first token.
|
||||
SourceLocation getBeginLoc() const { return NameLoc; }
|
||||
|
|
@ -829,11 +829,7 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
|||
return PD;
|
||||
}
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS,
|
||||
DeclarationNameInfo DNInfo) {
|
||||
DNInfo.printName(OS);
|
||||
return OS;
|
||||
}
|
||||
raw_ostream &operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo);
|
||||
|
||||
} // namespace clang
|
||||
|
||||
|
|
|
|||
|
|
@ -494,7 +494,13 @@ public:
|
|||
/// that is known to return 0 or 1. This happens for _Bool/bool expressions
|
||||
/// but also int expressions which are produced by things like comparisons in
|
||||
/// C.
|
||||
bool isKnownToHaveBooleanValue() const;
|
||||
///
|
||||
/// \param Semantic If true, only return true for expressions that are known
|
||||
/// to be semantically boolean, which might not be true even for expressions
|
||||
/// that are known to evaluate to 0/1. For instance, reading an unsigned
|
||||
/// bit-field with width '1' will evaluate to 0/1, but doesn't necessarily
|
||||
/// semantically correspond to a bool.
|
||||
bool isKnownToHaveBooleanValue(bool Semantic = true) const;
|
||||
|
||||
/// isIntegerConstantExpr - Return true if this expression is a valid integer
|
||||
/// constant expression, and, if so, return its value in Result. If not a
|
||||
|
|
@ -756,6 +762,15 @@ public:
|
|||
/// member expression.
|
||||
static QualType findBoundMemberType(const Expr *expr);
|
||||
|
||||
/// Skip past any invisble AST nodes which might surround this
|
||||
/// statement, such as ExprWithCleanups or ImplicitCastExpr nodes,
|
||||
/// but also injected CXXMemberExpr and CXXConstructExpr which represent
|
||||
/// implicit conversions.
|
||||
Expr *IgnoreUnlessSpelledInSource();
|
||||
const Expr *IgnoreUnlessSpelledInSource() const {
|
||||
return const_cast<Expr *>(this)->IgnoreUnlessSpelledInSource();
|
||||
}
|
||||
|
||||
/// Skip past any implicit casts which might surround this expression until
|
||||
/// reaching a fixed point. Skips:
|
||||
/// * ImplicitCastExpr
|
||||
|
|
@ -786,6 +801,16 @@ public:
|
|||
return const_cast<Expr *>(this)->IgnoreImplicit();
|
||||
}
|
||||
|
||||
/// Skip past any implicit AST nodes which might surround this expression
|
||||
/// until reaching a fixed point. Same as IgnoreImplicit, except that it
|
||||
/// also skips over implicit calls to constructors and conversion functions.
|
||||
///
|
||||
/// FIXME: Should IgnoreImplicit do this?
|
||||
Expr *IgnoreImplicitAsWritten() LLVM_READONLY;
|
||||
const Expr *IgnoreImplicitAsWritten() const {
|
||||
return const_cast<Expr *>(this)->IgnoreImplicitAsWritten();
|
||||
}
|
||||
|
||||
/// Skip past any parentheses which might surround this expression until
|
||||
/// reaching a fixed point. Skips:
|
||||
/// * ParenExpr
|
||||
|
|
@ -3711,22 +3736,25 @@ class ConditionalOperator : public AbstractConditionalOperator {
|
|||
friend class ASTStmtReader;
|
||||
public:
|
||||
ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
|
||||
SourceLocation CLoc, Expr *rhs,
|
||||
QualType t, ExprValueKind VK, ExprObjectKind OK)
|
||||
: AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK,
|
||||
// FIXME: the type of the conditional operator doesn't
|
||||
// depend on the type of the conditional, but the standard
|
||||
// seems to imply that it could. File a bug!
|
||||
(lhs->isTypeDependent() || rhs->isTypeDependent()),
|
||||
(cond->isValueDependent() || lhs->isValueDependent() ||
|
||||
rhs->isValueDependent()),
|
||||
(cond->isInstantiationDependent() ||
|
||||
lhs->isInstantiationDependent() ||
|
||||
rhs->isInstantiationDependent()),
|
||||
(cond->containsUnexpandedParameterPack() ||
|
||||
lhs->containsUnexpandedParameterPack() ||
|
||||
rhs->containsUnexpandedParameterPack()),
|
||||
QLoc, CLoc) {
|
||||
SourceLocation CLoc, Expr *rhs, QualType t,
|
||||
ExprValueKind VK, ExprObjectKind OK)
|
||||
: AbstractConditionalOperator(
|
||||
ConditionalOperatorClass, t, VK, OK,
|
||||
// The type of the conditional operator depends on the type
|
||||
// of the conditional to support the GCC vector conditional
|
||||
// extension. Additionally, [temp.dep.expr] does specify state that
|
||||
// this should be dependent on ALL sub expressions.
|
||||
(cond->isTypeDependent() || lhs->isTypeDependent() ||
|
||||
rhs->isTypeDependent()),
|
||||
(cond->isValueDependent() || lhs->isValueDependent() ||
|
||||
rhs->isValueDependent()),
|
||||
(cond->isInstantiationDependent() ||
|
||||
lhs->isInstantiationDependent() ||
|
||||
rhs->isInstantiationDependent()),
|
||||
(cond->containsUnexpandedParameterPack() ||
|
||||
lhs->containsUnexpandedParameterPack() ||
|
||||
rhs->containsUnexpandedParameterPack()),
|
||||
QLoc, CLoc) {
|
||||
SubExprs[COND] = cond;
|
||||
SubExprs[LHS] = lhs;
|
||||
SubExprs[RHS] = rhs;
|
||||
|
|
@ -5594,6 +5622,20 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// Copy initialization expr of a __block variable and a boolean flag that
|
||||
/// indicates whether the expression can throw.
|
||||
struct BlockVarCopyInit {
|
||||
BlockVarCopyInit() = default;
|
||||
BlockVarCopyInit(Expr *CopyExpr, bool CanThrow)
|
||||
: ExprAndFlag(CopyExpr, CanThrow) {}
|
||||
void setExprAndFlag(Expr *CopyExpr, bool CanThrow) {
|
||||
ExprAndFlag.setPointerAndInt(CopyExpr, CanThrow);
|
||||
}
|
||||
Expr *getCopyExpr() const { return ExprAndFlag.getPointer(); }
|
||||
bool canThrow() const { return ExprAndFlag.getInt(); }
|
||||
llvm::PointerIntPair<Expr *, 1, bool> ExprAndFlag;
|
||||
};
|
||||
|
||||
/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2]
|
||||
/// This AST node provides support for reinterpreting a type to another
|
||||
/// type of the same size.
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#ifndef LLVM_CLANG_AST_EXPRCXX_H
|
||||
#define LLVM_CLANG_AST_EXPRCXX_H
|
||||
|
||||
#include "clang/AST/ASTConcept.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
|
|
@ -4421,70 +4422,66 @@ private:
|
|||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
|
||||
struct ExtraState {
|
||||
/// The temporary-generating expression whose value will be
|
||||
/// materialized.
|
||||
Stmt *Temporary;
|
||||
|
||||
/// The declaration which lifetime-extended this reference, if any.
|
||||
/// Either a VarDecl, or (for a ctor-initializer) a FieldDecl.
|
||||
const ValueDecl *ExtendingDecl;
|
||||
|
||||
unsigned ManglingNumber;
|
||||
};
|
||||
llvm::PointerUnion<Stmt *, ExtraState *> State;
|
||||
llvm::PointerUnion<Stmt *, LifetimeExtendedTemporaryDecl *> State;
|
||||
|
||||
public:
|
||||
MaterializeTemporaryExpr(QualType T, Expr *Temporary,
|
||||
bool BoundToLvalueReference)
|
||||
: Expr(MaterializeTemporaryExprClass, T,
|
||||
BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary,
|
||||
Temporary->isTypeDependent(), Temporary->isValueDependent(),
|
||||
Temporary->isInstantiationDependent(),
|
||||
Temporary->containsUnexpandedParameterPack()),
|
||||
State(Temporary) {}
|
||||
bool BoundToLvalueReference,
|
||||
LifetimeExtendedTemporaryDecl *MTD = nullptr);
|
||||
|
||||
MaterializeTemporaryExpr(EmptyShell Empty)
|
||||
: Expr(MaterializeTemporaryExprClass, Empty) {}
|
||||
|
||||
Stmt *getTemporary() const {
|
||||
return State.is<Stmt *>() ? State.get<Stmt *>()
|
||||
: State.get<ExtraState *>()->Temporary;
|
||||
}
|
||||
|
||||
/// Retrieve the temporary-generating subexpression whose value will
|
||||
/// be materialized into a glvalue.
|
||||
Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); }
|
||||
Expr *getSubExpr() const {
|
||||
return cast<Expr>(
|
||||
State.is<Stmt *>()
|
||||
? State.get<Stmt *>()
|
||||
: State.get<LifetimeExtendedTemporaryDecl *>()->getTemporaryExpr());
|
||||
}
|
||||
|
||||
/// Retrieve the storage duration for the materialized temporary.
|
||||
StorageDuration getStorageDuration() const {
|
||||
const ValueDecl *ExtendingDecl = getExtendingDecl();
|
||||
if (!ExtendingDecl)
|
||||
return SD_FullExpression;
|
||||
// FIXME: This is not necessarily correct for a temporary materialized
|
||||
// within a default initializer.
|
||||
if (isa<FieldDecl>(ExtendingDecl))
|
||||
return SD_Automatic;
|
||||
// FIXME: This only works because storage class specifiers are not allowed
|
||||
// on decomposition declarations.
|
||||
if (isa<BindingDecl>(ExtendingDecl))
|
||||
return ExtendingDecl->getDeclContext()->isFunctionOrMethod()
|
||||
? SD_Automatic
|
||||
: SD_Static;
|
||||
return cast<VarDecl>(ExtendingDecl)->getStorageDuration();
|
||||
return State.is<Stmt *>() ? SD_FullExpression
|
||||
: State.get<LifetimeExtendedTemporaryDecl *>()
|
||||
->getStorageDuration();
|
||||
}
|
||||
|
||||
/// Get the storage for the constant value of a materialized temporary
|
||||
/// of static storage duration.
|
||||
APValue *getOrCreateValue(bool MayCreate) const {
|
||||
assert(State.is<LifetimeExtendedTemporaryDecl *>() &&
|
||||
"the temporary has not been lifetime extended");
|
||||
return State.get<LifetimeExtendedTemporaryDecl *>()->getOrCreateValue(
|
||||
MayCreate);
|
||||
}
|
||||
|
||||
LifetimeExtendedTemporaryDecl *getLifetimeExtendedTemporaryDecl() {
|
||||
return State.dyn_cast<LifetimeExtendedTemporaryDecl *>();
|
||||
}
|
||||
const LifetimeExtendedTemporaryDecl *
|
||||
getLifetimeExtendedTemporaryDecl() const {
|
||||
return State.dyn_cast<LifetimeExtendedTemporaryDecl *>();
|
||||
}
|
||||
|
||||
/// Get the declaration which triggered the lifetime-extension of this
|
||||
/// temporary, if any.
|
||||
const ValueDecl *getExtendingDecl() const {
|
||||
ValueDecl *getExtendingDecl() {
|
||||
return State.is<Stmt *>() ? nullptr
|
||||
: State.get<ExtraState *>()->ExtendingDecl;
|
||||
: State.get<LifetimeExtendedTemporaryDecl *>()
|
||||
->getExtendingDecl();
|
||||
}
|
||||
const ValueDecl *getExtendingDecl() const {
|
||||
return const_cast<MaterializeTemporaryExpr *>(this)->getExtendingDecl();
|
||||
}
|
||||
|
||||
void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber);
|
||||
void setExtendingDecl(ValueDecl *ExtendedBy, unsigned ManglingNumber);
|
||||
|
||||
unsigned getManglingNumber() const {
|
||||
return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber;
|
||||
return State.is<Stmt *>() ? 0
|
||||
: State.get<LifetimeExtendedTemporaryDecl *>()
|
||||
->getManglingNumber();
|
||||
}
|
||||
|
||||
/// Determine whether this materialized temporary is bound to an
|
||||
|
|
@ -4494,11 +4491,11 @@ public:
|
|||
}
|
||||
|
||||
SourceLocation getBeginLoc() const LLVM_READONLY {
|
||||
return getTemporary()->getBeginLoc();
|
||||
return getSubExpr()->getBeginLoc();
|
||||
}
|
||||
|
||||
SourceLocation getEndLoc() const LLVM_READONLY {
|
||||
return getTemporary()->getEndLoc();
|
||||
return getSubExpr()->getEndLoc();
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
|
|
@ -4507,20 +4504,18 @@ public:
|
|||
|
||||
// Iterators
|
||||
child_range children() {
|
||||
if (State.is<Stmt *>())
|
||||
return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1);
|
||||
|
||||
auto ES = State.get<ExtraState *>();
|
||||
return child_range(&ES->Temporary, &ES->Temporary + 1);
|
||||
return State.is<Stmt *>()
|
||||
? child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1)
|
||||
: State.get<LifetimeExtendedTemporaryDecl *>()->childrenExpr();
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
if (State.is<Stmt *>())
|
||||
return const_child_range(State.getAddrOfPtr1(),
|
||||
State.getAddrOfPtr1() + 1);
|
||||
|
||||
auto ES = State.get<ExtraState *>();
|
||||
return const_child_range(&ES->Temporary, &ES->Temporary + 1);
|
||||
return State.is<Stmt *>()
|
||||
? const_child_range(State.getAddrOfPtr1(),
|
||||
State.getAddrOfPtr1() + 1)
|
||||
: const_cast<const LifetimeExtendedTemporaryDecl *>(
|
||||
State.get<LifetimeExtendedTemporaryDecl *>())
|
||||
->childrenExpr();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -4846,107 +4841,81 @@ public:
|
|||
///
|
||||
/// 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,
|
||||
class ConceptSpecializationExpr final : public Expr, public ConceptReference,
|
||||
private llvm::TrailingObjects<ConceptSpecializationExpr,
|
||||
TemplateArgument> {
|
||||
friend class ASTStmtReader;
|
||||
friend TrailingObjects;
|
||||
public:
|
||||
using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
|
||||
|
||||
// \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;
|
||||
|
||||
protected:
|
||||
/// \brief The number of template arguments in the tail-allocated list of
|
||||
/// converted template arguments.
|
||||
unsigned NumTemplateArgs;
|
||||
|
||||
ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS,
|
||||
/// \brief Information about the satisfaction of the named concept with the
|
||||
/// given arguments. If this expression is value dependent, this is to be
|
||||
/// ignored.
|
||||
ASTConstraintSatisfaction *Satisfaction;
|
||||
|
||||
ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS,
|
||||
SourceLocation TemplateKWLoc,
|
||||
SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
|
||||
ConceptDecl *NamedConcept,
|
||||
DeclarationNameInfo ConceptNameInfo,
|
||||
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
ArrayRef<TemplateArgument> ConvertedArgs,
|
||||
Optional<bool> IsSatisfied);
|
||||
const ConstraintSatisfaction *Satisfaction);
|
||||
|
||||
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
|
||||
|
||||
public:
|
||||
|
||||
static ConceptSpecializationExpr *
|
||||
Create(ASTContext &C, NestedNameSpecifierLoc NNS,
|
||||
SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
|
||||
Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
|
||||
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
|
||||
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied);
|
||||
ArrayRef<TemplateArgument> ConvertedArgs,
|
||||
const ConstraintSatisfaction *Satisfaction);
|
||||
|
||||
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);
|
||||
void setTemplateArguments(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!
|
||||
/// when the expression was created.
|
||||
/// The expression must not be dependent.
|
||||
bool isSatisfied() const {
|
||||
assert(!isValueDependent()
|
||||
&& "isSatisfied called on a dependent ConceptSpecializationExpr");
|
||||
return NamedConcept.getInt();
|
||||
return Satisfaction->IsSatisfied;
|
||||
}
|
||||
|
||||
SourceLocation getConceptNameLoc() const { return ConceptNameLoc; }
|
||||
|
||||
SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
|
||||
/// \brief Get elaborated satisfaction info about the template arguments'
|
||||
/// satisfaction of the named concept.
|
||||
/// The expression must not be dependent.
|
||||
const ASTConstraintSatisfaction &getSatisfaction() const {
|
||||
assert(!isValueDependent()
|
||||
&& "getSatisfaction called on dependent ConceptSpecializationExpr");
|
||||
return *Satisfaction;
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == ConceptSpecializationExprClass;
|
||||
}
|
||||
|
||||
SourceLocation getBeginLoc() const LLVM_READONLY { return ConceptNameLoc; }
|
||||
SourceLocation getBeginLoc() const LLVM_READONLY {
|
||||
return ConceptName.getBeginLoc();
|
||||
}
|
||||
|
||||
SourceLocation getEndLoc() const LLVM_READONLY {
|
||||
return ArgsAsWritten->RAngleLoc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -642,7 +642,7 @@ private:
|
|||
/// the location of the 'super' keyword. When it's an interface,
|
||||
/// this is that interface.
|
||||
SourceLocation ReceiverLoc;
|
||||
llvm::PointerUnion3<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver;
|
||||
llvm::PointerUnion<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver;
|
||||
|
||||
public:
|
||||
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
|
||||
|
|
|
|||
|
|
@ -66,9 +66,8 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
|
|||
/// whenever we might have added new redeclarations for existing decls.
|
||||
uint32_t CurrentGeneration = 0;
|
||||
|
||||
/// Whether this AST source also provides information for
|
||||
/// semantic analysis.
|
||||
bool SemaSource = false;
|
||||
/// LLVM-style RTTI.
|
||||
static char ID;
|
||||
|
||||
public:
|
||||
ExternalASTSource() = default;
|
||||
|
|
@ -325,6 +324,12 @@ public:
|
|||
|
||||
virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
|
||||
|
||||
/// LLVM-style RTTI.
|
||||
/// \{
|
||||
virtual bool isA(const void *ClassID) const { return ClassID == &ID; }
|
||||
static bool classof(const ExternalASTSource *S) { return S->isA(&ID); }
|
||||
/// \}
|
||||
|
||||
protected:
|
||||
static DeclContextLookupResult
|
||||
SetExternalVisibleDeclsForName(const DeclContext *DC,
|
||||
|
|
|
|||
|
|
@ -16,12 +16,13 @@
|
|||
#define LLVM_CLANG_AST_JSONNODEDUMPER_H
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ASTNodeTraverser.h"
|
||||
#include "clang/AST/ASTDumperUtils.h"
|
||||
#include "clang/AST/ASTNodeTraverser.h"
|
||||
#include "clang/AST/AttrVisitor.h"
|
||||
#include "clang/AST/CommentCommandTraits.h"
|
||||
#include "clang/AST/CommentVisitor.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/Mangle.h"
|
||||
#include "llvm/Support/JSON.h"
|
||||
|
||||
namespace clang {
|
||||
|
|
@ -122,9 +123,10 @@ class JSONNodeDumper
|
|||
|
||||
const SourceManager &SM;
|
||||
ASTContext& Ctx;
|
||||
ASTNameGenerator ASTNameGen;
|
||||
PrintingPolicy PrintPolicy;
|
||||
const comments::CommandTraits *Traits;
|
||||
StringRef LastLocFilename;
|
||||
StringRef LastLocFilename, LastLocPresumedFilename;
|
||||
unsigned LastLocLine, LastLocPresumedLine;
|
||||
|
||||
using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>;
|
||||
|
|
@ -182,8 +184,9 @@ public:
|
|||
JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
|
||||
const PrintingPolicy &PrintPolicy,
|
||||
const comments::CommandTraits *Traits)
|
||||
: NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), PrintPolicy(PrintPolicy),
|
||||
Traits(Traits), LastLocLine(0), LastLocPresumedLine(0) {}
|
||||
: NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), ASTNameGen(Ctx),
|
||||
PrintPolicy(PrintPolicy), Traits(Traits), LastLocLine(0),
|
||||
LastLocPresumedLine(0) {}
|
||||
|
||||
void Visit(const Attr *A);
|
||||
void Visit(const Stmt *Node);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Frontend/OpenMP/OMPConstants.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/TrailingObjects.h"
|
||||
|
|
@ -111,7 +112,7 @@ class OMPClauseWithPreInit {
|
|||
Stmt *PreInit = nullptr;
|
||||
|
||||
/// Region that captures the associated stmt.
|
||||
OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
|
||||
OpenMPDirectiveKind CaptureRegion = llvm::omp::OMPD_unknown;
|
||||
|
||||
protected:
|
||||
OMPClauseWithPreInit(const OMPClause *This) {
|
||||
|
|
@ -119,7 +120,9 @@ protected:
|
|||
}
|
||||
|
||||
/// Set pre-initialization statement for the clause.
|
||||
void setPreInitStmt(Stmt *S, OpenMPDirectiveKind ThisRegion = OMPD_unknown) {
|
||||
void
|
||||
setPreInitStmt(Stmt *S,
|
||||
OpenMPDirectiveKind ThisRegion = llvm::omp::OMPD_unknown) {
|
||||
PreInit = S;
|
||||
CaptureRegion = ThisRegion;
|
||||
}
|
||||
|
|
@ -432,7 +435,7 @@ class OMPIfClause : public OMPClause, public OMPClauseWithPreInit {
|
|||
SourceLocation ColonLoc;
|
||||
|
||||
/// Directive name modifier for the clause.
|
||||
OpenMPDirectiveKind NameModifier = OMPD_unknown;
|
||||
OpenMPDirectiveKind NameModifier = llvm::omp::OMPD_unknown;
|
||||
|
||||
/// Name modifier location.
|
||||
SourceLocation NameModifierLoc;
|
||||
|
|
@ -943,7 +946,7 @@ class OMPProcBindClause : public OMPClause {
|
|||
SourceLocation LParenLoc;
|
||||
|
||||
/// A kind of the 'proc_bind' clause.
|
||||
OpenMPProcBindClauseKind Kind = OMPC_PROC_BIND_unknown;
|
||||
llvm::omp::ProcBindKind Kind = llvm::omp::OMP_PROC_BIND_unknown;
|
||||
|
||||
/// Start location of the kind in source code.
|
||||
SourceLocation KindKwLoc;
|
||||
|
|
@ -951,7 +954,7 @@ class OMPProcBindClause : public OMPClause {
|
|||
/// Set kind of the clause.
|
||||
///
|
||||
/// \param K Kind of clause.
|
||||
void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; }
|
||||
void setProcBindKind(llvm::omp::ProcBindKind K) { Kind = K; }
|
||||
|
||||
/// Set clause kind location.
|
||||
///
|
||||
|
|
@ -967,7 +970,7 @@ public:
|
|||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc,
|
||||
OMPProcBindClause(llvm::omp::ProcBindKind A, SourceLocation ALoc,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
|
|
@ -984,7 +987,7 @@ public:
|
|||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
|
||||
/// Returns kind of the clause.
|
||||
OpenMPProcBindClauseKind getProcBindKind() const { return Kind; }
|
||||
llvm::omp::ProcBindKind getProcBindKind() const { return Kind; }
|
||||
|
||||
/// Returns location of clause kind.
|
||||
SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; }
|
||||
|
|
@ -2150,6 +2153,13 @@ class OMPLastprivateClause final
|
|||
friend OMPVarListClause;
|
||||
friend TrailingObjects;
|
||||
|
||||
/// Optional lastprivate kind, e.g. 'conditional', if specified by user.
|
||||
OpenMPLastprivateModifier LPKind;
|
||||
/// Optional location of the lasptrivate kind, if specified by user.
|
||||
SourceLocation LPKindLoc;
|
||||
/// Optional colon location, if specified by user.
|
||||
SourceLocation ColonLoc;
|
||||
|
||||
/// Build clause with number of variables \a N.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
|
|
@ -2157,10 +2167,13 @@ class OMPLastprivateClause final
|
|||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param N Number of the variables in the clause.
|
||||
OMPLastprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, unsigned N)
|
||||
SourceLocation EndLoc, OpenMPLastprivateModifier LPKind,
|
||||
SourceLocation LPKindLoc, SourceLocation ColonLoc,
|
||||
unsigned N)
|
||||
: OMPVarListClause<OMPLastprivateClause>(OMPC_lastprivate, StartLoc,
|
||||
LParenLoc, EndLoc, N),
|
||||
OMPClauseWithPostUpdate(this) {}
|
||||
OMPClauseWithPostUpdate(this), LPKind(LPKind), LPKindLoc(LPKindLoc),
|
||||
ColonLoc(ColonLoc) {}
|
||||
|
||||
/// Build an empty clause.
|
||||
///
|
||||
|
|
@ -2221,6 +2234,13 @@ class OMPLastprivateClause final
|
|||
return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size());
|
||||
}
|
||||
|
||||
/// Sets lastprivate kind.
|
||||
void setKind(OpenMPLastprivateModifier Kind) { LPKind = Kind; }
|
||||
/// Sets location of the lastprivate kind.
|
||||
void setKindLoc(SourceLocation Loc) { LPKindLoc = Loc; }
|
||||
/// Sets colon symbol location.
|
||||
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
|
||||
|
||||
public:
|
||||
/// Creates clause with a list of variables \a VL.
|
||||
///
|
||||
|
|
@ -2242,6 +2262,9 @@ public:
|
|||
/// \endcode
|
||||
/// Required for proper codegen of final assignment performed by the
|
||||
/// lastprivate clause.
|
||||
/// \param LPKind Lastprivate kind, e.g. 'conditional'.
|
||||
/// \param LPKindLoc Location of the lastprivate kind.
|
||||
/// \param ColonLoc Location of the ':' symbol if lastprivate kind is used.
|
||||
/// \param PreInit Statement that must be executed before entering the OpenMP
|
||||
/// region with this clause.
|
||||
/// \param PostUpdate Expression that must be executed after exit from the
|
||||
|
|
@ -2250,7 +2273,8 @@ public:
|
|||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
|
||||
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps,
|
||||
Stmt *PreInit, Expr *PostUpdate);
|
||||
OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc,
|
||||
SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate);
|
||||
|
||||
/// Creates an empty clause with the place for \a N variables.
|
||||
///
|
||||
|
|
@ -2258,6 +2282,13 @@ public:
|
|||
/// \param N The number of variables.
|
||||
static OMPLastprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
|
||||
|
||||
/// Lastprivate kind.
|
||||
OpenMPLastprivateModifier getKind() const { return LPKind; }
|
||||
/// Returns the location of the lastprivate kind.
|
||||
SourceLocation getKindLoc() const { return LPKindLoc; }
|
||||
/// Returns the location of the ':' symbol, if any.
|
||||
SourceLocation getColonLoc() const { return ColonLoc; }
|
||||
|
||||
using helper_expr_iterator = MutableArrayRef<Expr *>::iterator;
|
||||
using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator;
|
||||
using helper_expr_range = llvm::iterator_range<helper_expr_iterator>;
|
||||
|
|
@ -6240,6 +6271,102 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// This represents clause 'nontemporal' in the '#pragma omp ...' directives.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp simd nontemporal(a)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp simd' has clause 'nontemporal' for
|
||||
/// the variable 'a'.
|
||||
class OMPNontemporalClause final
|
||||
: public OMPVarListClause<OMPNontemporalClause>,
|
||||
private llvm::TrailingObjects<OMPNontemporalClause, Expr *> {
|
||||
friend class OMPClauseReader;
|
||||
friend OMPVarListClause;
|
||||
friend TrailingObjects;
|
||||
|
||||
/// Build clause with number of variables \a N.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param N Number of the variables in the clause.
|
||||
OMPNontemporalClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, unsigned N)
|
||||
: OMPVarListClause<OMPNontemporalClause>(OMPC_nontemporal, StartLoc,
|
||||
LParenLoc, EndLoc, N) {}
|
||||
|
||||
/// Build an empty clause.
|
||||
///
|
||||
/// \param N Number of variables.
|
||||
explicit OMPNontemporalClause(unsigned N)
|
||||
: OMPVarListClause<OMPNontemporalClause>(
|
||||
OMPC_nontemporal, SourceLocation(), SourceLocation(),
|
||||
SourceLocation(), N) {}
|
||||
|
||||
/// Get the list of privatied copies if the member expression was captured by
|
||||
/// one of the privatization clauses.
|
||||
MutableArrayRef<Expr *> getPrivateRefs() {
|
||||
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
|
||||
}
|
||||
ArrayRef<const Expr *> getPrivateRefs() const {
|
||||
return llvm::makeArrayRef(varlist_end(), varlist_size());
|
||||
}
|
||||
|
||||
public:
|
||||
/// Creates clause with a list of variables \a VL.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param VL List of references to the variables.
|
||||
static OMPNontemporalClause *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, ArrayRef<Expr *> VL);
|
||||
|
||||
/// Creates an empty clause with the place for \a N variables.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param N The number of variables.
|
||||
static OMPNontemporalClause *CreateEmpty(const ASTContext &C, unsigned N);
|
||||
|
||||
/// Sets the list of references to private copies created in private clauses.
|
||||
/// \param VL List of references.
|
||||
void setPrivateRefs(ArrayRef<Expr *> VL);
|
||||
|
||||
child_range children() {
|
||||
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
reinterpret_cast<Stmt **>(varlist_end()));
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
auto Children = const_cast<OMPNontemporalClause *>(this)->children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
child_range private_refs() {
|
||||
return child_range(reinterpret_cast<Stmt **>(getPrivateRefs().begin()),
|
||||
reinterpret_cast<Stmt **>(getPrivateRefs().end()));
|
||||
}
|
||||
|
||||
const_child_range private_refs() const {
|
||||
auto Children = const_cast<OMPNontemporalClause *>(this)->private_refs();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_nontemporal;
|
||||
}
|
||||
};
|
||||
|
||||
/// This class implements a simple visitor for OMPClause
|
||||
/// subclasses.
|
||||
template<class ImplClass, template <typename> class Ptr, typename RetTy>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the PrinterHelper interface.
|
||||
// This file defines helper types for AST pretty-printing.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
|
@ -29,6 +29,16 @@ public:
|
|||
virtual bool handledStmt(Stmt* E, raw_ostream& OS) = 0;
|
||||
};
|
||||
|
||||
/// Callbacks to use to customize the behavior of the pretty-printer.
|
||||
class PrintingCallbacks {
|
||||
protected:
|
||||
~PrintingCallbacks() = default;
|
||||
|
||||
public:
|
||||
/// Remap a path to a form suitable for printing.
|
||||
virtual std::string remapPath(StringRef Path) const { return Path; }
|
||||
};
|
||||
|
||||
/// Describes how types, statements, expressions, and declarations should be
|
||||
/// printed.
|
||||
///
|
||||
|
|
@ -50,7 +60,7 @@ struct PrintingPolicy {
|
|||
MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
|
||||
MSVCFormatting(false), ConstantsAsWritten(false),
|
||||
SuppressImplicitBase(false), FullyQualifiedName(false),
|
||||
RemapFilePaths(false), PrintCanonicalTypes(false) {}
|
||||
PrintCanonicalTypes(false) {}
|
||||
|
||||
/// Adjust this printing policy for cases where it's known that we're
|
||||
/// printing C++ code (for instance, if AST dumping reaches a C++-only
|
||||
|
|
@ -224,14 +234,11 @@ struct PrintingPolicy {
|
|||
/// This is the opposite of SuppressScope and thus overrules it.
|
||||
unsigned FullyQualifiedName : 1;
|
||||
|
||||
/// Whether to apply -fdebug-prefix-map to any file paths.
|
||||
unsigned RemapFilePaths : 1;
|
||||
|
||||
/// Whether to print types as written or canonically.
|
||||
unsigned PrintCanonicalTypes : 1;
|
||||
|
||||
/// When RemapFilePaths is true, this function performs the action.
|
||||
std::function<std::string(StringRef)> remapPath;
|
||||
/// Callbacks to use to allow the behavior of printing to be customized.
|
||||
const PrintingCallbacks *Callbacks = nullptr;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
|||
495
clang/include/clang/AST/PropertiesBase.td
Normal file
495
clang/include/clang/AST/PropertiesBase.td
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
//==--- PropertiesBase.td - Baseline definitions for AST properties -------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class HasProperties;
|
||||
|
||||
/// The type of the property.
|
||||
class PropertyType<string typeName = ""> {
|
||||
/// The C++ type name for the type.
|
||||
string CXXName = !if(!ne(typeName, ""), typeName, NAME);
|
||||
|
||||
/// Whether the C++ type should generally be passed around by reference.
|
||||
bit PassByReference = 0;
|
||||
|
||||
/// Whether `const` should be prepended to the type when writing.
|
||||
bit ConstWhenWriting = 0;
|
||||
|
||||
/// Given a value of type Optional<CXXName> bound as 'value', yield a
|
||||
/// CXXName that can be serialized into a DataStreamTypeWriter.
|
||||
string PackOptional = "";
|
||||
|
||||
/// Given a value of type CXXName bound as 'value' that was deserialized
|
||||
/// by a DataStreamTypeReader, yield an Optional<CXXName>.
|
||||
string UnpackOptional = "";
|
||||
|
||||
/// A list of types for which buffeers must be passed to the read
|
||||
/// operations.
|
||||
list<PropertyType> BufferElementTypes = [];
|
||||
}
|
||||
|
||||
/// Property types that correspond to specific C++ enums.
|
||||
class EnumPropertyType<string typeName = ""> : PropertyType<typeName> {}
|
||||
|
||||
/// Property types that correspond to a specific C++ class.
|
||||
/// Supports optional values by using the null representation.
|
||||
class RefPropertyType<string className> : PropertyType<className # "*"> {
|
||||
let PackOptional =
|
||||
"value ? *value : nullptr";
|
||||
let UnpackOptional =
|
||||
"value ? llvm::Optional<" # CXXName # ">(value) : llvm::None";
|
||||
}
|
||||
|
||||
/// Property types that correspond to a specific subclass of another type.
|
||||
class SubclassPropertyType<string className, PropertyType base>
|
||||
: RefPropertyType<className> {
|
||||
PropertyType Base = base;
|
||||
string SubclassName = className;
|
||||
let ConstWhenWriting = base.ConstWhenWriting;
|
||||
}
|
||||
|
||||
/// Property types that support optional values by using their
|
||||
/// default value.
|
||||
class DefaultValuePropertyType<string typeName = ""> : PropertyType<typeName> {
|
||||
let PackOptional =
|
||||
"value ? *value : " # CXXName # "()";
|
||||
let UnpackOptional =
|
||||
"value.isNull() ? llvm::None : llvm::Optional<" # CXXName # ">(value)";
|
||||
}
|
||||
|
||||
/// Property types that correspond to integer types and support optional
|
||||
/// values by shifting the value over by 1.
|
||||
class CountPropertyType<string typeName = ""> : PropertyType<typeName> {
|
||||
let PackOptional =
|
||||
"value ? *value + 1 : 0";
|
||||
let UnpackOptional =
|
||||
"value ? llvm::Optional<" # CXXName # ">(value - 1) : llvm::None";
|
||||
}
|
||||
|
||||
def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
|
||||
def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; }
|
||||
def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">;
|
||||
def AttrKind : EnumPropertyType<"attr::Kind">;
|
||||
def AutoTypeKeyword : EnumPropertyType;
|
||||
def Bool : PropertyType<"bool">;
|
||||
def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;
|
||||
def CallingConv : EnumPropertyType;
|
||||
def DeclarationName : PropertyType;
|
||||
def DeclarationNameKind : EnumPropertyType<"DeclarationName::NameKind">;
|
||||
def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; }
|
||||
def CXXRecordDeclRef :
|
||||
SubclassPropertyType<"CXXRecordDecl", DeclRef>;
|
||||
def FunctionDeclRef :
|
||||
SubclassPropertyType<"FunctionDecl", DeclRef>;
|
||||
def NamedDeclRef :
|
||||
SubclassPropertyType<"NamedDecl", DeclRef>;
|
||||
def NamespaceDeclRef :
|
||||
SubclassPropertyType<"NamespaceDecl", DeclRef>;
|
||||
def NamespaceAliasDeclRef :
|
||||
SubclassPropertyType<"NamespaceAliasDecl", DeclRef>;
|
||||
def ObjCProtocolDeclRef :
|
||||
SubclassPropertyType<"ObjCProtocolDecl", DeclRef>;
|
||||
def ObjCTypeParamDeclRef :
|
||||
SubclassPropertyType<"ObjCTypeParamDecl", DeclRef>;
|
||||
def TagDeclRef :
|
||||
SubclassPropertyType<"TagDecl", DeclRef>;
|
||||
def TemplateDeclRef :
|
||||
SubclassPropertyType<"TemplateDecl", DeclRef>;
|
||||
def TemplateTypeParmDeclRef :
|
||||
SubclassPropertyType<"TemplateTypeParmDecl", DeclRef>;
|
||||
def TemplateTemplateParmDeclRef :
|
||||
SubclassPropertyType<"TemplateTemplateParmDecl", DeclRef>;
|
||||
def ValueDeclRef :
|
||||
SubclassPropertyType<"ValueDecl", DeclRef>;
|
||||
def ElaboratedTypeKeyword : EnumPropertyType;
|
||||
def ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">;
|
||||
def Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; }
|
||||
def NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">;
|
||||
def NestedNameSpecifierKind :
|
||||
EnumPropertyType<"NestedNameSpecifier::SpecifierKind">;
|
||||
def OverloadedOperatorKind : EnumPropertyType;
|
||||
def Qualifiers : PropertyType;
|
||||
def QualType : DefaultValuePropertyType;
|
||||
def RefQualifierKind : EnumPropertyType;
|
||||
def Selector : PropertyType;
|
||||
def SourceLocation : PropertyType;
|
||||
def StmtRef : RefPropertyType<"Stmt"> { let ConstWhenWriting = 1; }
|
||||
def ExprRef : SubclassPropertyType<"Expr", StmtRef>;
|
||||
def TemplateArgument : PropertyType;
|
||||
def TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">;
|
||||
def TemplateName : DefaultValuePropertyType;
|
||||
def TemplateNameKind : EnumPropertyType<"TemplateName::NameKind">;
|
||||
def UInt32 : CountPropertyType<"uint32_t">;
|
||||
def UInt64 : CountPropertyType<"uint64_t">;
|
||||
def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">;
|
||||
def VectorKind : EnumPropertyType<"VectorType::VectorKind">;
|
||||
|
||||
def ExceptionSpecInfo : PropertyType<"FunctionProtoType::ExceptionSpecInfo"> {
|
||||
let BufferElementTypes = [ QualType ];
|
||||
}
|
||||
|
||||
/// Arrays. The corresponding C++ type is ArrayRef of the corresponding
|
||||
/// C++ type of the element.
|
||||
class Array<PropertyType element> : PropertyType {
|
||||
PropertyType Element = element;
|
||||
let BufferElementTypes = [ element ];
|
||||
}
|
||||
|
||||
/// llvm::Optional<T>. The corresponding C++ type is generally just the
|
||||
/// corresponding C++ type of the element.
|
||||
///
|
||||
/// Optional<Unsigned> may restrict the range of the operand for some
|
||||
/// serialization clients.
|
||||
class Optional<PropertyType element> : PropertyType {
|
||||
PropertyType Element = element;
|
||||
let PassByReference = element.PassByReference;
|
||||
}
|
||||
|
||||
/// A property of an AST node.
|
||||
class Property<string name, PropertyType type> {
|
||||
HasProperties Class;
|
||||
string Name = name;
|
||||
PropertyType Type = type;
|
||||
|
||||
/// A function for reading the property, expressed in terms of a variable
|
||||
/// "node".
|
||||
code Read;
|
||||
|
||||
/// Code specifying when this property is available. Can be defined
|
||||
/// in terms of other properties, in which case this property must be
|
||||
/// read/written after those properties. Using this will make the
|
||||
/// value Optional when deserializing.
|
||||
///
|
||||
/// FIXME: the emitter doesn't yet force dependent properties to be
|
||||
/// read/written later; this only works if the properties used in the
|
||||
/// condition happen to be written first.
|
||||
code Conditional = "";
|
||||
}
|
||||
|
||||
/// A rule for declaring helper variables when read properties from a
|
||||
/// value of this type. Note that this means that this code is actually
|
||||
/// run when *writing* values of this type; however, naming this
|
||||
/// `ReadHelper` makes the connection to the `Read` operations on the
|
||||
/// properties much clearer.
|
||||
class ReadHelper<code _code> {
|
||||
HasProperties Class;
|
||||
|
||||
/// Code which will be run when writing objects of this type before
|
||||
/// writing any of the properties, specified in terms of a variable
|
||||
/// `node`.
|
||||
code Code = _code;
|
||||
}
|
||||
|
||||
/// A rule for creating objects of this type.
|
||||
class Creator<code create> {
|
||||
HasProperties Class;
|
||||
|
||||
/// A function for creating values of this kind, expressed in terms of a
|
||||
/// variable `ctx` of type `ASTContext &`. Must also refer to all of the
|
||||
/// properties by name.
|
||||
code Create = create;
|
||||
}
|
||||
|
||||
/// A rule which overrides some of the normal rules.
|
||||
class Override {
|
||||
HasProperties Class;
|
||||
|
||||
/// Properties from base classes that should be ignored.
|
||||
list<string> IgnoredProperties = [];
|
||||
}
|
||||
|
||||
/// A description of how to break a type into cases. Providing this and
|
||||
/// an exhaustive list of the cases will cause AbstractBasic{Reader,Writer}
|
||||
/// to be generated with a default implementation of how to read the
|
||||
/// type.
|
||||
///
|
||||
/// Creator rules for the cases can additionally access a variable
|
||||
/// `kind` of the KindType.
|
||||
class PropertyTypeKind<PropertyType type,
|
||||
PropertyType kindType,
|
||||
string readCode> {
|
||||
/// The type for which this describes cases.
|
||||
PropertyType Type = type;
|
||||
|
||||
/// The type of this type's kind enum.
|
||||
PropertyType KindType = kindType;
|
||||
|
||||
/// The property name to use for the kind.
|
||||
string KindPropertyName = "kind";
|
||||
|
||||
/// An expression which reads the kind from a value, expressed in terms
|
||||
/// of a variable `node`.
|
||||
string Read = readCode;
|
||||
}
|
||||
|
||||
/// One of the options for representing a particular type.
|
||||
class PropertyTypeCase<PropertyType type, string name> : HasProperties {
|
||||
/// The type of which this is a case.
|
||||
PropertyType Type = type;
|
||||
|
||||
/// The name of the case (a value of the type's kind enum).
|
||||
string Name = name;
|
||||
}
|
||||
|
||||
// Type cases for DeclarationName.
|
||||
def : PropertyTypeKind<DeclarationName, DeclarationNameKind,
|
||||
"node.getNameKind()">;
|
||||
let Class = PropertyTypeCase<DeclarationName, "Identifier"> in {
|
||||
def : Property<"identifier", Identifier> {
|
||||
let Read = [{ node.getAsIdentifierInfo() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return DeclarationName(identifier);
|
||||
}]>;
|
||||
}
|
||||
foreach count = ["Zero", "One", "Multi"] in {
|
||||
let Class = PropertyTypeCase<DeclarationName, "ObjC"#count#"ArgSelector"> in {
|
||||
def : Property<"selector", Selector> {
|
||||
let Read = [{ node.getObjCSelector() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return DeclarationName(selector);
|
||||
}]>;
|
||||
}
|
||||
}
|
||||
foreach kind = ["Constructor", "Destructor", "ConversionFunction"] in {
|
||||
let Class = PropertyTypeCase<DeclarationName, "CXX"#kind#"Name"> in {
|
||||
def : Property<"type", QualType> {
|
||||
let Read = [{ node.getCXXNameType() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return ctx.DeclarationNames.getCXX}]#kind#[{Name(
|
||||
ctx.getCanonicalType(type));
|
||||
}]>;
|
||||
}
|
||||
}
|
||||
let Class = PropertyTypeCase<DeclarationName, "CXXDeductionGuideName"> in {
|
||||
def : Property<"declaration", TemplateDeclRef> {
|
||||
let Read = [{ node.getCXXDeductionGuideTemplate() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return ctx.DeclarationNames.getCXXDeductionGuideName(declaration);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<DeclarationName, "CXXOperatorName"> in {
|
||||
def : Property<"operatorKind", OverloadedOperatorKind> {
|
||||
let Read = [{ node.getCXXOverloadedOperator() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return ctx.DeclarationNames.getCXXOperatorName(operatorKind);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<DeclarationName, "CXXLiteralOperatorName"> in {
|
||||
def : Property<"identifier", Identifier> {
|
||||
let Read = [{ node.getCXXLiteralIdentifier() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return ctx.DeclarationNames.getCXXLiteralOperatorName(identifier);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<DeclarationName, "CXXUsingDirective"> in {
|
||||
def : Creator<[{
|
||||
return DeclarationName::getUsingDirectiveName();
|
||||
}]>;
|
||||
}
|
||||
|
||||
// Type cases for TemplateName.
|
||||
def : PropertyTypeKind<TemplateName, TemplateNameKind, "node.getKind()">;
|
||||
let Class = PropertyTypeCase<TemplateName, "Template"> in {
|
||||
def : Property<"declaration", TemplateDeclRef> {
|
||||
let Read = [{ node.getAsTemplateDecl() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return TemplateName(declaration);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateName, "OverloadedTemplate"> in {
|
||||
def : Property<"overloads", Array<NamedDeclRef>> {
|
||||
let Read = [{ node.getAsOverloadedTemplate()->decls() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
// Copy into an UnresolvedSet to satisfy the interface.
|
||||
UnresolvedSet<8> overloadSet;
|
||||
for (auto overload : overloads) {
|
||||
overloadSet.addDecl(overload);
|
||||
}
|
||||
|
||||
return ctx.getOverloadedTemplateName(overloadSet.begin(),
|
||||
overloadSet.end());
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateName, "AssumedTemplate"> in {
|
||||
def : Property<"name", DeclarationName> {
|
||||
let Read = [{ node.getAsAssumedTemplateName()->getDeclName() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return ctx.getAssumedTemplateName(name);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateName, "QualifiedTemplate"> in {
|
||||
def : ReadHelper<[{
|
||||
auto qtn = node.getAsQualifiedTemplateName();
|
||||
}]>;
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ qtn->getQualifier() }];
|
||||
}
|
||||
def : Property<"hasTemplateKeyword", Bool> {
|
||||
let Read = [{ qtn->hasTemplateKeyword() }];
|
||||
}
|
||||
def : Property<"declaration", TemplateDeclRef> {
|
||||
let Read = [{ qtn->getTemplateDecl() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return ctx.getQualifiedTemplateName(qualifier, hasTemplateKeyword,
|
||||
declaration);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in {
|
||||
def : ReadHelper<[{
|
||||
auto dtn = node.getAsDependentTemplateName();
|
||||
}]>;
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ dtn->getQualifier() }];
|
||||
}
|
||||
def : Property<"identifier", Optional<Identifier>> {
|
||||
let Read = [{ makeOptionalFromPointer(
|
||||
dtn->isIdentifier()
|
||||
? dtn->getIdentifier()
|
||||
: nullptr) }];
|
||||
}
|
||||
def : Property<"operatorKind", OverloadedOperatorKind> {
|
||||
let Conditional = [{ !identifier }];
|
||||
let Read = [{ dtn->getOperator() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
if (identifier) {
|
||||
return ctx.getDependentTemplateName(qualifier, *identifier);
|
||||
} else {
|
||||
return ctx.getDependentTemplateName(qualifier, *operatorKind);
|
||||
}
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
|
||||
def : ReadHelper<[{
|
||||
auto parm = node.getAsSubstTemplateTemplateParm();
|
||||
}]>;
|
||||
def : Property<"parameter", TemplateTemplateParmDeclRef> {
|
||||
let Read = [{ parm->getParameter() }];
|
||||
}
|
||||
def : Property<"replacement", TemplateName> {
|
||||
let Read = [{ parm->getReplacement() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return ctx.getSubstTemplateTemplateParm(parameter, replacement);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
|
||||
def : ReadHelper<[{
|
||||
auto parm = node.getAsSubstTemplateTemplateParmPack();
|
||||
}]>;
|
||||
def : Property<"parameterPack", TemplateTemplateParmDeclRef> {
|
||||
let Read = [{ parm->getParameterPack() }];
|
||||
}
|
||||
def : Property<"argumentPack", TemplateArgument> {
|
||||
let Read = [{ parm->getArgumentPack() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return ctx.getSubstTemplateTemplateParmPack(parameterPack, argumentPack);
|
||||
}]>;
|
||||
}
|
||||
|
||||
// Type cases for TemplateArgument.
|
||||
def : PropertyTypeKind<TemplateArgument, TemplateArgumentKind,
|
||||
"node.getKind()">;
|
||||
let Class = PropertyTypeCase<TemplateArgument, "Null"> in {
|
||||
def : Creator<[{
|
||||
return TemplateArgument();
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "Type"> in {
|
||||
def : Property<"type", QualType> {
|
||||
let Read = [{ node.getAsType() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return TemplateArgument(type);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "Declaration"> in {
|
||||
def : Property<"declaration", ValueDeclRef> {
|
||||
let Read = [{ node.getAsDecl() }];
|
||||
}
|
||||
def : Property<"parameterType", QualType> {
|
||||
let Read = [{ node.getParamTypeForDecl() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return TemplateArgument(declaration, parameterType);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "NullPtr"> in {
|
||||
def : Property<"type", QualType> {
|
||||
let Read = [{ node.getNullPtrType() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return TemplateArgument(type, /*nullptr*/ true);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
|
||||
def : Property<"value", APSInt> {
|
||||
let Read = [{ node.getAsIntegral() }];
|
||||
}
|
||||
def : Property<"type", QualType> {
|
||||
let Read = [{ node.getIntegralType() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return TemplateArgument(ctx, value, type);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "Template"> in {
|
||||
def : Property<"name", TemplateName> {
|
||||
let Read = [{ node.getAsTemplateOrTemplatePattern() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return TemplateArgument(name);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in {
|
||||
def : Property<"name", TemplateName> {
|
||||
let Read = [{ node.getAsTemplateOrTemplatePattern() }];
|
||||
}
|
||||
def : Property<"numExpansions", Optional<UInt32>> {
|
||||
let Read = [{
|
||||
// Translate unsigned -> uint32_t just in case.
|
||||
node.getNumTemplateExpansions().map(
|
||||
[](unsigned i) { return uint32_t(i); })
|
||||
}];
|
||||
}
|
||||
def : Creator<[{
|
||||
auto numExpansionsUnsigned =
|
||||
numExpansions.map([](uint32_t i) { return unsigned(i); });
|
||||
return TemplateArgument(name, numExpansionsUnsigned);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "Expression"> in {
|
||||
def : Property<"expression", ExprRef> {
|
||||
let Read = [{ node.getAsExpr() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
return TemplateArgument(expression);
|
||||
}]>;
|
||||
}
|
||||
let Class = PropertyTypeCase<TemplateArgument, "Pack"> in {
|
||||
def : Property<"elements", Array<TemplateArgument>> {
|
||||
let Read = [{ node.pack_elements() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
// Copy the pack into the ASTContext.
|
||||
TemplateArgument *ctxElements = new (ctx) TemplateArgument[elements.size()];
|
||||
for (size_t i = 0, e = elements.size(); i != e; ++i)
|
||||
ctxElements[i] = elements[i];
|
||||
return TemplateArgument(llvm::makeArrayRef(ctxElements, elements.size()));
|
||||
}]>;
|
||||
}
|
||||
|
|
@ -304,6 +304,11 @@ public:
|
|||
bool TraverseSynOrSemInitListExpr(InitListExpr *S,
|
||||
DataRecursionQueue *Queue = nullptr);
|
||||
|
||||
/// Recursively visit a reference to a concept with potential arguments.
|
||||
///
|
||||
/// \returns false if the visitation was terminated early, true otherwise.
|
||||
bool TraverseConceptReference(const ConceptReference &C);
|
||||
|
||||
// ---- Methods on Attrs ----
|
||||
|
||||
// Visit an attribute.
|
||||
|
|
@ -1162,11 +1167,13 @@ DEF_TRAVERSE_TYPELOC(LValueReferenceType,
|
|||
DEF_TRAVERSE_TYPELOC(RValueReferenceType,
|
||||
{ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
|
||||
|
||||
// FIXME: location of base class?
|
||||
// We traverse this in the type case as well, but how is it not reached through
|
||||
// the pointee type?
|
||||
DEF_TRAVERSE_TYPELOC(MemberPointerType, {
|
||||
TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
|
||||
if (auto *TSI = TL.getClassTInfo())
|
||||
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
|
||||
else
|
||||
TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
|
||||
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
|
||||
})
|
||||
|
||||
|
|
@ -1435,6 +1442,10 @@ DEF_TRAVERSE_DECL(CapturedDecl, {
|
|||
|
||||
DEF_TRAVERSE_DECL(EmptyDecl, {})
|
||||
|
||||
DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
|
||||
TRY_TO(TraverseStmt(D->getTemporaryExpr()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(FileScopeAsmDecl,
|
||||
{ TRY_TO(TraverseStmt(D->getAsmString())); })
|
||||
|
||||
|
|
@ -1767,9 +1778,8 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
|
|||
// D is the "T" in something like
|
||||
// template <template <typename> class T> class container { };
|
||||
TRY_TO(TraverseDecl(D->getTemplatedDecl()));
|
||||
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
|
||||
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
|
||||
TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
|
||||
}
|
||||
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
|
||||
})
|
||||
|
||||
|
|
@ -1781,6 +1791,8 @@ DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
|
|||
// D is the "T" in something like "template<typename T> class vector;"
|
||||
if (D->getTypeForDecl())
|
||||
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
|
||||
if (const auto *TC = D->getTypeConstraint())
|
||||
TRY_TO(TraverseConceptReference(*TC));
|
||||
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
|
||||
TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
|
||||
})
|
||||
|
|
@ -2024,6 +2036,11 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
|
|||
}
|
||||
}
|
||||
|
||||
// Visit the trailing requires clause, if any.
|
||||
if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) {
|
||||
TRY_TO(TraverseStmt(TrailingRequiresClause));
|
||||
}
|
||||
|
||||
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
|
||||
// Constructor initializers.
|
||||
for (auto *I : Ctor->inits()) {
|
||||
|
|
@ -2319,6 +2336,18 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseConceptReference(
|
||||
const ConceptReference &C) {
|
||||
TRY_TO(TraverseNestedNameSpecifierLoc(C.getNestedNameSpecifierLoc()));
|
||||
TRY_TO(TraverseDeclarationNameInfo(C.getConceptNameInfo()));
|
||||
if (C.hasExplicitTemplateArgs())
|
||||
TRY_TO(TraverseTemplateArgumentLocsHelper(
|
||||
C.getTemplateArgsAsWritten()->getTemplateArgs(),
|
||||
C.getTemplateArgsAsWritten()->NumTemplateArgs));
|
||||
return true;
|
||||
}
|
||||
|
||||
// If shouldVisitImplicitCode() returns false, this method traverses only the
|
||||
// syntactic form of InitListExpr.
|
||||
// If shouldVisitImplicitCode() return true, this method is called once for
|
||||
|
|
@ -2351,7 +2380,7 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(
|
|||
// generic associations).
|
||||
DEF_TRAVERSE_STMT(GenericSelectionExpr, {
|
||||
TRY_TO(TraverseStmt(S->getControllingExpr()));
|
||||
for (const GenericSelectionExpr::Association &Assoc : S->associations()) {
|
||||
for (const GenericSelectionExpr::Association Assoc : S->associations()) {
|
||||
if (TypeSourceInfo *TSI = Assoc.getTypeSourceInfo())
|
||||
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(Assoc.getAssociationExpr());
|
||||
|
|
@ -2632,10 +2661,16 @@ DEF_TRAVERSE_STMT(SizeOfPackExpr, {})
|
|||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
|
||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
|
||||
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
|
||||
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
|
||||
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
|
||||
DEF_TRAVERSE_STMT(AtomicExpr, {})
|
||||
|
||||
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {
|
||||
if (S->getLifetimeExtendedTemporaryDecl()) {
|
||||
TRY_TO(TraverseLifetimeExtendedTemporaryDecl(
|
||||
S->getLifetimeExtendedTemporaryDecl()));
|
||||
ShouldVisitChildren = false;
|
||||
}
|
||||
})
|
||||
// For coroutines expressions, traverse either the operand
|
||||
// as written or the implied calls, depending on what the
|
||||
// derived class requests.
|
||||
|
|
@ -2671,9 +2706,7 @@ DEF_TRAVERSE_STMT(CoyieldExpr, {
|
|||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(ConceptSpecializationExpr, {
|
||||
TRY_TO(TraverseTemplateArgumentLocsHelper(
|
||||
S->getTemplateArgsAsWritten()->getTemplateArgs(),
|
||||
S->getTemplateArgsAsWritten()->NumTemplateArgs));
|
||||
TRY_TO(TraverseConceptReference(*S));
|
||||
})
|
||||
|
||||
// These literals (all of them) do not need any action.
|
||||
|
|
@ -2742,6 +2775,9 @@ DEF_TRAVERSE_STMT(OMPParallelForDirective,
|
|||
DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPParallelMasterDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
|
|
@ -2814,6 +2850,9 @@ DEF_TRAVERSE_STMT(OMPMasterTaskLoopSimdDirective,
|
|||
DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopSimdDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPDistributeDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
|
|
@ -3356,6 +3395,16 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIsDevicePtrClause(
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPNontemporalClause(
|
||||
OMPNontemporalClause *C) {
|
||||
TRY_TO(VisitOMPClauseList(C));
|
||||
for (auto *E : C->private_refs()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: look at the following tricky-seeming exprs to see if we
|
||||
// need to recurse on anything. These are ones that have methods
|
||||
// returning decls or qualtypes or nestednamespecifier -- though I'm
|
||||
|
|
|
|||
|
|
@ -1995,6 +1995,10 @@ public:
|
|||
bool isConstexpr() const { return IfStmtBits.IsConstexpr; }
|
||||
void setConstexpr(bool C) { IfStmtBits.IsConstexpr = C; }
|
||||
|
||||
/// If this is an 'if constexpr', determine which substatement will be taken.
|
||||
/// Otherwise, or if the condition is value-dependent, returns None.
|
||||
Optional<const Stmt*> getNondiscardedCase(const ASTContext &Ctx) const;
|
||||
|
||||
bool isObjCAvailabilityCheck() const;
|
||||
|
||||
SourceLocation getBeginLoc() const { return getIfLoc(); }
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ class CXXFoldExpr {
|
|||
}
|
||||
class GenericSelectionExpr {
|
||||
code Code = [{
|
||||
for (const GenericSelectionExpr::ConstAssociation &Assoc : S->associations()) {
|
||||
for (const GenericSelectionExpr::ConstAssociation Assoc : S->associations()) {
|
||||
addData(Assoc.getType());
|
||||
}
|
||||
}];
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -119,6 +119,10 @@ public:
|
|||
|
||||
iterator begin() const { return getStorage(); }
|
||||
iterator end() const { return getStorage() + size(); }
|
||||
|
||||
llvm::ArrayRef<NamedDecl*> decls() const {
|
||||
return llvm::makeArrayRef(begin(), end());
|
||||
}
|
||||
};
|
||||
|
||||
/// A structure for storing an already-substituted template template
|
||||
|
|
@ -186,8 +190,8 @@ public:
|
|||
/// only be understood in the context of
|
||||
class TemplateName {
|
||||
using StorageType =
|
||||
llvm::PointerUnion4<TemplateDecl *, UncommonTemplateNameStorage *,
|
||||
QualifiedTemplateName *, DependentTemplateName *>;
|
||||
llvm::PointerUnion<TemplateDecl *, UncommonTemplateNameStorage *,
|
||||
QualifiedTemplateName *, DependentTemplateName *>;
|
||||
|
||||
StorageType Storage;
|
||||
|
||||
|
|
|
|||
|
|
@ -346,6 +346,8 @@ public:
|
|||
void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
|
||||
void VisitBlockDecl(const BlockDecl *D);
|
||||
void VisitConceptDecl(const ConceptDecl *D);
|
||||
void
|
||||
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
|
|
|||
|
|
@ -66,6 +66,11 @@ enum {
|
|||
TypeAlignment = 1 << TypeAlignmentInBits
|
||||
};
|
||||
|
||||
namespace serialization {
|
||||
template <class T> class AbstractTypeReader;
|
||||
template <class T> class AbstractTypeWriter;
|
||||
}
|
||||
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
|
|
@ -472,7 +477,10 @@ public:
|
|||
return A == B ||
|
||||
// Otherwise in OpenCLC v2.0 s6.5.5: every address space except
|
||||
// for __constant can be used as __generic.
|
||||
(A == LangAS::opencl_generic && B != LangAS::opencl_constant);
|
||||
(A == LangAS::opencl_generic && B != LangAS::opencl_constant) ||
|
||||
// Consider pointer size address spaces to be equivalent to default.
|
||||
((isPtrSizeAddressSpace(A) || A == LangAS::Default) &&
|
||||
(isPtrSizeAddressSpace(B) || B == LangAS::Default));
|
||||
}
|
||||
|
||||
/// Returns true if the address space in these qualifiers is equal to or
|
||||
|
|
@ -553,6 +561,8 @@ public:
|
|||
std::string getAsString() const;
|
||||
std::string getAsString(const PrintingPolicy &Policy) const;
|
||||
|
||||
static std::string getAddrSpaceAsString(LangAS AS);
|
||||
|
||||
bool isEmptyWhenPrinted(const PrintingPolicy &Policy) const;
|
||||
void print(raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
bool appendSpaceIfNonEmpty = false) const;
|
||||
|
|
@ -1046,6 +1056,9 @@ public:
|
|||
ID.AddPointer(getAsOpaquePtr());
|
||||
}
|
||||
|
||||
/// Check if this type has any address space qualifier.
|
||||
inline bool hasAddressSpace() const;
|
||||
|
||||
/// Return the address space of this type.
|
||||
inline LangAS getAddressSpace() const;
|
||||
|
||||
|
|
@ -1842,6 +1855,8 @@ protected:
|
|||
public:
|
||||
friend class ASTReader;
|
||||
friend class ASTWriter;
|
||||
template <class T> friend class serialization::AbstractTypeReader;
|
||||
template <class T> friend class serialization::AbstractTypeWriter;
|
||||
|
||||
Type(const Type &) = delete;
|
||||
Type(Type &&) = delete;
|
||||
|
|
@ -1961,6 +1976,7 @@ public:
|
|||
|
||||
/// Determine whether this type is an integral or unscoped enumeration type.
|
||||
bool isIntegralOrUnscopedEnumerationType() const;
|
||||
bool isUnscopedEnumerationType() const;
|
||||
|
||||
/// Floating point categories.
|
||||
bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
|
||||
|
|
@ -1992,6 +2008,7 @@ public:
|
|||
bool isReferenceType() const;
|
||||
bool isLValueReferenceType() const;
|
||||
bool isRValueReferenceType() const;
|
||||
bool isObjectPointerType() const;
|
||||
bool isFunctionPointerType() const;
|
||||
bool isFunctionReferenceType() const;
|
||||
bool isMemberPointerType() const;
|
||||
|
|
@ -2069,6 +2086,8 @@ public:
|
|||
bool isAlignValT() const; // C++17 std::align_val_t
|
||||
bool isStdByteType() const; // C++17 std::byte
|
||||
bool isAtomicType() const; // C11 _Atomic()
|
||||
bool isUndeducedAutoType() const; // C++11 auto or
|
||||
// C++14 decltype(auto)
|
||||
|
||||
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
|
||||
bool is##Id##Type() const;
|
||||
|
|
@ -3726,9 +3745,9 @@ class FunctionProtoType final
|
|||
: public FunctionType,
|
||||
public llvm::FoldingSetNode,
|
||||
private llvm::TrailingObjects<
|
||||
FunctionProtoType, QualType, FunctionType::FunctionTypeExtraBitfields,
|
||||
FunctionType::ExceptionType, Expr *, FunctionDecl *,
|
||||
FunctionType::ExtParameterInfo, Qualifiers> {
|
||||
FunctionProtoType, QualType, SourceLocation,
|
||||
FunctionType::FunctionTypeExtraBitfields, FunctionType::ExceptionType,
|
||||
Expr *, FunctionDecl *, FunctionType::ExtParameterInfo, Qualifiers> {
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
friend TrailingObjects;
|
||||
|
||||
|
|
@ -3739,6 +3758,9 @@ class FunctionProtoType final
|
|||
// Always present. Note that for the vast majority of FunctionProtoType,
|
||||
// these will be the only trailing objects.
|
||||
//
|
||||
// * Optionally if the function is variadic, the SourceLocation of the
|
||||
// ellipsis.
|
||||
//
|
||||
// * Optionally if some extra data is stored in FunctionTypeExtraBitfields
|
||||
// (see FunctionTypeExtraBitfields and FunctionTypeBitfields):
|
||||
// a single FunctionTypeExtraBitfields. Present if and only if
|
||||
|
|
@ -3810,6 +3832,7 @@ public:
|
|||
RefQualifierKind RefQualifier = RQ_None;
|
||||
ExceptionSpecInfo ExceptionSpec;
|
||||
const ExtParameterInfo *ExtParameterInfos = nullptr;
|
||||
SourceLocation EllipsisLoc;
|
||||
|
||||
ExtProtoInfo() : Variadic(false), HasTrailingReturn(false) {}
|
||||
|
||||
|
|
@ -3828,6 +3851,10 @@ private:
|
|||
return getNumParams();
|
||||
}
|
||||
|
||||
unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
|
||||
return isVariadic();
|
||||
}
|
||||
|
||||
unsigned numTrailingObjects(OverloadToken<FunctionTypeExtraBitfields>) const {
|
||||
return hasExtraBitfields();
|
||||
}
|
||||
|
|
@ -3939,20 +3966,11 @@ public:
|
|||
ExtProtoInfo EPI;
|
||||
EPI.ExtInfo = getExtInfo();
|
||||
EPI.Variadic = isVariadic();
|
||||
EPI.EllipsisLoc = getEllipsisLoc();
|
||||
EPI.HasTrailingReturn = hasTrailingReturn();
|
||||
EPI.ExceptionSpec.Type = getExceptionSpecType();
|
||||
EPI.ExceptionSpec = getExceptionSpecInfo();
|
||||
EPI.TypeQuals = getMethodQuals();
|
||||
EPI.RefQualifier = getRefQualifier();
|
||||
if (EPI.ExceptionSpec.Type == EST_Dynamic) {
|
||||
EPI.ExceptionSpec.Exceptions = exceptions();
|
||||
} else if (isComputedNoexcept(EPI.ExceptionSpec.Type)) {
|
||||
EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr();
|
||||
} else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) {
|
||||
EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
|
||||
EPI.ExceptionSpec.SourceTemplate = getExceptionSpecTemplate();
|
||||
} else if (EPI.ExceptionSpec.Type == EST_Unevaluated) {
|
||||
EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
|
||||
}
|
||||
EPI.ExtParameterInfos = getExtParameterInfosOrNull();
|
||||
return EPI;
|
||||
}
|
||||
|
|
@ -3983,6 +4001,23 @@ public:
|
|||
/// spec.
|
||||
bool hasInstantiationDependentExceptionSpec() const;
|
||||
|
||||
/// Return all the available information about this type's exception spec.
|
||||
ExceptionSpecInfo getExceptionSpecInfo() const {
|
||||
ExceptionSpecInfo Result;
|
||||
Result.Type = getExceptionSpecType();
|
||||
if (Result.Type == EST_Dynamic) {
|
||||
Result.Exceptions = exceptions();
|
||||
} else if (isComputedNoexcept(Result.Type)) {
|
||||
Result.NoexceptExpr = getNoexceptExpr();
|
||||
} else if (Result.Type == EST_Uninstantiated) {
|
||||
Result.SourceDecl = getExceptionSpecDecl();
|
||||
Result.SourceTemplate = getExceptionSpecTemplate();
|
||||
} else if (Result.Type == EST_Unevaluated) {
|
||||
Result.SourceDecl = getExceptionSpecDecl();
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Return the number of types in the exception specification.
|
||||
unsigned getNumExceptions() const {
|
||||
return getExceptionSpecType() == EST_Dynamic
|
||||
|
|
@ -4040,6 +4075,11 @@ public:
|
|||
/// Whether this function prototype is variadic.
|
||||
bool isVariadic() const { return FunctionTypeBits.Variadic; }
|
||||
|
||||
SourceLocation getEllipsisLoc() const {
|
||||
return isVariadic() ? *getTrailingObjects<SourceLocation>()
|
||||
: SourceLocation();
|
||||
}
|
||||
|
||||
/// Determines whether this function prototype contains a
|
||||
/// parameter pack at the end.
|
||||
///
|
||||
|
|
@ -4420,6 +4460,7 @@ public:
|
|||
|
||||
class TagType : public Type {
|
||||
friend class ASTReader;
|
||||
template <class T> friend class serialization::AbstractTypeReader;
|
||||
|
||||
/// Stores the TagDecl associated with this type. The decl may point to any
|
||||
/// TagDecl that declares the entity.
|
||||
|
|
@ -5057,6 +5098,7 @@ class InjectedClassNameType : public Type {
|
|||
friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
|
||||
// currently suitable for AST reading, too much
|
||||
// interdependencies.
|
||||
template <class T> friend class serialization::AbstractTypeReader;
|
||||
|
||||
CXXRecordDecl *Decl;
|
||||
|
||||
|
|
@ -5569,7 +5611,7 @@ class ObjCTypeParamType : public Type,
|
|||
|
||||
public:
|
||||
bool isSugared() const { return true; }
|
||||
QualType desugar() const;
|
||||
QualType desugar() const { return getCanonicalTypeInternal(); }
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ObjCTypeParam;
|
||||
|
|
@ -5815,6 +5857,7 @@ class ObjCInterfaceType : public ObjCObjectType {
|
|||
friend class ASTContext; // ASTContext creates these.
|
||||
friend class ASTReader;
|
||||
friend class ObjCInterfaceDecl;
|
||||
template <class T> friend class serialization::AbstractTypeReader;
|
||||
|
||||
mutable ObjCInterfaceDecl *Decl;
|
||||
|
||||
|
|
@ -6136,6 +6179,33 @@ public:
|
|||
QualType apply(const ASTContext &Context, const Type* T) const;
|
||||
};
|
||||
|
||||
/// A container of type source information.
|
||||
///
|
||||
/// A client can read the relevant info using TypeLoc wrappers, e.g:
|
||||
/// @code
|
||||
/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
|
||||
/// TL.getBeginLoc().print(OS, SrcMgr);
|
||||
/// @endcode
|
||||
class alignas(8) TypeSourceInfo {
|
||||
// Contains a memory block after the class, used for type source information,
|
||||
// allocated by ASTContext.
|
||||
friend class ASTContext;
|
||||
|
||||
QualType Ty;
|
||||
|
||||
TypeSourceInfo(QualType ty) : Ty(ty) {}
|
||||
|
||||
public:
|
||||
/// Return the type wrapped by this type source info.
|
||||
QualType getType() const { return Ty; }
|
||||
|
||||
/// Return the TypeLoc wrapper for the type source info.
|
||||
TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
|
||||
|
||||
/// Override the type stored in this TypeSourceInfo. Use with caution!
|
||||
void overrideType(QualType T) { Ty = T; }
|
||||
};
|
||||
|
||||
// Inline function definitions.
|
||||
|
||||
inline SplitQualType SplitQualType::getSingleStepDesugaredType() const {
|
||||
|
|
@ -6260,6 +6330,11 @@ inline void QualType::removeLocalCVRQualifiers(unsigned Mask) {
|
|||
removeLocalFastQualifiers(Mask);
|
||||
}
|
||||
|
||||
/// Check if this type has any address space qualifier.
|
||||
inline bool QualType::hasAddressSpace() const {
|
||||
return getQualifiers().hasAddressSpace();
|
||||
}
|
||||
|
||||
/// Return the address space of this type.
|
||||
inline LangAS QualType::getAddressSpace() const {
|
||||
return getQualifiers().getAddressSpace();
|
||||
|
|
@ -6412,6 +6487,16 @@ inline bool Type::isRValueReferenceType() const {
|
|||
return isa<RValueReferenceType>(CanonicalType);
|
||||
}
|
||||
|
||||
inline bool Type::isObjectPointerType() const {
|
||||
// Note: an "object pointer type" is not the same thing as a pointer to an
|
||||
// object type; rather, it is a pointer to an object type or a pointer to cv
|
||||
// void.
|
||||
if (const auto *T = getAs<PointerType>())
|
||||
return !T->getPointeeType()->isFunctionType();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Type::isFunctionPointerType() const {
|
||||
if (const auto *T = getAs<PointerType>())
|
||||
return T->getPointeeType()->isFunctionType();
|
||||
|
|
@ -6509,6 +6594,10 @@ inline bool Type::isAtomicType() const {
|
|||
return isa<AtomicType>(CanonicalType);
|
||||
}
|
||||
|
||||
inline bool Type::isUndeducedAutoType() const {
|
||||
return isa<AutoType>(CanonicalType);
|
||||
}
|
||||
|
||||
inline bool Type::isObjCQualifiedIdType() const {
|
||||
if (const auto *OPT = getAs<ObjCObjectPointerType>())
|
||||
return OPT->isObjCQualifiedIdType();
|
||||
|
|
@ -6810,6 +6899,23 @@ inline const Type *Type::getPointeeOrArrayElementType() const {
|
|||
return type->getBaseElementTypeUnsafe();
|
||||
return type;
|
||||
}
|
||||
/// Insertion operator for diagnostics. This allows sending address spaces into
|
||||
/// a diagnostic with <<.
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
LangAS AS) {
|
||||
DB.AddTaggedVal(static_cast<std::underlying_type_t<LangAS>>(AS),
|
||||
DiagnosticsEngine::ArgumentKind::ak_addrspace);
|
||||
return DB;
|
||||
}
|
||||
|
||||
/// Insertion operator for partial diagnostics. This allows sending adress
|
||||
/// spaces into a diagnostic with <<.
|
||||
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
||||
LangAS AS) {
|
||||
PD.AddTaggedVal(static_cast<std::underlying_type_t<LangAS>>(AS),
|
||||
DiagnosticsEngine::ArgumentKind::ak_addrspace);
|
||||
return PD;
|
||||
}
|
||||
|
||||
/// Insertion operator for diagnostics. This allows sending Qualifiers into a
|
||||
/// diagnostic with <<.
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
#ifndef LLVM_CLANG_AST_TYPELOC_H
|
||||
#define LLVM_CLANG_AST_TYPELOC_H
|
||||
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "clang/AST/Type.h"
|
||||
|
|
@ -33,12 +31,14 @@
|
|||
|
||||
namespace clang {
|
||||
|
||||
class Attr;
|
||||
class ASTContext;
|
||||
class CXXRecordDecl;
|
||||
class Expr;
|
||||
class ObjCInterfaceDecl;
|
||||
class ObjCProtocolDecl;
|
||||
class ObjCTypeParamDecl;
|
||||
class ParmVarDecl;
|
||||
class TemplateTypeParmDecl;
|
||||
class UnqualTypeLoc;
|
||||
class UnresolvedUsingTypenameDecl;
|
||||
|
|
@ -173,9 +173,6 @@ public:
|
|||
|
||||
TypeLoc IgnoreParens() const;
|
||||
|
||||
/// Strips MacroDefinitionTypeLocs from a type location.
|
||||
TypeLoc IgnoreMacroDefinitions() const;
|
||||
|
||||
/// Find a type with the location of an explicit type qualifier.
|
||||
///
|
||||
/// The result, if non-null, will be one of:
|
||||
|
|
@ -707,11 +704,7 @@ public:
|
|||
TagDecl *getDecl() const { return getTypePtr()->getDecl(); }
|
||||
|
||||
/// True if the tag was defined in this type specifier.
|
||||
bool isDefinition() const {
|
||||
TagDecl *D = getDecl();
|
||||
return D->isCompleteDefinition() &&
|
||||
(D->getIdentifier() == nullptr || D->getLocation() == getNameLoc());
|
||||
}
|
||||
bool isDefinition() const;
|
||||
};
|
||||
|
||||
/// Wrapper for source info for record types.
|
||||
|
|
@ -881,18 +874,7 @@ public:
|
|||
return dyn_cast_or_null<T>(getAttr());
|
||||
}
|
||||
|
||||
SourceRange getLocalSourceRange() const {
|
||||
// Note that this does *not* include the range of the attribute
|
||||
// enclosure, e.g.:
|
||||
// __attribute__((foo(bar)))
|
||||
// ^~~~~~~~~~~~~~~ ~~
|
||||
// or
|
||||
// [[foo(bar)]]
|
||||
// ^~ ~~
|
||||
// That enclosure doesn't necessarily belong to a single attribute
|
||||
// anyway.
|
||||
return getAttr() ? getAttr()->getRange() : SourceRange();
|
||||
}
|
||||
SourceRange getLocalSourceRange() const;
|
||||
|
||||
void initializeLocal(ASTContext &Context, SourceLocation loc) {
|
||||
setAttr(nullptr);
|
||||
|
|
|
|||
815
clang/include/clang/AST/TypeProperties.td
Normal file
815
clang/include/clang/AST/TypeProperties.td
Normal file
|
|
@ -0,0 +1,815 @@
|
|||
//==--- TypeProperties.td - Type property definitions ---------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "clang/AST/PropertiesBase.td"
|
||||
include "clang/Basic/TypeNodes.td"
|
||||
|
||||
let Class = ComplexType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getComplexType(elementType); }]>;
|
||||
}
|
||||
|
||||
let Class = PointerType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getPointerType(pointeeType); }]>;
|
||||
}
|
||||
|
||||
let Class = AdjustedType in {
|
||||
def : Property<"originalType", QualType> {
|
||||
let Read = [{ node->getOriginalType() }];
|
||||
}
|
||||
def : Property<"adjustedType", QualType> {
|
||||
let Read = [{ node->getAdjustedType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getAdjustedType(originalType, adjustedType); }]>;
|
||||
}
|
||||
|
||||
let Class = DecayedType in {
|
||||
def : Override {
|
||||
// We don't need to serialize the adjusted type because we can always
|
||||
// derive it by decaying the original type.
|
||||
let IgnoredProperties = [ "adjustedType" ];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getAdjustedParameterType(originalType); }]>;
|
||||
}
|
||||
|
||||
let Class = BlockPointerType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getBlockPointerType(pointeeType); }]>;
|
||||
}
|
||||
|
||||
let Class = ReferenceType in {
|
||||
def : Property<"pointeeTypeAsWritten", QualType> {
|
||||
let Read = [{ node->getPointeeTypeAsWritten() }];
|
||||
}
|
||||
}
|
||||
|
||||
let Class = LValueReferenceType in {
|
||||
def : Property<"isSpelledAsLValue", Bool> {
|
||||
let Read = [{ node->isSpelledAsLValue() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getLValueReferenceType(pointeeTypeAsWritten,
|
||||
isSpelledAsLValue);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = RValueReferenceType in {
|
||||
def : Creator<[{
|
||||
return ctx.getRValueReferenceType(pointeeTypeAsWritten);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = MemberPointerType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
def : Property<"baseType", QualType> {
|
||||
let Read = [{ QualType(node->getClass(), 0) }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ArrayType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"sizeModifier", ArraySizeModifier> {
|
||||
let Read = [{ node->getSizeModifier() }];
|
||||
}
|
||||
def : Property<"indexQualifiers", Qualifiers> {
|
||||
let Read = [{ Qualifiers::fromCVRMask(node->getIndexTypeCVRQualifiers()) }];
|
||||
}
|
||||
}
|
||||
|
||||
let Class = ConstantArrayType in {
|
||||
def : Property<"sizeValue", APInt> {
|
||||
let Read = [{ node->getSize() }];
|
||||
}
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getConstantArrayType(elementType, sizeValue, size,
|
||||
sizeModifier,
|
||||
indexQualifiers.getCVRQualifiers());
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = IncompleteArrayType in {
|
||||
def : Creator<[{
|
||||
return ctx.getIncompleteArrayType(elementType, sizeModifier,
|
||||
indexQualifiers.getCVRQualifiers());
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = VariableArrayType in {
|
||||
def : Property<"leftBracketLoc", SourceLocation> {
|
||||
let Read = [{ node->getLBracketLoc() }];
|
||||
}
|
||||
def : Property<"rightBracketLoc", SourceLocation> {
|
||||
let Read = [{ node->getRBracketLoc() }];
|
||||
}
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getVariableArrayType(elementType, size, sizeModifier,
|
||||
indexQualifiers.getCVRQualifiers(),
|
||||
SourceRange(leftBracketLoc,
|
||||
rightBracketLoc));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentSizedArrayType in {
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
def : Property<"leftBracketLoc", SourceLocation> {
|
||||
let Read = [{ node->getLBracketLoc() }];
|
||||
}
|
||||
def : Property<"rightBracketLoc", SourceLocation> {
|
||||
let Read = [{ node->getRBracketLoc() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentSizedArrayType(elementType, size, sizeModifier,
|
||||
indexQualifiers.getCVRQualifiers(),
|
||||
SourceRange(leftBracketLoc,
|
||||
rightBracketLoc));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = VectorType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"numElements", UInt32> {
|
||||
let Read = [{ node->getNumElements() }];
|
||||
}
|
||||
def : Property<"vectorKind", VectorKind> {
|
||||
let Read = [{ node->getVectorKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getVectorType(elementType, numElements, vectorKind);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentVectorType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
def : Property<"attributeLoc", SourceLocation> {
|
||||
let Read = [{ node->getAttributeLoc() }];
|
||||
}
|
||||
def : Property<"vectorKind", VectorKind> {
|
||||
let Read = [{ node->getVectorKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentVectorType(elementType, size, attributeLoc,
|
||||
vectorKind);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ExtVectorType in {
|
||||
def : Override {
|
||||
let IgnoredProperties = [ "vectorKind" ];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getExtVectorType(elementType, numElements);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentSizedExtVectorType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
def : Property<"attributeLoc", SourceLocation> {
|
||||
let Read = [{ node->getAttributeLoc() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentSizedExtVectorType(elementType, size, attributeLoc);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = FunctionType in {
|
||||
def : Property<"returnType", QualType> {
|
||||
let Read = [{ node->getReturnType() }];
|
||||
}
|
||||
def : Property<"noReturn", Bool> {
|
||||
let Read = [{ node->getExtInfo().getNoReturn() }];
|
||||
}
|
||||
def : Property<"hasRegParm", Bool> {
|
||||
let Read = [{ node->getExtInfo().getHasRegParm() }];
|
||||
}
|
||||
def : Property<"regParm", UInt32> {
|
||||
let Read = [{ node->getExtInfo().getRegParm() }];
|
||||
}
|
||||
def : Property<"callingConvention", CallingConv> {
|
||||
let Read = [{ node->getExtInfo().getCC() }];
|
||||
}
|
||||
def : Property<"producesResult", Bool> {
|
||||
let Read = [{ node->getExtInfo().getProducesResult() }];
|
||||
}
|
||||
def : Property<"noCallerSavedRegs", Bool> {
|
||||
let Read = [{ node->getExtInfo().getNoCallerSavedRegs() }];
|
||||
}
|
||||
def : Property<"noCfCheck", Bool> {
|
||||
let Read = [{ node->getExtInfo().getNoCfCheck() }];
|
||||
}
|
||||
}
|
||||
|
||||
let Class = FunctionNoProtoType in {
|
||||
def : Creator<[{
|
||||
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
|
||||
callingConvention, producesResult,
|
||||
noCallerSavedRegs, noCfCheck);
|
||||
return ctx.getFunctionNoProtoType(returnType, extInfo);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = FunctionProtoType in {
|
||||
def : Property<"variadic", Bool> {
|
||||
let Read = [{ node->isVariadic() }];
|
||||
}
|
||||
def : Property<"trailingReturn", Bool> {
|
||||
let Read = [{ node->hasTrailingReturn() }];
|
||||
}
|
||||
def : Property<"methodQualifiers", Qualifiers> {
|
||||
let Read = [{ node->getMethodQuals() }];
|
||||
}
|
||||
def : Property<"refQualifier", RefQualifierKind> {
|
||||
let Read = [{ node->getRefQualifier() }];
|
||||
}
|
||||
def : Property<"exceptionSpecifier", ExceptionSpecInfo> {
|
||||
let Read = [{ node->getExceptionSpecInfo() }];
|
||||
}
|
||||
def : Property<"parameters", Array<QualType>> {
|
||||
let Read = [{ node->getParamTypes() }];
|
||||
}
|
||||
def : Property<"extParameterInfo", Array<ExtParameterInfo>> {
|
||||
let Read = [{ node->hasExtParameterInfos()
|
||||
? node->getExtParameterInfos()
|
||||
: llvm::ArrayRef<FunctionProtoType::ExtParameterInfo>() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
|
||||
callingConvention, producesResult,
|
||||
noCallerSavedRegs, noCfCheck);
|
||||
FunctionProtoType::ExtProtoInfo epi;
|
||||
epi.ExtInfo = extInfo;
|
||||
epi.Variadic = variadic;
|
||||
epi.HasTrailingReturn = trailingReturn;
|
||||
epi.TypeQuals = methodQualifiers;
|
||||
epi.RefQualifier = refQualifier;
|
||||
epi.ExceptionSpec = exceptionSpecifier;
|
||||
epi.ExtParameterInfos =
|
||||
extParameterInfo.empty() ? nullptr : extParameterInfo.data();
|
||||
return ctx.getFunctionType(returnType, parameters, epi);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = AtomicType in {
|
||||
def : Property<"valueType", QualType> {
|
||||
let Read = [{ node->getValueType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getAtomicType(valueType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = UnresolvedUsingType in {
|
||||
def : Property<"declaration", DeclRef> {
|
||||
let Read = [{ node->getDecl() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getTypeDeclType(cast<UnresolvedUsingTypenameDecl>(declaration));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TypedefType in {
|
||||
def : Property<"declaration", DeclRef> {
|
||||
let Read = [{ node->getDecl() }];
|
||||
}
|
||||
def : Property<"canonicalType", Optional<QualType>> {
|
||||
let Read = [{ makeOptionalFromNullable(node->getCanonicalTypeInternal()) }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
QualType finalCanonicalType =
|
||||
canonicalType ? ctx.getCanonicalType(*canonicalType)
|
||||
: QualType();
|
||||
return ctx.getTypedefType(cast<TypedefNameDecl>(declaration),
|
||||
finalCanonicalType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TypeOfExprType in {
|
||||
def : Property<"expression", ExprRef> {
|
||||
let Read = [{ node->getUnderlyingExpr() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getTypeOfExprType(expression);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TypeOfType in {
|
||||
def : Property<"underlyingType", QualType> {
|
||||
let Read = [{ node->getUnderlyingType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getTypeOfType(underlyingType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DecltypeType in {
|
||||
def : Property<"underlyingType", QualType> {
|
||||
let Read = [{ node->getUnderlyingType() }];
|
||||
}
|
||||
def : Property<"expression", ExprRef> {
|
||||
let Read = [{ node->getUnderlyingExpr() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDecltypeType(expression, underlyingType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = UnaryTransformType in {
|
||||
def : Property<"baseType", QualType> {
|
||||
let Read = [{ node->getBaseType() }];
|
||||
}
|
||||
def : Property<"underlyingType", QualType> {
|
||||
let Read = [{ node->getUnderlyingType() }];
|
||||
}
|
||||
def : Property<"transform", UnaryTypeTransformKind> {
|
||||
let Read = [{ node->getUTTKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getUnaryTransformType(baseType, underlyingType, transform);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = AutoType in {
|
||||
def : Property<"deducedType", Optional<QualType>> {
|
||||
let Read = [{ makeOptionalFromNullable(node->getDeducedType()) }];
|
||||
}
|
||||
def : Property<"keyword", AutoTypeKeyword> {
|
||||
let Read = [{ node->getKeyword() }];
|
||||
}
|
||||
// FIXME: better enumerated value
|
||||
// Only really required when the deduced type is null
|
||||
def : Property<"dependence", UInt32> {
|
||||
let Read = [{ !node->getDeducedType().isNull() ? 0 :
|
||||
node->containsUnexpandedParameterPack() ? 2 :
|
||||
node->isDependentType() ? 1 : 0 }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getAutoType(makeNullableFromOptional(deducedType), keyword,
|
||||
/*isDependentWithoutDeducedType*/ dependence > 0,
|
||||
/*isPackWithoutDeducedType*/ dependence > 1);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DeducedTemplateSpecializationType in {
|
||||
def : Property<"templateName", Optional<TemplateName>> {
|
||||
let Read = [{ makeOptionalFromNullable(node->getTemplateName()) }];
|
||||
}
|
||||
def : Property<"deducedType", QualType> {
|
||||
let Read = [{ node->getDeducedType() }];
|
||||
}
|
||||
// Only really required when the deduced type is null
|
||||
def : Property<"dependent", Bool> {
|
||||
let Read = [{ !node->getDeducedType().isNull()
|
||||
? false : node->isDependentType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDeducedTemplateSpecializationType(
|
||||
makeNullableFromOptional(templateName),
|
||||
deducedType, dependent);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TagType in {
|
||||
def : Property<"dependent", Bool> {
|
||||
let Read = [{ node->isDependentType() }];
|
||||
}
|
||||
def : Property<"declaration", DeclRef> {
|
||||
// Serializing a reference to the canonical declaration is apparently
|
||||
// necessary to make module-merging work.
|
||||
let Read = [{ node->getDecl()->getCanonicalDecl() }];
|
||||
}
|
||||
}
|
||||
|
||||
let Class = EnumType in {
|
||||
def : Creator<[{
|
||||
QualType result = ctx.getEnumType(cast<EnumDecl>(declaration));
|
||||
const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
|
||||
return result;
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = RecordType in {
|
||||
def : Creator<[{
|
||||
auto record = cast<RecordDecl>(declaration);
|
||||
QualType result = ctx.getRecordType(record);
|
||||
const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
|
||||
return result;
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ElaboratedType in {
|
||||
def : Property<"keyword", ElaboratedTypeKeyword> {
|
||||
let Read = [{ node->getKeyword() }];
|
||||
}
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ node->getQualifier() }];
|
||||
}
|
||||
def : Property<"namedType", QualType> {
|
||||
let Read = [{ node->getNamedType() }];
|
||||
}
|
||||
def : Property<"ownedTag", Optional<TagDeclRef>> {
|
||||
let Read = [{ makeOptionalFromPointer(
|
||||
const_cast<const TagDecl *>(node->getOwnedTagDecl())) }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getElaboratedType(keyword, qualifier, namedType,
|
||||
makePointerFromOptional(ownedTag));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = InjectedClassNameType in {
|
||||
def : Property<"declaration", DeclRef> {
|
||||
// FIXME: drilling down to the canonical declaration is what the
|
||||
// existing serialization code was doing, but it's not clear why.
|
||||
let Read = [{ node->getDecl()->getCanonicalDecl() }];
|
||||
}
|
||||
def : Property<"injectedSpecializationType", QualType> {
|
||||
let Read = [{ node->getInjectedSpecializationType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
// FIXME: ASTContext::getInjectedClassNameType is not currently suitable
|
||||
// for AST reading, too much interdependencies.
|
||||
const Type *T = nullptr;
|
||||
auto typeDecl = cast<CXXRecordDecl>(declaration);
|
||||
for (auto *DI = typeDecl; DI; DI = DI->getPreviousDecl()) {
|
||||
if (const Type *existing = DI->getTypeForDecl()) {
|
||||
T = existing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!T) {
|
||||
T = new (ctx, TypeAlignment)
|
||||
InjectedClassNameType(typeDecl, injectedSpecializationType);
|
||||
for (auto *DI = typeDecl; DI; DI = DI->getPreviousDecl())
|
||||
DI->setTypeForDecl(T);
|
||||
}
|
||||
return QualType(T, 0);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ParenType in {
|
||||
def : Property<"innerType", QualType> {
|
||||
let Read = [{ node->getInnerType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getParenType(innerType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = MacroQualifiedType in {
|
||||
def : Property<"underlyingType", QualType> {
|
||||
let Read = [{ node->getUnderlyingType() }];
|
||||
}
|
||||
def : Property<"macroIdentifier", Identifier> {
|
||||
let Read = [{ node->getMacroIdentifier() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getMacroQualifiedType(underlyingType, macroIdentifier);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = AttributedType in {
|
||||
def : Property<"modifiedType", QualType> {
|
||||
let Read = [{ node->getModifiedType() }];
|
||||
}
|
||||
def : Property<"equivalentType", QualType> {
|
||||
let Read = [{ node->getEquivalentType() }];
|
||||
}
|
||||
def : Property<"attribute", AttrKind> {
|
||||
let Read = [{ node->getAttrKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getAttributedType(attribute, modifiedType, equivalentType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentAddressSpaceType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
def : Property<"addressSpace", ExprRef> {
|
||||
let Read = [{ node->getAddrSpaceExpr() }];
|
||||
}
|
||||
def : Property<"attributeLoc", SourceLocation> {
|
||||
let Read = [{ node->getAttributeLoc() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentAddressSpaceType(pointeeType, addressSpace,
|
||||
attributeLoc);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TemplateSpecializationType in {
|
||||
def : Property<"dependent", Bool> {
|
||||
let Read = [{ node->isDependentType() }];
|
||||
}
|
||||
def : Property<"templateName", TemplateName> {
|
||||
let Read = [{ node->getTemplateName() }];
|
||||
}
|
||||
def : Property<"templateArguments", Array<TemplateArgument>> {
|
||||
let Read = [{ node->template_arguments() }];
|
||||
}
|
||||
def : Property<"underlyingType", Optional<QualType>> {
|
||||
let Read = [{
|
||||
node->isTypeAlias()
|
||||
? llvm::Optional<QualType>(node->getAliasedType())
|
||||
: node->isCanonicalUnqualified()
|
||||
? llvm::None
|
||||
: llvm::Optional<QualType>(node->getCanonicalTypeInternal())
|
||||
}];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
QualType result;
|
||||
if (!underlyingType.hasValue()) {
|
||||
result = ctx.getCanonicalTemplateSpecializationType(templateName,
|
||||
templateArguments);
|
||||
} else {
|
||||
result = ctx.getTemplateSpecializationType(templateName,
|
||||
templateArguments,
|
||||
*underlyingType);
|
||||
}
|
||||
const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
|
||||
return result;
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentTemplateSpecializationType in {
|
||||
def : Property<"keyword", ElaboratedTypeKeyword> {
|
||||
let Read = [{ node->getKeyword() }];
|
||||
}
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ node->getQualifier() }];
|
||||
}
|
||||
def : Property<"name", Identifier> {
|
||||
let Read = [{ node->getIdentifier() }];
|
||||
}
|
||||
def : Property<"templateArguments", Array<TemplateArgument>> {
|
||||
let Read = [{ node->template_arguments() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentTemplateSpecializationType(keyword, qualifier,
|
||||
name, templateArguments);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TemplateTypeParmType in {
|
||||
def : Property<"depth", UInt32> {
|
||||
let Read = [{ node->getDepth() }];
|
||||
}
|
||||
def : Property<"index", UInt32> {
|
||||
let Read = [{ node->getIndex() }];
|
||||
}
|
||||
def : Property<"isParameterPack", Bool> {
|
||||
let Read = [{ node->isParameterPack() }];
|
||||
}
|
||||
def : Property<"declaration", Optional<TemplateTypeParmDeclRef>> {
|
||||
let Read = [{ makeOptionalFromPointer(
|
||||
const_cast<const TemplateTypeParmDecl*>(node->getDecl())) }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getTemplateTypeParmType(depth, index, isParameterPack,
|
||||
makePointerFromOptional(declaration));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = SubstTemplateTypeParmType in {
|
||||
def : Property<"replacedParameter", QualType> {
|
||||
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
|
||||
}
|
||||
def : Property<"replacementType", QualType> {
|
||||
let Read = [{ node->getReplacementType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
// The call to getCanonicalType here existed in ASTReader.cpp, too.
|
||||
return ctx.getSubstTemplateTypeParmType(
|
||||
cast<TemplateTypeParmType>(replacedParameter),
|
||||
ctx.getCanonicalType(replacementType));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = PackExpansionType in {
|
||||
def : Property<"pattern", QualType> {
|
||||
let Read = [{ node->getPattern() }];
|
||||
}
|
||||
def : Property<"numExpansions", Optional<UInt32>> {
|
||||
let Read = [{ node->getNumExpansions() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getPackExpansionType(pattern, numExpansions);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = SubstTemplateTypeParmPackType in {
|
||||
def : Property<"replacedParameter", QualType> {
|
||||
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
|
||||
}
|
||||
def : Property<"replacementPack", TemplateArgument> {
|
||||
let Read = [{ node->getArgumentPack() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getSubstTemplateTypeParmPackType(
|
||||
cast<TemplateTypeParmType>(replacedParameter),
|
||||
replacementPack);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = BuiltinType in {
|
||||
def : Property<"kind", BuiltinTypeKind> {
|
||||
let Read = [{ node->getKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
switch (kind) {
|
||||
#define IMAGE_TYPE(IMGTYPE, ID, SINGLETON_ID, ACCESS, SUFFIX) \
|
||||
case BuiltinType::ID: return ctx.SINGLETON_ID;
|
||||
#include "clang/Basic/OpenCLImageTypes.def"
|
||||
|
||||
#define EXT_OPAQUE_TYPE(EXTTYPE, ID, EXT) \
|
||||
case BuiltinType::ID: return ctx.ID##Ty;
|
||||
#include "clang/Basic/OpenCLExtensionTypes.def"
|
||||
|
||||
#define SVE_TYPE(NAME, ID, SINGLETON_ID) \
|
||||
case BuiltinType::ID: return ctx.SINGLETON_ID;
|
||||
#include "clang/Basic/AArch64SVEACLETypes.def"
|
||||
|
||||
#define BUILTIN_TYPE(ID, SINGLETON_ID) \
|
||||
case BuiltinType::ID: return ctx.SINGLETON_ID;
|
||||
#include "clang/AST/BuiltinTypes.def"
|
||||
}
|
||||
llvm_unreachable("unreachable builtin case");
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentNameType in {
|
||||
def : Property<"keyword", ElaboratedTypeKeyword> {
|
||||
let Read = [{ node->getKeyword() }];
|
||||
}
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ node->getQualifier() }];
|
||||
}
|
||||
def : Property<"name", Identifier> {
|
||||
let Read = [{ node->getIdentifier() }];
|
||||
}
|
||||
def : Property<"underlyingType", Optional<QualType>> {
|
||||
let Read = [{
|
||||
node->isCanonicalUnqualified()
|
||||
? llvm::None
|
||||
: llvm::Optional<QualType>(node->getCanonicalTypeInternal())
|
||||
}];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
QualType canon = (underlyingType
|
||||
? ctx.getCanonicalType(*underlyingType)
|
||||
: QualType());
|
||||
return ctx.getDependentNameType(keyword, qualifier, name, canon);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ObjCObjectType in {
|
||||
def : Property<"baseType", QualType> {
|
||||
let Read = [{ node->getBaseType() }];
|
||||
}
|
||||
def : Property<"typeArgsAsWritten", Array<QualType>> {
|
||||
let Read = [{ node->getTypeArgsAsWritten() }];
|
||||
}
|
||||
def : Property<"qualifiers", Array<ObjCProtocolDeclRef>> {
|
||||
let Read = [{ node->getProtocols() }];
|
||||
}
|
||||
def : Property<"isKindOfTypeAsWritten", Bool> {
|
||||
let Read = [{ node->isKindOfTypeAsWritten() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getObjCObjectType(baseType, typeArgsAsWritten, qualifiers,
|
||||
isKindOfTypeAsWritten);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ObjCInterfaceType in {
|
||||
// We don't actually want any of the properties of the superclass.
|
||||
def : Override {
|
||||
let IgnoredProperties = [ "baseType", "typeArgsAsWritten",
|
||||
"qualifiers", "isKindOfTypeAsWritten" ];
|
||||
}
|
||||
|
||||
def : Property<"declaration", DeclRef> {
|
||||
// FIXME: drilling down to the canonical declaration is what the
|
||||
// existing serialization code was doing, but it's not clear why.
|
||||
let Read = [{ node->getDecl()->getCanonicalDecl() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getObjCInterfaceType(
|
||||
cast<ObjCInterfaceDecl>(declaration->getCanonicalDecl()));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ObjCTypeParamType in {
|
||||
def : Property<"declaration", ObjCTypeParamDeclRef> {
|
||||
let Read = [{ node->getDecl() }];
|
||||
}
|
||||
def : Property<"qualifiers", Array<ObjCProtocolDeclRef>> {
|
||||
let Read = [{ node->getProtocols() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getObjCTypeParamType(declaration, qualifiers);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ObjCObjectPointerType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getObjCObjectPointerType(pointeeType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = PipeType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"isReadOnly", Bool> {
|
||||
let Read = [{ node->isReadOnly() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getPipeType(elementType, isReadOnly);
|
||||
}]>;
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include "clang/AST/DeclAccessPair.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
#include <cstddef>
|
||||
|
|
@ -85,6 +86,8 @@ public:
|
|||
const_iterator begin() const { return const_iterator(decls().begin()); }
|
||||
const_iterator end() const { return const_iterator(decls().end()); }
|
||||
|
||||
ArrayRef<DeclAccessPair> pairs() const { return decls(); }
|
||||
|
||||
void addDecl(NamedDecl *D) {
|
||||
addDecl(D, AS_none);
|
||||
}
|
||||
|
|
@ -125,6 +128,8 @@ public:
|
|||
|
||||
void append(iterator I, iterator E) { decls().append(I.I, E.I); }
|
||||
|
||||
template<typename Iter> void assign(Iter I, Iter E) { decls().assign(I, E); }
|
||||
|
||||
DeclAccessPair &operator[](unsigned I) { return decls()[I]; }
|
||||
const DeclAccessPair &operator[](unsigned I) const { return decls()[I]; }
|
||||
|
||||
|
|
|
|||
|
|
@ -309,6 +309,33 @@ match(MatcherT Matcher, ASTContext &Context) {
|
|||
return std::move(Callback.Nodes);
|
||||
}
|
||||
|
||||
inline SmallVector<BoundNodes, 1>
|
||||
matchDynamic(internal::DynTypedMatcher Matcher,
|
||||
const ast_type_traits::DynTypedNode &Node, ASTContext &Context) {
|
||||
internal::CollectMatchesCallback Callback;
|
||||
MatchFinder Finder;
|
||||
Finder.addDynamicMatcher(Matcher, &Callback);
|
||||
Finder.match(Node, Context);
|
||||
return std::move(Callback.Nodes);
|
||||
}
|
||||
|
||||
template <typename NodeT>
|
||||
SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher,
|
||||
const NodeT &Node,
|
||||
ASTContext &Context) {
|
||||
return matchDynamic(Matcher, ast_type_traits::DynTypedNode::create(Node),
|
||||
Context);
|
||||
}
|
||||
|
||||
inline SmallVector<BoundNodes, 1>
|
||||
matchDynamic(internal::DynTypedMatcher Matcher, ASTContext &Context) {
|
||||
internal::CollectMatchesCallback Callback;
|
||||
MatchFinder Finder;
|
||||
Finder.addDynamicMatcher(Matcher, &Callback);
|
||||
Finder.matchAST(Context);
|
||||
return std::move(Callback.Nodes);
|
||||
}
|
||||
|
||||
} // end namespace ast_matchers
|
||||
} // end namespace clang
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/LambdaCapture.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/OpenMPClause.h"
|
||||
#include "clang/AST/OperationKinds.h"
|
||||
|
|
@ -689,6 +690,88 @@ AST_POLYMORPHIC_MATCHER_P(
|
|||
Builder);
|
||||
}
|
||||
|
||||
/// Causes all nested matchers to be matched with the specified traversal kind.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// void foo()
|
||||
/// {
|
||||
/// int i = 3.0;
|
||||
/// }
|
||||
/// \endcode
|
||||
/// The matcher
|
||||
/// \code
|
||||
/// traverse(ast_type_traits::TK_IgnoreImplicitCastsAndParentheses,
|
||||
/// varDecl(hasInitializer(floatLiteral().bind("init")))
|
||||
/// )
|
||||
/// \endcode
|
||||
/// matches the variable declaration with "init" bound to the "3.0".
|
||||
template <typename T>
|
||||
internal::Matcher<T> traverse(ast_type_traits::TraversalKind TK,
|
||||
const internal::Matcher<T> &InnerMatcher) {
|
||||
return internal::DynTypedMatcher::constructRestrictedWrapper(
|
||||
new internal::TraversalMatcher<T>(TK, InnerMatcher),
|
||||
InnerMatcher.getID().first)
|
||||
.template unconditionalConvertTo<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
internal::BindableMatcher<T>
|
||||
traverse(ast_type_traits::TraversalKind TK,
|
||||
const internal::BindableMatcher<T> &InnerMatcher) {
|
||||
return internal::BindableMatcher<T>(
|
||||
internal::DynTypedMatcher::constructRestrictedWrapper(
|
||||
new internal::TraversalMatcher<T>(TK, InnerMatcher),
|
||||
InnerMatcher.getID().first)
|
||||
.template unconditionalConvertTo<T>());
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
internal::TraversalWrapper<internal::VariadicOperatorMatcher<T...>>
|
||||
traverse(ast_type_traits::TraversalKind TK,
|
||||
const internal::VariadicOperatorMatcher<T...> &InnerMatcher) {
|
||||
return internal::TraversalWrapper<internal::VariadicOperatorMatcher<T...>>(
|
||||
TK, InnerMatcher);
|
||||
}
|
||||
|
||||
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
|
||||
typename T, typename ToTypes>
|
||||
internal::TraversalWrapper<
|
||||
internal::ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>>
|
||||
traverse(ast_type_traits::TraversalKind TK,
|
||||
const internal::ArgumentAdaptingMatcherFuncAdaptor<
|
||||
ArgumentAdapterT, T, ToTypes> &InnerMatcher) {
|
||||
return internal::TraversalWrapper<
|
||||
internal::ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T,
|
||||
ToTypes>>(TK, InnerMatcher);
|
||||
}
|
||||
|
||||
template <template <typename T, typename P1> class MatcherT, typename P1,
|
||||
typename ReturnTypesF>
|
||||
internal::TraversalWrapper<
|
||||
internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>>
|
||||
traverse(
|
||||
ast_type_traits::TraversalKind TK,
|
||||
const internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>
|
||||
&InnerMatcher) {
|
||||
return internal::TraversalWrapper<
|
||||
internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>>(
|
||||
TK, InnerMatcher);
|
||||
}
|
||||
|
||||
template <template <typename T, typename P1, typename P2> class MatcherT,
|
||||
typename P1, typename P2, typename ReturnTypesF>
|
||||
internal::TraversalWrapper<
|
||||
internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>>
|
||||
traverse(
|
||||
ast_type_traits::TraversalKind TK,
|
||||
const internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>
|
||||
&InnerMatcher) {
|
||||
return internal::TraversalWrapper<
|
||||
internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>>(
|
||||
TK, InnerMatcher);
|
||||
}
|
||||
|
||||
/// Matches expressions that match InnerMatcher after any implicit AST
|
||||
/// nodes are stripped off.
|
||||
///
|
||||
|
|
@ -2458,6 +2541,36 @@ extern const internal::VariadicOperatorMatcherFunc<
|
|||
2, std::numeric_limits<unsigned>::max()>
|
||||
allOf;
|
||||
|
||||
/// Matches any node regardless of the submatchers.
|
||||
///
|
||||
/// However, \c optionally will generate a result binding for each matching
|
||||
/// submatcher.
|
||||
///
|
||||
/// Useful when additional information which may or may not present about a
|
||||
/// main matching node is desired.
|
||||
///
|
||||
/// For example, in:
|
||||
/// \code
|
||||
/// class Foo {
|
||||
/// int bar;
|
||||
/// }
|
||||
/// \endcode
|
||||
/// The matcher:
|
||||
/// \code
|
||||
/// cxxRecordDecl(
|
||||
/// optionally(has(
|
||||
/// fieldDecl(hasName("bar")).bind("var")
|
||||
/// ))).bind("record")
|
||||
/// \endcode
|
||||
/// will produce a result binding for both "record" and "var".
|
||||
/// The matcher will produce a "record" binding for even if there is no data
|
||||
/// member named "bar" in that class.
|
||||
///
|
||||
/// Usable as: Any Matcher
|
||||
extern const internal::VariadicOperatorMatcherFunc<
|
||||
1, std::numeric_limits<unsigned>::max()>
|
||||
optionally;
|
||||
|
||||
/// Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
|
||||
///
|
||||
/// Given
|
||||
|
|
@ -3932,6 +4045,50 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Matches any capture of a lambda expression.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// void foo() {
|
||||
/// int x;
|
||||
/// auto f = [x](){};
|
||||
/// }
|
||||
/// \endcode
|
||||
/// lambdaExpr(hasAnyCapture(anything()))
|
||||
/// matches [x](){};
|
||||
AST_MATCHER_P_OVERLOAD(LambdaExpr, hasAnyCapture, internal::Matcher<VarDecl>,
|
||||
InnerMatcher, 0) {
|
||||
for (const LambdaCapture &Capture : Node.captures()) {
|
||||
if (Capture.capturesVariable()) {
|
||||
BoundNodesTreeBuilder Result(*Builder);
|
||||
if (InnerMatcher.matches(*Capture.getCapturedVar(), Finder, &Result)) {
|
||||
*Builder = std::move(Result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Matches any capture of 'this' in a lambda expression.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// struct foo {
|
||||
/// void bar() {
|
||||
/// auto f = [this](){};
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
/// lambdaExpr(hasAnyCapture(cxxThisExpr()))
|
||||
/// matches [this](){};
|
||||
AST_MATCHER_P_OVERLOAD(LambdaExpr, hasAnyCapture,
|
||||
internal::Matcher<CXXThisExpr>, InnerMatcher, 1) {
|
||||
return llvm::any_of(Node.captures(), [](const LambdaCapture &LC) {
|
||||
return LC.capturesThis();
|
||||
});
|
||||
}
|
||||
|
||||
/// Matches a constructor call expression which uses list initialization.
|
||||
AST_MATCHER(CXXConstructExpr, isListInitialization) {
|
||||
return Node.isListInitialization();
|
||||
|
|
@ -4272,6 +4429,35 @@ AST_POLYMORPHIC_MATCHER(isConstexpr,
|
|||
return Node.isConstexpr();
|
||||
}
|
||||
|
||||
/// Matches selection statements with initializer.
|
||||
///
|
||||
/// Given:
|
||||
/// \code
|
||||
/// void foo() {
|
||||
/// if (int i = foobar(); i > 0) {}
|
||||
/// switch (int i = foobar(); i) {}
|
||||
/// for (auto& a = get_range(); auto& x : a) {}
|
||||
/// }
|
||||
/// void bar() {
|
||||
/// if (foobar() > 0) {}
|
||||
/// switch (foobar()) {}
|
||||
/// for (auto& x : get_range()) {}
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ifStmt(hasInitStatement(anything()))
|
||||
/// matches the if statement in foo but not in bar.
|
||||
/// switchStmt(hasInitStatement(anything()))
|
||||
/// matches the switch statement in foo but not in bar.
|
||||
/// cxxForRangeStmt(hasInitStatement(anything()))
|
||||
/// matches the range for statement in foo but not in bar.
|
||||
AST_POLYMORPHIC_MATCHER_P(hasInitStatement,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, SwitchStmt,
|
||||
CXXForRangeStmt),
|
||||
internal::Matcher<Stmt>, InnerMatcher) {
|
||||
const Stmt *Init = Node.getInit();
|
||||
return Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder);
|
||||
}
|
||||
|
||||
/// Matches the condition expression of an if statement, for loop,
|
||||
/// switch statement or conditional operator.
|
||||
///
|
||||
|
|
@ -6519,6 +6705,20 @@ AST_MATCHER(NamedDecl, hasExternalFormalLinkage) {
|
|||
/// void x(int val) {}
|
||||
/// void y(int val = 0) {}
|
||||
/// \endcode
|
||||
///
|
||||
/// Deprecated. Use hasInitializer() instead to be able to
|
||||
/// match on the contents of the default argument. For example:
|
||||
///
|
||||
/// \code
|
||||
/// void x(int val = 7) {}
|
||||
/// void y(int val = 42) {}
|
||||
/// \endcode
|
||||
/// parmVarDecl(hasInitializer(integerLiteral(equals(42))))
|
||||
/// matches the parameter of y
|
||||
///
|
||||
/// A matcher such as
|
||||
/// parmVarDecl(hasInitializer(anything()))
|
||||
/// is equivalent to parmVarDecl(hasDefaultArgument()).
|
||||
AST_MATCHER(ParmVarDecl, hasDefaultArgument) {
|
||||
return Node.hasDefaultArg();
|
||||
}
|
||||
|
|
@ -6541,7 +6741,7 @@ AST_MATCHER(CXXNewExpr, isArray) {
|
|||
/// \code
|
||||
/// MyClass *p1 = new MyClass[10];
|
||||
/// \endcode
|
||||
/// cxxNewExpr(hasArraySize(intgerLiteral(equals(10))))
|
||||
/// cxxNewExpr(hasArraySize(integerLiteral(equals(10))))
|
||||
/// matches the expression 'new MyClass[10]'.
|
||||
AST_MATCHER_P(CXXNewExpr, hasArraySize, internal::Matcher<Expr>, InnerMatcher) {
|
||||
return Node.isArray() && *Node.getArraySize() &&
|
||||
|
|
@ -6621,8 +6821,8 @@ AST_MATCHER_P(Expr, ignoringElidableConstructorCall,
|
|||
if (CtorExpr->isElidable()) {
|
||||
if (const auto *MaterializeTemp =
|
||||
dyn_cast<MaterializeTemporaryExpr>(CtorExpr->getArg(0))) {
|
||||
return InnerMatcher.matches(*MaterializeTemp->GetTemporaryExpr(),
|
||||
Finder, Builder);
|
||||
return InnerMatcher.matches(*MaterializeTemp->getSubExpr(), Finder,
|
||||
Builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6781,7 +6981,9 @@ AST_MATCHER(OMPDefaultClause, isSharedKind) {
|
|||
/// ``isAllowedToContainClauseKind("OMPC_default").``
|
||||
AST_MATCHER_P(OMPExecutableDirective, isAllowedToContainClauseKind,
|
||||
OpenMPClauseKind, CKind) {
|
||||
return isAllowedClauseForDirective(Node.getDirectiveKind(), CKind);
|
||||
return isAllowedClauseForDirective(
|
||||
Node.getDirectiveKind(), CKind,
|
||||
Finder->getASTContext().getLangOpts().OpenMP);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
|
|
|||
|
|
@ -283,6 +283,10 @@ public:
|
|||
virtual bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
|
||||
ASTMatchFinder *Finder,
|
||||
BoundNodesTreeBuilder *Builder) const = 0;
|
||||
|
||||
virtual llvm::Optional<ast_type_traits::TraversalKind> TraversalKind() const {
|
||||
return llvm::None;
|
||||
}
|
||||
};
|
||||
|
||||
/// Generic interface for matchers on an AST node of type T.
|
||||
|
|
@ -359,6 +363,10 @@ public:
|
|||
/// matches, but doesn't stop at the first match.
|
||||
VO_EachOf,
|
||||
|
||||
/// Matches any node but executes all inner matchers to find result
|
||||
/// bindings.
|
||||
VO_Optionally,
|
||||
|
||||
/// Matches nodes that do not match the provided matcher.
|
||||
///
|
||||
/// Uses the variadic matcher interface, but fails if
|
||||
|
|
@ -371,6 +379,10 @@ public:
|
|||
ast_type_traits::ASTNodeKind SupportedKind,
|
||||
std::vector<DynTypedMatcher> InnerMatchers);
|
||||
|
||||
static DynTypedMatcher
|
||||
constructRestrictedWrapper(const DynTypedMatcher &InnerMatcher,
|
||||
ast_type_traits::ASTNodeKind RestrictKind);
|
||||
|
||||
/// Get a "true" matcher for \p NodeKind.
|
||||
///
|
||||
/// It only checks that the node is of the right kind.
|
||||
|
|
@ -1002,7 +1014,7 @@ public:
|
|||
std::is_base_of<QualType, T>::value,
|
||||
"unsupported type for recursive matching");
|
||||
return matchesChildOf(ast_type_traits::DynTypedNode::create(Node),
|
||||
Matcher, Builder, Traverse, Bind);
|
||||
getASTContext(), Matcher, Builder, Traverse, Bind);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -1018,7 +1030,7 @@ public:
|
|||
std::is_base_of<QualType, T>::value,
|
||||
"unsupported type for recursive matching");
|
||||
return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node),
|
||||
Matcher, Builder, Bind);
|
||||
getASTContext(), Matcher, Builder, Bind);
|
||||
}
|
||||
|
||||
// FIXME: Implement support for BindKind.
|
||||
|
|
@ -1033,24 +1045,26 @@ public:
|
|||
std::is_base_of<TypeLoc, T>::value,
|
||||
"type not allowed for recursive matching");
|
||||
return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node),
|
||||
Matcher, Builder, MatchMode);
|
||||
getASTContext(), Matcher, Builder, MatchMode);
|
||||
}
|
||||
|
||||
virtual ASTContext &getASTContext() const = 0;
|
||||
|
||||
protected:
|
||||
virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
|
||||
const DynTypedMatcher &Matcher,
|
||||
ASTContext &Ctx, const DynTypedMatcher &Matcher,
|
||||
BoundNodesTreeBuilder *Builder,
|
||||
ast_type_traits::TraversalKind Traverse,
|
||||
BindKind Bind) = 0;
|
||||
|
||||
virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
|
||||
ASTContext &Ctx,
|
||||
const DynTypedMatcher &Matcher,
|
||||
BoundNodesTreeBuilder *Builder,
|
||||
BindKind Bind) = 0;
|
||||
|
||||
virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
|
||||
ASTContext &Ctx,
|
||||
const DynTypedMatcher &Matcher,
|
||||
BoundNodesTreeBuilder *Builder,
|
||||
AncestorMatchMode MatchMode) = 0;
|
||||
|
|
@ -1119,6 +1133,23 @@ using HasDeclarationSupportedTypes =
|
|||
TemplateSpecializationType, TemplateTypeParmType, TypedefType,
|
||||
UnresolvedUsingType, ObjCIvarRefExpr>;
|
||||
|
||||
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
|
||||
typename T, typename ToTypes>
|
||||
class ArgumentAdaptingMatcherFuncAdaptor {
|
||||
public:
|
||||
explicit ArgumentAdaptingMatcherFuncAdaptor(const Matcher<T> &InnerMatcher)
|
||||
: InnerMatcher(InnerMatcher) {}
|
||||
|
||||
using ReturnTypes = ToTypes;
|
||||
|
||||
template <typename To> operator Matcher<To>() const {
|
||||
return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
|
||||
}
|
||||
|
||||
private:
|
||||
const Matcher<T> InnerMatcher;
|
||||
};
|
||||
|
||||
/// Converts a \c Matcher<T> to a matcher of desired type \c To by
|
||||
/// "adapting" a \c To into a \c T.
|
||||
///
|
||||
|
|
@ -1136,32 +1167,60 @@ template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
|
|||
typename FromTypes = AdaptativeDefaultFromTypes,
|
||||
typename ToTypes = AdaptativeDefaultToTypes>
|
||||
struct ArgumentAdaptingMatcherFunc {
|
||||
template <typename T> class Adaptor {
|
||||
public:
|
||||
explicit Adaptor(const Matcher<T> &InnerMatcher)
|
||||
: InnerMatcher(InnerMatcher) {}
|
||||
|
||||
using ReturnTypes = ToTypes;
|
||||
|
||||
template <typename To> operator Matcher<To>() const {
|
||||
return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
|
||||
}
|
||||
|
||||
private:
|
||||
const Matcher<T> InnerMatcher;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static Adaptor<T> create(const Matcher<T> &InnerMatcher) {
|
||||
return Adaptor<T>(InnerMatcher);
|
||||
static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
|
||||
create(const Matcher<T> &InnerMatcher) {
|
||||
return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>(
|
||||
InnerMatcher);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Adaptor<T> operator()(const Matcher<T> &InnerMatcher) const {
|
||||
ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
|
||||
operator()(const Matcher<T> &InnerMatcher) const {
|
||||
return create(InnerMatcher);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TraversalMatcher : public WrapperMatcherInterface<T> {
|
||||
ast_type_traits::TraversalKind Traversal;
|
||||
|
||||
public:
|
||||
explicit TraversalMatcher(ast_type_traits::TraversalKind TK,
|
||||
const Matcher<T> &ChildMatcher)
|
||||
: TraversalMatcher::WrapperMatcherInterface(ChildMatcher), Traversal(TK) {
|
||||
}
|
||||
|
||||
bool matches(const T &Node, ASTMatchFinder *Finder,
|
||||
BoundNodesTreeBuilder *Builder) const override {
|
||||
return this->InnerMatcher.matches(
|
||||
ast_type_traits::DynTypedNode::create(Node), Finder, Builder);
|
||||
}
|
||||
|
||||
llvm::Optional<ast_type_traits::TraversalKind>
|
||||
TraversalKind() const override {
|
||||
return Traversal;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MatcherType> class TraversalWrapper {
|
||||
public:
|
||||
TraversalWrapper(ast_type_traits::TraversalKind TK,
|
||||
const MatcherType &InnerMatcher)
|
||||
: TK(TK), InnerMatcher(InnerMatcher) {}
|
||||
|
||||
template <typename T> operator Matcher<T>() const {
|
||||
return internal::DynTypedMatcher::constructRestrictedWrapper(
|
||||
new internal::TraversalMatcher<T>(TK, InnerMatcher),
|
||||
ast_type_traits::ASTNodeKind::getFromNodeKind<T>())
|
||||
.template unconditionalConvertTo<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
ast_type_traits::TraversalKind TK;
|
||||
MatcherType InnerMatcher;
|
||||
};
|
||||
|
||||
/// A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
|
||||
/// created from N parameters p1, ..., pN (of type P1, ..., PN) and
|
||||
/// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN)
|
||||
|
|
|
|||
|
|
@ -164,16 +164,14 @@ public:
|
|||
/// description of the error.
|
||||
/// The caller takes ownership of the DynTypedMatcher object returned.
|
||||
static llvm::Optional<DynTypedMatcher>
|
||||
parseMatcherExpression(StringRef MatcherCode, Sema *S,
|
||||
const NamedValueMap *NamedValues,
|
||||
Diagnostics *Error);
|
||||
parseMatcherExpression(StringRef &MatcherCode, Sema *S,
|
||||
const NamedValueMap *NamedValues, Diagnostics *Error);
|
||||
static llvm::Optional<DynTypedMatcher>
|
||||
parseMatcherExpression(StringRef MatcherCode, Sema *S,
|
||||
Diagnostics *Error) {
|
||||
parseMatcherExpression(StringRef &MatcherCode, Sema *S, Diagnostics *Error) {
|
||||
return parseMatcherExpression(MatcherCode, S, nullptr, Error);
|
||||
}
|
||||
static llvm::Optional<DynTypedMatcher>
|
||||
parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error) {
|
||||
parseMatcherExpression(StringRef &MatcherCode, Diagnostics *Error) {
|
||||
return parseMatcherExpression(MatcherCode, nullptr, Error);
|
||||
}
|
||||
|
||||
|
|
@ -189,14 +187,14 @@ public:
|
|||
/// \param NamedValues A map of precomputed named values. This provides
|
||||
/// the dictionary for the <NamedValue> rule of the grammar.
|
||||
/// If null, it is ignored.
|
||||
static bool parseExpression(StringRef Code, Sema *S,
|
||||
static bool parseExpression(StringRef &Code, Sema *S,
|
||||
const NamedValueMap *NamedValues,
|
||||
VariantValue *Value, Diagnostics *Error);
|
||||
static bool parseExpression(StringRef Code, Sema *S,
|
||||
VariantValue *Value, Diagnostics *Error) {
|
||||
static bool parseExpression(StringRef &Code, Sema *S, VariantValue *Value,
|
||||
Diagnostics *Error) {
|
||||
return parseExpression(Code, S, nullptr, Value, Error);
|
||||
}
|
||||
static bool parseExpression(StringRef Code, VariantValue *Value,
|
||||
static bool parseExpression(StringRef &Code, VariantValue *Value,
|
||||
Diagnostics *Error) {
|
||||
return parseExpression(Code, nullptr, Value, Error);
|
||||
}
|
||||
|
|
@ -213,14 +211,14 @@ public:
|
|||
/// \return The list of completions, which may be empty if there are no
|
||||
/// available completions or if an error occurred.
|
||||
static std::vector<MatcherCompletion>
|
||||
completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
|
||||
completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S,
|
||||
const NamedValueMap *NamedValues);
|
||||
static std::vector<MatcherCompletion>
|
||||
completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S) {
|
||||
completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S) {
|
||||
return completeExpression(Code, CompletionOffset, S, nullptr);
|
||||
}
|
||||
static std::vector<MatcherCompletion>
|
||||
completeExpression(StringRef Code, unsigned CompletionOffset) {
|
||||
completeExpression(StringRef &Code, unsigned CompletionOffset) {
|
||||
return completeExpression(Code, CompletionOffset, nullptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1248,9 +1248,11 @@ public:
|
|||
bool AddStaticInitBranches = false;
|
||||
bool AddCXXNewAllocator = false;
|
||||
bool AddCXXDefaultInitExprInCtors = false;
|
||||
bool AddCXXDefaultInitExprInAggregates = false;
|
||||
bool AddRichCXXConstructors = false;
|
||||
bool MarkElidedCXXConstructors = false;
|
||||
bool AddVirtualBaseBranches = false;
|
||||
bool OmitImplicitValueInitializers = false;
|
||||
|
||||
BuildOptions() = default;
|
||||
|
||||
|
|
|
|||
8
clang/include/clang/Basic/ASTNode.td
Normal file
8
clang/include/clang/Basic/ASTNode.td
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef AST_NODE_TD
|
||||
#define AST_NODE_TD
|
||||
|
||||
class HasProperties;
|
||||
class ASTNode : HasProperties;
|
||||
class AttrSubject;
|
||||
|
||||
#endif
|
||||
|
|
@ -42,6 +42,11 @@ enum class LangAS : unsigned {
|
|||
cuda_constant,
|
||||
cuda_shared,
|
||||
|
||||
// Pointer size and extension address spaces.
|
||||
ptr32_sptr,
|
||||
ptr32_uptr,
|
||||
ptr64,
|
||||
|
||||
// This denotes the count of language-specific address spaces and also
|
||||
// the offset added to the target-specific address spaces, which are usually
|
||||
// specified by address space attributes __attribute__(address_space(n))).
|
||||
|
|
@ -68,6 +73,11 @@ inline LangAS getLangASFromTargetAS(unsigned TargetAS) {
|
|||
(unsigned)LangAS::FirstTargetAddressSpace);
|
||||
}
|
||||
|
||||
inline bool isPtrSizeAddressSpace(LangAS AS) {
|
||||
return (AS == LangAS::ptr32_sptr || AS == LangAS::ptr32_uptr ||
|
||||
AS == LangAS::ptr64);
|
||||
}
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_ADDRESSSPACES_H
|
||||
|
|
|
|||
|
|
@ -121,6 +121,11 @@ def GlobalVar : SubsetSubject<Var,
|
|||
def InlineFunction : SubsetSubject<Function,
|
||||
[{S->isInlineSpecified()}], "inline functions">;
|
||||
|
||||
def FunctionTmpl
|
||||
: SubsetSubject<Function, [{S->getTemplatedKind() ==
|
||||
FunctionDecl::TK_FunctionTemplate}],
|
||||
"function templates">;
|
||||
|
||||
// FIXME: this hack is needed because DeclNodes.td defines the base Decl node
|
||||
// type to be a class, not a definition. This makes it impossible to create an
|
||||
// attribute subject which accepts a Decl. Normally, this is not a problem,
|
||||
|
|
@ -173,8 +178,8 @@ class FunctionArgument<string name, bit opt = 0, bit fake = 0> : Argument<name,
|
|||
opt,
|
||||
fake>;
|
||||
class NamedArgument<string name, bit opt = 0, bit fake = 0> : Argument<name,
|
||||
opt,
|
||||
fake>;
|
||||
opt,
|
||||
fake>;
|
||||
class TypeArgument<string name, bit opt = 0> : Argument<name, opt>;
|
||||
class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;
|
||||
class VariadicUnsignedArgument<string name> : Argument<name, 1>;
|
||||
|
|
@ -296,6 +301,7 @@ def MicrosoftExt : LangOpt<"MicrosoftExt">;
|
|||
def Borland : LangOpt<"Borland">;
|
||||
def CUDA : LangOpt<"CUDA">;
|
||||
def HIP : LangOpt<"HIP">;
|
||||
def SYCL : LangOpt<"SYCLIsDevice">;
|
||||
def COnly : LangOpt<"COnly", "!LangOpts.CPlusPlus">;
|
||||
def CPlusPlus : LangOpt<"CPlusPlus">;
|
||||
def OpenCL : LangOpt<"OpenCL">;
|
||||
|
|
@ -332,6 +338,7 @@ class TargetArch<list<string> arches> : TargetSpec {
|
|||
}
|
||||
def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
|
||||
def TargetAVR : TargetArch<["avr"]>;
|
||||
def TargetBPF : TargetArch<["bpfel", "bpfeb"]>;
|
||||
def TargetMips32 : TargetArch<["mips", "mipsel"]>;
|
||||
def TargetAnyMips : TargetArch<["mips", "mipsel", "mips64", "mips64el"]>;
|
||||
def TargetMSP430 : TargetArch<["msp430"]>;
|
||||
|
|
@ -594,6 +601,13 @@ def Alias : Attr {
|
|||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def ArmMveAlias : InheritableAttr, TargetSpecificAttr<TargetARM> {
|
||||
let Spellings = [Clang<"__clang_arm_mve_alias">];
|
||||
let Args = [IdentifierArgument<"BuiltinName">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
let Documentation = [ArmMveAliasDocs];
|
||||
}
|
||||
|
||||
def Aligned : InheritableAttr {
|
||||
let Spellings = [GCC<"aligned">, Declspec<"align">, Keyword<"alignas">,
|
||||
Keyword<"_Alignas">];
|
||||
|
|
@ -669,6 +683,15 @@ def XRayLogArgs : InheritableAttr {
|
|||
let Documentation = [XRayDocs];
|
||||
}
|
||||
|
||||
def PatchableFunctionEntry
|
||||
: InheritableAttr,
|
||||
TargetSpecificAttr<TargetArch<["aarch64", "x86", "x86_64"]>> {
|
||||
let Spellings = [GCC<"patchable_function_entry">];
|
||||
let Subjects = SubjectList<[Function, ObjCMethod]>;
|
||||
let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>];
|
||||
let Documentation = [PatchableFunctionEntryDocs];
|
||||
}
|
||||
|
||||
def TLSModel : InheritableAttr {
|
||||
let Spellings = [GCC<"tls_model">];
|
||||
let Subjects = SubjectList<[TLSVar], ErrorDiag>;
|
||||
|
|
@ -1048,6 +1071,13 @@ def CUDAShared : InheritableAttr {
|
|||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def SYCLKernel : InheritableAttr {
|
||||
let Spellings = [Clang<"sycl_kernel">];
|
||||
let Subjects = SubjectList<[FunctionTmpl]>;
|
||||
let LangOpts = [SYCL];
|
||||
let Documentation = [SYCLKernelDocs];
|
||||
}
|
||||
|
||||
def C11NoReturn : InheritableAttr {
|
||||
let Spellings = [Keyword<"_Noreturn">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
|
|
@ -1099,27 +1129,27 @@ def OpenCLAccess : Attr {
|
|||
}
|
||||
|
||||
def OpenCLPrivateAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__private">, Keyword<"private">];
|
||||
let Spellings = [Keyword<"__private">, Keyword<"private">, Clang<"opencl_private">];
|
||||
let Documentation = [OpenCLAddressSpacePrivateDocs];
|
||||
}
|
||||
|
||||
def OpenCLGlobalAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__global">, Keyword<"global">];
|
||||
let Spellings = [Keyword<"__global">, Keyword<"global">, Clang<"opencl_global">];
|
||||
let Documentation = [OpenCLAddressSpaceGlobalDocs];
|
||||
}
|
||||
|
||||
def OpenCLLocalAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__local">, Keyword<"local">];
|
||||
let Spellings = [Keyword<"__local">, Keyword<"local">, Clang<"opencl_local">];
|
||||
let Documentation = [OpenCLAddressSpaceLocalDocs];
|
||||
}
|
||||
|
||||
def OpenCLConstantAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__constant">, Keyword<"constant">];
|
||||
let Spellings = [Keyword<"__constant">, Keyword<"constant">, Clang<"opencl_constant">];
|
||||
let Documentation = [OpenCLAddressSpaceConstantDocs];
|
||||
}
|
||||
|
||||
def OpenCLGenericAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__generic">, Keyword<"generic">];
|
||||
let Spellings = [Keyword<"__generic">, Keyword<"generic">, Clang<"opencl_generic">];
|
||||
let Documentation = [OpenCLAddressSpaceGenericDocs];
|
||||
}
|
||||
|
||||
|
|
@ -1571,6 +1601,22 @@ def AMDGPUNumVGPR : InheritableAttr {
|
|||
let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
|
||||
}
|
||||
|
||||
def BPFPreserveAccessIndex : InheritableAttr,
|
||||
TargetSpecificAttr<TargetBPF> {
|
||||
let Spellings = [Clang<"preserve_access_index">];
|
||||
let Subjects = SubjectList<[Record], ErrorDiag>;
|
||||
let Documentation = [BPFPreserveAccessIndexDocs];
|
||||
let LangOpts = [COnly];
|
||||
}
|
||||
|
||||
def WebAssemblyExportName : InheritableAttr,
|
||||
TargetSpecificAttr<TargetWebAssembly> {
|
||||
let Spellings = [Clang<"export_name">];
|
||||
let Args = [StringArgument<"ExportName">];
|
||||
let Documentation = [WebAssemblyExportNameDocs];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
}
|
||||
|
||||
def WebAssemblyImportModule : InheritableAttr,
|
||||
TargetSpecificAttr<TargetWebAssembly> {
|
||||
let Spellings = [Clang<"import_module">];
|
||||
|
|
@ -1845,6 +1891,20 @@ def ObjCDesignatedInitializer : Attr {
|
|||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def ObjCDirect : Attr {
|
||||
let Spellings = [Clang<"objc_direct">];
|
||||
let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
|
||||
let LangOpts = [ObjC];
|
||||
let Documentation = [ObjCDirectDocs];
|
||||
}
|
||||
|
||||
def ObjCDirectMembers : Attr {
|
||||
let Spellings = [Clang<"objc_direct_members">];
|
||||
let Subjects = SubjectList<[ObjCImpl, ObjCCategory], ErrorDiag>;
|
||||
let LangOpts = [ObjC];
|
||||
let Documentation = [ObjCDirectMembersDocs];
|
||||
}
|
||||
|
||||
def ObjCRuntimeName : Attr {
|
||||
let Spellings = [Clang<"objc_runtime_name">];
|
||||
let Subjects = SubjectList<[ObjCInterface, ObjCProtocol], ErrorDiag>;
|
||||
|
|
@ -2119,15 +2179,6 @@ def Target : InheritableAttr {
|
|||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
let Documentation = [TargetDocs];
|
||||
let AdditionalMembers = [{
|
||||
struct ParsedTargetAttr {
|
||||
std::vector<std::string> Features;
|
||||
StringRef Architecture;
|
||||
bool DuplicateArchitecture = false;
|
||||
bool operator ==(const ParsedTargetAttr &Other) const {
|
||||
return DuplicateArchitecture == Other.DuplicateArchitecture &&
|
||||
Architecture == Other.Architecture && Features == Other.Features;
|
||||
}
|
||||
};
|
||||
ParsedTargetAttr parse() const {
|
||||
return parse(getFeaturesStr());
|
||||
}
|
||||
|
|
@ -2194,6 +2245,11 @@ def Target : InheritableAttr {
|
|||
if (Feature.startswith("fpmath=") || Feature.startswith("tune="))
|
||||
continue;
|
||||
|
||||
if (Feature.startswith("branch-protection=")) {
|
||||
Ret.BranchProtection = Feature.split('=').second.trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
// While we're here iterating check for a different target cpu.
|
||||
if (Feature.startswith("arch=")) {
|
||||
if (!Ret.Architecture.empty())
|
||||
|
|
@ -2860,6 +2916,15 @@ def MSAllocator : InheritableAttr {
|
|||
let Documentation = [MSAllocatorDocs];
|
||||
}
|
||||
|
||||
def CFGuard : InheritableAttr {
|
||||
// Currently only the __declspec(guard(nocf)) modifier is supported. In future
|
||||
// we might also want to support __declspec(guard(suppress)).
|
||||
let Spellings = [Declspec<"guard">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Args = [EnumArgument<"Guard", "GuardArg", ["nocf"], ["nocf"]>];
|
||||
let Documentation = [CFGuardDocs];
|
||||
}
|
||||
|
||||
def MSStruct : InheritableAttr {
|
||||
let Spellings = [GCC<"ms_struct">];
|
||||
let Subjects = SubjectList<[Record]>;
|
||||
|
|
@ -2928,22 +2993,22 @@ def Win64 : IgnoredAttr {
|
|||
|
||||
def Ptr32 : TypeAttr {
|
||||
let Spellings = [Keyword<"__ptr32">];
|
||||
let Documentation = [Undocumented];
|
||||
let Documentation = [Ptr32Docs];
|
||||
}
|
||||
|
||||
def Ptr64 : TypeAttr {
|
||||
let Spellings = [Keyword<"__ptr64">];
|
||||
let Documentation = [Undocumented];
|
||||
let Documentation = [Ptr64Docs];
|
||||
}
|
||||
|
||||
def SPtr : TypeAttr {
|
||||
let Spellings = [Keyword<"__sptr">];
|
||||
let Documentation = [Undocumented];
|
||||
let Documentation = [SPtrDocs];
|
||||
}
|
||||
|
||||
def UPtr : TypeAttr {
|
||||
let Spellings = [Keyword<"__uptr">];
|
||||
let Documentation = [Undocumented];
|
||||
let Documentation = [UPtrDocs];
|
||||
}
|
||||
|
||||
def MSInheritance : InheritableAttr {
|
||||
|
|
@ -2954,25 +3019,9 @@ def MSInheritance : InheritableAttr {
|
|||
Keyword<"__virtual_inheritance">,
|
||||
Keyword<"__unspecified_inheritance">];
|
||||
let AdditionalMembers = [{
|
||||
static bool hasVBPtrOffsetField(Spelling Inheritance) {
|
||||
return Inheritance == Keyword_unspecified_inheritance;
|
||||
}
|
||||
|
||||
// Only member pointers to functions need a this adjustment, since it can be
|
||||
// combined with the field offset for data pointers.
|
||||
static bool hasNVOffsetField(bool IsMemberFunction, Spelling Inheritance) {
|
||||
return IsMemberFunction && Inheritance >= Keyword_multiple_inheritance;
|
||||
}
|
||||
|
||||
static bool hasVBTableOffsetField(Spelling Inheritance) {
|
||||
return Inheritance >= Keyword_virtual_inheritance;
|
||||
}
|
||||
|
||||
static bool hasOnlyOneField(bool IsMemberFunction,
|
||||
Spelling Inheritance) {
|
||||
if (IsMemberFunction)
|
||||
return Inheritance <= Keyword_single_inheritance;
|
||||
return Inheritance <= Keyword_multiple_inheritance;
|
||||
MSInheritanceModel getInheritanceModel() const {
|
||||
// The spelling enum should agree with MSInheritanceModel.
|
||||
return MSInheritanceModel(getSemanticSpelling());
|
||||
}
|
||||
}];
|
||||
let Documentation = [MSInheritanceDocs];
|
||||
|
|
@ -2985,13 +3034,7 @@ def MSVtorDisp : InheritableAttr {
|
|||
let SemaHandler = 0;
|
||||
|
||||
let AdditionalMembers = [{
|
||||
enum Mode {
|
||||
Never,
|
||||
ForVBaseOverride,
|
||||
ForVFTable
|
||||
};
|
||||
|
||||
Mode getVtorDispMode() const { return Mode(vdm); }
|
||||
MSVtorDispMode getVtorDispMode() const { return MSVtorDispMode(vdm); }
|
||||
}];
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
|
@ -3298,30 +3341,15 @@ def OMPDeclareVariant : InheritableAttr {
|
|||
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">
|
||||
VariadicExprArgument<"Scores">,
|
||||
VariadicUnsignedArgument<"CtxSelectorSets">,
|
||||
VariadicUnsignedArgument<"CtxSelectors">,
|
||||
VariadicStringArgument<"ImplVendors">,
|
||||
VariadicStringArgument<"DeviceKinds">
|
||||
];
|
||||
let AdditionalMembers = [{
|
||||
void printScore(raw_ostream & OS, const PrintingPolicy &Policy) const {
|
||||
if (const Expr *E = getScore()) {
|
||||
void printScore(raw_ostream & OS, const PrintingPolicy &Policy, unsigned I) const {
|
||||
if (const Expr *E = *std::next(scores_begin(), I)) {
|
||||
OS << "score(";
|
||||
E->printPretty(OS, nullptr, Policy);
|
||||
OS << "):";
|
||||
|
|
@ -3329,8 +3357,6 @@ def OMPDeclareVariant : InheritableAttr {
|
|||
}
|
||||
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);
|
||||
|
|
@ -3338,27 +3364,63 @@ def OMPDeclareVariant : InheritableAttr {
|
|||
}
|
||||
// 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 << ")";
|
||||
int Used[OMP_CTX_SET_unknown] = {0};
|
||||
for (unsigned I = 0, E = ctxSelectorSets_size(); I < E; ++I) {
|
||||
auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
|
||||
*std::next(ctxSelectorSets_begin(), I));
|
||||
if (Used[CtxSet])
|
||||
continue;
|
||||
if (I > 0)
|
||||
OS << ",";
|
||||
switch (CtxSet) {
|
||||
case OMP_CTX_SET_implementation:
|
||||
OS << "implementation={";
|
||||
break;
|
||||
case CtxUnknown:
|
||||
llvm_unreachable("Unknown context selector.");
|
||||
case OMP_CTX_SET_device:
|
||||
OS << "device={";
|
||||
break;
|
||||
case OMP_CTX_SET_unknown:
|
||||
llvm_unreachable("Unknown context selector set.");
|
||||
}
|
||||
Used[CtxSet] = 1;
|
||||
for (unsigned K = I, EK = ctxSelectors_size(); K < EK; ++K) {
|
||||
auto CtxSetK = static_cast<OpenMPContextSelectorSetKind>(
|
||||
*std::next(ctxSelectorSets_begin(), K));
|
||||
if (CtxSet != CtxSetK)
|
||||
continue;
|
||||
if (K != I)
|
||||
OS << ",";
|
||||
auto Ctx = static_cast<OpenMPContextSelectorKind>(
|
||||
*std::next(ctxSelectors_begin(), K));
|
||||
switch (Ctx) {
|
||||
case OMP_CTX_vendor:
|
||||
assert(CtxSet == OMP_CTX_SET_implementation &&
|
||||
"Expected implementation context selector set.");
|
||||
OS << "vendor(";
|
||||
printScore(OS, Policy, K);
|
||||
if (implVendors_size() > 0) {
|
||||
OS << *implVendors(). begin();
|
||||
for (StringRef VendorName : llvm::drop_begin(implVendors(), 1))
|
||||
OS << ", " << VendorName;
|
||||
}
|
||||
OS << ")";
|
||||
break;
|
||||
case OMP_CTX_kind:
|
||||
assert(CtxSet == OMP_CTX_SET_device &&
|
||||
"Expected device context selector set.");
|
||||
OS << "kind(";
|
||||
if (deviceKinds_size() > 0) {
|
||||
OS << *deviceKinds().begin();
|
||||
for (StringRef KindName : llvm::drop_begin(deviceKinds(), 1))
|
||||
OS << ", " << KindName;
|
||||
}
|
||||
OS << ")";
|
||||
break;
|
||||
case OMP_CTX_unknown:
|
||||
llvm_unreachable("Unknown context selector.");
|
||||
}
|
||||
}
|
||||
OS << "}";
|
||||
break;
|
||||
case CtxSetUnknown:
|
||||
llvm_unreachable("Unknown context selector set.");
|
||||
}
|
||||
OS << ")";
|
||||
}
|
||||
|
|
@ -3420,3 +3482,34 @@ def ObjCExternallyRetained : InheritableAttr {
|
|||
let Subjects = SubjectList<[NonParmVar, Function, Block, ObjCMethod]>;
|
||||
let Documentation = [ObjCExternallyRetainedDocs];
|
||||
}
|
||||
|
||||
def NoBuiltin : Attr {
|
||||
let Spellings = [Clang<"no_builtin">];
|
||||
let Args = [VariadicStringArgument<"BuiltinNames">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Documentation = [NoBuiltinDocs];
|
||||
}
|
||||
|
||||
// FIXME: This attribute is not inheritable, it will not be propagated to
|
||||
// redecls. [[clang::lifetimebound]] has the same problems. This should be
|
||||
// fixed in TableGen (by probably adding a new inheritable flag).
|
||||
def AcquireHandle : DeclOrTypeAttr {
|
||||
let Spellings = [Clang<"acquire_handle">];
|
||||
let Args = [StringArgument<"HandleType">];
|
||||
let Subjects = SubjectList<[Function, TypedefName, ParmVar]>;
|
||||
let Documentation = [AcquireHandleDocs];
|
||||
}
|
||||
|
||||
def UseHandle : InheritableParamAttr {
|
||||
let Spellings = [Clang<"use_handle">];
|
||||
let Args = [StringArgument<"HandleType">];
|
||||
let Subjects = SubjectList<[ParmVar]>;
|
||||
let Documentation = [UseHandleDocs];
|
||||
}
|
||||
|
||||
def ReleaseHandle : InheritableParamAttr {
|
||||
let Spellings = [Clang<"release_handle">];
|
||||
let Args = [StringArgument<"HandleType">];
|
||||
let Subjects = SubjectList<[ParmVar]>;
|
||||
let Documentation = [ReleaseHandleDocs];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,12 +253,87 @@ any option of a multiversioned function is undefined.
|
|||
}];
|
||||
}
|
||||
|
||||
def SYCLKernelDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``sycl_kernel`` attribute specifies that a function template will be used
|
||||
to outline device code and to generate an OpenCL kernel.
|
||||
Here is a code example of the SYCL program, which demonstrates the compiler's
|
||||
outlining job:
|
||||
.. code-block:: c++
|
||||
|
||||
int foo(int x) { return ++x; }
|
||||
|
||||
using namespace cl::sycl;
|
||||
queue Q;
|
||||
buffer<int, 1> a(range<1>{1024});
|
||||
Q.submit([&](handler& cgh) {
|
||||
auto A = a.get_access<access::mode::write>(cgh);
|
||||
cgh.parallel_for<init_a>(range<1>{1024}, [=](id<1> index) {
|
||||
A[index] = index[0] + foo(42);
|
||||
});
|
||||
}
|
||||
|
||||
A C++ function object passed to the ``parallel_for`` is called a "SYCL kernel".
|
||||
A SYCL kernel defines the entry point to the "device part" of the code. The
|
||||
compiler will emit all symbols accessible from a "kernel". In this code
|
||||
example, the compiler will emit "foo" function. More details about the
|
||||
compilation of functions for the device part can be found in the SYCL 1.2.1
|
||||
specification Section 6.4.
|
||||
To show to the compiler entry point to the "device part" of the code, the SYCL
|
||||
runtime can use the ``sycl_kernel`` attribute in the following way:
|
||||
.. code-block:: c++
|
||||
namespace cl {
|
||||
namespace sycl {
|
||||
class handler {
|
||||
template <typename KernelName, typename KernelType/*, ...*/>
|
||||
__attribute__((sycl_kernel)) void sycl_kernel_function(KernelType KernelFuncObj) {
|
||||
// ...
|
||||
KernelFuncObj();
|
||||
}
|
||||
|
||||
template <typename KernelName, typename KernelType, int Dims>
|
||||
void parallel_for(range<Dims> NumWorkItems, KernelType KernelFunc) {
|
||||
#ifdef __SYCL_DEVICE_ONLY__
|
||||
sycl_kernel_function<KernelName, KernelType, Dims>(KernelFunc);
|
||||
#else
|
||||
// Host implementation
|
||||
#endif
|
||||
}
|
||||
};
|
||||
} // namespace sycl
|
||||
} // namespace cl
|
||||
|
||||
The compiler will also generate an OpenCL kernel using the function marked with
|
||||
the ``sycl_kernel`` attribute.
|
||||
Here is the list of SYCL device compiler expectations with regard to the
|
||||
function marked with the ``sycl_kernel`` attribute:
|
||||
|
||||
- The function must be a template with at least two type template parameters.
|
||||
The compiler generates an OpenCL kernel and uses the first template parameter
|
||||
as a unique name for the generated OpenCL kernel. The host application uses
|
||||
this unique name to invoke the OpenCL kernel generated for the SYCL kernel
|
||||
specialized by this name and second template parameter ``KernelType`` (which
|
||||
might be an unnamed function object type).
|
||||
- The function must have at least one parameter. The first parameter is
|
||||
required to be a function object type (named or unnamed i.e. lambda). The
|
||||
compiler uses function object type fields to generate OpenCL kernel
|
||||
parameters.
|
||||
- The function must return void. The compiler reuses the body of marked functions to
|
||||
generate the OpenCL kernel body, and the OpenCL kernel must return `void`.
|
||||
|
||||
The SYCL kernel in the previous code sample meets these expectations.
|
||||
}];
|
||||
}
|
||||
|
||||
def C11NoReturnDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
A function declared as ``_Noreturn`` shall not return to its caller. The
|
||||
compiler will generate a diagnostic for a function declared as ``_Noreturn``
|
||||
that appears to be capable of returning to its caller.
|
||||
that appears to be capable of returning to its caller. Despite being a type
|
||||
specifier, the ``_Noreturn`` attribute cannot be specified on a function
|
||||
pointer type.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -1632,6 +1707,17 @@ The semantics are as follows:
|
|||
}];
|
||||
}
|
||||
|
||||
def BPFPreserveAccessIndexDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the ``__attribute__((preserve_access_index))``
|
||||
attribute for the BPF target. This attribute may be attached to a
|
||||
struct or union declaration, where if -g is specified, it enables
|
||||
preserving struct or union member access debuginfo indicies of this
|
||||
struct or union, similar to clang ``__builtin_preserve_acceess_index()``.
|
||||
}];
|
||||
}
|
||||
|
||||
def MipsInterruptDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Heading = "interrupt (MIPS)";
|
||||
|
|
@ -1793,6 +1879,10 @@ the target with or without a "-mno-" in front corresponding to the absence
|
|||
of the feature, as well as ``arch="CPU"`` which will change the default "CPU"
|
||||
for the function.
|
||||
|
||||
For AArch64, the attribute also allows the "branch-protection=<args>" option,
|
||||
where the permissible arguments and their effect on code generation are the same
|
||||
as for the command-line option ``-mbranch-protection``.
|
||||
|
||||
Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2",
|
||||
"avx", "xop" and largely correspond to the machine specific options handled by
|
||||
the front end.
|
||||
|
|
@ -2976,6 +3066,7 @@ More details can be found in the OpenCL C language Spec v2.0, Section 6.5.
|
|||
|
||||
def OpenCLAddressSpaceGenericDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__generic, generic, [[clang::opencl_generic]]";
|
||||
let Content = [{
|
||||
The generic address space attribute is only available with OpenCL v2.0 and later.
|
||||
It can be used with pointer types. Variables in global and local scope and
|
||||
|
|
@ -2988,6 +3079,7 @@ spaces.
|
|||
|
||||
def OpenCLAddressSpaceConstantDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__constant, constant, [[clang::opencl_constant]]";
|
||||
let Content = [{
|
||||
The constant address space attribute signals that an object is located in
|
||||
a constant (non-modifiable) memory region. It is available to all work items.
|
||||
|
|
@ -2999,6 +3091,7 @@ have an initializer.
|
|||
|
||||
def OpenCLAddressSpaceGlobalDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__global, global, [[clang::opencl_global]]";
|
||||
let Content = [{
|
||||
The global address space attribute specifies that an object is allocated in
|
||||
global memory, which is accessible by all work items. The content stored in this
|
||||
|
|
@ -3011,6 +3104,7 @@ scope) variables and static local variable as well.
|
|||
|
||||
def OpenCLAddressSpaceLocalDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__local, local, [[clang::opencl_local]]";
|
||||
let Content = [{
|
||||
The local address space specifies that an object is allocated in the local (work
|
||||
group) memory area, which is accessible to all work items in the same work
|
||||
|
|
@ -3023,6 +3117,7 @@ space are allowed. Local address space variables cannot have an initializer.
|
|||
|
||||
def OpenCLAddressSpacePrivateDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__private, private, [[clang::opencl_private]]";
|
||||
let Content = [{
|
||||
The private address space specifies that an object is allocated in the private
|
||||
(work item) memory. Other work items cannot access the same memory area and its
|
||||
|
|
@ -3044,6 +3139,44 @@ Since it is not widely used and has been removed from OpenCL 2.1, it is ignored
|
|||
by Clang.
|
||||
}];
|
||||
}
|
||||
|
||||
def Ptr32Docs : Documentation {
|
||||
let Category = DocCatType;
|
||||
let Content = [{
|
||||
The ``__ptr32`` qualifier represents a native pointer on a 32-bit system. On a
|
||||
64-bit system, a pointer with ``__ptr32`` is extended to a 64-bit pointer. The
|
||||
``__sptr`` and ``__uptr`` qualifiers can be used to specify whether the pointer
|
||||
is sign extended or zero extended. This qualifier is enabled under
|
||||
``-fms-extensions``.
|
||||
}];
|
||||
}
|
||||
|
||||
def Ptr64Docs : Documentation {
|
||||
let Category = DocCatType;
|
||||
let Content = [{
|
||||
The ``__ptr64`` qualifier represents a native pointer on a 64-bit system. On a
|
||||
32-bit system, a ``__ptr64`` pointer is truncated to a 32-bit pointer. This
|
||||
qualifier is enabled under ``-fms-extensions``.
|
||||
}];
|
||||
}
|
||||
|
||||
def SPtrDocs : Documentation {
|
||||
let Category = DocCatType;
|
||||
let Content = [{
|
||||
The ``__sptr`` qualifier specifies that a 32-bit pointer should be sign
|
||||
extended when converted to a 64-bit pointer.
|
||||
}];
|
||||
}
|
||||
|
||||
def UPtrDocs : Documentation {
|
||||
let Category = DocCatType;
|
||||
let Content = [{
|
||||
The ``__uptr`` qualifier specifies that a 32-bit pointer should be zero
|
||||
extended when converted to a 64-bit pointer.
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
def NullabilityDocs : DocumentationCategory<"Nullability Attributes"> {
|
||||
let Content = [{
|
||||
Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``).
|
||||
|
|
@ -3855,6 +3988,18 @@ If a function has neither of these attributes, they become subject to the XRay h
|
|||
}];
|
||||
}
|
||||
|
||||
def PatchableFunctionEntryDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
``__attribute__((patchable_function_entry(N,M)))`` is used to generate M NOPs
|
||||
before the function entry and N-M NOPs after the function entry. This attribute
|
||||
takes precedence over the command line option ``-fpatchable-function-entry=N,M``.
|
||||
``M`` defaults to 0 if omitted.
|
||||
|
||||
Currently, only M=0 is supported.
|
||||
}];
|
||||
}
|
||||
|
||||
def TransparentUnionDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
|
|
@ -3895,6 +4040,104 @@ overheads associated with defining and calling such a method.
|
|||
}];
|
||||
}
|
||||
|
||||
def ObjCDirectDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
The ``objc_direct`` attribute can be used to mark an Objective-C method as
|
||||
being *direct*. A direct method is treated statically like an ordinary method,
|
||||
but dynamically it behaves more like a C function. This lowers some of the costs
|
||||
associated with the method but also sacrifices some of the ordinary capabilities
|
||||
of Objective-C methods.
|
||||
|
||||
A message send of a direct method calls the implementation directly, as if it
|
||||
were a C function, rather than using ordinary Objective-C method dispatch. This
|
||||
is substantially faster and potentially allows the implementation to be inlined,
|
||||
but it also means the method cannot be overridden in subclasses or replaced
|
||||
dynamically, as ordinary Objective-C methods can.
|
||||
|
||||
Furthermore, a direct method is not listed in the class's method lists. This
|
||||
substantially reduces the code-size overhead of the method but also means it
|
||||
cannot be called dynamically using ordinary Objective-C method dispatch at all;
|
||||
in particular, this means that it cannot override a superclass method or satisfy
|
||||
a protocol requirement.
|
||||
|
||||
Because a direct method cannot be overridden, it is an error to perform
|
||||
a ``super`` message send of one.
|
||||
|
||||
Although a message send of a direct method causes the method to be called
|
||||
directly as if it were a C function, it still obeys Objective-C semantics in other
|
||||
ways:
|
||||
|
||||
- If the receiver is ``nil``, the message send does nothing and returns the zero value
|
||||
for the return type.
|
||||
|
||||
- A message send of a direct class method will cause the class to be initialized,
|
||||
including calling the ``+initialize`` method if present.
|
||||
|
||||
- The implicit ``_cmd`` parameter containing the method's selector is still defined.
|
||||
In order to minimize code-size costs, the implementation will not emit a reference
|
||||
to the selector if the parameter is unused within the method.
|
||||
|
||||
Symbols for direct method implementations are implicitly given hidden
|
||||
visibility, meaning that they can only be called within the same linkage unit.
|
||||
|
||||
It is an error to do any of the following:
|
||||
|
||||
- declare a direct method in a protocol,
|
||||
- declare an override of a direct method with a method in a subclass,
|
||||
- declare an override of a non-direct method with a direct method in a subclass,
|
||||
- declare a method with different directness in different class interfaces, or
|
||||
- implement a non-direct method (as declared in any class interface) with a direct method.
|
||||
|
||||
If any of these rules would be violated if every method defined in an
|
||||
``@implementation`` within a single linkage unit were declared in an
|
||||
appropriate class interface, the program is ill-formed with no diagnostic
|
||||
required. If a violation of this rule is not diagnosed, behavior remains
|
||||
well-defined; this paragraph is simply reserving the right to diagnose such
|
||||
conflicts in the future, not to treat them as undefined behavior.
|
||||
|
||||
Additionally, Clang will warn about any ``@selector`` expression that
|
||||
names a selector that is only known to be used for direct methods.
|
||||
|
||||
For the purpose of these rules, a "class interface" includes a class's primary
|
||||
``@interface`` block, its class extensions, its categories, its declared protocols,
|
||||
and all the class interfaces of its superclasses.
|
||||
|
||||
An Objective-C property can be declared with the ``direct`` property
|
||||
attribute. If a direct property declaration causes an implicit declaration of
|
||||
a getter or setter method (that is, if the given method is not explicitly
|
||||
declared elsewhere), the method is declared to be direct.
|
||||
|
||||
Some programmers may wish to make many methods direct at once. In order
|
||||
to simplify this, the ``objc_direct_members`` attribute is provided; see its
|
||||
documentation for more information.
|
||||
}];
|
||||
}
|
||||
|
||||
def ObjCDirectMembersDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
The ``objc_direct_members`` attribute can be placed on an Objective-C
|
||||
``@interface`` or ``@implementation`` to mark that methods declared
|
||||
therein should be considered direct by default. See the documentation
|
||||
for ``objc_direct`` for more information about direct methods.
|
||||
|
||||
When ``objc_direct_members`` is placed on an ``@interface`` block, every
|
||||
method in the block is considered to be declared as direct. This includes any
|
||||
implicit method declarations introduced by property declarations. If the method
|
||||
redeclares a non-direct method, the declaration is ill-formed, exactly as if the
|
||||
method was annotated with the ``objc_direct`` attribute. ``objc_direct_members``
|
||||
cannot be placed on the primary interface of a class, only on category or class
|
||||
extension interfaces.
|
||||
|
||||
When ``objc_direct_members`` is placed on an ``@implementation`` block,
|
||||
methods defined in the block are considered to be declared as direct unless
|
||||
they have been previously declared as non-direct in any interface of the class.
|
||||
This includes the implicit method definitions introduced by synthesized
|
||||
properties, including auto-synthesized properties.
|
||||
}];
|
||||
}
|
||||
|
||||
def SelectAnyDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
|
|
@ -3908,10 +4151,25 @@ For more information see
|
|||
or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_.
|
||||
}]; }
|
||||
|
||||
def WebAssemblyExportNameDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the ``__attribute__((export_name(<name>)))``
|
||||
attribute for the WebAssembly target. This attribute may be attached to a
|
||||
function declaration, where it modifies how the symbol is to be exported
|
||||
from the linked WebAssembly.
|
||||
|
||||
WebAssembly functions are exported via string name. By default when a symbol
|
||||
is exported, the export name for C/C++ symbols are the same as their C/C++
|
||||
symbol names. This attribute can be used to override the default behavior, and
|
||||
request a specific string name be used instead.
|
||||
}];
|
||||
}
|
||||
|
||||
def WebAssemblyImportModuleDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the ``__attribute__((import_module(<module_name>)))``
|
||||
Clang supports the ``__attribute__((import_module(<module_name>)))``
|
||||
attribute for the WebAssembly target. This attribute may be attached to a
|
||||
function declaration, where it modifies how the symbol is to be imported
|
||||
within the WebAssembly linking environment.
|
||||
|
|
@ -3921,14 +4179,14 @@ name, which typically identifies a module from which to import, and a field
|
|||
name, which typically identifies a field from that module to import. By
|
||||
default, module names for C/C++ symbols are assigned automatically by the
|
||||
linker. This attribute can be used to override the default behavior, and
|
||||
reuqest a specific module name be used instead.
|
||||
request a specific module name be used instead.
|
||||
}];
|
||||
}
|
||||
|
||||
def WebAssemblyImportNameDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the ``__attribute__((import_name(<name>)))``
|
||||
Clang supports the ``__attribute__((import_name(<name>)))``
|
||||
attribute for the WebAssembly target. This attribute may be attached to a
|
||||
function declaration, where it modifies how the symbol is to be imported
|
||||
within the WebAssembly linking environment.
|
||||
|
|
@ -3938,7 +4196,7 @@ name, which typically identifies a module from which to import, and a field
|
|||
name, which typically identifies a field from that module to import. By
|
||||
default, field names for C/C++ symbols are the same as their C/C++ symbol
|
||||
names. This attribute can be used to override the default behavior, and
|
||||
reuqest a specific field name be used instead.
|
||||
request a specific field name be used instead.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -4132,7 +4390,7 @@ below. The explicit attribute annotation indicates that the third parameter
|
|||
(`start_routine`) is called zero or more times by the `pthread_create` function,
|
||||
and that the fourth parameter (`arg`) is passed along. Note that the callback
|
||||
behavior of `pthread_create` is automatically recognized by Clang. In addition,
|
||||
the declarations of `__kmpc_fork_teams` and `__kmpc_fork_call`, generated for
|
||||
the declarations of `__kmpc_fork_teams` and `__kmpc_fork_call`, generated for
|
||||
`#pragma omp target teams` and `#pragma omp parallel`, respectively, are also
|
||||
automatically recognized as broker functions. Further functions might be added
|
||||
in the future.
|
||||
|
|
@ -4312,6 +4570,26 @@ This attribute does not affect optimizations in any way, unlike GCC's
|
|||
}];
|
||||
}
|
||||
|
||||
def CFGuardDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Code can indicate CFG checks are not wanted with the ``__declspec(guard(nocf))``
|
||||
attribute. This directs the compiler to not insert any CFG checks for the entire
|
||||
function. This approach is typically used only sparingly in specific situations
|
||||
where the programmer has manually inserted "CFG-equivalent" protection. The
|
||||
programmer knows that they are calling through some read-only function table
|
||||
whose address is obtained through read-only memory references and for which the
|
||||
index is masked to the function table limit. This approach may also be applied
|
||||
to small wrapper functions that are not inlined and that do nothing more than
|
||||
make a call through a function pointer. Since incorrect usage of this directive
|
||||
can compromise the security of CFG, the programmer must be very careful using
|
||||
the directive. Typically, this usage is limited to very small functions that
|
||||
only call one function.
|
||||
|
||||
`Control Flow Guard documentation <https://docs.microsoft.com/en-us/windows/win32/secbp/pe-metadata>`
|
||||
}];
|
||||
}
|
||||
|
||||
def HIPPinnedShadowDocs : Documentation {
|
||||
let Category = DocCatType;
|
||||
let Content = [{
|
||||
|
|
@ -4344,7 +4622,7 @@ object of type ``T``:
|
|||
|
||||
The argument ``T`` is optional and is ignored.
|
||||
This attribute may be used by analysis tools and has no effect on code
|
||||
generation.
|
||||
generation. A ``void`` argument means that the class can own any type.
|
||||
|
||||
See Pointer_ for an example.
|
||||
}];
|
||||
|
|
@ -4370,7 +4648,7 @@ like pointers to an object of type ``T``:
|
|||
|
||||
The argument ``T`` is optional and is ignored.
|
||||
This attribute may be used by analysis tools and has no effect on code
|
||||
generation.
|
||||
generation. A ``void`` argument means that the pointer can point to any type.
|
||||
|
||||
Example:
|
||||
When constructing an instance of a class annotated like this (a Pointer) from
|
||||
|
|
@ -4391,3 +4669,123 @@ When the Owner's lifetime ends, it will consider the Pointer to be dangling.
|
|||
|
||||
}];
|
||||
}
|
||||
|
||||
def ArmMveAliasDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
This attribute is used in the implementation of the ACLE intrinsics
|
||||
for the Arm MVE instruction set. It allows the intrinsic functions to
|
||||
be declared using the names defined in ACLE, and still be recognized
|
||||
as clang builtins equivalent to the underlying name. For example,
|
||||
``arm_mve.h`` declares the function ``vaddq_u32`` with
|
||||
``__attribute__((__clang_arm_mve_alias(__builtin_arm_mve_vaddq_u32)))``,
|
||||
and similarly, one of the type-overloaded declarations of ``vaddq``
|
||||
will have the same attribute. This ensures that both functions are
|
||||
recognized as that clang builtin, and in the latter case, the choice
|
||||
of which builtin to identify the function as can be deferred until
|
||||
after overload resolution.
|
||||
|
||||
This attribute can only be used to set up the aliases for the MVE
|
||||
intrinsic functions; it is intended for use only inside ``arm_mve.h``,
|
||||
and is not a general mechanism for declaring arbitrary aliases for
|
||||
clang builtin functions.
|
||||
}];
|
||||
}
|
||||
|
||||
def NoBuiltinDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
.. Note:: This attribute is not yet fully implemented, it is validated but has
|
||||
no effect on the generated code.
|
||||
|
||||
The ``__attribute__((no_builtin))`` is similar to the ``-fno-builtin`` flag
|
||||
except it is specific to the body of a function. The attribute may also be
|
||||
applied to a virtual function but has no effect on the behavior of overriding
|
||||
functions in a derived class.
|
||||
|
||||
It accepts one or more strings corresponding to the specific names of the
|
||||
builtins to disable (e.g. "memcpy", "memset").
|
||||
If the attribute is used without parameters it will disable all buitins at
|
||||
once.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// The compiler is not allowed to add any builtin to foo's body.
|
||||
void foo(char* data, size_t count) __attribute__((no_builtin)) {
|
||||
// The compiler is not allowed to convert the loop into
|
||||
// `__builtin_memset(data, 0xFE, count);`.
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
data[i] = 0xFE;
|
||||
}
|
||||
|
||||
// The compiler is not allowed to add the `memcpy` builtin to bar's body.
|
||||
void bar(char* data, size_t count) __attribute__((no_builtin("memcpy"))) {
|
||||
// The compiler is allowed to convert the loop into
|
||||
// `__builtin_memset(data, 0xFE, count);` but cannot generate any
|
||||
// `__builtin_memcpy`
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
data[i] = 0xFE;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def HandleDocs : DocumentationCategory<"Handle Attributes"> {
|
||||
let Content = [{
|
||||
Handles are a way to identify resources like files, sockets, and processes.
|
||||
They are more opaque than pointers and widely used in system programming. They
|
||||
have similar risks such as never releasing a resource associated with a handle,
|
||||
attempting to use a handle that was already released, or trying to release a
|
||||
handle twice. Using the annotations below it is possible to make the ownership
|
||||
of the handles clear: whose responsibility is to release them. They can also
|
||||
aid static analysis tools to find bugs.
|
||||
}];
|
||||
}
|
||||
|
||||
def AcquireHandleDocs : Documentation {
|
||||
let Category = HandleDocs;
|
||||
let Content = [{
|
||||
If this annotation is on a function or a function type it is assumed to return
|
||||
a new handle. In case this annotation is on an output parameter,
|
||||
the function is assumed to fill the corresponding argument with a new
|
||||
handle.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Output arguments from Zircon.
|
||||
zx_status_t zx_socket_create(uint32_t options,
|
||||
zx_handle_t __attribute__((acquire_handle)) * out0,
|
||||
zx_handle_t* out1 [[clang::acquire_handle]]);
|
||||
|
||||
|
||||
// Returned handle.
|
||||
[[clang::acquire_handle]] int open(const char *path, int oflag, ... );
|
||||
int open(const char *path, int oflag, ... ) __attribute__((acquire_handle));
|
||||
}];
|
||||
}
|
||||
|
||||
def UseHandleDocs : Documentation {
|
||||
let Category = HandleDocs;
|
||||
let Content = [{
|
||||
A function taking a handle by value might close the handle. If a function
|
||||
parameter is annotated with `use_handle` it is assumed to not to change
|
||||
the state of the handle. It is also assumed to require an open handle to work with.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
zx_status_t zx_port_wait(zx_handle_t handle [[clang::use_handle]],
|
||||
zx_time_t deadline,
|
||||
zx_port_packet_t* packet);
|
||||
}];
|
||||
}
|
||||
|
||||
def ReleaseHandleDocs : Documentation {
|
||||
let Category = HandleDocs;
|
||||
let Content = [{
|
||||
If a function parameter is annotated with `release_handle` it is assumed to
|
||||
close the handle. It is also assumed to require an open handle to work with.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
zx_status_t zx_handle_close(zx_handle_t handle [[clang::release_handle]]);
|
||||
}];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -391,23 +391,23 @@ BUILTIN(__builtin_ctanhf, "XfXf", "Fne")
|
|||
BUILTIN(__builtin_ctanhl, "XLdXLd", "Fne")
|
||||
|
||||
// FP Comparisons.
|
||||
BUILTIN(__builtin_isgreater , "i.", "Fnc")
|
||||
BUILTIN(__builtin_isgreaterequal, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isless , "i.", "Fnc")
|
||||
BUILTIN(__builtin_islessequal , "i.", "Fnc")
|
||||
BUILTIN(__builtin_islessgreater , "i.", "Fnc")
|
||||
BUILTIN(__builtin_isunordered , "i.", "Fnc")
|
||||
BUILTIN(__builtin_isgreater , "i.", "Fnct")
|
||||
BUILTIN(__builtin_isgreaterequal, "i.", "Fnct")
|
||||
BUILTIN(__builtin_isless , "i.", "Fnct")
|
||||
BUILTIN(__builtin_islessequal , "i.", "Fnct")
|
||||
BUILTIN(__builtin_islessgreater , "i.", "Fnct")
|
||||
BUILTIN(__builtin_isunordered , "i.", "Fnct")
|
||||
|
||||
// Unary FP classification
|
||||
BUILTIN(__builtin_fpclassify, "iiiiii.", "Fnc")
|
||||
BUILTIN(__builtin_isfinite, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isinf, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isinf_sign, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isnan, "i.", "Fnc")
|
||||
BUILTIN(__builtin_isnormal, "i.", "Fnc")
|
||||
BUILTIN(__builtin_fpclassify, "iiiiii.", "Fnct")
|
||||
BUILTIN(__builtin_isfinite, "i.", "Fnct")
|
||||
BUILTIN(__builtin_isinf, "i.", "Fnct")
|
||||
BUILTIN(__builtin_isinf_sign, "i.", "Fnct")
|
||||
BUILTIN(__builtin_isnan, "i.", "Fnct")
|
||||
BUILTIN(__builtin_isnormal, "i.", "Fnct")
|
||||
|
||||
// FP signbit builtins
|
||||
BUILTIN(__builtin_signbit, "i.", "Fnc")
|
||||
BUILTIN(__builtin_signbit, "i.", "Fnct")
|
||||
BUILTIN(__builtin_signbitf, "if", "Fnc")
|
||||
BUILTIN(__builtin_signbitl, "iLd", "Fnc")
|
||||
|
||||
|
|
@ -718,6 +718,8 @@ ATOMIC_BUILTIN(__c11_atomic_fetch_sub, "v.", "t")
|
|||
ATOMIC_BUILTIN(__c11_atomic_fetch_and, "v.", "t")
|
||||
ATOMIC_BUILTIN(__c11_atomic_fetch_or, "v.", "t")
|
||||
ATOMIC_BUILTIN(__c11_atomic_fetch_xor, "v.", "t")
|
||||
ATOMIC_BUILTIN(__c11_atomic_fetch_max, "v.", "t")
|
||||
ATOMIC_BUILTIN(__c11_atomic_fetch_min, "v.", "t")
|
||||
BUILTIN(__c11_atomic_thread_fence, "vi", "n")
|
||||
BUILTIN(__c11_atomic_signal_fence, "vi", "n")
|
||||
BUILTIN(__c11_atomic_is_lock_free, "iz", "n")
|
||||
|
|
@ -742,6 +744,8 @@ ATOMIC_BUILTIN(__atomic_sub_fetch, "v.", "t")
|
|||
ATOMIC_BUILTIN(__atomic_and_fetch, "v.", "t")
|
||||
ATOMIC_BUILTIN(__atomic_or_fetch, "v.", "t")
|
||||
ATOMIC_BUILTIN(__atomic_xor_fetch, "v.", "t")
|
||||
ATOMIC_BUILTIN(__atomic_max_fetch, "v.", "t")
|
||||
ATOMIC_BUILTIN(__atomic_min_fetch, "v.", "t")
|
||||
ATOMIC_BUILTIN(__atomic_nand_fetch, "v.", "t")
|
||||
BUILTIN(__atomic_test_and_set, "bvD*i", "n")
|
||||
BUILTIN(__atomic_clear, "vvD*i", "n")
|
||||
|
|
@ -979,6 +983,8 @@ LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES)
|
|||
// when these functions are used in non-GNU mode. PR16138.
|
||||
LIBBUILTIN(alloca, "v*z", "f", "stdlib.h", ALL_GNU_LANGUAGES)
|
||||
// POSIX string.h
|
||||
LIBBUILTIN(memccpy, "v*v*vC*iz", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
LIBBUILTIN(mempcpy, "v*v*vC*z", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
LIBBUILTIN(strdup, "c*cC*", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
|
|
@ -1470,6 +1476,11 @@ BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
|
|||
BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
|
||||
BUILTIN(__builtin_preserve_access_index, "v.", "t")
|
||||
|
||||
// Alignment builtins (uses custom parsing to support pointers and integers)
|
||||
BUILTIN(__builtin_is_aligned, "bvC*z", "nct")
|
||||
BUILTIN(__builtin_align_up, "v*vC*z", "nct")
|
||||
BUILTIN(__builtin_align_down, "v*vC*z", "nct")
|
||||
|
||||
// Safestack builtins
|
||||
BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
|
||||
BUILTIN(__builtin___get_unsafe_stack_bottom, "v*", "Fn")
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@
|
|||
namespace clang {
|
||||
class TargetInfo;
|
||||
class IdentifierTable;
|
||||
class ASTContext;
|
||||
class QualType;
|
||||
class LangOptions;
|
||||
|
||||
enum LanguageID {
|
||||
|
|
@ -224,7 +222,7 @@ public:
|
|||
|
||||
/// Returns true if this is a libc/libm function without the '__builtin_'
|
||||
/// prefix.
|
||||
static bool isBuiltinFunc(const char *Name);
|
||||
static bool isBuiltinFunc(llvm::StringRef Name);
|
||||
|
||||
/// Returns true if this is a builtin that can be redeclared. Returns true
|
||||
/// for non-builtins.
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ BUILTIN(__builtin_arm_clrex, "v", "")
|
|||
// Bit manipulation
|
||||
BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
|
||||
BUILTIN(__builtin_arm_rbit64, "WUiWUi", "nc")
|
||||
BUILTIN(__builtin_arm_cls, "UiZUi", "nc")
|
||||
BUILTIN(__builtin_arm_cls64, "UiWUi", "nc")
|
||||
|
||||
// HINT
|
||||
BUILTIN(__builtin_arm_nop, "v", "")
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@ BUILTIN(__builtin_arm_smusdx, "iii", "nc")
|
|||
|
||||
// Bit manipulation
|
||||
BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
|
||||
BUILTIN(__builtin_arm_cls, "UiZUi", "nc")
|
||||
BUILTIN(__builtin_arm_cls64, "UiWUi", "nc")
|
||||
|
||||
// Store and load exclusive
|
||||
BUILTIN(__builtin_arm_ldrexd, "LLUiv*", "")
|
||||
|
|
@ -164,6 +166,12 @@ BUILTIN(__builtin_arm_crc32cw, "UiUiUi", "nc")
|
|||
BUILTIN(__builtin_arm_crc32d, "UiUiLLUi", "nc")
|
||||
BUILTIN(__builtin_arm_crc32cd, "UiUiLLUi", "nc")
|
||||
|
||||
// ARMv8-M Security Extensions a.k.a CMSE
|
||||
BUILTIN(__builtin_arm_cmse_TT, "Uiv*", "n")
|
||||
BUILTIN(__builtin_arm_cmse_TTT, "Uiv*", "n")
|
||||
BUILTIN(__builtin_arm_cmse_TTA, "Uiv*", "n")
|
||||
BUILTIN(__builtin_arm_cmse_TTAT, "Uiv*", "n")
|
||||
|
||||
// HINT
|
||||
BUILTIN(__builtin_arm_nop, "v", "")
|
||||
BUILTIN(__builtin_arm_yield, "v", "")
|
||||
|
|
@ -189,6 +197,11 @@ BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
|
|||
BUILTIN(__builtin_arm_wsr64, "vcC*LLUi", "nc")
|
||||
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
|
||||
|
||||
// Builtins for implementing ACLE MVE intrinsics. (Unlike NEON, these
|
||||
// don't need to live in a separate BuiltinsMVE.def, because they
|
||||
// aren't included from both here and BuiltinsAArch64.def.)
|
||||
#include "clang/Basic/arm_mve_builtins.inc"
|
||||
|
||||
// MSVC
|
||||
LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,9 @@ TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i8x16, "V16cV16cV16c", "nc", "simd1
|
|||
TARGET_BUILTIN(__builtin_wasm_sub_saturate_s_i16x8, "V8sV8sV8s", "nc", "simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i16x8, "V8sV8sV8s", "nc", "simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_avgr_u_i8x16, "V16cV16cV16c", "nc", "unimplemented-simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_avgr_u_i16x8, "V8sV8sV8s", "nc", "unimplemented-simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_bitselect, "V4iV4iV4iV4i", "nc", "simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_any_true_i8x16, "iV16c", "nc", "simd128")
|
||||
|
|
@ -117,6 +120,8 @@ TARGET_BUILTIN(__builtin_wasm_max_f32x4, "V4fV4fV4f", "nc", "simd128")
|
|||
TARGET_BUILTIN(__builtin_wasm_min_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_dot_s_i32x4_i16x8, "V4iV8sV8s", "nc", "simd128")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_sqrt_f32x4, "V4fV4f", "nc", "unimplemented-simd128")
|
||||
TARGET_BUILTIN(__builtin_wasm_sqrt_f64x2, "V2dV2d", "nc", "unimplemented-simd128")
|
||||
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "ncV:128:", "sse2")
|
|||
TARGET_BUILTIN(__builtin_ia32_pslldqi128_byteshift, "V2OiV2OiIi", "ncV:128:", "sse2")
|
||||
TARGET_BUILTIN(__builtin_ia32_psrldqi128_byteshift, "V2OiV2OiIi", "ncV:128:", "sse2")
|
||||
|
||||
TARGET_BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "n", "sse3")
|
||||
TARGET_BUILTIN(__builtin_ia32_monitor, "vvC*UiUi", "n", "sse3")
|
||||
TARGET_BUILTIN(__builtin_ia32_mwait, "vUiUi", "n", "sse3")
|
||||
TARGET_BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "nV:128:", "sse3")
|
||||
|
||||
|
|
@ -1396,8 +1396,8 @@ TARGET_BUILTIN(__builtin_ia32_psrlw512, "V32sV32sV8s", "ncV:512:", "avx512bw")
|
|||
TARGET_BUILTIN(__builtin_ia32_psrlwi512, "V32sV32si", "ncV:512:", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_pslldqi512_byteshift, "V8OiV8OiIi", "ncV:512:", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_psrldqi512_byteshift, "V8OiV8OiIi", "ncV:512:", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_movdqa32load128_mask, "V4iV4i*V4iUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_movdqa32load256_mask, "V8iV8i*V8iUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_movdqa32load128_mask, "V4iV4iC*V4iUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_movdqa32load256_mask, "V8iV8iC*V8iUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_movdqa32load512_mask, "V16iV16iC*V16iUs", "nV:512:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_movdqa32store512_mask, "vV16i*V16iUs", "nV:512:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_movdqa64load512_mask, "V8OiV8OiC*V8OiUc", "nV:512:", "avx512f")
|
||||
|
|
@ -1418,8 +1418,8 @@ TARGET_BUILTIN(__builtin_ia32_vcomisd, "iV2dV2dIiIi", "ncV:128:", "avx512f")
|
|||
TARGET_BUILTIN(__builtin_ia32_vcomiss, "iV4fV4fIiIi", "ncV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_kunpckdi, "UOiUOiUOi", "nc", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_kunpcksi, "UiUiUi", "nc", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquhi512_mask, "V32sV32s*V32sUi", "nV:512:", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquqi512_mask, "V64cV64c*V64cUOi", "nV:512:", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquhi512_mask, "V32sV32sC*V32sUi", "nV:512:", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquqi512_mask, "V64cV64cC*V64cUOi", "nV:512:", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_mask, "V8dV8dV8dV8OiIiUcIi", "ncV:512:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_maskz, "V8dV8dV8dV8OiIiUcIi", "ncV:512:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_fixupimmps512_mask, "V16fV16fV16fV16iIiUsIi", "ncV:512:", "avx512f")
|
||||
|
|
@ -1432,10 +1432,10 @@ TARGET_BUILTIN(__builtin_ia32_getexpsd128_round_mask, "V2dV2dV2dV2dUcIi", "ncV:1
|
|||
TARGET_BUILTIN(__builtin_ia32_getexpss128_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_getmantsd_round_mask, "V2dV2dV2dIiV2dUcIi", "ncV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_getmantss_round_mask, "V4fV4fV4fIiV4fUcIi", "ncV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquhi128_mask, "V8sV8s*V8sUc", "nV:128:", "avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquhi256_mask, "V16sV16s*V16sUs", "nV:256:", "avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquqi128_mask, "V16cV16c*V16cUs", "nV:128:", "avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquqi256_mask, "V32cV32c*V32cUi", "nV:256:", "avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquhi128_mask, "V8sV8sC*V8sUc", "nV:128:", "avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquhi256_mask, "V16sV16sC*V16sUs", "nV:256:", "avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquqi128_mask, "V16cV16cC*V16cUs", "nV:128:", "avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddquqi256_mask, "V32cV32cC*V32cUi", "nV:256:", "avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_mask, "V2dV2dV2dV2OiIiUc", "ncV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_maskz, "V2dV2dV2dV2OiIiUc", "ncV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_mask, "V4dV4dV4dV4OiIiUc", "ncV:256:", "avx512vl")
|
||||
|
|
@ -1444,20 +1444,20 @@ TARGET_BUILTIN(__builtin_ia32_fixupimmps128_mask, "V4fV4fV4fV4iIiUc", "ncV:128:"
|
|||
TARGET_BUILTIN(__builtin_ia32_fixupimmps128_maskz, "V4fV4fV4fV4iIiUc", "ncV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_fixupimmps256_mask, "V8fV8fV8fV8iIiUc", "ncV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_fixupimmps256_maskz, "V8fV8fV8fV8iIiUc", "ncV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadapd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadsd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadapd256_mask, "V4dV4d*V4dUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadaps128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadss128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadaps256_mask, "V8fV8f*V8fUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddqudi128_mask, "V2OiV2Oi*V2OiUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddqudi256_mask, "V4OiV4Oi*V4OiUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddqusi128_mask, "V4iV4i*V4iUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddqusi256_mask, "V8iV8i*V8iUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadupd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadupd256_mask, "V4dV4d*V4dUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadups128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadups256_mask, "V8fV8f*V8fUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadapd128_mask, "V2dV2dC*V2dUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadsd128_mask, "V2dV2dC*V2dUc", "nV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadapd256_mask, "V4dV4dC*V4dUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadaps128_mask, "V4fV4fC*V4fUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadss128_mask, "V4fV4fC*V4fUc", "nV:128:", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadaps256_mask, "V8fV8fC*V8fUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddqudi128_mask, "V2OiV2OiC*V2OiUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddqudi256_mask, "V4OiV4OiC*V4OiUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddqusi128_mask, "V4iV4iC*V4iUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loaddqusi256_mask, "V8iV8iC*V8iUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadupd128_mask, "V2dV2dC*V2dUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadupd256_mask, "V4dV4dC*V4dUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadups128_mask, "V4fV4fC*V4fUc", "nV:128:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_loadups256_mask, "V8fV8fC*V8fUc", "nV:256:", "avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_storedquhi512_mask, "vV32s*V32sUi", "nV:512:", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_storedquqi512_mask, "vV64c*V64cUOi", "nV:512:", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_storedquhi128_mask, "vV8s*V8sUc", "nV:128:", "avx512vl,avx512bw")
|
||||
|
|
@ -1872,11 +1872,11 @@ TARGET_BUILTIN(__builtin_ia32_selectss_128, "V4fUcV4fV4f", "ncV:128:", "avx512f"
|
|||
TARGET_BUILTIN(__builtin_ia32_selectsd_128, "V2dUcV2dV2d", "ncV:128:", "avx512f")
|
||||
|
||||
// MONITORX/MWAITX
|
||||
TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "n", "mwaitx")
|
||||
TARGET_BUILTIN(__builtin_ia32_monitorx, "vvC*UiUi", "n", "mwaitx")
|
||||
TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "n", "mwaitx")
|
||||
|
||||
// WAITPKG
|
||||
TARGET_BUILTIN(__builtin_ia32_umonitor, "vv*", "n", "waitpkg")
|
||||
TARGET_BUILTIN(__builtin_ia32_umonitor, "vvC*", "n", "waitpkg")
|
||||
TARGET_BUILTIN(__builtin_ia32_umwait, "UcUiUiUi", "n", "waitpkg")
|
||||
TARGET_BUILTIN(__builtin_ia32_tpause, "UcUiUiUi", "n", "waitpkg")
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) o
|
|||
CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink
|
||||
CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe.
|
||||
CODEGENOPT(Backchain , 1, 0) ///< -mbackchain
|
||||
CODEGENOPT(ControlFlowGuardNoChecks , 1, 0) ///< -cfguard-no-checks
|
||||
CODEGENOPT(ControlFlowGuard , 1, 0) ///< -cfguard
|
||||
CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files.
|
||||
CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files.
|
||||
|
|
@ -96,6 +97,8 @@ CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-protection is
|
|||
CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is
|
||||
///< enabled.
|
||||
CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabled.
|
||||
CODEGENOPT(ForceDwarfFrameSection , 1, 0) ///< Set when -fforce-dwarf-frame is
|
||||
///< enabled.
|
||||
|
||||
///< Set when -fxray-always-emit-customevents is enabled.
|
||||
CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0)
|
||||
|
|
@ -107,8 +110,13 @@ CODEGENOPT(XRayAlwaysEmitTypedEvents , 1, 0)
|
|||
///< XRay instrumentation.
|
||||
VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200)
|
||||
|
||||
VALUE_CODEGENOPT(PatchableFunctionEntryCount , 32, 0) ///< Number of NOPs at function entry
|
||||
|
||||
CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
|
||||
CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled.
|
||||
CODEGENOPT(MNopMCount , 1, 0) ///< Set when -mnop-mcount is enabled.
|
||||
CODEGENOPT(RecordMCount , 1, 0) ///< Set when -mrecord-mcount is enabled.
|
||||
CODEGENOPT(PackedStack , 1, 0) ///< Set when -mpacked-stack is enabled.
|
||||
CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to
|
||||
///< be generated.
|
||||
CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the
|
||||
|
|
@ -135,6 +143,8 @@ 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(NoInlineLineTables, 1, 0) ///< Whether debug info should contain
|
||||
///< inline line tables.
|
||||
CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled.
|
||||
CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf.
|
||||
CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero
|
||||
|
|
@ -323,6 +333,9 @@ ENUM_CODEGENOPT(VecLib, VectorLibrary, 2, NoLibrary)
|
|||
/// The default TLS model to use.
|
||||
ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel)
|
||||
|
||||
/// Bit size of immediate TLS offsets (0 == use the default).
|
||||
VALUE_CODEGENOPT(TLSSize, 8, 0)
|
||||
|
||||
/// Number of path components to strip when emitting checks. (0 == full
|
||||
/// filename)
|
||||
VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0)
|
||||
|
|
@ -364,8 +377,8 @@ CODEGENOPT(ForceEmitVTables, 1, 0)
|
|||
/// Whether to emit an address-significance table into the object file.
|
||||
CODEGENOPT(Addrsig, 1, 0)
|
||||
|
||||
ENUM_CODEGENOPT(SignReturnAddress, SignReturnAddressScope, 2, None)
|
||||
ENUM_CODEGENOPT(SignReturnAddressKey, SignReturnAddressKeyValue, 1, AKey)
|
||||
ENUM_CODEGENOPT(SignReturnAddress, SignReturnAddressScope, 2, SignReturnAddressScope::None)
|
||||
ENUM_CODEGENOPT(SignReturnAddressKey, SignReturnAddressKeyValue, 1, SignReturnAddressKeyValue::AKey)
|
||||
CODEGENOPT(BranchTargetEnforcement, 1, 0)
|
||||
|
||||
/// Whether to emit unused static constants.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "clang/Basic/DebugInfoOptions.h"
|
||||
#include "clang/Basic/Sanitizers.h"
|
||||
#include "clang/Basic/XRayInstr.h"
|
||||
#include "llvm/ADT/FloatingPointMode.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
|
|
@ -109,13 +110,13 @@ public:
|
|||
Embed_Marker // Embed a marker as a placeholder for bitcode.
|
||||
};
|
||||
|
||||
enum SignReturnAddressScope {
|
||||
enum class SignReturnAddressScope {
|
||||
None, // No signing for any function
|
||||
NonLeaf, // Sign the return address of functions that spill LR
|
||||
All // Sign the return address of all functions
|
||||
};
|
||||
|
||||
enum SignReturnAddressKeyValue { AKey, BKey };
|
||||
enum class SignReturnAddressKeyValue { AKey, BKey };
|
||||
|
||||
enum class FramePointerKind {
|
||||
None, // Omit all frame pointers.
|
||||
|
|
@ -163,7 +164,7 @@ public:
|
|||
std::string FloatABI;
|
||||
|
||||
/// The floating-point denormal mode to use.
|
||||
std::string FPDenormalMode;
|
||||
llvm::DenormalMode FPDenormalMode = llvm::DenormalMode::Invalid;
|
||||
|
||||
/// The float precision limit to use, if non-empty.
|
||||
std::string LimitFloatPrecision;
|
||||
|
|
@ -356,6 +357,11 @@ public:
|
|||
|
||||
/// Check if CSIR profile use is on.
|
||||
bool hasProfileCSIRUse() const { return getProfileUse() == ProfileCSIRInstr; }
|
||||
|
||||
/// Check if type and variable info should be emitted.
|
||||
bool hasReducedDebugInfo() const {
|
||||
return getDebugInfo() >= codegenoptions::DebugInfoConstructor;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
|||
|
|
@ -1,27 +1,27 @@
|
|||
class Comment<bit abstract = 0> {
|
||||
include "clang/Basic/ASTNode.td"
|
||||
|
||||
class CommentNode<CommentNode base, bit abstract = 0> : ASTNode {
|
||||
CommentNode Base = base;
|
||||
bit Abstract = abstract;
|
||||
}
|
||||
|
||||
class DComment<Comment base, bit abstract = 0> : Comment<abstract> {
|
||||
Comment Base = base;
|
||||
}
|
||||
def Comment : CommentNode<?, 1>;
|
||||
def InlineContentComment : CommentNode<Comment, 1>;
|
||||
def TextComment : CommentNode<InlineContentComment>;
|
||||
def InlineCommandComment : CommentNode<InlineContentComment>;
|
||||
def HTMLTagComment : CommentNode<InlineContentComment, 1>;
|
||||
def HTMLStartTagComment : CommentNode<HTMLTagComment>;
|
||||
def HTMLEndTagComment : CommentNode<HTMLTagComment>;
|
||||
|
||||
def InlineContentComment : Comment<1>;
|
||||
def TextComment : DComment<InlineContentComment>;
|
||||
def InlineCommandComment : DComment<InlineContentComment>;
|
||||
def HTMLTagComment : DComment<InlineContentComment, 1>;
|
||||
def HTMLStartTagComment : DComment<HTMLTagComment>;
|
||||
def HTMLEndTagComment : DComment<HTMLTagComment>;
|
||||
def BlockContentComment : CommentNode<Comment, 1>;
|
||||
def ParagraphComment : CommentNode<BlockContentComment>;
|
||||
def BlockCommandComment : CommentNode<BlockContentComment>;
|
||||
def ParamCommandComment : CommentNode<BlockCommandComment>;
|
||||
def TParamCommandComment : CommentNode<BlockCommandComment>;
|
||||
def VerbatimBlockComment : CommentNode<BlockCommandComment>;
|
||||
def VerbatimLineComment : CommentNode<BlockCommandComment>;
|
||||
|
||||
def BlockContentComment : Comment<1>;
|
||||
def ParagraphComment : DComment<BlockContentComment>;
|
||||
def BlockCommandComment : DComment<BlockContentComment>;
|
||||
def ParamCommandComment : DComment<BlockCommandComment>;
|
||||
def TParamCommandComment : DComment<BlockCommandComment>;
|
||||
def VerbatimBlockComment : DComment<BlockCommandComment>;
|
||||
def VerbatimLineComment : DComment<BlockCommandComment>;
|
||||
def VerbatimBlockLineComment : CommentNode<Comment>;
|
||||
|
||||
def VerbatimBlockLineComment : Comment;
|
||||
|
||||
def FullComment : Comment;
|
||||
def FullComment : CommentNode<Comment>;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,24 +18,35 @@ enum DebugInfoFormat {
|
|||
};
|
||||
|
||||
enum DebugInfoKind {
|
||||
NoDebugInfo, /// Don't generate debug info.
|
||||
LocTrackingOnly, /// Emit location information but do not generate
|
||||
/// debug info in the output. This is useful in
|
||||
/// cases where the backend wants to track source
|
||||
/// locations for instructions without actually
|
||||
/// emitting debug info for them (e.g., when -Rpass
|
||||
/// is used).
|
||||
DebugDirectivesOnly, /// Emit only debug directives with the line numbers data
|
||||
DebugLineTablesOnly, /// Emit only debug info necessary for generating
|
||||
/// line number tables (-gline-tables-only).
|
||||
LimitedDebugInfo, /// Limit generated debug info to reduce size
|
||||
/// (-fno-standalone-debug). This emits
|
||||
/// forward decls for types that could be
|
||||
/// replaced with forward decls in the source
|
||||
/// code. For dynamic C++ classes type info
|
||||
/// is only emitted into the module that
|
||||
/// contains the classe's vtable.
|
||||
FullDebugInfo /// Generate complete debug info.
|
||||
/// Don't generate debug info.
|
||||
NoDebugInfo,
|
||||
|
||||
/// Emit location information but do not generate debug info in the output.
|
||||
/// This is useful in cases where the backend wants to track source
|
||||
/// locations for instructions without actually emitting debug info for them
|
||||
/// (e.g., when -Rpass is used).
|
||||
LocTrackingOnly,
|
||||
|
||||
/// Emit only debug directives with the line numbers data
|
||||
DebugDirectivesOnly,
|
||||
|
||||
/// Emit only debug info necessary for generating line number tables
|
||||
/// (-gline-tables-only).
|
||||
DebugLineTablesOnly,
|
||||
|
||||
/// Limit generated debug info for classes to reduce size. This emits class
|
||||
/// type info only where the constructor is emitted, if it is a class that
|
||||
/// has a constructor.
|
||||
DebugInfoConstructor,
|
||||
|
||||
/// Limit generated debug info to reduce size (-fno-standalone-debug). This
|
||||
/// emits forward decls for types that could be replaced with forward decls in
|
||||
/// the source code. For dynamic C++ classes type info is only emitted into
|
||||
/// the module that contains the classe's vtable.
|
||||
LimitedDebugInfo,
|
||||
|
||||
/// Generate complete debug info.
|
||||
FullDebugInfo
|
||||
};
|
||||
|
||||
} // end namespace codegenoptions
|
||||
|
|
|
|||
|
|
@ -1,105 +1,104 @@
|
|||
class AttrSubject;
|
||||
include "clang/Basic/ASTNode.td"
|
||||
|
||||
class Decl<string diagSpelling = "", bit abstract = 0> : AttrSubject {
|
||||
class DeclNode<DeclNode base, string diagSpelling = "", bit abstract = 0>
|
||||
: ASTNode, AttrSubject {
|
||||
DeclNode Base = base;
|
||||
bit Abstract = abstract;
|
||||
string DiagSpelling = diagSpelling;
|
||||
}
|
||||
|
||||
class DDecl<Decl base, string diagSpelling = "", bit abstract = 0>
|
||||
: Decl<diagSpelling, abstract> {
|
||||
Decl Base = base;
|
||||
}
|
||||
|
||||
class DeclContext {}
|
||||
|
||||
def TranslationUnit : Decl, DeclContext;
|
||||
def PragmaComment : Decl;
|
||||
def PragmaDetectMismatch : Decl;
|
||||
def ExternCContext : Decl, DeclContext;
|
||||
def Named : Decl<"named declarations", 1>;
|
||||
def Namespace : DDecl<Named, "namespaces">, DeclContext;
|
||||
def UsingDirective : DDecl<Named>;
|
||||
def NamespaceAlias : DDecl<Named>;
|
||||
def Label : DDecl<Named, "labels">;
|
||||
def Type : DDecl<Named, "types", 1>;
|
||||
def TypedefName : DDecl<Type, "typedefs", 1>;
|
||||
def Typedef : DDecl<TypedefName>;
|
||||
def TypeAlias : DDecl<TypedefName>;
|
||||
def ObjCTypeParam : DDecl<TypedefName>;
|
||||
def UnresolvedUsingTypename : DDecl<Type>;
|
||||
def Tag : DDecl<Type, "tag types", 1>, DeclContext;
|
||||
def Enum : DDecl<Tag, "enums">;
|
||||
def Record : DDecl<Tag, "structs, unions, classes">;
|
||||
def CXXRecord : DDecl<Record, "classes">;
|
||||
def ClassTemplateSpecialization : DDecl<CXXRecord>;
|
||||
def Decl : DeclNode<?, "", 1>;
|
||||
def TranslationUnit : DeclNode<Decl>, DeclContext;
|
||||
def PragmaComment : DeclNode<Decl>;
|
||||
def PragmaDetectMismatch : DeclNode<Decl>;
|
||||
def ExternCContext : DeclNode<Decl>, DeclContext;
|
||||
def Named : DeclNode<Decl, "named declarations", 1>;
|
||||
def Namespace : DeclNode<Named, "namespaces">, DeclContext;
|
||||
def UsingDirective : DeclNode<Named>;
|
||||
def NamespaceAlias : DeclNode<Named>;
|
||||
def Label : DeclNode<Named, "labels">;
|
||||
def Type : DeclNode<Named, "types", 1>;
|
||||
def TypedefName : DeclNode<Type, "typedefs", 1>;
|
||||
def Typedef : DeclNode<TypedefName>;
|
||||
def TypeAlias : DeclNode<TypedefName>;
|
||||
def ObjCTypeParam : DeclNode<TypedefName>;
|
||||
def UnresolvedUsingTypename : DeclNode<Type>;
|
||||
def Tag : DeclNode<Type, "tag types", 1>, DeclContext;
|
||||
def Enum : DeclNode<Tag, "enums">;
|
||||
def Record : DeclNode<Tag, "structs, unions, classes">;
|
||||
def CXXRecord : DeclNode<Record, "classes">;
|
||||
def ClassTemplateSpecialization : DeclNode<CXXRecord>;
|
||||
def ClassTemplatePartialSpecialization
|
||||
: DDecl<ClassTemplateSpecialization>;
|
||||
def TemplateTypeParm : DDecl<Type>;
|
||||
def Value : DDecl<Named, "value declarations", 1>;
|
||||
def EnumConstant : DDecl<Value, "enumerators">;
|
||||
def UnresolvedUsingValue : DDecl<Value>;
|
||||
def IndirectField : DDecl<Value>;
|
||||
def Binding : DDecl<Value>;
|
||||
def OMPDeclareReduction : DDecl<Value>, DeclContext;
|
||||
def OMPDeclareMapper : DDecl<Value>, DeclContext;
|
||||
def Declarator : DDecl<Value, "declarators", 1>;
|
||||
def Field : DDecl<Declarator, "non-static data members">;
|
||||
def ObjCIvar : DDecl<Field>;
|
||||
def ObjCAtDefsField : DDecl<Field>;
|
||||
def MSProperty : DDecl<Declarator>;
|
||||
def Function : DDecl<Declarator, "functions">, DeclContext;
|
||||
def CXXDeductionGuide : DDecl<Function>;
|
||||
def CXXMethod : DDecl<Function>;
|
||||
def CXXConstructor : DDecl<CXXMethod>;
|
||||
def CXXDestructor : DDecl<CXXMethod>;
|
||||
def CXXConversion : DDecl<CXXMethod>;
|
||||
def Var : DDecl<Declarator, "variables">;
|
||||
def VarTemplateSpecialization : DDecl<Var>;
|
||||
: DeclNode<ClassTemplateSpecialization>;
|
||||
def TemplateTypeParm : DeclNode<Type>;
|
||||
def Value : DeclNode<Named, "value declarations", 1>;
|
||||
def EnumConstant : DeclNode<Value, "enumerators">;
|
||||
def UnresolvedUsingValue : DeclNode<Value>;
|
||||
def IndirectField : DeclNode<Value>;
|
||||
def Binding : DeclNode<Value>;
|
||||
def OMPDeclareReduction : DeclNode<Value>, DeclContext;
|
||||
def OMPDeclareMapper : DeclNode<Value>, DeclContext;
|
||||
def Declarator : DeclNode<Value, "declarators", 1>;
|
||||
def Field : DeclNode<Declarator, "non-static data members">;
|
||||
def ObjCIvar : DeclNode<Field>;
|
||||
def ObjCAtDefsField : DeclNode<Field>;
|
||||
def MSProperty : DeclNode<Declarator>;
|
||||
def Function : DeclNode<Declarator, "functions">, DeclContext;
|
||||
def CXXDeductionGuide : DeclNode<Function>;
|
||||
def CXXMethod : DeclNode<Function>;
|
||||
def CXXConstructor : DeclNode<CXXMethod>;
|
||||
def CXXDestructor : DeclNode<CXXMethod>;
|
||||
def CXXConversion : DeclNode<CXXMethod>;
|
||||
def Var : DeclNode<Declarator, "variables">;
|
||||
def VarTemplateSpecialization : DeclNode<Var>;
|
||||
def VarTemplatePartialSpecialization
|
||||
: DDecl<VarTemplateSpecialization>;
|
||||
def ImplicitParam : DDecl<Var>;
|
||||
def ParmVar : DDecl<Var, "parameters">;
|
||||
def Decomposition : DDecl<Var>;
|
||||
def OMPCapturedExpr : DDecl<Var>;
|
||||
def NonTypeTemplateParm : DDecl<Declarator>;
|
||||
def Template : DDecl<Named, "templates", 1>;
|
||||
def RedeclarableTemplate : DDecl<Template, "redeclarable templates", 1>;
|
||||
def FunctionTemplate : DDecl<RedeclarableTemplate>;
|
||||
def ClassTemplate : DDecl<RedeclarableTemplate>;
|
||||
def VarTemplate : DDecl<RedeclarableTemplate>;
|
||||
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
|
||||
def TemplateTemplateParm : DDecl<Template>;
|
||||
def BuiltinTemplate : DDecl<Template>;
|
||||
def Concept : DDecl<Template>;
|
||||
def Using : DDecl<Named>;
|
||||
def UsingPack : DDecl<Named>;
|
||||
def UsingShadow : DDecl<Named>;
|
||||
def ConstructorUsingShadow : DDecl<UsingShadow>;
|
||||
def ObjCMethod : DDecl<Named, "Objective-C methods">, DeclContext;
|
||||
def ObjCContainer : DDecl<Named, "Objective-C containers", 1>, DeclContext;
|
||||
def ObjCCategory : DDecl<ObjCContainer>;
|
||||
def ObjCProtocol : DDecl<ObjCContainer, "Objective-C protocols">;
|
||||
def ObjCInterface : DDecl<ObjCContainer, "Objective-C interfaces">;
|
||||
: DeclNode<VarTemplateSpecialization>;
|
||||
def ImplicitParam : DeclNode<Var>;
|
||||
def ParmVar : DeclNode<Var, "parameters">;
|
||||
def Decomposition : DeclNode<Var>;
|
||||
def OMPCapturedExpr : DeclNode<Var>;
|
||||
def NonTypeTemplateParm : DeclNode<Declarator>;
|
||||
def Template : DeclNode<Named, "templates", 1>;
|
||||
def RedeclarableTemplate : DeclNode<Template, "redeclarable templates", 1>;
|
||||
def FunctionTemplate : DeclNode<RedeclarableTemplate>;
|
||||
def ClassTemplate : DeclNode<RedeclarableTemplate>;
|
||||
def VarTemplate : DeclNode<RedeclarableTemplate>;
|
||||
def TypeAliasTemplate : DeclNode<RedeclarableTemplate>;
|
||||
def TemplateTemplateParm : DeclNode<Template>;
|
||||
def BuiltinTemplate : DeclNode<Template>;
|
||||
def Concept : DeclNode<Template>;
|
||||
def Using : DeclNode<Named>;
|
||||
def UsingPack : DeclNode<Named>;
|
||||
def UsingShadow : DeclNode<Named>;
|
||||
def ConstructorUsingShadow : DeclNode<UsingShadow>;
|
||||
def ObjCMethod : DeclNode<Named, "Objective-C methods">, DeclContext;
|
||||
def ObjCContainer : DeclNode<Named, "Objective-C containers", 1>, DeclContext;
|
||||
def ObjCCategory : DeclNode<ObjCContainer>;
|
||||
def ObjCProtocol : DeclNode<ObjCContainer, "Objective-C protocols">;
|
||||
def ObjCInterface : DeclNode<ObjCContainer, "Objective-C interfaces">;
|
||||
def ObjCImpl
|
||||
: DDecl<ObjCContainer, "Objective-C implementation declarations", 1>;
|
||||
def ObjCCategoryImpl : DDecl<ObjCImpl>;
|
||||
def ObjCImplementation : DDecl<ObjCImpl>;
|
||||
def ObjCProperty : DDecl<Named, "Objective-C properties">;
|
||||
def ObjCCompatibleAlias : DDecl<Named>;
|
||||
def LinkageSpec : Decl, DeclContext;
|
||||
def Export : Decl, DeclContext;
|
||||
def ObjCPropertyImpl : Decl;
|
||||
def FileScopeAsm : Decl;
|
||||
def AccessSpec : Decl;
|
||||
def Friend : Decl;
|
||||
def FriendTemplate : Decl;
|
||||
def StaticAssert : Decl;
|
||||
def Block : Decl<"blocks">, DeclContext;
|
||||
def Captured : Decl, DeclContext;
|
||||
def ClassScopeFunctionSpecialization : Decl;
|
||||
def Import : Decl;
|
||||
def OMPThreadPrivate : Decl;
|
||||
def OMPAllocate : Decl;
|
||||
def OMPRequires : Decl;
|
||||
def Empty : Decl;
|
||||
: DeclNode<ObjCContainer, "Objective-C implementation declarations", 1>;
|
||||
def ObjCCategoryImpl : DeclNode<ObjCImpl>;
|
||||
def ObjCImplementation : DeclNode<ObjCImpl>;
|
||||
def ObjCProperty : DeclNode<Named, "Objective-C properties">;
|
||||
def ObjCCompatibleAlias : DeclNode<Named>;
|
||||
def LinkageSpec : DeclNode<Decl>, DeclContext;
|
||||
def Export : DeclNode<Decl>, DeclContext;
|
||||
def ObjCPropertyImpl : DeclNode<Decl>;
|
||||
def FileScopeAsm : DeclNode<Decl>;
|
||||
def AccessSpec : DeclNode<Decl>;
|
||||
def Friend : DeclNode<Decl>;
|
||||
def FriendTemplate : DeclNode<Decl>;
|
||||
def StaticAssert : DeclNode<Decl>;
|
||||
def Block : DeclNode<Decl, "blocks">, DeclContext;
|
||||
def Captured : DeclNode<Decl>, DeclContext;
|
||||
def ClassScopeFunctionSpecialization : DeclNode<Decl>;
|
||||
def Import : DeclNode<Decl>;
|
||||
def OMPThreadPrivate : DeclNode<Decl>;
|
||||
def OMPAllocate : DeclNode<Decl>;
|
||||
def OMPRequires : DeclNode<Decl>;
|
||||
def Empty : DeclNode<Decl>;
|
||||
def LifetimeExtendedTemporary : DeclNode<Decl>;
|
||||
|
||||
|
|
|
|||
|
|
@ -177,6 +177,9 @@ public:
|
|||
/// IdentifierInfo
|
||||
ak_identifierinfo,
|
||||
|
||||
/// address space
|
||||
ak_addrspace,
|
||||
|
||||
/// Qualifiers
|
||||
ak_qual,
|
||||
|
||||
|
|
@ -473,6 +476,9 @@ private:
|
|||
/// Second string argument for the delayed diagnostic.
|
||||
std::string DelayedDiagArg2;
|
||||
|
||||
/// Third string argument for the delayed diagnostic.
|
||||
std::string DelayedDiagArg3;
|
||||
|
||||
/// Optional flag value.
|
||||
///
|
||||
/// Some flags accept values, for instance: -Wframe-larger-than=<value> and
|
||||
|
|
@ -874,8 +880,12 @@ public:
|
|||
/// \param Arg2 A string argument that will be provided to the
|
||||
/// diagnostic. A copy of this string will be stored in the
|
||||
/// DiagnosticsEngine object itself.
|
||||
///
|
||||
/// \param Arg3 A string argument that will be provided to the
|
||||
/// diagnostic. A copy of this string will be stored in the
|
||||
/// DiagnosticsEngine object itself.
|
||||
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
|
||||
StringRef Arg2 = "");
|
||||
StringRef Arg2 = "", StringRef Arg3 = "");
|
||||
|
||||
/// Clear out the current diagnostic.
|
||||
void Clear() { CurDiagID = std::numeric_limits<unsigned>::max(); }
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ def note_constexpr_pointer_subtraction_not_same_array : Note<
|
|||
"subtracted pointers are not elements of the same array">;
|
||||
def note_constexpr_pointer_subtraction_zero_size : Note<
|
||||
"subtraction of pointers to type %0 of zero size">;
|
||||
def note_constexpr_pointer_comparison_unspecified : Note<
|
||||
"comparison has unspecified value">;
|
||||
def note_constexpr_pointer_comparison_base_classes : Note<
|
||||
"comparison of addresses of subobjects of different base classes "
|
||||
"has unspecified value">;
|
||||
|
|
@ -216,6 +218,14 @@ 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_invalid_alignment : Note<
|
||||
"requested alignment %0 is not a positive power of two">;
|
||||
def note_constexpr_alignment_too_big : Note<
|
||||
"requested alignment must be %0 or less for type %1; %2 is invalid">;
|
||||
def note_constexpr_alignment_compute : Note<
|
||||
"cannot constant evaluate whether run-time alignment is at least %0">;
|
||||
def note_constexpr_alignment_adjust : Note<
|
||||
"cannot constant evaluate the result of adjusting alignment to %0">;
|
||||
def note_constexpr_destroy_out_of_lifetime : Note<
|
||||
"destroying object '%0' whose lifetime has already ended">;
|
||||
def note_constexpr_unsupported_destruction : Note<
|
||||
|
|
@ -329,6 +339,10 @@ def warn_integer_constant_overflow : Warning<
|
|||
def note_unimplemented_constexpr_lambda_feature_ast : Note<
|
||||
"unimplemented constexpr lambda feature: %0 (coming soon!)">;
|
||||
|
||||
def warn_is_constant_evaluated_always_true_constexpr : Warning<
|
||||
"'%0' will always evaluate to 'true' in a manifestly constant-evaluated expression">,
|
||||
InGroup<DiagGroup<"constant-evaluated">>;
|
||||
|
||||
// inline asm related.
|
||||
let CategoryName = "Inline Assembly Issue" in {
|
||||
def err_asm_invalid_escape : Error<
|
||||
|
|
|
|||
|
|
@ -146,8 +146,8 @@ def warn_doc_returns_attached_to_a_void_function : Warning<
|
|||
// \deprecated command
|
||||
|
||||
def warn_doc_deprecated_not_sync : Warning<
|
||||
"declaration is marked with '\\deprecated' command but does not have "
|
||||
"a deprecation attribute">,
|
||||
"declaration is marked with '%select{\\|@}0deprecated' command but does "
|
||||
"not have a deprecation attribute">,
|
||||
InGroup<DocumentationDeprecatedSync>, DefaultIgnore;
|
||||
|
||||
def note_add_deprecation_attr : Note<
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ def warn_cxx98_compat_variadic_templates :
|
|||
Warning<"variadic templates are incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
def err_default_special_members : Error<
|
||||
"only special member functions may be defaulted">;
|
||||
"only special member functions %select{|and comparison operators }0"
|
||||
"may be defaulted">;
|
||||
def err_deleted_non_function : Error<
|
||||
"only functions can have deleted definitions">;
|
||||
def err_module_not_found : Error<"module '%0' not found">, DefaultFatal;
|
||||
|
|
@ -270,6 +271,8 @@ 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">;
|
||||
|
||||
|
|
@ -304,6 +307,11 @@ def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to b
|
|||
def err_openclcxx_not_supported : Error<
|
||||
"'%0' is not supported in C++ for OpenCL">;
|
||||
|
||||
// HIP
|
||||
def warn_ignored_hip_only_option : Warning<
|
||||
"'%0' is ignored since it is only supported for HIP">,
|
||||
InGroup<HIPOnly>;
|
||||
|
||||
// OpenMP
|
||||
def err_omp_more_one_clause : Error<
|
||||
"directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">;
|
||||
|
|
|
|||
|
|
@ -143,8 +143,8 @@ def err_drv_missing_arg_mtp : Error<
|
|||
"missing argument to '%0'">;
|
||||
def err_drv_invalid_libcxx_deployment : Error<
|
||||
"invalid deployment target for -stdlib=libc++ (requires %0 or later)">;
|
||||
def err_drv_invalid_argument_to_fdebug_prefix_map : Error<
|
||||
"invalid argument '%0' to -fdebug-prefix-map">;
|
||||
def err_drv_invalid_argument_to_option : Error<
|
||||
"invalid argument '%0' to -%1">;
|
||||
def err_drv_malformed_sanitizer_blacklist : Error<
|
||||
"malformed sanitizer blacklist: '%0'">;
|
||||
def err_drv_duplicate_config : Error<
|
||||
|
|
@ -250,6 +250,9 @@ def err_drv_unsupported_embed_bitcode
|
|||
def err_drv_bitcode_unsupported_on_toolchain : Error<
|
||||
"-fembed-bitcode is not supported on versions of iOS prior to 6.0">;
|
||||
|
||||
def err_drv_invalid_malign_branch_EQ : Error<
|
||||
"invalid argument '%0' to -malign-branch=; each element must be one of: %1">;
|
||||
|
||||
def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
|
||||
def warn_drv_optimization_value : Warning<"optimization level '%0' is not supported; using '%1%2' instead">,
|
||||
InGroup<InvalidCommandLineArgument>;
|
||||
|
|
@ -404,6 +407,8 @@ def err_drv_unsupported_indirect_jump_opt : Error<
|
|||
"'-mindirect-jump=%0' is unsupported with the '%1' architecture">;
|
||||
def err_drv_unknown_indirect_jump_opt : Error<
|
||||
"unknown '-mindirect-jump=' option '%0'">;
|
||||
def err_drv_unsupported_fpatchable_function_entry_argument : Error<
|
||||
"the second argument of '-fpatchable-function-entry' must be 0 or omitted">;
|
||||
|
||||
def warn_drv_unable_to_find_directory_expected : Warning<
|
||||
"unable to find %0 directory, expected to be in '%1'">,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,27 @@ def UndefinedBoolConversion : DiagGroup<"undefined-bool-conversion">;
|
|||
def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
|
||||
UndefinedBoolConversion]>;
|
||||
def IntConversion : DiagGroup<"int-conversion">;
|
||||
def EnumConversion : DiagGroup<"enum-conversion">;
|
||||
def DeprecatedEnumCompareConditional :
|
||||
DiagGroup<"deprecated-enum-compare-conditional">;
|
||||
def EnumCompareConditional : DiagGroup<"enum-compare-conditional",
|
||||
[DeprecatedEnumCompareConditional]>;
|
||||
def EnumCompareSwitch : DiagGroup<"enum-compare-switch">;
|
||||
def DeprecatedEnumCompare : DiagGroup<"deprecated-enum-compare">;
|
||||
def EnumCompare : DiagGroup<"enum-compare", [EnumCompareSwitch,
|
||||
DeprecatedEnumCompare]>;
|
||||
def DeprecatedAnonEnumEnumConversion : DiagGroup<"deprecated-anon-enum-enum-conversion">;
|
||||
def DeprecatedEnumEnumConversion : DiagGroup<"deprecated-enum-enum-conversion">;
|
||||
def DeprecatedEnumFloatConversion : DiagGroup<"deprecated-enum-float-conversion">;
|
||||
def AnonEnumEnumConversion : DiagGroup<"anon-enum-enum-conversion",
|
||||
[DeprecatedAnonEnumEnumConversion]>;
|
||||
def EnumEnumConversion : DiagGroup<"enum-enum-conversion",
|
||||
[DeprecatedEnumEnumConversion]>;
|
||||
def EnumFloatConversion : DiagGroup<"enum-float-conversion",
|
||||
[DeprecatedEnumFloatConversion]>;
|
||||
def EnumConversion : DiagGroup<"enum-conversion",
|
||||
[EnumEnumConversion,
|
||||
EnumFloatConversion,
|
||||
EnumCompareConditional]>;
|
||||
def ObjCSignedCharBoolImplicitIntConversion :
|
||||
DiagGroup<"objc-signed-char-bool-implicit-int-conversion">;
|
||||
def ImplicitIntConversion : DiagGroup<"implicit-int-conversion",
|
||||
|
|
@ -113,6 +133,7 @@ def UndefinedVarTemplate : DiagGroup<"undefined-var-template">;
|
|||
def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">;
|
||||
def MissingNoEscape : DiagGroup<"missing-noescape">;
|
||||
|
||||
def DefaultedFunctionDeleted : DiagGroup<"defaulted-function-deleted">;
|
||||
def DeleteIncomplete : DiagGroup<"delete-incomplete">;
|
||||
def DeleteNonAbstractNonVirtualDtor : DiagGroup<"delete-non-abstract-non-virtual-dtor">;
|
||||
def DeleteAbstractNonVirtualDtor : DiagGroup<"delete-abstract-non-virtual-dtor">;
|
||||
|
|
@ -125,8 +146,11 @@ def FinalDtorNonFinalClass : DiagGroup<"final-dtor-non-final-class">;
|
|||
def CXX11CompatDeprecatedWritableStr :
|
||||
DiagGroup<"c++11-compat-deprecated-writable-strings">;
|
||||
|
||||
def DeprecatedArrayCompare : DiagGroup<"deprecated-array-compare">;
|
||||
def DeprecatedAttributes : DiagGroup<"deprecated-attributes">;
|
||||
def DeprecatedCommaSubscript : DiagGroup<"deprecated-comma-subscript">;
|
||||
def DeprecatedCopy : DiagGroup<"deprecated-copy">;
|
||||
def DeprecatedCopyDtor : DiagGroup<"deprecated-copy-dtor">;
|
||||
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
|
||||
def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
|
||||
def UnguardedAvailabilityNew : DiagGroup<"unguarded-availability-new">;
|
||||
|
|
@ -144,10 +168,18 @@ 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,
|
||||
def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion,
|
||||
DeprecatedArrayCompare,
|
||||
DeprecatedAttributes,
|
||||
DeprecatedCommaSubscript,
|
||||
DeprecatedCopy,
|
||||
DeprecatedCopyDtor,
|
||||
DeprecatedDeclarations,
|
||||
DeprecatedDynamicExceptionSpec,
|
||||
DeprecatedEnumCompare,
|
||||
DeprecatedEnumCompareConditional,
|
||||
DeprecatedEnumEnumConversion,
|
||||
DeprecatedEnumFloatConversion,
|
||||
DeprecatedIncrementBool,
|
||||
DeprecatedRegister,
|
||||
DeprecatedThisCapture,
|
||||
|
|
@ -568,9 +600,6 @@ 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 :
|
||||
DiagGroup<"implicit-fallthrough-per-function">;
|
||||
def ImplicitFallthrough : DiagGroup<"implicit-fallthrough",
|
||||
|
|
@ -688,6 +717,7 @@ def ZeroLengthArray : DiagGroup<"zero-length-array">;
|
|||
def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">;
|
||||
def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">;
|
||||
def Fallback : DiagGroup<"fallback">;
|
||||
def MisleadingIndentation : DiagGroup<"misleading-indentation">;
|
||||
|
||||
// This covers both the deprecated case (in C++98)
|
||||
// and the extension case (in C++11 onwards).
|
||||
|
|
@ -811,6 +841,7 @@ def Move : DiagGroup<"move", [
|
|||
]>;
|
||||
|
||||
def Extra : DiagGroup<"extra", [
|
||||
DeprecatedCopy,
|
||||
MissingFieldInitializers,
|
||||
IgnoredQualifiers,
|
||||
InitializerOverrides,
|
||||
|
|
@ -826,11 +857,11 @@ def Most : DiagGroup<"most", [
|
|||
CharSubscript,
|
||||
Comment,
|
||||
DeleteNonVirtualDtor,
|
||||
ForLoopAnalysis,
|
||||
Format,
|
||||
Implicit,
|
||||
InfiniteRecursion,
|
||||
IntInBoolContext,
|
||||
LoopAnalysis,
|
||||
MismatchedTags,
|
||||
MissingBraces,
|
||||
Move,
|
||||
|
|
@ -842,6 +873,7 @@ def Most : DiagGroup<"most", [
|
|||
SizeofArrayArgument,
|
||||
SizeofArrayDecay,
|
||||
StringPlusInt,
|
||||
TautologicalCompare,
|
||||
Trigraphs,
|
||||
Uninitialized,
|
||||
UnknownPragmas,
|
||||
|
|
@ -877,7 +909,7 @@ def Consumed : DiagGroup<"consumed">;
|
|||
// Note that putting warnings in -Wall will not disable them by default. If a
|
||||
// warning should be active _only_ when -Wall is passed in, mark it as
|
||||
// DefaultIgnore in addition to putting it here.
|
||||
def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>;
|
||||
def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool, MisleadingIndentation]>;
|
||||
|
||||
// Warnings that should be in clang-cl /w4.
|
||||
def : DiagGroup<"CL4", [All, Extra]>;
|
||||
|
|
@ -1049,7 +1081,11 @@ def ASM : DiagGroup<"asm", [
|
|||
def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">;
|
||||
def OpenMPClauses : DiagGroup<"openmp-clauses">;
|
||||
def OpenMPLoopForm : DiagGroup<"openmp-loop-form">;
|
||||
def OpenMPTarget : DiagGroup<"openmp-target">;
|
||||
def OpenMPMapping : DiagGroup<"openmp-mapping">;
|
||||
def OpenMPTarget : DiagGroup<"openmp-target", [OpenMPMapping]>;
|
||||
def OpenMP : DiagGroup<"openmp", [
|
||||
SourceUsesOpenMP, OpenMPClauses, OpenMPLoopForm, OpenMPTarget, OpenMPMapping
|
||||
]>;
|
||||
|
||||
// Backend warnings.
|
||||
def BackendInlineAsm : DiagGroup<"inline-asm">;
|
||||
|
|
@ -1077,6 +1113,10 @@ def SerializedDiagnostics : DiagGroup<"serialized-diagnostics">;
|
|||
// compiling CUDA C/C++ but which is not compatible with the CUDA spec.
|
||||
def CudaCompat : DiagGroup<"cuda-compat">;
|
||||
|
||||
// A warning group for warnings about features supported by HIP but
|
||||
// ignored by CUDA.
|
||||
def HIPOnly : DiagGroup<"hip-only">;
|
||||
|
||||
// Warnings which cause linking of the runtime libraries like
|
||||
// libc and the CRT to be skipped.
|
||||
def AVRRtlibLinkingQuirks : DiagGroup<"avr-rtlib-linking-quirks">;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,13 @@ def warn_null_statement : Warning<
|
|||
"remove unnecessary ';' to silence this warning">,
|
||||
InGroup<ExtraSemiStmt>, DefaultIgnore;
|
||||
|
||||
def warn_misleading_indentation : Warning<
|
||||
"misleading indentation; statement is not part of "
|
||||
"the previous '%select{if|else|for|while}0'">,
|
||||
InGroup<MisleadingIndentation>, DefaultIgnore;
|
||||
def note_previous_statement : Note<
|
||||
"previous statement is here">;
|
||||
|
||||
def ext_thread_before : Extension<"'__thread' before '%0'">;
|
||||
def ext_keyword_as_ident : ExtWarn<
|
||||
"keyword '%0' will be made available as an identifier "
|
||||
|
|
@ -174,6 +181,13 @@ def err_function_declared_typedef : Error<
|
|||
def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
|
||||
def err_at_in_class : Error<"unexpected '@' in member specification">;
|
||||
def err_unexpected_semi : Error<"unexpected ';' before %0">;
|
||||
def err_unparenthesized_non_primary_expr_in_requires_clause : Error<
|
||||
"parentheses are required around this expression in a requires clause">;
|
||||
def note_unparenthesized_non_primary_expr_in_requires_clause : Note<
|
||||
"parentheses are required around this expression in a requires clause">;
|
||||
def err_potential_function_call_in_constraint_logical_or : Error<
|
||||
"function call must be parenthesized to be considered part of the requires "
|
||||
"clause">;
|
||||
|
||||
def err_expected_fn_body : Error<
|
||||
"expected function body after function declarator">;
|
||||
|
|
@ -258,7 +272,7 @@ def err_label_end_of_compound_statement : Error<
|
|||
def err_address_of_label_outside_fn : Error<
|
||||
"use of address-of-label extension outside of a function body">;
|
||||
def err_asm_operand_wide_string_literal : Error<
|
||||
"cannot use %select{unicode|wide}0 string literal in 'asm'">;
|
||||
"cannot use %select{unicode|wide|an empty}0 string literal in 'asm'">;
|
||||
def err_expected_selector_for_method : Error<
|
||||
"expected selector for Objective-C method">;
|
||||
def err_expected_property_name : Error<"expected property name">;
|
||||
|
|
@ -302,6 +316,12 @@ def err_init_list_bin_op : Error<"initializer list cannot be used on the "
|
|||
def warn_cxx98_compat_trailing_return_type : Warning<
|
||||
"trailing return types are incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
def err_requires_clause_must_appear_after_trailing_return : Error<
|
||||
"trailing return type must appear before trailing requires clause">;
|
||||
def err_requires_clause_on_declarator_not_declaring_a_function : Error<
|
||||
"trailing requires clause can only be used when declaring a function">;
|
||||
def err_requires_clause_inside_parens : Error<
|
||||
"trailing requires clause should be placed outside parentheses">;
|
||||
def ext_auto_storage_class : ExtWarn<
|
||||
"'auto' storage class specifier is not permitted in C++11, and will not "
|
||||
"be supported in future releases">, InGroup<DiagGroup<"auto-storage-class">>;
|
||||
|
|
@ -325,6 +345,8 @@ def err_for_range_expected_decl : Error<
|
|||
def err_argument_required_after_attribute : Error<
|
||||
"argument required after attribute">;
|
||||
def err_missing_param : Error<"expected parameter declarator">;
|
||||
def err_function_scope_depth_exceeded : Error<
|
||||
"function scope depth exceeded maximum of %0">, DefaultFatal;
|
||||
def err_missing_comma_before_ellipsis : Error<
|
||||
"C requires a comma prior to the ellipsis in a variadic function type">;
|
||||
def err_unexpected_typedef_ident : Error<
|
||||
|
|
@ -871,7 +893,7 @@ def warn_cxx98_compat_lambda : Warning<
|
|||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
def err_lambda_missing_parens : Error<
|
||||
"lambda requires '()' before %select{'mutable'|return type|"
|
||||
"attribute specifier|'constexpr'|'consteval'}0">;
|
||||
"attribute specifier|'constexpr'|'consteval'|'requires' clause}0">;
|
||||
def err_lambda_decl_specifier_repeated : Error<
|
||||
"%select{'mutable'|'constexpr'|'consteval'}0 cannot appear multiple times in a lambda declarator">;
|
||||
def err_lambda_capture_misplaced_ellipsis : Error<
|
||||
|
|
@ -1223,6 +1245,9 @@ def note_omp_declare_variant_ctx_used_here : Note<
|
|||
def warn_omp_more_one_device_type_clause : Warning<
|
||||
"more than one 'device_type' clause is specified">,
|
||||
InGroup<OpenMPClauses>;
|
||||
def err_omp_wrong_device_kind_trait : Error<
|
||||
"unknown '%0' device kind trait in the 'device' context selector set, expected"
|
||||
" one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'">;
|
||||
|
||||
// Pragma loop support.
|
||||
def err_pragma_loop_missing_argument : Error<
|
||||
|
|
|
|||
|
|
@ -551,9 +551,13 @@ def err_access_decl : Error<
|
|||
"use using declarations instead">;
|
||||
def warn_deprecated_copy_operation : Warning<
|
||||
"definition of implicit copy %select{constructor|assignment operator}1 "
|
||||
"for %0 is deprecated because it has a user-declared "
|
||||
"%select{copy %select{assignment operator|constructor}1|destructor}2">,
|
||||
InGroup<Deprecated>, DefaultIgnore;
|
||||
"for %0 is deprecated because it has a user-declared copy "
|
||||
"%select{assignment operator|constructor}1">,
|
||||
InGroup<DeprecatedCopy>, DefaultIgnore;
|
||||
def warn_deprecated_copy_dtor_operation : Warning<
|
||||
"definition of implicit copy %select{constructor|assignment operator}1 "
|
||||
"for %0 is deprecated because it has a user-declared destructor">,
|
||||
InGroup<DeprecatedCopyDtor>, DefaultIgnore;
|
||||
def warn_cxx17_compat_exception_spec_in_signature : Warning<
|
||||
"mangled name of %0 will change in C++17 due to non-throwing exception "
|
||||
"specification in function signature">, InGroup<CXX17CompatMangling>;
|
||||
|
|
@ -575,21 +579,22 @@ def err_thread_non_global : Error<
|
|||
def err_thread_unsupported : Error<
|
||||
"thread-local storage is not supported for the current target">;
|
||||
|
||||
// FIXME: Combine fallout warnings to just one warning.
|
||||
def warn_maybe_falloff_nonvoid_function : Warning<
|
||||
"control may reach end of non-void function">,
|
||||
"non-void function does not return a value in all control paths">,
|
||||
InGroup<ReturnType>;
|
||||
def warn_falloff_nonvoid_function : Warning<
|
||||
"control reaches end of non-void function">,
|
||||
"non-void function does not return a value">,
|
||||
InGroup<ReturnType>;
|
||||
def err_maybe_falloff_nonvoid_block : Error<
|
||||
"control may reach end of non-void block">;
|
||||
"non-void block does not return a value in all control paths">;
|
||||
def err_falloff_nonvoid_block : Error<
|
||||
"control reaches end of non-void block">;
|
||||
"non-void block does not return a value">;
|
||||
def warn_maybe_falloff_nonvoid_coroutine : Warning<
|
||||
"control may reach end of coroutine; which is undefined behavior because the promise type %0 does not declare 'return_void()'">,
|
||||
"non-void coroutine does not return a value in all control paths">,
|
||||
InGroup<ReturnType>;
|
||||
def warn_falloff_nonvoid_coroutine : Warning<
|
||||
"control reaches end of coroutine; which is undefined behavior because the promise type %0 does not declare 'return_void()'">,
|
||||
"non-void coroutine does not return a value">,
|
||||
InGroup<ReturnType>;
|
||||
def warn_suggest_noreturn_function : Warning<
|
||||
"%select{function|method}0 %1 could be declared with attribute 'noreturn'">,
|
||||
|
|
@ -987,6 +992,28 @@ def warn_objc_boxing_invalid_utf8_string : Warning<
|
|||
"string is ill-formed as UTF-8 and will become a null %0 when boxed">,
|
||||
InGroup<ObjCBoxing>;
|
||||
|
||||
def err_objc_direct_on_protocol : Error<
|
||||
"'objc_direct' attribute cannot be applied to %select{methods|properties}0 "
|
||||
"declared in an Objective-C protocol">;
|
||||
def err_objc_direct_duplicate_decl : Error<
|
||||
"%select{|direct }0method declaration conflicts "
|
||||
"with previous %select{|direct }1declaration of method %2">;
|
||||
def err_objc_direct_impl_decl_mismatch : Error<
|
||||
"direct method was declared in %select{the primary interface|an extension|a category}0 "
|
||||
"but is implemented in %select{the primary interface|a category|a different category}1">;
|
||||
def err_objc_direct_missing_on_decl : Error<
|
||||
"direct method implementation was previously declared not direct">;
|
||||
def err_objc_direct_on_override : Error<
|
||||
"methods that %select{override superclass methods|implement protocol requirements}0 cannot be direct">;
|
||||
def err_objc_override_direct_method : Error<
|
||||
"cannot override a method that is declared direct by a superclass">;
|
||||
def warn_objc_direct_ignored : Warning<
|
||||
"%0 attribute isn't implemented by this Objective-C runtime">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
def warn_objc_direct_property_ignored : Warning<
|
||||
"direct attribute on property %0 ignored (not implemented by this Objective-C runtime)">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
|
||||
def warn_conflicting_overriding_ret_types : Warning<
|
||||
"conflicting return type in "
|
||||
"declaration of %0%diff{: $ vs $|}1,2">,
|
||||
|
|
@ -1072,6 +1099,7 @@ def warn_accessor_property_type_mismatch : Warning<
|
|||
"type of property %0 does not match type of accessor %1">;
|
||||
def note_conv_function_declared_at : Note<"type conversion function declared here">;
|
||||
def note_method_declared_at : Note<"method %0 declared here">;
|
||||
def note_direct_method_declared_at : Note<"direct method %0 declared here">;
|
||||
def note_property_attribute : Note<"property %0 is declared "
|
||||
"%select{deprecated|unavailable|partial}1 here">;
|
||||
def err_setter_type_void : Error<"type of setter must be void">;
|
||||
|
|
@ -1307,6 +1335,8 @@ def warn_multiple_selectors: Warning<
|
|||
"several methods with selector %0 of mismatched types are found "
|
||||
"for the @selector expression">,
|
||||
InGroup<SelectorTypeMismatch>, DefaultIgnore;
|
||||
def err_direct_selector_expression: Error<
|
||||
"@selector expression formed with direct selector %0">;
|
||||
|
||||
def err_objc_kindof_nonobject : Error<
|
||||
"'__kindof' specifier cannot be applied to non-object type %0">;
|
||||
|
|
@ -1320,6 +1350,12 @@ def err_objc_method_unsupported_param_ret_type : Error<
|
|||
def warn_messaging_unqualified_id : Warning<
|
||||
"messaging unqualified id">, DefaultIgnore,
|
||||
InGroup<DiagGroup<"objc-messaging-id">>;
|
||||
def err_messaging_unqualified_id_with_direct_method : Error<
|
||||
"messaging unqualified id with a method that is possibly direct">;
|
||||
def err_messaging_super_with_direct_method : Error<
|
||||
"messaging super with a direct method">;
|
||||
def err_messaging_class_with_direct_method : Error<
|
||||
"messaging a Class with a method that is possibly direct">;
|
||||
|
||||
// C++ declarations
|
||||
def err_static_assert_expression_is_not_constant : Error<
|
||||
|
|
@ -1702,7 +1738,10 @@ def note_ivar_decl : Note<"instance variable is declared here">;
|
|||
def note_bitfield_decl : Note<"bit-field is declared here">;
|
||||
def note_implicit_param_decl : Note<"%0 is an implicit parameter">;
|
||||
def note_member_synthesized_at : Note<
|
||||
"in implicit %sub{select_special_member_kind}0 for %1 "
|
||||
"in %select{implicit|defaulted}0 %sub{select_special_member_kind}1 for %2 "
|
||||
"first required here">;
|
||||
def note_comparison_synthesized_at : Note<
|
||||
"in defaulted %sub{select_defaulted_comparison_kind}0 for %1 "
|
||||
"first required here">;
|
||||
def err_missing_default_ctor : Error<
|
||||
"%select{constructor for %1 must explicitly initialize the|"
|
||||
|
|
@ -1894,7 +1933,8 @@ def err_lvalue_reference_bind_to_unrelated : Error<
|
|||
"cannot bind to a value of unrelated type}1,2">;
|
||||
def err_reference_bind_drops_quals : Error<
|
||||
"binding reference %diff{of type $ to value of type $|to value}0,1 "
|
||||
"%select{drops %3 qualifier%plural{1:|2:|4:|:s}4|changes address space}2">;
|
||||
"%select{drops %3 qualifier%plural{1:|2:|4:|:s}4|changes address space|"
|
||||
"not permitted due to incompatible qualifiers}2">;
|
||||
def err_reference_bind_failed : Error<
|
||||
"reference %diff{to %select{type|incomplete type}1 $ could not bind to an "
|
||||
"%select{rvalue|lvalue}2 of type $|could not bind to %select{rvalue|lvalue}2 of "
|
||||
|
|
@ -2542,9 +2582,47 @@ def err_non_constant_constraint_expression : Error<
|
|||
"expression">;
|
||||
def err_non_bool_atomic_constraint : Error<
|
||||
"atomic constraint must be of type 'bool' (found %0)">;
|
||||
def err_template_arg_list_constraints_not_satisfied : Error<
|
||||
"constraints not satisfied for %select{class template|function template|variable template|alias template|"
|
||||
"template template parameter|template}0 %1%2">;
|
||||
def note_constraints_not_satisfied : Note<
|
||||
"constraints not satisfied">;
|
||||
def note_substituted_constraint_expr_is_ill_formed : Note<
|
||||
"because substituted constraint expression is ill-formed%0">;
|
||||
def note_atomic_constraint_evaluated_to_false : Note<
|
||||
"%select{and |because }0'%1' evaluated to false">;
|
||||
def note_concept_specialization_constraint_evaluated_to_false : Note<
|
||||
"%select{and |because }0'%1' evaluated to false">;
|
||||
def note_single_arg_concept_specialization_constraint_evaluated_to_false : Note<
|
||||
"%select{and |because }0%1 does not satisfy %2">;
|
||||
def note_atomic_constraint_evaluated_to_false_elaborated : Note<
|
||||
"%select{and |because }0'%1' (%2 %3 %4) evaluated to false">;
|
||||
def err_constrained_virtual_method : Error<
|
||||
"virtual function cannot have a requires clause">;
|
||||
def err_trailing_requires_clause_on_deduction_guide : Error<
|
||||
"deduction guide cannot have a requires clause">;
|
||||
def err_reference_to_function_with_unsatisfied_constraints : Error<
|
||||
"invalid reference to function %0: constraints not satisfied">;
|
||||
def note_ambiguous_atomic_constraints : Note<
|
||||
"similar constraint expressions not considered equivalent; constraint "
|
||||
"expressions cannot be considered equivalent unless they originate from the "
|
||||
"same concept">;
|
||||
def note_ambiguous_atomic_constraints_similar_expression : Note<
|
||||
"similar constraint expression here">;
|
||||
|
||||
def err_template_different_requires_clause : Error<
|
||||
"requires clause differs in template redeclaration">;
|
||||
def err_template_different_type_constraint : Error<
|
||||
"type constraint differs in template redeclaration">;
|
||||
def err_template_template_parameter_not_at_least_as_constrained : Error<
|
||||
"template template argument %0 is more constrained than template template "
|
||||
"parameter %1">;
|
||||
|
||||
def err_type_constraint_non_type_concept : Error<
|
||||
"concept named in type constraint is not a type concept">;
|
||||
def err_type_constraint_missing_arguments : Error<
|
||||
"%0 requires more than 1 template argument; provide the remaining arguments "
|
||||
"explicitly to use it here">;
|
||||
|
||||
// C++11 char16_t/char32_t
|
||||
def warn_cxx98_compat_unicode_type : Warning<
|
||||
|
|
@ -2577,7 +2655,7 @@ def err_nsobject_attribute : Error<
|
|||
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 "
|
||||
"%select{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|"
|
||||
|
|
@ -2594,6 +2672,8 @@ def err_attribute_requires_positive_integer : Error<
|
|||
"integral compile time constant expression">;
|
||||
def err_attribute_requires_opencl_version : Error<
|
||||
"%0 attribute requires OpenCL version %1%select{| or above}2">;
|
||||
def err_invalid_branch_protection_spec : Error<
|
||||
"invalid or misplaced branch protection specification '%0'">;
|
||||
def warn_unsupported_target_attribute
|
||||
: Warning<"%select{unsupported|duplicate}0%select{| architecture}1 '%2' in"
|
||||
" the 'target' attribute string; 'target' attribute ignored">,
|
||||
|
|
@ -2854,6 +2934,9 @@ def err_alignment_not_power_of_two : Error<
|
|||
def err_alignment_dependent_typedef_name : Error<
|
||||
"requested alignment is dependent but declaration is not dependent">;
|
||||
|
||||
def warn_alignment_builtin_useless : Warning<
|
||||
"%select{aligning a value|the result of checking whether a value is aligned}0"
|
||||
" to 1 byte is %select{a no-op|always true}0">, InGroup<TautologicalCompare>;
|
||||
def err_attribute_aligned_too_great : Error<
|
||||
"requested alignment must be %0 bytes or smaller">;
|
||||
def warn_assume_aligned_too_great
|
||||
|
|
@ -3069,6 +3152,8 @@ def warn_declspec_allocator_nonpointer : Warning<
|
|||
def err_cconv_incomplete_param_type : Error<
|
||||
"parameter %0 must have a complete type to use function %1 with the %2 "
|
||||
"calling convention">;
|
||||
def err_attribute_output_parameter : Error<
|
||||
"attribute only applies to output parameters">;
|
||||
|
||||
def ext_cannot_use_trivial_abi : ExtWarn<
|
||||
"'trivial_abi' cannot be applied to %0">, InGroup<IgnoredAttributes>;
|
||||
|
|
@ -3604,6 +3689,15 @@ def err_attribute_overloadable_no_prototype : Error<
|
|||
def err_attribute_overloadable_multiple_unmarked_overloads : Error<
|
||||
"at most one overload for a given name may lack the 'overloadable' "
|
||||
"attribute">;
|
||||
def warn_attribute_no_builtin_invalid_builtin_name : Warning<
|
||||
"'%0' is not a valid builtin name for %1">,
|
||||
InGroup<DiagGroup<"invalid-no-builtin-names">>;
|
||||
def err_attribute_no_builtin_wildcard_or_builtin_name : Error<
|
||||
"empty %0 cannot be composed with named ones">;
|
||||
def err_attribute_no_builtin_on_non_definition : Error<
|
||||
"%0 attribute is permitted on definitions only">;
|
||||
def err_attribute_no_builtin_on_defaulted_deleted_function : Error<
|
||||
"%0 attribute has no effect on defaulted or deleted functions">;
|
||||
def warn_ns_attribute_wrong_return_type : Warning<
|
||||
"%0 attribute only applies to %select{functions|methods|properties}1 that "
|
||||
"return %select{an Objective-C object|a pointer|a non-retainable pointer}2">,
|
||||
|
|
@ -3776,6 +3870,7 @@ def select_ovl_candidate_kind : TextSubstitution<
|
|||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"function (the implicit 'operator==' for this 'operator<=>)'|"
|
||||
"inherited constructor}0%select{| template| %2}1">;
|
||||
|
||||
def note_ovl_candidate : Note<
|
||||
|
|
@ -3788,10 +3883,9 @@ def note_ovl_candidate : Note<
|
|||
"| has different qualifiers (expected %5 but found %6)"
|
||||
"| has different exception specification}4">;
|
||||
|
||||
def note_ovl_candidate_explicit_forbidden : Note<
|
||||
"candidate %0 ignored: cannot be explicit">;
|
||||
def note_explicit_bool_resolved_to_true : Note<
|
||||
"explicit(bool) specifier resolved to true">;
|
||||
def note_ovl_candidate_explicit : Note<
|
||||
"explicit %select{constructor|conversion function|deduction guide}0 "
|
||||
"is not a candidate%select{| (explicit specifier evaluates to true)}1">;
|
||||
def note_ovl_candidate_inherited_constructor : Note<
|
||||
"constructor from base class %0 inherited here">;
|
||||
def note_ovl_candidate_inherited_constructor_slice : Note<
|
||||
|
|
@ -3807,12 +3901,14 @@ def note_ovl_candidate_bad_deduction : Note<
|
|||
"candidate template ignored: failed template argument deduction">;
|
||||
def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: "
|
||||
"couldn't infer template argument %0">;
|
||||
def note_ovl_candidate_incomplete_deduction_pack : Note<"candidate template ignored: "
|
||||
def note_ovl_candidate_incomplete_deduction_pack : Note<
|
||||
"candidate template ignored: "
|
||||
"deduced too few arguments for expanded pack %0; no argument for %ordinal1 "
|
||||
"expanded parameter in deduced argument pack %2">;
|
||||
def note_ovl_candidate_inconsistent_deduction : Note<
|
||||
"candidate template ignored: deduced conflicting %select{types|values|"
|
||||
"templates}0 for parameter %1%diff{ ($ vs. $)|}2,3">;
|
||||
"candidate template ignored: deduced %select{conflicting types|"
|
||||
"conflicting values|conflicting templates|packs of different lengths}0 "
|
||||
"for parameter %1%diff{ ($ vs. $)|}2,3">;
|
||||
def note_ovl_candidate_inconsistent_deduction_types : Note<
|
||||
"candidate template ignored: deduced values %diff{"
|
||||
"of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
|
||||
|
|
@ -3820,6 +3916,8 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
|
|||
def note_ovl_candidate_explicit_arg_mismatch_named : Note<
|
||||
"candidate template ignored: invalid explicitly-specified argument "
|
||||
"for template parameter %0">;
|
||||
def note_ovl_candidate_unsatisfied_constraints : Note<
|
||||
"candidate template ignored: constraints not satisfied%0">;
|
||||
def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
|
||||
"candidate template ignored: invalid explicitly-specified argument "
|
||||
"for %ordinal0 template parameter">;
|
||||
|
|
@ -3848,6 +3946,9 @@ def note_ovl_candidate_disabled_by_extension : Note<
|
|||
def err_addrof_function_disabled_by_enable_if_attr : Error<
|
||||
"cannot take address of function %0 because it has one or more "
|
||||
"non-tautological enable_if conditions">;
|
||||
def err_addrof_function_constraints_not_satisfied : Error<
|
||||
"cannot take address of function %0 because its constraints are not "
|
||||
"satisfied">;
|
||||
def note_addrof_ovl_candidate_disabled_by_enable_if_attr : Note<
|
||||
"candidate function made ineligible by enable_if">;
|
||||
def note_ovl_candidate_deduced_mismatch : Note<
|
||||
|
|
@ -3920,8 +4021,12 @@ def note_ovl_candidate_bad_lvalue : Note<
|
|||
"%select{%ordinal4 argument|object argument}3">;
|
||||
def note_ovl_candidate_bad_addrspace : Note<
|
||||
"candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
|
||||
"address space mismatch in %select{%ordinal6|'this'}5 argument (%3), "
|
||||
"parameter type must be %4">;
|
||||
"cannot %select{pass pointer to|bind reference in}5 %3 "
|
||||
"%select{as a pointer to|to object in}5 %4 in %ordinal6 "
|
||||
"argument">;
|
||||
def note_ovl_candidate_bad_addrspace_this : Note<
|
||||
"candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
|
||||
"'this' object is in %3, but method expects object in %4">;
|
||||
def note_ovl_candidate_bad_gc : Note<
|
||||
"candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
|
||||
"%select{%ordinal7|'this'}6 argument (%3) has %select{no|__weak|__strong}4 "
|
||||
|
|
@ -3957,6 +4062,9 @@ def note_ovl_candidate_bad_target : Note<
|
|||
"call to "
|
||||
"%select{__device__|__global__|__host__|__host__ __device__|invalid}3 function from"
|
||||
" %select{__device__|__global__|__host__|__host__ __device__|invalid}4 function">;
|
||||
def note_ovl_candidate_constraints_not_satisfied : Note<
|
||||
"candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: constraints "
|
||||
"not satisfied">;
|
||||
def note_implicit_member_target_infer_collision : Note<
|
||||
"implicit %sub{select_special_member_kind}0 inferred target collision: call to both "
|
||||
"%select{__device__|__global__|__host__|__host__ __device__}1 and "
|
||||
|
|
@ -4004,7 +4112,10 @@ def err_ovl_deleted_oper : Error<
|
|||
"overload resolution selected deleted operator '%0'">;
|
||||
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">;
|
||||
"assigned|destroyed}1 because its %sub{select_special_member_kind}1 is "
|
||||
"implicitly deleted">;
|
||||
def err_ovl_deleted_comparison : Error<
|
||||
"object of type %0 cannot be compared because its %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'">;
|
||||
|
|
@ -4512,8 +4623,21 @@ 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_checking_constraints_for_template_id_here : Note<
|
||||
"while checking constraint satisfaction for template '%0' required here">;
|
||||
def note_checking_constraints_for_var_spec_id_here : Note<
|
||||
"while checking constraint satisfaction for variable template "
|
||||
"partial specialization '%0' required here">;
|
||||
def note_checking_constraints_for_class_spec_id_here : Note<
|
||||
"while checking constraint satisfaction for class template partial "
|
||||
"specialization '%0' required here">;
|
||||
def note_constraint_substitution_here : Note<
|
||||
"while substituting template arguments into constraint expression here">;
|
||||
def note_constraint_normalization_here : Note<
|
||||
"while calculating associated constraint of template '%0' here">;
|
||||
def note_parameter_mapping_substitution_here : Note<
|
||||
"while substituting into concept arguments here; substitution failures not "
|
||||
"allowed in concept arguments">;
|
||||
def note_instantiation_contexts_suppressed : Note<
|
||||
"(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to "
|
||||
"see all)">;
|
||||
|
|
@ -4677,8 +4801,9 @@ def note_template_declared_here : Note<
|
|||
"%select{function template|class template|variable template"
|
||||
"|type alias template|template template parameter}0 "
|
||||
"%1 declared here">;
|
||||
def err_alias_template_expansion_into_fixed_list : Error<
|
||||
"pack expansion used as argument for non-pack parameter of alias template">;
|
||||
def err_template_expansion_into_fixed_list : Error<
|
||||
"pack expansion used as argument for non-pack parameter of %select{alias "
|
||||
"template|concept}0">;
|
||||
def note_parameter_type : Note<
|
||||
"parameter of type %0 is declared here">;
|
||||
|
||||
|
|
@ -4705,8 +4830,8 @@ def err_unexpanded_parameter_pack : Error<
|
|||
"size|static assertion|fixed underlying type|enumerator value|"
|
||||
"using declaration|friend declaration|qualifier|initializer|default argument|"
|
||||
"non-type template parameter type|exception type|partial specialization|"
|
||||
"__if_exists name|__if_not_exists name|lambda|block}0 contains"
|
||||
"%plural{0: an|:}1 unexpanded parameter pack"
|
||||
"__if_exists name|__if_not_exists name|lambda|block|type constraint}0 "
|
||||
"contains%plural{0: an|:}1 unexpanded parameter pack"
|
||||
"%plural{0:|1: %2|2:s %2 and %3|:s %2, %3, ...}1">;
|
||||
|
||||
def err_pack_expansion_without_parameter_packs : Error<
|
||||
|
|
@ -6108,6 +6233,8 @@ def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension<
|
|||
"ordered comparison between pointer and zero (%0 and %1) is an extension">;
|
||||
def err_typecheck_ordered_comparison_of_pointer_and_zero : Error<
|
||||
"ordered comparison between pointer and zero (%0 and %1)">;
|
||||
def err_typecheck_three_way_comparison_of_pointer_and_zero : Error<
|
||||
"three-way comparison between pointer and zero">;
|
||||
def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn<
|
||||
"ordered comparison of function pointers (%0 and %1)">,
|
||||
InGroup<DiagGroup<"ordered-compare-function-pointers">>;
|
||||
|
|
@ -6137,6 +6264,52 @@ def err_typecheck_op_on_nonoverlapping_address_space_pointers : Error<
|
|||
"%diff{ ($ and $)|}0,1}2"
|
||||
" which are pointers to non-overlapping address spaces">;
|
||||
|
||||
def select_arith_conv_kind : TextSubstitution<
|
||||
"%select{arithmetic between|bitwise operation between|comparison of|"
|
||||
"conditional expression between|compound assignment of}0">;
|
||||
def warn_arith_conv_enum_float : Warning<
|
||||
"%sub{select_arith_conv_kind}0 "
|
||||
"%select{floating-point|enumeration}1 type %2 "
|
||||
"%plural{2:with|4:from|:and}0 "
|
||||
"%select{enumeration|floating-point}1 type %3">,
|
||||
InGroup<EnumFloatConversion>, DefaultIgnore;
|
||||
def warn_arith_conv_enum_float_cxx2a : Warning<
|
||||
"%sub{select_arith_conv_kind}0 "
|
||||
"%select{floating-point|enumeration}1 type %2 "
|
||||
"%plural{2:with|4:from|:and}0 "
|
||||
"%select{enumeration|floating-point}1 type %3 is deprecated">,
|
||||
InGroup<DeprecatedEnumFloatConversion>;
|
||||
def warn_arith_conv_mixed_enum_types : Warning<
|
||||
"%sub{select_arith_conv_kind}0 "
|
||||
"different enumeration types%diff{ ($ and $)|}1,2">,
|
||||
InGroup<EnumEnumConversion>, DefaultIgnore;
|
||||
def warn_arith_conv_mixed_enum_types_cxx2a : Warning<
|
||||
"%sub{select_arith_conv_kind}0 "
|
||||
"different enumeration types%diff{ ($ and $)|}1,2 is deprecated">,
|
||||
InGroup<DeprecatedEnumEnumConversion>;
|
||||
def warn_arith_conv_mixed_anon_enum_types : Warning<
|
||||
warn_arith_conv_mixed_enum_types.Text>,
|
||||
InGroup<AnonEnumEnumConversion>, DefaultIgnore;
|
||||
def warn_arith_conv_mixed_anon_enum_types_cxx2a : Warning<
|
||||
warn_arith_conv_mixed_enum_types_cxx2a.Text>,
|
||||
InGroup<DeprecatedAnonEnumEnumConversion>;
|
||||
def warn_conditional_mixed_enum_types : Warning<
|
||||
warn_arith_conv_mixed_enum_types.Text>,
|
||||
InGroup<EnumCompareConditional>, DefaultIgnore;
|
||||
def warn_conditional_mixed_enum_types_cxx2a : Warning<
|
||||
warn_arith_conv_mixed_enum_types_cxx2a.Text>,
|
||||
InGroup<DeprecatedEnumCompareConditional>;
|
||||
def warn_comparison_mixed_enum_types : Warning<
|
||||
warn_arith_conv_mixed_enum_types.Text>,
|
||||
InGroup<EnumCompare>;
|
||||
def warn_comparison_mixed_enum_types_cxx2a : Warning<
|
||||
warn_arith_conv_mixed_enum_types_cxx2a.Text>,
|
||||
InGroup<DeprecatedEnumCompare>;
|
||||
def warn_comparison_of_mixed_enum_types_switch : Warning<
|
||||
"comparison of different enumeration types in switch statement"
|
||||
"%diff{ ($ and $)|}0,1">,
|
||||
InGroup<EnumCompareSwitch>;
|
||||
|
||||
def err_typecheck_assign_const : Error<
|
||||
"%select{"
|
||||
"cannot assign to return value because function %1 returns a const value|"
|
||||
|
|
@ -6190,18 +6363,6 @@ 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">,
|
||||
InGroup<EnumCompareSwitch>;
|
||||
def warn_null_in_arithmetic_operation : Warning<
|
||||
"use of NULL in arithmetic operation">,
|
||||
InGroup<NullArithmetic>;
|
||||
|
|
@ -6430,6 +6591,8 @@ def warn_objc_unsafe_perform_selector : Warning<
|
|||
InGroup<DiagGroup<"objc-unsafe-perform-selector">>;
|
||||
def note_objc_unsafe_perform_selector_method_declared_here : Note<
|
||||
"method %0 that returns %1 declared here">;
|
||||
def err_attribute_arm_mve_alias : Error<
|
||||
"'__clang_arm_mve_alias' attribute can only be applied to an ARM MVE builtin">;
|
||||
|
||||
def warn_setter_getter_impl_required : Warning<
|
||||
"property %0 requires method %1 to be defined - "
|
||||
|
|
@ -6557,10 +6720,10 @@ def err_downcast_from_inaccessible_base : Error<
|
|||
def err_upcast_to_inaccessible_base : Error<
|
||||
"cannot cast %0 to its %select{private|protected}2 base class %1">;
|
||||
def err_bad_dynamic_cast_not_ref_or_ptr : Error<
|
||||
"%0 is not a reference or pointer">;
|
||||
def err_bad_dynamic_cast_not_class : Error<"%0 is not a class">;
|
||||
def err_bad_dynamic_cast_incomplete : Error<"%0 is an incomplete type">;
|
||||
def err_bad_dynamic_cast_not_ptr : Error<"%0 is not a pointer">;
|
||||
"invalid target type %0 for dynamic_cast; target type must be a reference or pointer type to a defined class">;
|
||||
def err_bad_dynamic_cast_not_class : Error<"%0 is not a class type">;
|
||||
def err_bad_cast_incomplete : Error<"%0 is an incomplete type">;
|
||||
def err_bad_dynamic_cast_not_ptr : Error<"cannot use dynamic_cast to convert from %0 to %1">;
|
||||
def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">;
|
||||
|
||||
// Other C++ expressions
|
||||
|
|
@ -6792,6 +6955,14 @@ def err_conditional_vector_size : Error<
|
|||
def err_conditional_vector_element_size : Error<
|
||||
"vector condition type %0 and result type %1 do not have elements of the "
|
||||
"same size">;
|
||||
def err_conditional_vector_has_void : Error<
|
||||
"GNU vector conditional operand cannot be %select{void|a throw expression}0">;
|
||||
def err_conditional_vector_operand_type
|
||||
: Error<"%select{enumeration|extended vector}0 type %1 is not allowed in a "
|
||||
"vector conditional">;
|
||||
def err_conditional_vector_mismatched_vectors
|
||||
: Error<"vector operands to the vector conditional must be the same type "
|
||||
"%diff{($ and $)|}0,1}">;
|
||||
|
||||
def err_throw_incomplete : Error<
|
||||
"cannot throw object of incomplete type %0">;
|
||||
|
|
@ -6847,10 +7018,10 @@ let CategoryName = "Lambda Issue" in {
|
|||
def err_noreturn_lambda_has_return_expr : Error<
|
||||
"lambda declared 'noreturn' should not return">;
|
||||
def warn_maybe_falloff_nonvoid_lambda : Warning<
|
||||
"control may reach end of non-void lambda">,
|
||||
"non-void lambda does not return a value in all control paths">,
|
||||
InGroup<ReturnType>;
|
||||
def warn_falloff_nonvoid_lambda : Warning<
|
||||
"control reaches end of non-void lambda">,
|
||||
"non-void lambda does not return a value">,
|
||||
InGroup<ReturnType>;
|
||||
def err_access_lambda_capture : Error<
|
||||
// The ERRORs represent other special members that aren't constructors, in
|
||||
|
|
@ -7391,10 +7562,8 @@ def err_atomic_op_needs_trivial_copy : Error<
|
|||
def err_atomic_op_needs_atomic_int_or_ptr : Error<
|
||||
"address argument to atomic operation must be a pointer to %select{|atomic }0"
|
||||
"integer or pointer (%1 invalid)">;
|
||||
def err_atomic_op_needs_int32_or_ptr : Error<
|
||||
"address argument to atomic operation must be a pointer to signed or unsigned 32-bit integer">;
|
||||
def err_atomic_op_bitwise_needs_atomic_int : Error<
|
||||
"address argument to bitwise atomic operation must be a pointer to "
|
||||
def err_atomic_op_needs_atomic_int : Error<
|
||||
"address argument to atomic operation must be a pointer to "
|
||||
"%select{|atomic }0integer (%1 invalid)">;
|
||||
def warn_atomic_op_has_invalid_memory_order : Warning<
|
||||
"memory order argument to atomic operation is invalid">,
|
||||
|
|
@ -8081,7 +8250,7 @@ def err_incorrect_defaulted_consteval : Error<
|
|||
"cannot be consteval because implicit definition is not constexpr">;
|
||||
def warn_defaulted_method_deleted : Warning<
|
||||
"explicitly defaulted %sub{select_special_member_kind}0 is implicitly "
|
||||
"deleted">, InGroup<DiagGroup<"defaulted-function-deleted">>;
|
||||
"deleted">, InGroup<DefaultedFunctionDeleted>;
|
||||
def err_out_of_line_default_deletes : Error<
|
||||
"defaulting this %sub{select_special_member_kind}0 "
|
||||
"would delete it after its first declaration">;
|
||||
|
|
@ -8099,6 +8268,89 @@ def note_vbase_moved_here : Note<
|
|||
"%select{%1 is a virtual base class of base class %2 declared here|"
|
||||
"virtual base class %1 declared here}0">;
|
||||
|
||||
// C++20 defaulted comparisons
|
||||
// This corresponds to values of Sema::DefaultedComparisonKind.
|
||||
def select_defaulted_comparison_kind : TextSubstitution<
|
||||
"%select{<ERROR>|equality|three-way|equality|relational}0 comparison "
|
||||
"operator">;
|
||||
def ext_defaulted_comparison : ExtWarn<
|
||||
"defaulted comparison operators are a C++20 extension">, InGroup<CXX2a>;
|
||||
def warn_cxx17_compat_defaulted_comparison : Warning<
|
||||
"defaulted comparison operators are incompatible with C++ standards "
|
||||
"before C++20">, InGroup<CXXPre2aCompat>, DefaultIgnore;
|
||||
def err_defaulted_comparison_template : Error<
|
||||
"comparison operator template cannot be defaulted">;
|
||||
def err_defaulted_comparison_out_of_class : Error<
|
||||
"%sub{select_defaulted_comparison_kind}0 can only be defaulted in a class "
|
||||
"definition">;
|
||||
def err_defaulted_comparison_param : Error<
|
||||
"invalid parameter type for defaulted %sub{select_defaulted_comparison_kind}0"
|
||||
"; found %1, expected %2%select{| or %4}3">;
|
||||
def err_defaulted_comparison_param_mismatch : Error<
|
||||
"parameters for defaulted %sub{select_defaulted_comparison_kind}0 "
|
||||
"must have the same type%diff{ (found $ vs $)|}1,2">;
|
||||
def err_defaulted_comparison_non_const : Error<
|
||||
"defaulted member %sub{select_defaulted_comparison_kind}0 must be "
|
||||
"const-qualified">;
|
||||
def err_defaulted_comparison_return_type_not_bool : Error<
|
||||
"return type for defaulted %sub{select_defaulted_comparison_kind}0 "
|
||||
"must be 'bool', not %1">;
|
||||
def err_defaulted_comparison_deduced_return_type_not_auto : Error<
|
||||
"deduced return type for defaulted %sub{select_defaulted_comparison_kind}0 "
|
||||
"must be 'auto', not %1">;
|
||||
def warn_defaulted_comparison_deleted : Warning<
|
||||
"explicitly defaulted %sub{select_defaulted_comparison_kind}0 is implicitly "
|
||||
"deleted">, InGroup<DefaultedFunctionDeleted>;
|
||||
def err_non_first_default_compare_deletes : Error<
|
||||
"defaulting %select{this %sub{select_defaulted_comparison_kind}1|"
|
||||
"the corresponding implicit 'operator==' for this defaulted 'operator<=>'}0 "
|
||||
"would delete it after its first declaration">;
|
||||
def note_defaulted_comparison_union : Note<
|
||||
"defaulted %0 is implicitly deleted because "
|
||||
"%2 is a %select{union-like class|union}1 with variant members">;
|
||||
def note_defaulted_comparison_reference_member : Note<
|
||||
"defaulted %0 is implicitly deleted because "
|
||||
"class %1 has a reference member">;
|
||||
def note_defaulted_comparison_ambiguous : Note<
|
||||
"defaulted %0 is implicitly deleted because implied %select{|'==' |'<' }1"
|
||||
"comparison %select{|for member %3 |for base class %3 }2is ambiguous">;
|
||||
def note_defaulted_comparison_inaccessible : Note<
|
||||
"defaulted %0 is implicitly deleted because it would invoke a "
|
||||
"%select{private|protected}3 %4%select{ member of %6|"
|
||||
" member of %6 to compare member %2| to compare base class %2}1">;
|
||||
def note_defaulted_comparison_calls_deleted : Note<
|
||||
"defaulted %0 is implicitly deleted because it would invoke a deleted "
|
||||
"comparison function%select{| for member %2| for base class %2}1">;
|
||||
def note_defaulted_comparison_no_viable_function : Note<
|
||||
"defaulted %0 is implicitly deleted because there is no viable comparison "
|
||||
"function%select{| for member %2| for base class %2}1">;
|
||||
def note_defaulted_comparison_no_viable_function_synthesized : Note<
|
||||
"three-way comparison cannot be synthesized because there is no viable "
|
||||
"function for %select{'=='|'<'}0 comparison">;
|
||||
def note_defaulted_comparison_not_rewritten_callee : Note<
|
||||
"defaulted %0 is implicitly deleted because this non-rewritten comparison "
|
||||
"function would be the best match for the comparison">;
|
||||
def note_defaulted_comparison_cannot_deduce : Note<
|
||||
"return type of defaulted 'operator<=>' cannot be deduced because "
|
||||
"return type %2 of three-way comparison for %select{|member|base class}0 %1 "
|
||||
"is not a standard comparison category type">;
|
||||
def note_defaulted_comparison_cannot_deduce_callee : Note<
|
||||
"selected 'operator<=>' for %select{|member|base class}0 %1 declared here">;
|
||||
def err_incorrect_defaulted_comparison_constexpr : Error<
|
||||
"defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
|
||||
"three-way comparison operator}0 "
|
||||
"cannot be declared %select{constexpr|consteval}2 because "
|
||||
"%select{it|the corresponding implicit 'operator=='}0 "
|
||||
"invokes a non-constexpr comparison function">;
|
||||
def note_defaulted_comparison_not_constexpr : Note<
|
||||
"non-constexpr comparison function would be used to compare "
|
||||
"%select{|member %1|base class %1}0">;
|
||||
def note_defaulted_comparison_not_constexpr_here : Note<
|
||||
"non-constexpr comparison function declared here">;
|
||||
def note_in_declaration_of_implicit_equality_comparison : Note<
|
||||
"while declaring the corresponding implicit 'operator==' "
|
||||
"for this defaulted 'operator<=>'">;
|
||||
|
||||
def ext_implicit_exception_spec_mismatch : ExtWarn<
|
||||
"function previously declared with an %select{explicit|implicit}0 exception "
|
||||
"specification redeclared with an %select{implicit|explicit}0 exception "
|
||||
|
|
@ -8342,10 +8594,14 @@ def warn_comparison_bitwise_or : Warning<
|
|||
def warn_tautological_overlap_comparison : Warning<
|
||||
"overlapping comparisons always evaluate to %select{false|true}0">,
|
||||
InGroup<TautologicalOverlapCompare>, DefaultIgnore;
|
||||
def warn_depr_array_comparison : Warning<
|
||||
"comparison between two arrays is deprecated; "
|
||||
"to compare array addresses, use unary '+' to decay operands to pointers">,
|
||||
InGroup<DeprecatedArrayCompare>;
|
||||
|
||||
def warn_stringcompare : Warning<
|
||||
"result of comparison against %select{a string literal|@encode}0 is "
|
||||
"unspecified (use strncmp instead)">,
|
||||
"unspecified (use an explicit string comparison function instead)">,
|
||||
InGroup<StringCompare>;
|
||||
|
||||
def warn_identity_field_assign : Warning<
|
||||
|
|
@ -8635,6 +8891,12 @@ def warn_argument_invalid_range : Warning<
|
|||
InGroup<DiagGroup<"argument-outside-range">>;
|
||||
def err_argument_not_multiple : Error<
|
||||
"argument should be a multiple of %0">;
|
||||
def err_argument_not_power_of_2 : Error<
|
||||
"argument should be a power of 2">;
|
||||
def err_argument_not_shifted_byte : Error<
|
||||
"argument should be an 8-bit value shifted by a multiple of 8 bits">;
|
||||
def err_argument_not_shifted_byte_or_xxff : Error<
|
||||
"argument should be an 8-bit value shifted by a multiple of 8 bits, or in the form 0x??FF">;
|
||||
def warn_neon_vector_initializer_non_portable : Warning<
|
||||
"vector initializers are not compatible with NEON intrinsics in big endian "
|
||||
"mode">, InGroup<DiagGroup<"nonportable-vector-initialization">>;
|
||||
|
|
@ -8653,6 +8915,12 @@ def err_32_bit_builtin_64_bit_tgt : Error<
|
|||
"this builtin is only available on 32-bit targets">;
|
||||
def err_builtin_x64_aarch64_only : Error<
|
||||
"this builtin is only available on x86-64 and aarch64 targets">;
|
||||
def err_mips_builtin_requires_dsp : Error<
|
||||
"this builtin requires 'dsp' ASE, please use -mdsp">;
|
||||
def err_mips_builtin_requires_dspr2 : Error<
|
||||
"this builtin requires 'dsp r2' ASE, please use -mdspr2">;
|
||||
def err_mips_builtin_requires_msa : Error<
|
||||
"this builtin requires 'msa' ASE, please use -mmsa">;
|
||||
def err_ppc_builtin_only_on_pwr7 : Error<
|
||||
"this builtin is only valid on POWER7 or later CPUs">;
|
||||
def err_x86_builtin_invalid_rounding : Error<
|
||||
|
|
@ -8878,7 +9146,7 @@ def err_unknown_any_function : Error<
|
|||
"function %0 with unknown type must be given a function type">;
|
||||
|
||||
def err_filter_expression_integral : Error<
|
||||
"filter expression type should be an integral value not %0">;
|
||||
"filter expression has non-integral type %0">;
|
||||
|
||||
def err_non_asm_stmt_in_naked_function : Error<
|
||||
"non-ASM statement in naked function is not supported">;
|
||||
|
|
@ -9109,8 +9377,12 @@ def err_omp_threadprivate_incomplete_type : Error<
|
|||
"threadprivate variable with incomplete type %0">;
|
||||
def err_omp_no_dsa_for_variable : Error<
|
||||
"variable %0 must have explicitly specified data sharing attributes">;
|
||||
def err_omp_defaultmap_no_attr_for_variable : Error<
|
||||
"variable %0 must have explicitly specified data sharing attributes, data mapping attributes, or in an is_device_ptr clause">;
|
||||
def note_omp_default_dsa_none : Note<
|
||||
"explicit data sharing attribute requested here">;
|
||||
def note_omp_defaultmap_attr_none : Note<
|
||||
"explicit data sharing attribute, data mapping attribute, or is_device_ptr clause requested here">;
|
||||
def err_omp_wrong_dsa : Error<
|
||||
"%0 variable cannot be %1">;
|
||||
def err_omp_variably_modified_type_not_supported : Error<
|
||||
|
|
@ -9187,8 +9459,8 @@ def err_omp_aligned_expected_array_or_ptr : Error<
|
|||
"argument of aligned clause should be array"
|
||||
"%select{ or pointer|, pointer, reference to array or reference to pointer}1"
|
||||
", not %0">;
|
||||
def err_omp_aligned_twice : Error<
|
||||
"%select{a variable|a parameter|'this'}0 cannot appear in more than one aligned clause">;
|
||||
def err_omp_used_in_clause_twice : Error<
|
||||
"%select{a variable|a parameter|'this'}0 cannot appear in more than one %1 clause">;
|
||||
def err_omp_local_var_in_threadprivate_init : Error<
|
||||
"variable with local storage in initial value of threadprivate variable">;
|
||||
def err_omp_loop_not_canonical_init : Error<
|
||||
|
|
@ -9199,7 +9471,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 "
|
||||
"('<', '<=', '>', %select{or '>='|'>=', or '!='}0) of loop variable %1">;
|
||||
"('<', '<=', '>', %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">;
|
||||
|
|
@ -9254,7 +9526,7 @@ def err_omp_prohibited_region : Error<
|
|||
"; perhaps you forget to enclose 'omp %3' directive into a target region?|"
|
||||
"; perhaps you forget to enclose 'omp %3' directive into a teams region?}2">;
|
||||
def err_omp_prohibited_region_simd : Error<
|
||||
"OpenMP constructs may not be nested inside a simd region">;
|
||||
"OpenMP constructs may not be nested inside a simd region%select{| except for ordered simd, simd or atomic directive}0">;
|
||||
def err_omp_prohibited_region_atomic : Error<
|
||||
"OpenMP constructs may not be nested inside an atomic region">;
|
||||
def err_omp_prohibited_region_critical_same_name : Error<
|
||||
|
|
@ -9365,7 +9637,7 @@ def err_omp_wrong_if_directive_name_modifier : Error<
|
|||
def err_omp_no_more_if_clause : Error<
|
||||
"no more 'if' clause is allowed">;
|
||||
def err_omp_unnamed_if_clause : Error<
|
||||
"expected %select{|one of}0 %1 directive name modifier%select{|s}0">;
|
||||
"expected%select{| one of}0 %1 directive name modifier%select{|s}0">;
|
||||
def note_omp_previous_named_if_clause : Note<
|
||||
"previous clause with directive name modifier specified here">;
|
||||
def err_omp_ordered_directive_with_param : Error<
|
||||
|
|
@ -9410,6 +9682,8 @@ def err_omp_depend_sink_expected_plus_minus : Error<
|
|||
"expected '+' or '-' operation">;
|
||||
def err_omp_depend_sink_source_not_allowed : Error<
|
||||
"'depend(%select{source|sink:vec}0)' clause%select{|s}0 cannot be mixed with 'depend(%select{sink:vec|source}0)' clause%select{s|}0">;
|
||||
def err_omp_depend_zero_length_array_section_not_allowed : Error<
|
||||
"zero-length array section is not allowed in 'depend' clause">;
|
||||
def err_omp_linear_ordered : Error<
|
||||
"'linear' clause cannot be specified along with 'ordered' clause with a parameter">;
|
||||
def err_omp_unexpected_schedule_modifier : Error<
|
||||
|
|
@ -9449,8 +9723,8 @@ def err_omp_reduction_vla_unsupported : Error<
|
|||
def err_omp_linear_distribute_var_non_loop_iteration : Error<
|
||||
"only loop iteration variables are allowed in 'linear' clause in distribute directives">;
|
||||
def warn_omp_non_trivial_type_mapped : Warning<
|
||||
"Non-trivial type %0 is mapped, only trivial types are guaranteed to be mapped correctly">,
|
||||
InGroup<OpenMPTarget>;
|
||||
"Type %0 is not trivially copyable and not guaranteed to be mapped correctly">,
|
||||
InGroup<OpenMPMapping>;
|
||||
def err_omp_requires_clause_redeclaration : Error <
|
||||
"Only one %0 clause can appear on a requires directive in a single translation unit">;
|
||||
def note_omp_requires_previous_clause : Note <
|
||||
|
|
@ -9519,10 +9793,6 @@ def warn_omp_declare_variant_after_used : Warning<
|
|||
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|"
|
||||
|
|
@ -9539,6 +9809,11 @@ 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">;
|
||||
def err_omp_one_defaultmap_each_category: Error<
|
||||
"at most one defaultmap clause for each variable-category can appear on the directive">;
|
||||
def err_omp_lastprivate_conditional_non_scalar : Error<
|
||||
"expected list item of scalar type in 'lastprivate' clause with 'conditional' modifier"
|
||||
>;
|
||||
} // end of OpenMP category
|
||||
|
||||
let CategoryName = "Related Result Type Issue" in {
|
||||
|
|
@ -9966,8 +10241,8 @@ def warn_dispatch_body_ignored : Warning<
|
|||
|
||||
// three-way comparison operator diagnostics
|
||||
def err_implied_comparison_category_type_not_found : Error<
|
||||
"cannot deduce return type of 'operator<=>' because type '%0' was not found; "
|
||||
"include <compare>">;
|
||||
"cannot %select{use builtin operator '<=>'|default 'operator<=>'}1 "
|
||||
"because type '%0' was not found; include <compare>">;
|
||||
def err_spaceship_argument_narrowing : Error<
|
||||
"argument to 'operator<=>' "
|
||||
"%select{cannot be narrowed from type %1 to %2|"
|
||||
|
|
@ -9980,6 +10255,8 @@ def err_std_compare_type_not_supported : Error<
|
|||
"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">;
|
||||
def err_three_way_vector_comparison : Error<
|
||||
"three-way comparison between vectors is not supported">;
|
||||
|
||||
// Memory Tagging Extensions (MTE) diagnostics
|
||||
def err_memtag_arg_null_or_pointer : Error<
|
||||
|
|
@ -10013,4 +10290,19 @@ 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<
|
||||
"__builtin_bit_cast source size does not equal destination size (%0 vs %1)">;
|
||||
|
||||
// SYCL-specific diagnostics
|
||||
def warn_sycl_kernel_num_of_template_params : Warning<
|
||||
"'sycl_kernel' attribute only applies to a function template with at least"
|
||||
" two template parameters">, InGroup<IgnoredAttributes>;
|
||||
def warn_sycl_kernel_invalid_template_param_type : Warning<
|
||||
"template parameter of a function template with the 'sycl_kernel' attribute"
|
||||
" cannot be a non-type template parameter">, InGroup<IgnoredAttributes>;
|
||||
def warn_sycl_kernel_num_of_function_params : Warning<
|
||||
"function template with 'sycl_kernel' attribute must have a single parameter">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
def warn_sycl_kernel_return_type : Warning<
|
||||
"function template with 'sycl_kernel' attribute must have a 'void' return type">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
|
||||
} // end of sema component.
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ def note_module_file_imported_by : Note<
|
|||
"imported by %select{|module '%2' in }1'%0'">;
|
||||
def err_module_file_not_module : Error<
|
||||
"AST file '%0' was not built as a module">, DefaultFatal;
|
||||
def err_module_file_missing_top_level_submodule : Error<
|
||||
"module file '%0' is missing its top-level submodule">, DefaultFatal;
|
||||
|
||||
def remark_module_import : Remark<
|
||||
"importing module '%0'%select{| into '%3'}2 from '%1'">,
|
||||
|
|
|
|||
|
|
@ -222,8 +222,8 @@ class FileManager : public RefCountedBase<FileManager> {
|
|||
llvm::BumpPtrAllocator>
|
||||
SeenFileEntries;
|
||||
|
||||
/// The canonical names of directories.
|
||||
llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames;
|
||||
/// The canonical names of files and directories .
|
||||
llvm::DenseMap<const void *, llvm::StringRef> CanonicalNames;
|
||||
|
||||
/// Storage for canonical names that we have computed.
|
||||
llvm::BumpPtrAllocator CanonicalNameStorage;
|
||||
|
|
@ -421,6 +421,13 @@ public:
|
|||
/// required, which is (almost) never.
|
||||
StringRef getCanonicalName(const DirectoryEntry *Dir);
|
||||
|
||||
/// Retrieve the canonical name for a given file.
|
||||
///
|
||||
/// This is a very expensive operation, despite its results being cached,
|
||||
/// and should only be used when the physical layout of the file system is
|
||||
/// required, which is (almost) never.
|
||||
StringRef getCanonicalName(const FileEntry *File);
|
||||
|
||||
void PrintStats() const;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -384,6 +384,17 @@ public:
|
|||
return getName().startswith("<#") && getName().endswith("#>");
|
||||
}
|
||||
|
||||
/// Determine whether \p this is a name reserved for the implementation (C99
|
||||
/// 7.1.3, C++ [lib.global.names]).
|
||||
bool isReservedName(bool doubleUnderscoreOnly = false) const {
|
||||
if (getLength() < 2)
|
||||
return false;
|
||||
const char *Name = getNameStart();
|
||||
return Name[0] == '_' &&
|
||||
(Name[1] == '_' ||
|
||||
(Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
|
||||
}
|
||||
|
||||
/// Provide less than operator for lexicographical sorting.
|
||||
bool operator<(const IdentifierInfo &RHS) const {
|
||||
return getName() < RHS.getName();
|
||||
|
|
@ -581,6 +592,8 @@ public:
|
|||
iterator end() const { return HashTable.end(); }
|
||||
unsigned size() const { return HashTable.size(); }
|
||||
|
||||
iterator find(StringRef Name) const { return HashTable.find(Name); }
|
||||
|
||||
/// Print some statistics to stderr that indicate how well the
|
||||
/// hashing is doing.
|
||||
void PrintStats() const;
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ LANGOPT(WritableStrings , 1, 0, "writable string support")
|
|||
LANGOPT(ConstStrings , 1, 0, "const-qualified string support")
|
||||
ENUM_LANGOPT(LaxVectorConversions, LaxVectorConversionKind, 2,
|
||||
LaxVectorConversionKind::All, "lax vector conversions")
|
||||
LANGOPT(ConvergentFunctions, 1, 1, "Assume convergent functions")
|
||||
LANGOPT(AltiVec , 1, 0, "AltiVec-style vector initializers")
|
||||
LANGOPT(ZVector , 1, 0, "System z vector extensions")
|
||||
LANGOPT(Exceptions , 1, 0, "exception handling")
|
||||
|
|
@ -212,6 +213,7 @@ LANGOPT(OpenMPSimd , 1, 0, "Use SIMD only OpenMP support.")
|
|||
LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
|
||||
LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device")
|
||||
LANGOPT(OpenMPCUDAMode , 1, 0, "Generate code for OpenMP pragmas in SIMT/SPMD mode")
|
||||
LANGOPT(OpenMPIRBuilder , 1, 0, "Use the experimental OpenMP-IR-Builder codegen path.")
|
||||
LANGOPT(OpenMPCUDAForceFullRuntime , 1, 0, "Force to use full runtime in all constructs when offloading to CUDA devices")
|
||||
LANGOPT(OpenMPCUDANumSMs , 32, 0, "Number of SMs for CUDA devices.")
|
||||
LANGOPT(OpenMPCUDABlocksPerSM , 32, 0, "Number of blocks per SM for CUDA devices.")
|
||||
|
|
@ -224,6 +226,8 @@ LANGOPT(CUDAAllowVariadicFunctions, 1, 0, "allowing variadic functions in CUDA d
|
|||
LANGOPT(CUDAHostDeviceConstexpr, 1, 1, "treating unattributed constexpr functions as __host__ __device__")
|
||||
LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental functions")
|
||||
LANGOPT(GPURelocatableDeviceCode, 1, 0, "generate relocatable device code")
|
||||
LANGOPT(GPUAllowDeviceInit, 1, 0, "allowing device side global init functions for HIP")
|
||||
LANGOPT(GPUMaxThreadsPerBlock, 32, 256, "default max threads per block for kernel launch bounds for HIP")
|
||||
|
||||
LANGOPT(SYCLIsDevice , 1, 0, "Generate code for SYCL device")
|
||||
|
||||
|
|
@ -253,6 +257,8 @@ LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating poi
|
|||
LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math")
|
||||
/// FP_CONTRACT mode (on/off/fast).
|
||||
ENUM_LANGOPT(DefaultFPContractMode, FPContractModeKind, 2, FPC_Off, "FP contraction type")
|
||||
ENUM_LANGOPT(FPRoundingMode, FPRoundingModeKind, 3, FPR_ToNearest, "FP Rounding Mode type")
|
||||
ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Ignore, "FP Exception Behavior Mode type")
|
||||
LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
|
||||
LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
|
||||
LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
|
||||
|
|
@ -295,14 +301,13 @@ 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,
|
||||
"if non-zero, warn about parameter or return Warn if parameter/return value is larger in bytes than this setting. 0 is no check.")
|
||||
VALUE_LANGOPT(MSCompatibilityVersion, 32, 0, "Microsoft Visual C/C++ Version")
|
||||
VALUE_LANGOPT(VtorDispMode, 2, 1, "How many vtordisps to insert")
|
||||
ENUM_LANGOPT(VtorDispMode, MSVtorDispMode, 2, MSVtorDispMode::ForVBaseOverride,
|
||||
"How many vtordisps to insert")
|
||||
|
||||
LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling")
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ protected:
|
|||
#include "clang/Basic/LangOptions.def"
|
||||
};
|
||||
|
||||
/// In the Microsoft ABI, this controls the placement of virtual displacement
|
||||
/// members used to implement virtual inheritance.
|
||||
enum class MSVtorDispMode { Never, ForVBaseOverride, ForVFTable };
|
||||
|
||||
/// Keeps track of the various options that can be
|
||||
/// enabled, which controls the dialect of C or C++ that is accepted.
|
||||
class LangOptions : public LangOptionsBase {
|
||||
|
|
@ -91,6 +95,8 @@ public:
|
|||
PPTMK_FullGeneralityVirtualInheritance
|
||||
};
|
||||
|
||||
using MSVtorDispMode = clang::MSVtorDispMode;
|
||||
|
||||
enum DefaultCallingConvention {
|
||||
DCC_None,
|
||||
DCC_CDecl,
|
||||
|
|
@ -184,6 +190,34 @@ public:
|
|||
FEA_On
|
||||
};
|
||||
|
||||
// Values of the following enumerations correspond to metadata arguments
|
||||
// specified for constrained floating-point intrinsics:
|
||||
// http://llvm.org/docs/LangRef.html#constrained-floating-point-intrinsics.
|
||||
|
||||
/// Possible rounding modes.
|
||||
enum FPRoundingModeKind {
|
||||
/// Rounding to nearest, corresponds to "round.tonearest".
|
||||
FPR_ToNearest,
|
||||
/// Rounding toward -Inf, corresponds to "round.downward".
|
||||
FPR_Downward,
|
||||
/// Rounding toward +Inf, corresponds to "round.upward".
|
||||
FPR_Upward,
|
||||
/// Rounding toward zero, corresponds to "round.towardzero".
|
||||
FPR_TowardZero,
|
||||
/// Is determined by runtime environment, corresponds to "round.dynamic".
|
||||
FPR_Dynamic
|
||||
};
|
||||
|
||||
/// Possible floating point exception behavior.
|
||||
enum FPExceptionModeKind {
|
||||
/// Assume that floating-point exceptions are masked.
|
||||
FPE_Ignore,
|
||||
/// Transformations do not cause new exceptions but may hide some.
|
||||
FPE_MayTrap,
|
||||
/// Strictly preserve the floating-point exception semantics.
|
||||
FPE_Strict
|
||||
};
|
||||
|
||||
enum class LaxVectorConversionKind {
|
||||
/// Permit no implicit vector bitcasts.
|
||||
None,
|
||||
|
|
@ -312,7 +346,7 @@ public:
|
|||
}
|
||||
|
||||
bool assumeFunctionsAreConvergent() const {
|
||||
return (CUDA && CUDAIsDevice) || OpenCL;
|
||||
return ConvergentFunctions;
|
||||
}
|
||||
|
||||
/// Return the OpenCL C or C++ version as a VersionTuple.
|
||||
|
|
|
|||
|
|
@ -446,6 +446,20 @@ public:
|
|||
llvm_unreachable("bad kind");
|
||||
}
|
||||
|
||||
/// Does this runtime supports direct dispatch
|
||||
bool allowsDirectDispatch() const {
|
||||
switch (getKind()) {
|
||||
case FragileMacOSX: return false;
|
||||
case MacOSX: return true;
|
||||
case iOS: return true;
|
||||
case WatchOS: return true;
|
||||
case GCC: return false;
|
||||
case GNUstep: return false;
|
||||
case ObjFW: return false;
|
||||
}
|
||||
llvm_unreachable("bad kind");
|
||||
}
|
||||
|
||||
/// Try to parse an Objective-C runtime specification from the given
|
||||
/// string.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -11,12 +11,6 @@
|
|||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_DIRECTIVE
|
||||
# define OPENMP_DIRECTIVE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DIRECTIVE_EXT
|
||||
#define OPENMP_DIRECTIVE_EXT(Name, Str)
|
||||
#endif
|
||||
#ifndef OPENMP_CLAUSE
|
||||
# define OPENMP_CLAUSE(Name, Class)
|
||||
#endif
|
||||
|
|
@ -44,6 +38,9 @@
|
|||
#ifndef OPENMP_PARALLEL_FOR_SIMD_CLAUSE
|
||||
# define OPENMP_PARALLEL_FOR_SIMD_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_PARALLEL_MASTER_CLAUSE
|
||||
# define OPENMP_PARALLEL_MASTER_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_PARALLEL_SECTIONS_CLAUSE
|
||||
# define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name)
|
||||
#endif
|
||||
|
|
@ -101,6 +98,9 @@
|
|||
#ifndef OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE
|
||||
# define OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE
|
||||
# define OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_CRITICAL_CLAUSE
|
||||
# define OPENMP_CRITICAL_CLAUSE(Name)
|
||||
#endif
|
||||
|
|
@ -110,9 +110,6 @@
|
|||
#ifndef OPENMP_DEFAULT_KIND
|
||||
# define OPENMP_DEFAULT_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_PROC_BIND_KIND
|
||||
# define OPENMP_PROC_BIND_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_SCHEDULE_KIND
|
||||
#define OPENMP_SCHEDULE_KIND(Name)
|
||||
#endif
|
||||
|
|
@ -206,70 +203,23 @@
|
|||
#ifndef OPENMP_DECLARE_VARIANT_CLAUSE
|
||||
#define OPENMP_DECLARE_VARIANT_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_MATCH_KIND
|
||||
#define OPENMP_MATCH_KIND(Name)
|
||||
#ifndef OPENMP_CONTEXT_SELECTOR_SET
|
||||
#define OPENMP_CONTEXT_SELECTOR_SET(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_CONTEXT_SELECTOR
|
||||
#define OPENMP_CONTEXT_SELECTOR(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_LASTPRIVATE_KIND
|
||||
#define OPENMP_LASTPRIVATE_KIND(Name)
|
||||
#endif
|
||||
|
||||
// OpenMP directives.
|
||||
OPENMP_DIRECTIVE(threadprivate)
|
||||
OPENMP_DIRECTIVE(parallel)
|
||||
OPENMP_DIRECTIVE(task)
|
||||
OPENMP_DIRECTIVE(simd)
|
||||
OPENMP_DIRECTIVE(for)
|
||||
OPENMP_DIRECTIVE(sections)
|
||||
OPENMP_DIRECTIVE(section)
|
||||
OPENMP_DIRECTIVE(single)
|
||||
OPENMP_DIRECTIVE(master)
|
||||
OPENMP_DIRECTIVE(critical)
|
||||
OPENMP_DIRECTIVE(taskyield)
|
||||
OPENMP_DIRECTIVE(barrier)
|
||||
OPENMP_DIRECTIVE(taskwait)
|
||||
OPENMP_DIRECTIVE(taskgroup)
|
||||
OPENMP_DIRECTIVE(flush)
|
||||
OPENMP_DIRECTIVE(ordered)
|
||||
OPENMP_DIRECTIVE(atomic)
|
||||
OPENMP_DIRECTIVE(target)
|
||||
OPENMP_DIRECTIVE(teams)
|
||||
OPENMP_DIRECTIVE(cancel)
|
||||
OPENMP_DIRECTIVE(requires)
|
||||
OPENMP_DIRECTIVE_EXT(target_data, "target data")
|
||||
OPENMP_DIRECTIVE_EXT(target_enter_data, "target enter data")
|
||||
OPENMP_DIRECTIVE_EXT(target_exit_data, "target exit data")
|
||||
OPENMP_DIRECTIVE_EXT(target_parallel, "target parallel")
|
||||
OPENMP_DIRECTIVE_EXT(target_parallel_for, "target parallel for")
|
||||
OPENMP_DIRECTIVE_EXT(target_update, "target update")
|
||||
OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for")
|
||||
OPENMP_DIRECTIVE_EXT(parallel_for_simd, "parallel for simd")
|
||||
OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
|
||||
OPENMP_DIRECTIVE_EXT(for_simd, "for simd")
|
||||
OPENMP_DIRECTIVE_EXT(cancellation_point, "cancellation point")
|
||||
OPENMP_DIRECTIVE_EXT(declare_reduction, "declare reduction")
|
||||
OPENMP_DIRECTIVE_EXT(declare_mapper, "declare mapper")
|
||||
OPENMP_DIRECTIVE_EXT(declare_simd, "declare simd")
|
||||
OPENMP_DIRECTIVE(taskloop)
|
||||
OPENMP_DIRECTIVE_EXT(taskloop_simd, "taskloop simd")
|
||||
OPENMP_DIRECTIVE(distribute)
|
||||
OPENMP_DIRECTIVE_EXT(declare_target, "declare target")
|
||||
OPENMP_DIRECTIVE_EXT(end_declare_target, "end declare target")
|
||||
OPENMP_DIRECTIVE_EXT(distribute_parallel_for, "distribute parallel for")
|
||||
OPENMP_DIRECTIVE_EXT(distribute_parallel_for_simd, "distribute parallel for simd")
|
||||
OPENMP_DIRECTIVE_EXT(distribute_simd, "distribute simd")
|
||||
OPENMP_DIRECTIVE_EXT(target_parallel_for_simd, "target parallel for simd")
|
||||
OPENMP_DIRECTIVE_EXT(target_simd, "target simd")
|
||||
OPENMP_DIRECTIVE_EXT(teams_distribute, "teams distribute")
|
||||
OPENMP_DIRECTIVE_EXT(teams_distribute_simd, "teams distribute simd")
|
||||
OPENMP_DIRECTIVE_EXT(teams_distribute_parallel_for_simd, "teams distribute parallel for simd")
|
||||
OPENMP_DIRECTIVE_EXT(teams_distribute_parallel_for, "teams distribute parallel for")
|
||||
OPENMP_DIRECTIVE_EXT(target_teams, "target teams")
|
||||
OPENMP_DIRECTIVE_EXT(target_teams_distribute, "target teams distribute")
|
||||
OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for, "target teams distribute parallel for")
|
||||
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 context selector sets.
|
||||
OPENMP_CONTEXT_SELECTOR_SET(implementation)
|
||||
OPENMP_CONTEXT_SELECTOR_SET(device)
|
||||
|
||||
// OpenMP context selectors.
|
||||
OPENMP_CONTEXT_SELECTOR(vendor)
|
||||
OPENMP_CONTEXT_SELECTOR(kind)
|
||||
|
||||
// OpenMP clauses.
|
||||
OPENMP_CLAUSE(allocator, OMPAllocatorClause)
|
||||
|
|
@ -327,6 +277,7 @@ OPENMP_CLAUSE(reverse_offload, OMPReverseOffloadClause)
|
|||
OPENMP_CLAUSE(dynamic_allocators, OMPDynamicAllocatorsClause)
|
||||
OPENMP_CLAUSE(atomic_default_mem_order, OMPAtomicDefaultMemOrderClause)
|
||||
OPENMP_CLAUSE(allocate, OMPAllocateClause)
|
||||
OPENMP_CLAUSE(nontemporal, OMPNontemporalClause)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel'.
|
||||
OPENMP_PARALLEL_CLAUSE(if)
|
||||
|
|
@ -350,6 +301,8 @@ OPENMP_SIMD_CLAUSE(simdlen)
|
|||
OPENMP_SIMD_CLAUSE(collapse)
|
||||
OPENMP_SIMD_CLAUSE(reduction)
|
||||
OPENMP_SIMD_CLAUSE(allocate)
|
||||
OPENMP_SIMD_CLAUSE(if)
|
||||
OPENMP_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for directive 'omp for'.
|
||||
OPENMP_FOR_CLAUSE(private)
|
||||
|
|
@ -377,6 +330,8 @@ OPENMP_FOR_SIMD_CLAUSE(linear)
|
|||
OPENMP_FOR_SIMD_CLAUSE(aligned)
|
||||
OPENMP_FOR_SIMD_CLAUSE(ordered)
|
||||
OPENMP_FOR_SIMD_CLAUSE(allocate)
|
||||
OPENMP_FOR_SIMD_CLAUSE(if)
|
||||
OPENMP_FOR_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'omp sections'.
|
||||
OPENMP_SECTIONS_CLAUSE(private)
|
||||
|
|
@ -400,11 +355,6 @@ OPENMP_CANCEL_CLAUSE(if)
|
|||
OPENMP_DEFAULT_KIND(none)
|
||||
OPENMP_DEFAULT_KIND(shared)
|
||||
|
||||
// Static attributes for 'proc_bind' clause.
|
||||
OPENMP_PROC_BIND_KIND(master)
|
||||
OPENMP_PROC_BIND_KIND(close)
|
||||
OPENMP_PROC_BIND_KIND(spread)
|
||||
|
||||
// Static attributes for 'schedule' clause.
|
||||
OPENMP_SCHEDULE_KIND(static)
|
||||
OPENMP_SCHEDULE_KIND(dynamic)
|
||||
|
|
@ -419,9 +369,17 @@ OPENMP_SCHEDULE_MODIFIER(simd)
|
|||
|
||||
// Static attributes for 'defaultmap' clause.
|
||||
OPENMP_DEFAULTMAP_KIND(scalar)
|
||||
OPENMP_DEFAULTMAP_KIND(aggregate)
|
||||
OPENMP_DEFAULTMAP_KIND(pointer)
|
||||
|
||||
// Modifiers for 'defaultmap' clause.
|
||||
OPENMP_DEFAULTMAP_MODIFIER(alloc)
|
||||
OPENMP_DEFAULTMAP_MODIFIER(to)
|
||||
OPENMP_DEFAULTMAP_MODIFIER(from)
|
||||
OPENMP_DEFAULTMAP_MODIFIER(tofrom)
|
||||
OPENMP_DEFAULTMAP_MODIFIER(firstprivate)
|
||||
OPENMP_DEFAULTMAP_MODIFIER(none)
|
||||
OPENMP_DEFAULTMAP_MODIFIER(default)
|
||||
|
||||
// Static attributes for 'depend' clause.
|
||||
OPENMP_DEPEND_KIND(in)
|
||||
|
|
@ -472,6 +430,19 @@ OPENMP_PARALLEL_FOR_SIMD_CLAUSE(linear)
|
|||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(aligned)
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(ordered)
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(allocate)
|
||||
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel master'.
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(if)
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(num_threads)
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(default)
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(private)
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(firstprivate)
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(shared)
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(copyin)
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(reduction)
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(proc_bind)
|
||||
OPENMP_PARALLEL_MASTER_CLAUSE(allocate)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel sections'.
|
||||
OPENMP_PARALLEL_SECTIONS_CLAUSE(if)
|
||||
|
|
@ -677,6 +648,7 @@ OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks)
|
|||
OPENMP_TASKLOOP_SIMD_CLAUSE(reduction)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(in_reduction)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(allocate)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'master taskloop'.
|
||||
OPENMP_MASTER_TASKLOOP_CLAUSE(if)
|
||||
|
|
@ -719,6 +691,7 @@ 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)
|
||||
OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel master taskloop'.
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(if)
|
||||
|
|
@ -741,6 +714,32 @@ 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 'parallel master taskloop simd'.
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(if)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(shared)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(private)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(firstprivate)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(lastprivate)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(default)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(collapse)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(final)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(untied)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(mergeable)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(priority)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(grainsize)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(nogroup)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(num_tasks)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(reduction)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(allocate)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(num_threads)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(proc_bind)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(copyin)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(linear)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(aligned)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(safelen)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_PARALLEL_MASTER_TASKLOOP_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'critical'.
|
||||
OPENMP_CRITICAL_CLAUSE(hint)
|
||||
|
||||
|
|
@ -790,6 +789,7 @@ OPENMP_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(aligned)
|
|||
OPENMP_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(safelen)
|
||||
OPENMP_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(allocate)
|
||||
OPENMP_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'distribute simd'
|
||||
OPENMP_DISTRIBUTE_SIMD_CLAUSE(private)
|
||||
|
|
@ -803,6 +803,8 @@ OPENMP_DISTRIBUTE_SIMD_CLAUSE(safelen)
|
|||
OPENMP_DISTRIBUTE_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_DISTRIBUTE_SIMD_CLAUSE(reduction)
|
||||
OPENMP_DISTRIBUTE_SIMD_CLAUSE(allocate)
|
||||
OPENMP_DISTRIBUTE_SIMD_CLAUSE(if)
|
||||
OPENMP_DISTRIBUTE_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'target parallel for simd'.
|
||||
OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(if)
|
||||
|
|
@ -828,6 +830,7 @@ OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(simdlen)
|
|||
OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(aligned)
|
||||
OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(is_device_ptr)
|
||||
OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(allocate)
|
||||
OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'target simd'.
|
||||
OPENMP_TARGET_SIMD_CLAUSE(if)
|
||||
|
|
@ -847,6 +850,7 @@ OPENMP_TARGET_SIMD_CLAUSE(simdlen)
|
|||
OPENMP_TARGET_SIMD_CLAUSE(collapse)
|
||||
OPENMP_TARGET_SIMD_CLAUSE(reduction)
|
||||
OPENMP_TARGET_SIMD_CLAUSE(allocate)
|
||||
OPENMP_TARGET_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'teams distribute'.
|
||||
OPENMP_TEAMS_DISTRIBUTE_CLAUSE(default)
|
||||
|
|
@ -877,6 +881,8 @@ OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(aligned)
|
|||
OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(safelen)
|
||||
OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(allocate)
|
||||
OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(if)
|
||||
OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'teams distribute parallel for simd'
|
||||
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(firstprivate)
|
||||
|
|
@ -898,6 +904,7 @@ OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(simdlen)
|
|||
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(num_teams)
|
||||
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(thread_limit)
|
||||
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(allocate)
|
||||
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'teams distribute parallel for'
|
||||
OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(firstprivate)
|
||||
|
|
@ -1004,6 +1011,7 @@ OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(aligned)
|
|||
OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(safelen)
|
||||
OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(allocate)
|
||||
OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'target teams distribute simd'.
|
||||
OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(if)
|
||||
|
|
@ -1027,6 +1035,7 @@ OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(aligned)
|
|||
OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(safelen)
|
||||
OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(simdlen)
|
||||
OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(allocate)
|
||||
OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(nontemporal)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'taskgroup'.
|
||||
OPENMP_TASKGROUP_CLAUSE(task_reduction)
|
||||
|
|
@ -1043,16 +1052,18 @@ 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)
|
||||
// Type of the 'lastprivate' clause.
|
||||
OPENMP_LASTPRIVATE_KIND(conditional)
|
||||
|
||||
#undef OPENMP_MATCH_KIND
|
||||
#undef OPENMP_LASTPRIVATE_KIND
|
||||
#undef OPENMP_CONTEXT_SELECTOR
|
||||
#undef OPENMP_CONTEXT_SELECTOR_SET
|
||||
#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_SIMD_CLAUSE
|
||||
#undef OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE
|
||||
#undef OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE
|
||||
#undef OPENMP_MASTER_TASKLOOP_CLAUSE
|
||||
|
|
@ -1062,10 +1073,7 @@ OPENMP_MATCH_KIND(implementation)
|
|||
#undef OPENMP_DEPEND_KIND
|
||||
#undef OPENMP_SCHEDULE_MODIFIER
|
||||
#undef OPENMP_SCHEDULE_KIND
|
||||
#undef OPENMP_PROC_BIND_KIND
|
||||
#undef OPENMP_DEFAULT_KIND
|
||||
#undef OPENMP_DIRECTIVE
|
||||
#undef OPENMP_DIRECTIVE_EXT
|
||||
#undef OPENMP_CLAUSE
|
||||
#undef OPENMP_CRITICAL_CLAUSE
|
||||
#undef OPENMP_ORDERED_CLAUSE
|
||||
|
|
@ -1075,6 +1083,7 @@ OPENMP_MATCH_KIND(implementation)
|
|||
#undef OPENMP_PARALLEL_CLAUSE
|
||||
#undef OPENMP_PARALLEL_FOR_CLAUSE
|
||||
#undef OPENMP_PARALLEL_FOR_SIMD_CLAUSE
|
||||
#undef OPENMP_PARALLEL_MASTER_CLAUSE
|
||||
#undef OPENMP_PARALLEL_SECTIONS_CLAUSE
|
||||
#undef OPENMP_TASK_CLAUSE
|
||||
#undef OPENMP_ATOMIC_CLAUSE
|
||||
|
|
|
|||
|
|
@ -15,19 +15,52 @@
|
|||
#define LLVM_CLANG_BASIC_OPENMPKINDS_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Frontend/OpenMP/OMPConstants.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// OpenMP directives.
|
||||
enum OpenMPDirectiveKind {
|
||||
#define OPENMP_DIRECTIVE(Name) \
|
||||
OMPD_##Name,
|
||||
#define OPENMP_DIRECTIVE_EXT(Name, Str) \
|
||||
OMPD_##Name,
|
||||
/// OpenMP context selector sets.
|
||||
enum OpenMPContextSelectorSetKind {
|
||||
#define OPENMP_CONTEXT_SELECTOR_SET(Name) OMP_CTX_SET_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPD_unknown
|
||||
OMP_CTX_SET_unknown,
|
||||
};
|
||||
|
||||
/// OpenMP context selectors.
|
||||
enum OpenMPContextSelectorKind {
|
||||
#define OPENMP_CONTEXT_SELECTOR(Name) OMP_CTX_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMP_CTX_unknown,
|
||||
};
|
||||
|
||||
OpenMPContextSelectorSetKind getOpenMPContextSelectorSet(llvm::StringRef Str);
|
||||
llvm::StringRef
|
||||
getOpenMPContextSelectorSetName(OpenMPContextSelectorSetKind Kind);
|
||||
OpenMPContextSelectorKind getOpenMPContextSelector(llvm::StringRef Str);
|
||||
llvm::StringRef getOpenMPContextSelectorName(OpenMPContextSelectorKind Kind);
|
||||
|
||||
/// Struct to store the context selectors info.
|
||||
template <typename VectorType, typename ScoreT> struct OpenMPCtxSelectorData {
|
||||
OpenMPContextSelectorSetKind CtxSet = OMP_CTX_SET_unknown;
|
||||
OpenMPContextSelectorKind Ctx = OMP_CTX_unknown;
|
||||
ScoreT Score;
|
||||
VectorType Names;
|
||||
explicit OpenMPCtxSelectorData() = default;
|
||||
explicit OpenMPCtxSelectorData(OpenMPContextSelectorSetKind CtxSet,
|
||||
OpenMPContextSelectorKind Ctx,
|
||||
const ScoreT &Score, VectorType &&Names)
|
||||
: CtxSet(CtxSet), Ctx(Ctx), Score(Score), Names(Names) {}
|
||||
template <typename U>
|
||||
explicit OpenMPCtxSelectorData(OpenMPContextSelectorSetKind CtxSet,
|
||||
OpenMPContextSelectorKind Ctx,
|
||||
const ScoreT &Score, const U &Names)
|
||||
: CtxSet(CtxSet), Ctx(Ctx), Score(Score),
|
||||
Names(Names.begin(), Names.end()) {}
|
||||
};
|
||||
|
||||
/// OpenMP directives.
|
||||
using OpenMPDirectiveKind = llvm::omp::Directive;
|
||||
|
||||
/// OpenMP clauses.
|
||||
enum OpenMPClauseKind {
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
|
|
@ -48,14 +81,6 @@ enum OpenMPDefaultClauseKind {
|
|||
OMPC_DEFAULT_unknown
|
||||
};
|
||||
|
||||
/// OpenMP attributes for 'proc_bind' clause.
|
||||
enum OpenMPProcBindClauseKind {
|
||||
#define OPENMP_PROC_BIND_KIND(Name) \
|
||||
OMPC_PROC_BIND_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_PROC_BIND_unknown
|
||||
};
|
||||
|
||||
/// OpenMP attributes for 'schedule' clause.
|
||||
enum OpenMPScheduleClauseKind {
|
||||
#define OPENMP_SCHEDULE_KIND(Name) \
|
||||
|
|
@ -162,6 +187,13 @@ enum OpenMPDeviceType {
|
|||
OMPC_DEVICE_TYPE_unknown
|
||||
};
|
||||
|
||||
/// OpenMP 'lastprivate' clause modifier.
|
||||
enum OpenMPLastprivateModifier {
|
||||
#define OPENMP_LASTPRIVATE_KIND(Name) OMPC_LASTPRIVATE_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_LASTPRIVATE_unknown,
|
||||
};
|
||||
|
||||
/// Scheduling data for loop-based OpenMP directives.
|
||||
struct OpenMPScheduleTy final {
|
||||
OpenMPScheduleClauseKind Schedule = OMPC_SCHEDULE_unknown;
|
||||
|
|
@ -169,9 +201,6 @@ struct OpenMPScheduleTy final {
|
|||
OpenMPScheduleClauseModifier M2 = OMPC_SCHEDULE_MODIFIER_unknown;
|
||||
};
|
||||
|
||||
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
|
||||
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
|
||||
|
||||
OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str);
|
||||
const char *getOpenMPClauseName(OpenMPClauseKind Kind);
|
||||
|
||||
|
|
@ -179,7 +208,8 @@ unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str);
|
|||
const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type);
|
||||
|
||||
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
|
||||
OpenMPClauseKind CKind);
|
||||
OpenMPClauseKind CKind,
|
||||
unsigned OpenMPVersion);
|
||||
|
||||
/// Checks if the specified directive is a directive with an associated
|
||||
/// loop construct.
|
||||
|
|
@ -269,8 +299,8 @@ bool isOpenMPPrivate(OpenMPClauseKind Kind);
|
|||
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind);
|
||||
|
||||
/// Checks if the specified directive kind is one of tasking directives - task,
|
||||
/// taskloop, taksloop simd, master taskloop, parallel master taskloop or master
|
||||
/// taskloop simd.
|
||||
/// taskloop, taksloop simd, master taskloop, parallel master taskloop, master
|
||||
/// taskloop simd, or parallel master taskloop simd.
|
||||
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind);
|
||||
|
||||
/// Checks if the specified directive kind is one of the composite or combined
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
|
||||
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/PartialDiagnostic.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "clang/Basic/Sanitizers.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/SpecialCaseList.h"
|
||||
#include "llvm/Support/VirtualFileSystem.h"
|
||||
#include <memory>
|
||||
|
||||
namespace clang {
|
||||
|
|
@ -24,10 +25,12 @@ namespace clang {
|
|||
class SanitizerSpecialCaseList : public llvm::SpecialCaseList {
|
||||
public:
|
||||
static std::unique_ptr<SanitizerSpecialCaseList>
|
||||
create(const std::vector<std::string> &Paths, std::string &Error);
|
||||
create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS,
|
||||
std::string &Error);
|
||||
|
||||
static std::unique_ptr<SanitizerSpecialCaseList>
|
||||
createOrDie(const std::vector<std::string> &Paths);
|
||||
createOrDie(const std::vector<std::string> &Paths,
|
||||
llvm::vfs::FileSystem &VFS);
|
||||
|
||||
// Query blacklisted entries if any bit in Mask matches the entry's section.
|
||||
bool inSection(SanitizerMask Mask, StringRef Prefix, StringRef Query,
|
||||
|
|
|
|||
|
|
@ -52,10 +52,11 @@ public:
|
|||
|
||||
/// Create a mask with a bit enabled at position Pos.
|
||||
static constexpr SanitizerMask bitPosToMask(const unsigned Pos) {
|
||||
return SanitizerMask((Pos < kNumBitElem) ? 1ULL << Pos % kNumBitElem : 0,
|
||||
(Pos >= kNumBitElem && Pos < kNumBitElem * 2)
|
||||
? 1ULL << Pos % kNumBitElem
|
||||
: 0);
|
||||
uint64_t mask1 = (Pos < kNumBitElem) ? 1ULL << (Pos % kNumBitElem) : 0;
|
||||
uint64_t mask2 = (Pos >= kNumBitElem && Pos < (kNumBitElem * 2))
|
||||
? 1ULL << (Pos % kNumBitElem)
|
||||
: 0;
|
||||
return SanitizerMask(mask1, mask2);
|
||||
}
|
||||
|
||||
unsigned countPopulation() const {
|
||||
|
|
|
|||
|
|
@ -188,9 +188,20 @@ inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
|
|||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
// Ordering is meaningful only if LHS and RHS have the same FileID!
|
||||
// Otherwise use SourceManager::isBeforeInTranslationUnit().
|
||||
inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
|
||||
return LHS.getRawEncoding() < RHS.getRawEncoding();
|
||||
}
|
||||
inline bool operator>(const SourceLocation &LHS, const SourceLocation &RHS) {
|
||||
return LHS.getRawEncoding() > RHS.getRawEncoding();
|
||||
}
|
||||
inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) {
|
||||
return LHS.getRawEncoding() <= RHS.getRawEncoding();
|
||||
}
|
||||
inline bool operator>=(const SourceLocation &LHS, const SourceLocation &RHS) {
|
||||
return LHS.getRawEncoding() >= RHS.getRawEncoding();
|
||||
}
|
||||
|
||||
/// A trivial tuple used to represent a source range.
|
||||
class SourceRange {
|
||||
|
|
@ -219,6 +230,11 @@ public:
|
|||
return B != X.B || E != X.E;
|
||||
}
|
||||
|
||||
// Returns true iff other is wholly contained within this range.
|
||||
bool fullyContains(const SourceRange &other) const {
|
||||
return B <= other.B && E >= other.E;
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS, const SourceManager &SM) const;
|
||||
std::string printToString(const SourceManager &SM) const;
|
||||
void dump(const SourceManager &SM) const;
|
||||
|
|
|
|||
|
|
@ -226,6 +226,10 @@ namespace SrcMgr {
|
|||
bool shouldFreeBuffer() const {
|
||||
return (Buffer.getInt() & DoNotFreeFlag) == 0;
|
||||
}
|
||||
|
||||
// If BufStr has an invalid BOM, returns the BOM name; otherwise, returns
|
||||
// nullptr
|
||||
static const char *getInvalidBOM(StringRef BufStr);
|
||||
};
|
||||
|
||||
// Assert that the \c ContentCache objects will always be 8-byte aligned so
|
||||
|
|
@ -827,6 +831,7 @@ public:
|
|||
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
|
||||
SrcMgr::CharacteristicKind FileCharacter,
|
||||
int LoadedID = 0, unsigned LoadedOffset = 0) {
|
||||
assert(SourceFile && "Null source file!");
|
||||
const SrcMgr::ContentCache *IR =
|
||||
getOrCreateContentCache(SourceFile, isSystem(FileCharacter));
|
||||
assert(IR && "getOrCreateContentCache() cannot return NULL");
|
||||
|
|
|
|||
|
|
@ -354,6 +354,15 @@ namespace clang {
|
|||
SwiftContext
|
||||
};
|
||||
|
||||
/// Assigned inheritance model for a class in the MS C++ ABI. Must match order
|
||||
/// of spellings in MSInheritanceAttr.
|
||||
enum class MSInheritanceModel {
|
||||
Single = 0,
|
||||
Multiple = 1,
|
||||
Virtual = 2,
|
||||
Unspecified = 3,
|
||||
};
|
||||
|
||||
llvm::StringRef getParameterABISpelling(ParameterABI kind);
|
||||
} // end namespace clang
|
||||
|
||||
|
|
|
|||
|
|
@ -1,266 +1,266 @@
|
|||
class AttrSubject;
|
||||
include "clang/Basic/ASTNode.td"
|
||||
|
||||
class Stmt<bit abstract = 0> : AttrSubject {
|
||||
class StmtNode<StmtNode base, bit abstract = 0> : ASTNode, AttrSubject {
|
||||
StmtNode Base = base;
|
||||
bit Abstract = abstract;
|
||||
}
|
||||
|
||||
class DStmt<Stmt base, bit abstract = 0> : Stmt<abstract> {
|
||||
Stmt Base = base;
|
||||
}
|
||||
|
||||
// Statements
|
||||
def NullStmt : Stmt;
|
||||
def CompoundStmt : Stmt;
|
||||
def IfStmt : Stmt;
|
||||
def SwitchStmt : Stmt;
|
||||
def WhileStmt : Stmt;
|
||||
def DoStmt : Stmt;
|
||||
def ForStmt : Stmt;
|
||||
def GotoStmt : Stmt;
|
||||
def IndirectGotoStmt : Stmt;
|
||||
def ContinueStmt : Stmt;
|
||||
def BreakStmt : Stmt;
|
||||
def ReturnStmt : Stmt;
|
||||
def DeclStmt : Stmt;
|
||||
def SwitchCase : Stmt<1>;
|
||||
def CaseStmt : DStmt<SwitchCase>;
|
||||
def DefaultStmt : DStmt<SwitchCase>;
|
||||
def CapturedStmt : Stmt;
|
||||
def Stmt : StmtNode<?, 1>;
|
||||
def NullStmt : StmtNode<Stmt>;
|
||||
def CompoundStmt : StmtNode<Stmt>;
|
||||
def IfStmt : StmtNode<Stmt>;
|
||||
def SwitchStmt : StmtNode<Stmt>;
|
||||
def WhileStmt : StmtNode<Stmt>;
|
||||
def DoStmt : StmtNode<Stmt>;
|
||||
def ForStmt : StmtNode<Stmt>;
|
||||
def GotoStmt : StmtNode<Stmt>;
|
||||
def IndirectGotoStmt : StmtNode<Stmt>;
|
||||
def ContinueStmt : StmtNode<Stmt>;
|
||||
def BreakStmt : StmtNode<Stmt>;
|
||||
def ReturnStmt : StmtNode<Stmt>;
|
||||
def DeclStmt : StmtNode<Stmt>;
|
||||
def SwitchCase : StmtNode<Stmt, 1>;
|
||||
def CaseStmt : StmtNode<SwitchCase>;
|
||||
def DefaultStmt : StmtNode<SwitchCase>;
|
||||
def CapturedStmt : StmtNode<Stmt>;
|
||||
|
||||
// Statements that might produce a value (for example, as the last non-null
|
||||
// statement in a GNU statement-expression).
|
||||
def ValueStmt : Stmt<1>;
|
||||
def LabelStmt : DStmt<ValueStmt>;
|
||||
def AttributedStmt : DStmt<ValueStmt>;
|
||||
def ValueStmt : StmtNode<Stmt, 1>;
|
||||
def LabelStmt : StmtNode<ValueStmt>;
|
||||
def AttributedStmt : StmtNode<ValueStmt>;
|
||||
|
||||
// Asm statements
|
||||
def AsmStmt : Stmt<1>;
|
||||
def GCCAsmStmt : DStmt<AsmStmt>;
|
||||
def MSAsmStmt : DStmt<AsmStmt>;
|
||||
def AsmStmt : StmtNode<Stmt, 1>;
|
||||
def GCCAsmStmt : StmtNode<AsmStmt>;
|
||||
def MSAsmStmt : StmtNode<AsmStmt>;
|
||||
|
||||
// Obj-C statements
|
||||
def ObjCAtTryStmt : Stmt;
|
||||
def ObjCAtCatchStmt : Stmt;
|
||||
def ObjCAtFinallyStmt : Stmt;
|
||||
def ObjCAtThrowStmt : Stmt;
|
||||
def ObjCAtSynchronizedStmt : Stmt;
|
||||
def ObjCForCollectionStmt : Stmt;
|
||||
def ObjCAutoreleasePoolStmt : Stmt;
|
||||
def ObjCAtTryStmt : StmtNode<Stmt>;
|
||||
def ObjCAtCatchStmt : StmtNode<Stmt>;
|
||||
def ObjCAtFinallyStmt : StmtNode<Stmt>;
|
||||
def ObjCAtThrowStmt : StmtNode<Stmt>;
|
||||
def ObjCAtSynchronizedStmt : StmtNode<Stmt>;
|
||||
def ObjCForCollectionStmt : StmtNode<Stmt>;
|
||||
def ObjCAutoreleasePoolStmt : StmtNode<Stmt>;
|
||||
|
||||
// C++ statements
|
||||
def CXXCatchStmt : Stmt;
|
||||
def CXXTryStmt : Stmt;
|
||||
def CXXForRangeStmt : Stmt;
|
||||
def CXXCatchStmt : StmtNode<Stmt>;
|
||||
def CXXTryStmt : StmtNode<Stmt>;
|
||||
def CXXForRangeStmt : StmtNode<Stmt>;
|
||||
|
||||
// C++ Coroutines TS statements
|
||||
def CoroutineBodyStmt : Stmt;
|
||||
def CoreturnStmt : Stmt;
|
||||
def CoroutineBodyStmt : StmtNode<Stmt>;
|
||||
def CoreturnStmt : StmtNode<Stmt>;
|
||||
|
||||
// Expressions
|
||||
def Expr : DStmt<ValueStmt, 1>;
|
||||
def PredefinedExpr : DStmt<Expr>;
|
||||
def DeclRefExpr : DStmt<Expr>;
|
||||
def IntegerLiteral : DStmt<Expr>;
|
||||
def FixedPointLiteral : DStmt<Expr>;
|
||||
def FloatingLiteral : DStmt<Expr>;
|
||||
def ImaginaryLiteral : DStmt<Expr>;
|
||||
def StringLiteral : DStmt<Expr>;
|
||||
def CharacterLiteral : DStmt<Expr>;
|
||||
def ParenExpr : DStmt<Expr>;
|
||||
def UnaryOperator : DStmt<Expr>;
|
||||
def OffsetOfExpr : DStmt<Expr>;
|
||||
def UnaryExprOrTypeTraitExpr : DStmt<Expr>;
|
||||
def ArraySubscriptExpr : DStmt<Expr>;
|
||||
def OMPArraySectionExpr : DStmt<Expr>;
|
||||
def CallExpr : DStmt<Expr>;
|
||||
def MemberExpr : DStmt<Expr>;
|
||||
def CastExpr : DStmt<Expr, 1>;
|
||||
def BinaryOperator : DStmt<Expr>;
|
||||
def CompoundAssignOperator : DStmt<BinaryOperator>;
|
||||
def AbstractConditionalOperator : DStmt<Expr, 1>;
|
||||
def ConditionalOperator : DStmt<AbstractConditionalOperator>;
|
||||
def BinaryConditionalOperator : DStmt<AbstractConditionalOperator>;
|
||||
def ImplicitCastExpr : DStmt<CastExpr>;
|
||||
def ExplicitCastExpr : DStmt<CastExpr, 1>;
|
||||
def CStyleCastExpr : DStmt<ExplicitCastExpr>;
|
||||
def CompoundLiteralExpr : DStmt<Expr>;
|
||||
def ExtVectorElementExpr : DStmt<Expr>;
|
||||
def InitListExpr : DStmt<Expr>;
|
||||
def DesignatedInitExpr : DStmt<Expr>;
|
||||
def DesignatedInitUpdateExpr : DStmt<Expr>;
|
||||
def ImplicitValueInitExpr : DStmt<Expr>;
|
||||
def NoInitExpr : DStmt<Expr>;
|
||||
def ArrayInitLoopExpr : DStmt<Expr>;
|
||||
def ArrayInitIndexExpr : DStmt<Expr>;
|
||||
def ParenListExpr : DStmt<Expr>;
|
||||
def VAArgExpr : DStmt<Expr>;
|
||||
def GenericSelectionExpr : DStmt<Expr>;
|
||||
def PseudoObjectExpr : DStmt<Expr>;
|
||||
def SourceLocExpr : DStmt<Expr>;
|
||||
def Expr : StmtNode<ValueStmt, 1>;
|
||||
def PredefinedExpr : StmtNode<Expr>;
|
||||
def DeclRefExpr : StmtNode<Expr>;
|
||||
def IntegerLiteral : StmtNode<Expr>;
|
||||
def FixedPointLiteral : StmtNode<Expr>;
|
||||
def FloatingLiteral : StmtNode<Expr>;
|
||||
def ImaginaryLiteral : StmtNode<Expr>;
|
||||
def StringLiteral : StmtNode<Expr>;
|
||||
def CharacterLiteral : StmtNode<Expr>;
|
||||
def ParenExpr : StmtNode<Expr>;
|
||||
def UnaryOperator : StmtNode<Expr>;
|
||||
def OffsetOfExpr : StmtNode<Expr>;
|
||||
def UnaryExprOrTypeTraitExpr : StmtNode<Expr>;
|
||||
def ArraySubscriptExpr : StmtNode<Expr>;
|
||||
def OMPArraySectionExpr : StmtNode<Expr>;
|
||||
def CallExpr : StmtNode<Expr>;
|
||||
def MemberExpr : StmtNode<Expr>;
|
||||
def CastExpr : StmtNode<Expr, 1>;
|
||||
def BinaryOperator : StmtNode<Expr>;
|
||||
def CompoundAssignOperator : StmtNode<BinaryOperator>;
|
||||
def AbstractConditionalOperator : StmtNode<Expr, 1>;
|
||||
def ConditionalOperator : StmtNode<AbstractConditionalOperator>;
|
||||
def BinaryConditionalOperator : StmtNode<AbstractConditionalOperator>;
|
||||
def ImplicitCastExpr : StmtNode<CastExpr>;
|
||||
def ExplicitCastExpr : StmtNode<CastExpr, 1>;
|
||||
def CStyleCastExpr : StmtNode<ExplicitCastExpr>;
|
||||
def CompoundLiteralExpr : StmtNode<Expr>;
|
||||
def ExtVectorElementExpr : StmtNode<Expr>;
|
||||
def InitListExpr : StmtNode<Expr>;
|
||||
def DesignatedInitExpr : StmtNode<Expr>;
|
||||
def DesignatedInitUpdateExpr : StmtNode<Expr>;
|
||||
def ImplicitValueInitExpr : StmtNode<Expr>;
|
||||
def NoInitExpr : StmtNode<Expr>;
|
||||
def ArrayInitLoopExpr : StmtNode<Expr>;
|
||||
def ArrayInitIndexExpr : StmtNode<Expr>;
|
||||
def ParenListExpr : StmtNode<Expr>;
|
||||
def VAArgExpr : StmtNode<Expr>;
|
||||
def GenericSelectionExpr : StmtNode<Expr>;
|
||||
def PseudoObjectExpr : StmtNode<Expr>;
|
||||
def SourceLocExpr : StmtNode<Expr>;
|
||||
|
||||
// Wrapper expressions
|
||||
def FullExpr : DStmt<Expr, 1>;
|
||||
def ConstantExpr : DStmt<FullExpr>;
|
||||
def FullExpr : StmtNode<Expr, 1>;
|
||||
def ConstantExpr : StmtNode<FullExpr>;
|
||||
|
||||
// Atomic expressions
|
||||
def AtomicExpr : DStmt<Expr>;
|
||||
def AtomicExpr : StmtNode<Expr>;
|
||||
|
||||
// GNU Extensions.
|
||||
def AddrLabelExpr : DStmt<Expr>;
|
||||
def StmtExpr : DStmt<Expr>;
|
||||
def ChooseExpr : DStmt<Expr>;
|
||||
def GNUNullExpr : DStmt<Expr>;
|
||||
def AddrLabelExpr : StmtNode<Expr>;
|
||||
def StmtExpr : StmtNode<Expr>;
|
||||
def ChooseExpr : StmtNode<Expr>;
|
||||
def GNUNullExpr : StmtNode<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>;
|
||||
def CXXReinterpretCastExpr : DStmt<CXXNamedCastExpr>;
|
||||
def CXXConstCastExpr : DStmt<CXXNamedCastExpr>;
|
||||
def CXXFunctionalCastExpr : DStmt<ExplicitCastExpr>;
|
||||
def CXXTypeidExpr : DStmt<Expr>;
|
||||
def UserDefinedLiteral : DStmt<CallExpr>;
|
||||
def CXXBoolLiteralExpr : DStmt<Expr>;
|
||||
def CXXNullPtrLiteralExpr : DStmt<Expr>;
|
||||
def CXXThisExpr : DStmt<Expr>;
|
||||
def CXXThrowExpr : DStmt<Expr>;
|
||||
def CXXDefaultArgExpr : DStmt<Expr>;
|
||||
def CXXDefaultInitExpr : DStmt<Expr>;
|
||||
def CXXScalarValueInitExpr : DStmt<Expr>;
|
||||
def CXXStdInitializerListExpr : DStmt<Expr>;
|
||||
def CXXNewExpr : DStmt<Expr>;
|
||||
def CXXDeleteExpr : DStmt<Expr>;
|
||||
def CXXPseudoDestructorExpr : DStmt<Expr>;
|
||||
def TypeTraitExpr : DStmt<Expr>;
|
||||
def ArrayTypeTraitExpr : DStmt<Expr>;
|
||||
def ExpressionTraitExpr : DStmt<Expr>;
|
||||
def DependentScopeDeclRefExpr : DStmt<Expr>;
|
||||
def CXXConstructExpr : DStmt<Expr>;
|
||||
def CXXInheritedCtorInitExpr : DStmt<Expr>;
|
||||
def CXXBindTemporaryExpr : DStmt<Expr>;
|
||||
def ExprWithCleanups : DStmt<FullExpr>;
|
||||
def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
|
||||
def CXXUnresolvedConstructExpr : DStmt<Expr>;
|
||||
def CXXDependentScopeMemberExpr : DStmt<Expr>;
|
||||
def OverloadExpr : DStmt<Expr, 1>;
|
||||
def UnresolvedLookupExpr : DStmt<OverloadExpr>;
|
||||
def UnresolvedMemberExpr : DStmt<OverloadExpr>;
|
||||
def CXXNoexceptExpr : DStmt<Expr>;
|
||||
def PackExpansionExpr : DStmt<Expr>;
|
||||
def SizeOfPackExpr : DStmt<Expr>;
|
||||
def SubstNonTypeTemplateParmExpr : DStmt<Expr>;
|
||||
def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
|
||||
def FunctionParmPackExpr : DStmt<Expr>;
|
||||
def MaterializeTemporaryExpr : DStmt<Expr>;
|
||||
def LambdaExpr : DStmt<Expr>;
|
||||
def CXXFoldExpr : DStmt<Expr>;
|
||||
def CXXOperatorCallExpr : StmtNode<CallExpr>;
|
||||
def CXXMemberCallExpr : StmtNode<CallExpr>;
|
||||
def CXXRewrittenBinaryOperator : StmtNode<Expr>;
|
||||
def CXXNamedCastExpr : StmtNode<ExplicitCastExpr, 1>;
|
||||
def CXXStaticCastExpr : StmtNode<CXXNamedCastExpr>;
|
||||
def CXXDynamicCastExpr : StmtNode<CXXNamedCastExpr>;
|
||||
def CXXReinterpretCastExpr : StmtNode<CXXNamedCastExpr>;
|
||||
def CXXConstCastExpr : StmtNode<CXXNamedCastExpr>;
|
||||
def CXXFunctionalCastExpr : StmtNode<ExplicitCastExpr>;
|
||||
def CXXTypeidExpr : StmtNode<Expr>;
|
||||
def UserDefinedLiteral : StmtNode<CallExpr>;
|
||||
def CXXBoolLiteralExpr : StmtNode<Expr>;
|
||||
def CXXNullPtrLiteralExpr : StmtNode<Expr>;
|
||||
def CXXThisExpr : StmtNode<Expr>;
|
||||
def CXXThrowExpr : StmtNode<Expr>;
|
||||
def CXXDefaultArgExpr : StmtNode<Expr>;
|
||||
def CXXDefaultInitExpr : StmtNode<Expr>;
|
||||
def CXXScalarValueInitExpr : StmtNode<Expr>;
|
||||
def CXXStdInitializerListExpr : StmtNode<Expr>;
|
||||
def CXXNewExpr : StmtNode<Expr>;
|
||||
def CXXDeleteExpr : StmtNode<Expr>;
|
||||
def CXXPseudoDestructorExpr : StmtNode<Expr>;
|
||||
def TypeTraitExpr : StmtNode<Expr>;
|
||||
def ArrayTypeTraitExpr : StmtNode<Expr>;
|
||||
def ExpressionTraitExpr : StmtNode<Expr>;
|
||||
def DependentScopeDeclRefExpr : StmtNode<Expr>;
|
||||
def CXXConstructExpr : StmtNode<Expr>;
|
||||
def CXXInheritedCtorInitExpr : StmtNode<Expr>;
|
||||
def CXXBindTemporaryExpr : StmtNode<Expr>;
|
||||
def ExprWithCleanups : StmtNode<FullExpr>;
|
||||
def CXXTemporaryObjectExpr : StmtNode<CXXConstructExpr>;
|
||||
def CXXUnresolvedConstructExpr : StmtNode<Expr>;
|
||||
def CXXDependentScopeMemberExpr : StmtNode<Expr>;
|
||||
def OverloadExpr : StmtNode<Expr, 1>;
|
||||
def UnresolvedLookupExpr : StmtNode<OverloadExpr>;
|
||||
def UnresolvedMemberExpr : StmtNode<OverloadExpr>;
|
||||
def CXXNoexceptExpr : StmtNode<Expr>;
|
||||
def PackExpansionExpr : StmtNode<Expr>;
|
||||
def SizeOfPackExpr : StmtNode<Expr>;
|
||||
def SubstNonTypeTemplateParmExpr : StmtNode<Expr>;
|
||||
def SubstNonTypeTemplateParmPackExpr : StmtNode<Expr>;
|
||||
def FunctionParmPackExpr : StmtNode<Expr>;
|
||||
def MaterializeTemporaryExpr : StmtNode<Expr>;
|
||||
def LambdaExpr : StmtNode<Expr>;
|
||||
def CXXFoldExpr : StmtNode<Expr>;
|
||||
|
||||
// C++ Coroutines TS expressions
|
||||
def CoroutineSuspendExpr : DStmt<Expr, 1>;
|
||||
def CoawaitExpr : DStmt<CoroutineSuspendExpr>;
|
||||
def DependentCoawaitExpr : DStmt<Expr>;
|
||||
def CoyieldExpr : DStmt<CoroutineSuspendExpr>;
|
||||
def CoroutineSuspendExpr : StmtNode<Expr, 1>;
|
||||
def CoawaitExpr : StmtNode<CoroutineSuspendExpr>;
|
||||
def DependentCoawaitExpr : StmtNode<Expr>;
|
||||
def CoyieldExpr : StmtNode<CoroutineSuspendExpr>;
|
||||
|
||||
// C++2a Concepts expressions
|
||||
def ConceptSpecializationExpr : DStmt<Expr>;
|
||||
def ConceptSpecializationExpr : StmtNode<Expr>;
|
||||
|
||||
// Obj-C Expressions.
|
||||
def ObjCStringLiteral : DStmt<Expr>;
|
||||
def ObjCBoxedExpr : DStmt<Expr>;
|
||||
def ObjCArrayLiteral : DStmt<Expr>;
|
||||
def ObjCDictionaryLiteral : DStmt<Expr>;
|
||||
def ObjCEncodeExpr : DStmt<Expr>;
|
||||
def ObjCMessageExpr : DStmt<Expr>;
|
||||
def ObjCSelectorExpr : DStmt<Expr>;
|
||||
def ObjCProtocolExpr : DStmt<Expr>;
|
||||
def ObjCIvarRefExpr : DStmt<Expr>;
|
||||
def ObjCPropertyRefExpr : DStmt<Expr>;
|
||||
def ObjCIsaExpr : DStmt<Expr>;
|
||||
def ObjCIndirectCopyRestoreExpr : DStmt<Expr>;
|
||||
def ObjCBoolLiteralExpr : DStmt<Expr>;
|
||||
def ObjCSubscriptRefExpr : DStmt<Expr>;
|
||||
def ObjCAvailabilityCheckExpr : DStmt<Expr>;
|
||||
def ObjCStringLiteral : StmtNode<Expr>;
|
||||
def ObjCBoxedExpr : StmtNode<Expr>;
|
||||
def ObjCArrayLiteral : StmtNode<Expr>;
|
||||
def ObjCDictionaryLiteral : StmtNode<Expr>;
|
||||
def ObjCEncodeExpr : StmtNode<Expr>;
|
||||
def ObjCMessageExpr : StmtNode<Expr>;
|
||||
def ObjCSelectorExpr : StmtNode<Expr>;
|
||||
def ObjCProtocolExpr : StmtNode<Expr>;
|
||||
def ObjCIvarRefExpr : StmtNode<Expr>;
|
||||
def ObjCPropertyRefExpr : StmtNode<Expr>;
|
||||
def ObjCIsaExpr : StmtNode<Expr>;
|
||||
def ObjCIndirectCopyRestoreExpr : StmtNode<Expr>;
|
||||
def ObjCBoolLiteralExpr : StmtNode<Expr>;
|
||||
def ObjCSubscriptRefExpr : StmtNode<Expr>;
|
||||
def ObjCAvailabilityCheckExpr : StmtNode<Expr>;
|
||||
|
||||
// Obj-C ARC Expressions.
|
||||
def ObjCBridgedCastExpr : DStmt<ExplicitCastExpr>;
|
||||
def ObjCBridgedCastExpr : StmtNode<ExplicitCastExpr>;
|
||||
|
||||
// CUDA Expressions.
|
||||
def CUDAKernelCallExpr : DStmt<CallExpr>;
|
||||
def CUDAKernelCallExpr : StmtNode<CallExpr>;
|
||||
|
||||
// Clang Extensions.
|
||||
def ShuffleVectorExpr : DStmt<Expr>;
|
||||
def ConvertVectorExpr : DStmt<Expr>;
|
||||
def BlockExpr : DStmt<Expr>;
|
||||
def OpaqueValueExpr : DStmt<Expr>;
|
||||
def TypoExpr : DStmt<Expr>;
|
||||
def BuiltinBitCastExpr : DStmt<ExplicitCastExpr>;
|
||||
def ShuffleVectorExpr : StmtNode<Expr>;
|
||||
def ConvertVectorExpr : StmtNode<Expr>;
|
||||
def BlockExpr : StmtNode<Expr>;
|
||||
def OpaqueValueExpr : StmtNode<Expr>;
|
||||
def TypoExpr : StmtNode<Expr>;
|
||||
def BuiltinBitCastExpr : StmtNode<ExplicitCastExpr>;
|
||||
|
||||
// Microsoft Extensions.
|
||||
def MSPropertyRefExpr : DStmt<Expr>;
|
||||
def MSPropertySubscriptExpr : DStmt<Expr>;
|
||||
def CXXUuidofExpr : DStmt<Expr>;
|
||||
def SEHTryStmt : Stmt;
|
||||
def SEHExceptStmt : Stmt;
|
||||
def SEHFinallyStmt : Stmt;
|
||||
def SEHLeaveStmt : Stmt;
|
||||
def MSDependentExistsStmt : Stmt;
|
||||
def MSPropertyRefExpr : StmtNode<Expr>;
|
||||
def MSPropertySubscriptExpr : StmtNode<Expr>;
|
||||
def CXXUuidofExpr : StmtNode<Expr>;
|
||||
def SEHTryStmt : StmtNode<Stmt>;
|
||||
def SEHExceptStmt : StmtNode<Stmt>;
|
||||
def SEHFinallyStmt : StmtNode<Stmt>;
|
||||
def SEHLeaveStmt : StmtNode<Stmt>;
|
||||
def MSDependentExistsStmt : StmtNode<Stmt>;
|
||||
|
||||
// OpenCL Extensions.
|
||||
def AsTypeExpr : DStmt<Expr>;
|
||||
def AsTypeExpr : StmtNode<Expr>;
|
||||
|
||||
// OpenMP Directives.
|
||||
def OMPExecutableDirective : Stmt<1>;
|
||||
def OMPLoopDirective : DStmt<OMPExecutableDirective, 1>;
|
||||
def OMPParallelDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPForDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPForSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPSectionsDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPSectionDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPSingleDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPMasterDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPCriticalDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPParallelForDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPParallelForSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTaskDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPBarrierDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTaskwaitDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTaskgroupDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPFlushDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPOrderedDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPAtomicDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetDataDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetEnterDataDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetExitDataDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetParallelDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetParallelForDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetUpdateDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTeamsDirective : DStmt<OMPExecutableDirective>;
|
||||
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>;
|
||||
def OMPDistributeSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTargetParallelForSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTargetSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTeamsDistributeDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTeamsDistributeSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTeamsDistributeParallelForSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTeamsDistributeParallelForDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTargetTeamsDistributeDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDistributeParallelForDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDistributeParallelForSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDistributeSimdDirective : DStmt<OMPLoopDirective>;
|
||||
def OMPExecutableDirective : StmtNode<Stmt, 1>;
|
||||
def OMPLoopDirective : StmtNode<OMPExecutableDirective, 1>;
|
||||
def OMPParallelDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPForDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPForSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPSectionsDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPSectionDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPSingleDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPMasterDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPCriticalDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPParallelForDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPParallelForSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPParallelMasterDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPParallelSectionsDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTaskDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTaskyieldDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPBarrierDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTaskwaitDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTaskgroupDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPFlushDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPOrderedDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPAtomicDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTargetDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTargetDataDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTargetEnterDataDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTargetExitDataDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTargetParallelDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTargetParallelForDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTargetUpdateDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTeamsDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPCancellationPointDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPCancelDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTaskLoopDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTaskLoopSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPMasterTaskLoopDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPMasterTaskLoopSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPParallelMasterTaskLoopDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPParallelMasterTaskLoopSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPDistributeDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPDistributeParallelForDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPDistributeParallelForSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPDistributeSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTargetParallelForSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTargetSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTeamsDistributeDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTeamsDistributeSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTeamsDistributeParallelForSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTeamsDistributeParallelForDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTargetTeamsDistributeDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDistributeParallelForDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDistributeParallelForSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTargetTeamsDistributeSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
|
|
|
|||
|
|
@ -103,6 +103,12 @@ public:
|
|||
/// of these details is necessarily final yet.
|
||||
WebAssembly,
|
||||
|
||||
/// The Fuchsia ABI is a modified version of the Itanium ABI.
|
||||
///
|
||||
/// The relevant changes from the Itanium ABI are:
|
||||
/// - constructors and destructors return 'this', as in ARM.
|
||||
Fuchsia,
|
||||
|
||||
/// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and
|
||||
/// compatible compilers).
|
||||
///
|
||||
|
|
@ -133,6 +139,7 @@ public:
|
|||
/// Does this ABI generally fall into the Itanium family of ABIs?
|
||||
bool isItaniumFamily() const {
|
||||
switch (getKind()) {
|
||||
case Fuchsia:
|
||||
case GenericAArch64:
|
||||
case GenericItanium:
|
||||
case GenericARM:
|
||||
|
|
@ -152,6 +159,7 @@ public:
|
|||
/// Is this ABI an MSVC-compatible ABI?
|
||||
bool isMicrosoft() const {
|
||||
switch (getKind()) {
|
||||
case Fuchsia:
|
||||
case GenericAArch64:
|
||||
case GenericItanium:
|
||||
case GenericARM:
|
||||
|
|
@ -182,6 +190,7 @@ public:
|
|||
case WebAssembly:
|
||||
// WebAssembly doesn't require any special alignment for member functions.
|
||||
return false;
|
||||
case Fuchsia:
|
||||
case GenericARM:
|
||||
case GenericAArch64:
|
||||
case GenericMIPS:
|
||||
|
|
@ -257,6 +266,7 @@ public:
|
|||
/// done on a generic Itanium platform.
|
||||
bool canKeyFunctionBeInline() const {
|
||||
switch (getKind()) {
|
||||
case Fuchsia:
|
||||
case GenericARM:
|
||||
case iOS64:
|
||||
case WebAssembly:
|
||||
|
|
@ -277,27 +287,18 @@ public:
|
|||
/// padding of a base class?
|
||||
///
|
||||
/// This decision cannot be changed without breaking platform ABI
|
||||
/// compatibility, and yet it is tied to language guarantees which
|
||||
/// the committee has so far seen fit to strengthen no less than
|
||||
/// three separate times:
|
||||
/// - originally, there were no restrictions at all;
|
||||
/// - C++98 declared that objects could not be allocated in the
|
||||
/// tail padding of a POD type;
|
||||
/// - C++03 extended the definition of POD to include classes
|
||||
/// containing member pointers; and
|
||||
/// - C++11 greatly broadened the definition of POD to include
|
||||
/// all trivial standard-layout classes.
|
||||
/// Each of these changes technically took several existing
|
||||
/// platforms and made them permanently non-conformant.
|
||||
/// compatibility. In ISO C++98, tail padding reuse was only permitted for
|
||||
/// non-POD base classes, but that restriction was removed retroactively by
|
||||
/// DR 43, and tail padding reuse is always permitted in all de facto C++
|
||||
/// language modes. However, many platforms use a variant of the old C++98
|
||||
/// rule for compatibility.
|
||||
enum TailPaddingUseRules {
|
||||
/// The tail-padding of a base class is always theoretically
|
||||
/// available, even if it's POD. This is not strictly conforming
|
||||
/// in any language mode.
|
||||
/// available, even if it's POD.
|
||||
AlwaysUseTailPadding,
|
||||
|
||||
/// Only allocate objects in the tail padding of a base class if
|
||||
/// the base class is not POD according to the rules of C++ TR1.
|
||||
/// This is non-strictly conforming in C++11 mode.
|
||||
UseTailPaddingUnlessPOD03,
|
||||
|
||||
/// Only allocate objects in the tail padding of a base class if
|
||||
|
|
@ -318,6 +319,7 @@ public:
|
|||
|
||||
// iOS on ARM64 and WebAssembly use the C++11 POD rules. They do not honor
|
||||
// the Itanium exception about classes with over-large bitfields.
|
||||
case Fuchsia:
|
||||
case iOS64:
|
||||
case WebAssembly:
|
||||
case WatchOS:
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "clang/Basic/AddressSpaces.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/CodeGenOptions.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Basic/TargetCXXABI.h"
|
||||
#include "clang/Basic/TargetOptions.h"
|
||||
|
|
@ -944,12 +945,14 @@ public:
|
|||
bool validateInputConstraint(MutableArrayRef<ConstraintInfo> OutputConstraints,
|
||||
ConstraintInfo &info) const;
|
||||
|
||||
virtual bool validateOutputSize(StringRef /*Constraint*/,
|
||||
virtual bool validateOutputSize(const llvm::StringMap<bool> &FeatureMap,
|
||||
StringRef /*Constraint*/,
|
||||
unsigned /*Size*/) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool validateInputSize(StringRef /*Constraint*/,
|
||||
virtual bool validateInputSize(const llvm::StringMap<bool> &FeatureMap,
|
||||
StringRef /*Constraint*/,
|
||||
unsigned /*Size*/) const {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1103,6 +1106,23 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
struct BranchProtectionInfo {
|
||||
CodeGenOptions::SignReturnAddressScope SignReturnAddr =
|
||||
CodeGenOptions::SignReturnAddressScope::None;
|
||||
CodeGenOptions::SignReturnAddressKeyValue SignKey =
|
||||
CodeGenOptions::SignReturnAddressKeyValue::AKey;
|
||||
bool BranchTargetEnforcement = false;
|
||||
};
|
||||
|
||||
/// Determine if this TargetInfo supports the given branch protection
|
||||
/// specification
|
||||
virtual bool validateBranchProtection(StringRef Spec,
|
||||
BranchProtectionInfo &BPI,
|
||||
StringRef &Err) const {
|
||||
Err = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Perform initialization based on the user configured
|
||||
/// set of features (e.g., +sse4).
|
||||
///
|
||||
|
|
@ -1126,10 +1146,7 @@ public:
|
|||
|
||||
/// Identify whether this target supports multiversioning of functions,
|
||||
/// which requires support for cpu_supports and cpu_is functionality.
|
||||
bool supportsMultiVersioning() const {
|
||||
return getTriple().getArch() == llvm::Triple::x86 ||
|
||||
getTriple().getArch() == llvm::Triple::x86_64;
|
||||
}
|
||||
bool supportsMultiVersioning() const { return getTriple().isX86(); }
|
||||
|
||||
/// Identify whether this target supports IFuncs.
|
||||
bool supportsIFunc() const { return getTriple().isOSBinFormatELF(); }
|
||||
|
|
@ -1194,8 +1211,7 @@ public:
|
|||
/// Whether the target supports SEH __try.
|
||||
bool isSEHTrySupported() const {
|
||||
return getTriple().isOSWindows() &&
|
||||
(getTriple().getArch() == llvm::Triple::x86 ||
|
||||
getTriple().getArch() == llvm::Triple::x86_64 ||
|
||||
(getTriple().isX86() ||
|
||||
getTriple().getArch() == llvm::Triple::aarch64);
|
||||
}
|
||||
|
||||
|
|
@ -1371,6 +1387,9 @@ public:
|
|||
|
||||
virtual void setAuxTarget(const TargetInfo *Aux) {}
|
||||
|
||||
/// Whether target allows debuginfo types for decl only variables.
|
||||
virtual bool allowDebugInfoForExternalVar() const { return false; }
|
||||
|
||||
protected:
|
||||
/// Copy type and layout related info.
|
||||
void copyAuxTarget(const TargetInfo *Aux);
|
||||
|
|
|
|||
|
|
@ -524,6 +524,8 @@ TYPE_TRAIT_2(__is_same, IsSame, KEYCXX)
|
|||
TYPE_TRAIT_2(__is_convertible, IsConvertible, KEYCXX)
|
||||
KEYWORD(__array_rank , KEYCXX)
|
||||
KEYWORD(__array_extent , KEYCXX)
|
||||
// Name for GCC 6 compatibility.
|
||||
ALIAS("__is_same_as", __is_same, KEYCXX)
|
||||
|
||||
// Apple Extension.
|
||||
KEYWORD(__private_extern__ , KEYALL)
|
||||
|
|
@ -727,7 +729,9 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly
|
|||
// template-id that names a type ("std::vector<int>")
|
||||
ANNOTATION(template_id) // annotation for a C++ template-id that names a
|
||||
// function template specialization (not a type),
|
||||
// e.g., "std::swap<int>"
|
||||
// e.g., "std::swap<int>", or a type-constraint (which
|
||||
// might not have explicit template arguments),
|
||||
// e.g. "C", "C<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
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
class Type<bit abstract = 0> {
|
||||
include "clang/Basic/ASTNode.td"
|
||||
|
||||
class TypeNode<TypeNode base, bit abstract = 0> : ASTNode {
|
||||
TypeNode Base = base;
|
||||
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
|
||||
|
|
@ -51,56 +50,57 @@ class NeverCanonicalUnlessDependent {}
|
|||
/// 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;
|
||||
def Type : TypeNode<?, 1>;
|
||||
def BuiltinType : TypeNode<Type>, LeafType;
|
||||
def ComplexType : TypeNode<Type>;
|
||||
def PointerType : TypeNode<Type>;
|
||||
def BlockPointerType : TypeNode<Type>;
|
||||
def ReferenceType : TypeNode<Type, 1>;
|
||||
def LValueReferenceType : TypeNode<ReferenceType>;
|
||||
def RValueReferenceType : TypeNode<ReferenceType>;
|
||||
def MemberPointerType : TypeNode<Type>;
|
||||
def ArrayType : TypeNode<Type, 1>;
|
||||
def ConstantArrayType : TypeNode<ArrayType>;
|
||||
def IncompleteArrayType : TypeNode<ArrayType>;
|
||||
def VariableArrayType : TypeNode<ArrayType>;
|
||||
def DependentSizedArrayType : TypeNode<ArrayType>, AlwaysDependent;
|
||||
def DependentSizedExtVectorType : TypeNode<Type>, AlwaysDependent;
|
||||
def DependentAddressSpaceType : TypeNode<Type>, AlwaysDependent;
|
||||
def VectorType : TypeNode<Type>;
|
||||
def DependentVectorType : TypeNode<Type>, AlwaysDependent;
|
||||
def ExtVectorType : TypeNode<VectorType>;
|
||||
def FunctionType : TypeNode<Type, 1>;
|
||||
def FunctionProtoType : TypeNode<FunctionType>;
|
||||
def FunctionNoProtoType : TypeNode<FunctionType>;
|
||||
def UnresolvedUsingType : TypeNode<Type>, AlwaysDependent;
|
||||
def ParenType : TypeNode<Type>, NeverCanonical;
|
||||
def TypedefType : TypeNode<Type>, NeverCanonical;
|
||||
def MacroQualifiedType : TypeNode<Type>, NeverCanonical;
|
||||
def AdjustedType : TypeNode<Type>, NeverCanonical;
|
||||
def DecayedType : TypeNode<AdjustedType>, NeverCanonical;
|
||||
def TypeOfExprType : TypeNode<Type>, NeverCanonicalUnlessDependent;
|
||||
def TypeOfType : TypeNode<Type>, NeverCanonicalUnlessDependent;
|
||||
def DecltypeType : TypeNode<Type>, NeverCanonicalUnlessDependent;
|
||||
def UnaryTransformType : TypeNode<Type>, NeverCanonicalUnlessDependent;
|
||||
def TagType : TypeNode<Type, 1>;
|
||||
def RecordType : TypeNode<TagType>, LeafType;
|
||||
def EnumType : TypeNode<TagType>, LeafType;
|
||||
def ElaboratedType : TypeNode<Type>, NeverCanonical;
|
||||
def AttributedType : TypeNode<Type>, NeverCanonical;
|
||||
def TemplateTypeParmType : TypeNode<Type>, AlwaysDependent, LeafType;
|
||||
def SubstTemplateTypeParmType : TypeNode<Type>, NeverCanonical;
|
||||
def SubstTemplateTypeParmPackType : TypeNode<Type>, AlwaysDependent;
|
||||
def TemplateSpecializationType : TypeNode<Type>, NeverCanonicalUnlessDependent;
|
||||
def DeducedType : TypeNode<Type, 1>;
|
||||
def AutoType : TypeNode<DeducedType>;
|
||||
def DeducedTemplateSpecializationType : TypeNode<DeducedType>;
|
||||
def InjectedClassNameType : TypeNode<Type>, AlwaysDependent, LeafType;
|
||||
def DependentNameType : TypeNode<Type>, AlwaysDependent;
|
||||
def DependentTemplateSpecializationType : TypeNode<Type>, AlwaysDependent;
|
||||
def PackExpansionType : TypeNode<Type>, NeverCanonicalUnlessDependent;
|
||||
def ObjCTypeParamType : TypeNode<Type>, NeverCanonical;
|
||||
def ObjCObjectType : TypeNode<Type>;
|
||||
def ObjCInterfaceType : TypeNode<ObjCObjectType>, LeafType;
|
||||
def ObjCObjectPointerType : TypeNode<Type>;
|
||||
def PipeType : TypeNode<Type>;
|
||||
def AtomicType : TypeNode<Type>;
|
||||
|
|
|
|||
|
|
@ -17,114 +17,118 @@ include "arm_neon_incl.td"
|
|||
let ArchGuard = "defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC) && defined(__aarch64__)" in {
|
||||
|
||||
// Negate
|
||||
def VNEGSH : SInst<"vneg", "ss", "Sh">;
|
||||
def VNEGSH : SInst<"vneg", "11", "Sh">;
|
||||
|
||||
// Reciprocal/Sqrt
|
||||
def SCALAR_FRECPSH : IInst<"vrecps", "sss", "Sh">;
|
||||
def FSQRTSH : SInst<"vsqrt", "ss", "Sh">;
|
||||
def SCALAR_FRSQRTSH : IInst<"vrsqrts", "sss", "Sh">;
|
||||
def SCALAR_FRECPSH : IInst<"vrecps", "111", "Sh">;
|
||||
def FSQRTSH : SInst<"vsqrt", "11", "Sh">;
|
||||
def SCALAR_FRSQRTSH : IInst<"vrsqrts", "111", "Sh">;
|
||||
|
||||
// Reciprocal Estimate
|
||||
def SCALAR_FRECPEH : IInst<"vrecpe", "ss", "Sh">;
|
||||
def SCALAR_FRECPEH : IInst<"vrecpe", "11", "Sh">;
|
||||
|
||||
// Reciprocal Exponent
|
||||
def SCALAR_FRECPXH : IInst<"vrecpx", "ss", "Sh">;
|
||||
def SCALAR_FRECPXH : IInst<"vrecpx", "11", "Sh">;
|
||||
|
||||
// Reciprocal Square Root Estimate
|
||||
def SCALAR_FRSQRTEH : IInst<"vrsqrte", "ss", "Sh">;
|
||||
def SCALAR_FRSQRTEH : IInst<"vrsqrte", "11", "Sh">;
|
||||
|
||||
// Rounding
|
||||
def FRINTZ_S64H : SInst<"vrnd", "ss", "Sh">;
|
||||
def FRINTA_S64H : SInst<"vrnda", "ss", "Sh">;
|
||||
def FRINTI_S64H : SInst<"vrndi", "ss", "Sh">;
|
||||
def FRINTM_S64H : SInst<"vrndm", "ss", "Sh">;
|
||||
def FRINTN_S64H : SInst<"vrndn", "ss", "Sh">;
|
||||
def FRINTP_S64H : SInst<"vrndp", "ss", "Sh">;
|
||||
def FRINTX_S64H : SInst<"vrndx", "ss", "Sh">;
|
||||
def FRINTZ_S64H : SInst<"vrnd", "11", "Sh">;
|
||||
def FRINTA_S64H : SInst<"vrnda", "11", "Sh">;
|
||||
def FRINTI_S64H : SInst<"vrndi", "11", "Sh">;
|
||||
def FRINTM_S64H : SInst<"vrndm", "11", "Sh">;
|
||||
def FRINTN_S64H : SInst<"vrndn", "11", "Sh">;
|
||||
def FRINTP_S64H : SInst<"vrndp", "11", "Sh">;
|
||||
def FRINTX_S64H : SInst<"vrndx", "11", "Sh">;
|
||||
|
||||
// Conversion
|
||||
def SCALAR_SCVTFSH : SInst<"vcvth_f16", "Ys", "silUsUiUl">;
|
||||
def SCALAR_FCVTZSH : SInst<"vcvt_s16", "$s", "Sh">;
|
||||
def SCALAR_FCVTZSH1 : SInst<"vcvt_s32", "Is", "Sh">;
|
||||
def SCALAR_FCVTZSH2 : SInst<"vcvt_s64", "Ls", "Sh">;
|
||||
def SCALAR_FCVTZUH : SInst<"vcvt_u16", "bs", "Sh">;
|
||||
def SCALAR_FCVTZUH1 : SInst<"vcvt_u32", "Us", "Sh">;
|
||||
def SCALAR_FCVTZUH2 : SInst<"vcvt_u64", "Os", "Sh">;
|
||||
def SCALAR_FCVTASH : SInst<"vcvta_s16", "$s", "Sh">;
|
||||
def SCALAR_FCVTASH1 : SInst<"vcvta_s32", "Is", "Sh">;
|
||||
def SCALAR_FCVTASH2 : SInst<"vcvta_s64", "Ls", "Sh">;
|
||||
def SCALAR_FCVTAUH : SInst<"vcvta_u16", "bs", "Sh">;
|
||||
def SCALAR_FCVTAUH1 : SInst<"vcvta_u32", "Us", "Sh">;
|
||||
def SCALAR_FCVTAUH2 : SInst<"vcvta_u64", "Os", "Sh">;
|
||||
def SCALAR_FCVTMSH : SInst<"vcvtm_s16", "$s", "Sh">;
|
||||
def SCALAR_FCVTMSH1 : SInst<"vcvtm_s32", "Is", "Sh">;
|
||||
def SCALAR_FCVTMSH2 : SInst<"vcvtm_s64", "Ls", "Sh">;
|
||||
def SCALAR_FCVTMUH : SInst<"vcvtm_u16", "bs", "Sh">;
|
||||
def SCALAR_FCVTMUH1 : SInst<"vcvtm_u32", "Us", "Sh">;
|
||||
def SCALAR_FCVTMUH2 : SInst<"vcvtm_u64", "Os", "Sh">;
|
||||
def SCALAR_FCVTNSH : SInst<"vcvtn_s16", "$s", "Sh">;
|
||||
def SCALAR_FCVTNSH1 : SInst<"vcvtn_s32", "Is", "Sh">;
|
||||
def SCALAR_FCVTNSH2 : SInst<"vcvtn_s64", "Ls", "Sh">;
|
||||
def SCALAR_FCVTNUH : SInst<"vcvtn_u16", "bs", "Sh">;
|
||||
def SCALAR_FCVTNUH1 : SInst<"vcvtn_u32", "Us", "Sh">;
|
||||
def SCALAR_FCVTNUH2 : SInst<"vcvtn_u64", "Os", "Sh">;
|
||||
def SCALAR_FCVTPSH : SInst<"vcvtp_s16", "$s", "Sh">;
|
||||
def SCALAR_FCVTPSH1 : SInst<"vcvtp_s32", "Is", "Sh">;
|
||||
def SCALAR_FCVTPSH2 : SInst<"vcvtp_s64", "Ls", "Sh">;
|
||||
def SCALAR_FCVTPUH : SInst<"vcvtp_u16", "bs", "Sh">;
|
||||
def SCALAR_FCVTPUH1 : SInst<"vcvtp_u32", "Us", "Sh">;
|
||||
def SCALAR_FCVTPUH2 : SInst<"vcvtp_u64", "Os", "Sh">;
|
||||
def SCALAR_SCVTFSH : SInst<"vcvth_f16", "(1F)(1!)", "sUs">;
|
||||
def SCALAR_SCVTFSH1 : SInst<"vcvth_f16", "(1F<)(1!)", "iUi">;
|
||||
def SCALAR_SCVTFSH2 : SInst<"vcvth_f16", "(1F<<)(1!)", "lUl">;
|
||||
def SCALAR_FCVTZSH : SInst<"vcvt_s16", "(1S)1", "Sh">;
|
||||
def SCALAR_FCVTZSH1 : SInst<"vcvt_s32", "(1S>)1", "Sh">;
|
||||
def SCALAR_FCVTZSH2 : SInst<"vcvt_s64", "(1S>>)1", "Sh">;
|
||||
def SCALAR_FCVTZUH : SInst<"vcvt_u16", "(1U)1", "Sh">;
|
||||
def SCALAR_FCVTZUH1 : SInst<"vcvt_u32", "(1U>)1", "Sh">;
|
||||
def SCALAR_FCVTZUH2 : SInst<"vcvt_u64", "(1U>>)1", "Sh">;
|
||||
def SCALAR_FCVTASH : SInst<"vcvta_s16", "(1S)1", "Sh">;
|
||||
def SCALAR_FCVTASH1 : SInst<"vcvta_s32", "(1S>)1", "Sh">;
|
||||
def SCALAR_FCVTASH2 : SInst<"vcvta_s64", "(1S>>)1", "Sh">;
|
||||
def SCALAR_FCVTAUH : SInst<"vcvta_u16", "(1U)1", "Sh">;
|
||||
def SCALAR_FCVTAUH1 : SInst<"vcvta_u32", "(1U>)1", "Sh">;
|
||||
def SCALAR_FCVTAUH2 : SInst<"vcvta_u64", "(1U>>)1", "Sh">;
|
||||
def SCALAR_FCVTMSH : SInst<"vcvtm_s16", "(1S)1", "Sh">;
|
||||
def SCALAR_FCVTMSH1 : SInst<"vcvtm_s32", "(1S>)1", "Sh">;
|
||||
def SCALAR_FCVTMSH2 : SInst<"vcvtm_s64", "(1S>>)1", "Sh">;
|
||||
def SCALAR_FCVTMUH : SInst<"vcvtm_u16", "(1U)1", "Sh">;
|
||||
def SCALAR_FCVTMUH1 : SInst<"vcvtm_u32", "(1U>)1", "Sh">;
|
||||
def SCALAR_FCVTMUH2 : SInst<"vcvtm_u64", "(1U>>)1", "Sh">;
|
||||
def SCALAR_FCVTNSH : SInst<"vcvtn_s16", "(1S)1", "Sh">;
|
||||
def SCALAR_FCVTNSH1 : SInst<"vcvtn_s32", "(1S>)1", "Sh">;
|
||||
def SCALAR_FCVTNSH2 : SInst<"vcvtn_s64", "(1S>>)1", "Sh">;
|
||||
def SCALAR_FCVTNUH : SInst<"vcvtn_u16", "(1U)1", "Sh">;
|
||||
def SCALAR_FCVTNUH1 : SInst<"vcvtn_u32", "(1U>)1", "Sh">;
|
||||
def SCALAR_FCVTNUH2 : SInst<"vcvtn_u64", "(1U>>)1", "Sh">;
|
||||
def SCALAR_FCVTPSH : SInst<"vcvtp_s16", "(1S)1", "Sh">;
|
||||
def SCALAR_FCVTPSH1 : SInst<"vcvtp_s32", "(1S>)1", "Sh">;
|
||||
def SCALAR_FCVTPSH2 : SInst<"vcvtp_s64", "(1S>>)1", "Sh">;
|
||||
def SCALAR_FCVTPUH : SInst<"vcvtp_u16", "(1U)1", "Sh">;
|
||||
def SCALAR_FCVTPUH1 : SInst<"vcvtp_u32", "(1U>)1", "Sh">;
|
||||
def SCALAR_FCVTPUH2 : SInst<"vcvtp_u64", "(1U>>)1", "Sh">;
|
||||
let isVCVT_N = 1 in {
|
||||
def SCALAR_SCVTFSHO : SInst<"vcvth_n_f16", "Ysi", "silUsUiUl">;
|
||||
def SCALAR_FCVTZSHO : SInst<"vcvt_n_s16", "$si", "Sh">;
|
||||
def SCALAR_FCVTZSH1O: SInst<"vcvt_n_s32", "Isi", "Sh">;
|
||||
def SCALAR_FCVTZSH2O: SInst<"vcvt_n_s64", "Lsi", "Sh">;
|
||||
def SCALAR_FCVTZUHO : SInst<"vcvt_n_u16", "bsi", "Sh">;
|
||||
def SCALAR_FCVTZUH1O: SInst<"vcvt_n_u32", "Usi", "Sh">;
|
||||
def SCALAR_FCVTZUH2O: SInst<"vcvt_n_u64", "Osi", "Sh">;
|
||||
def SCALAR_SCVTFSHO : SInst<"vcvth_n_f16", "(1F)(1!)I", "sUs">;
|
||||
def SCALAR_SCVTFSH1O: SInst<"vcvth_n_f16", "(1F<)(1!)I", "iUi">;
|
||||
def SCALAR_SCVTFSH2O: SInst<"vcvth_n_f16", "(1F<<)(1!)I", "lUl">;
|
||||
def SCALAR_FCVTZSHO : SInst<"vcvt_n_s16", "(1S)1I", "Sh">;
|
||||
def SCALAR_FCVTZSH1O: SInst<"vcvt_n_s32", "(1S>)1I", "Sh">;
|
||||
def SCALAR_FCVTZSH2O: SInst<"vcvt_n_s64", "(1S>>)1I", "Sh">;
|
||||
def SCALAR_FCVTZUHO : SInst<"vcvt_n_u16", "(1U)1I", "Sh">;
|
||||
def SCALAR_FCVTZUH1O: SInst<"vcvt_n_u32", "(1U>)1I", "Sh">;
|
||||
def SCALAR_FCVTZUH2O: SInst<"vcvt_n_u64", "(1U>>)1I", "Sh">;
|
||||
}
|
||||
// Comparison
|
||||
def SCALAR_CMEQRH : SInst<"vceq", "bss", "Sh">;
|
||||
def SCALAR_CMEQZH : SInst<"vceqz", "bs", "Sh">;
|
||||
def SCALAR_CMGERH : SInst<"vcge", "bss", "Sh">;
|
||||
def SCALAR_CMGEZH : SInst<"vcgez", "bs", "Sh">;
|
||||
def SCALAR_CMGTRH : SInst<"vcgt", "bss", "Sh">;
|
||||
def SCALAR_CMGTZH : SInst<"vcgtz", "bs", "Sh">;
|
||||
def SCALAR_CMLERH : SInst<"vcle", "bss", "Sh">;
|
||||
def SCALAR_CMLEZH : SInst<"vclez", "bs", "Sh">;
|
||||
def SCALAR_CMLTH : SInst<"vclt", "bss", "Sh">;
|
||||
def SCALAR_CMLTZH : SInst<"vcltz", "bs", "Sh">;
|
||||
def SCALAR_CMEQRH : SInst<"vceq", "(1U)11", "Sh">;
|
||||
def SCALAR_CMEQZH : SInst<"vceqz", "(1U)1", "Sh">;
|
||||
def SCALAR_CMGERH : SInst<"vcge", "(1U)11", "Sh">;
|
||||
def SCALAR_CMGEZH : SInst<"vcgez", "(1U)1", "Sh">;
|
||||
def SCALAR_CMGTRH : SInst<"vcgt", "(1U)11", "Sh">;
|
||||
def SCALAR_CMGTZH : SInst<"vcgtz", "(1U)1", "Sh">;
|
||||
def SCALAR_CMLERH : SInst<"vcle", "(1U)11", "Sh">;
|
||||
def SCALAR_CMLEZH : SInst<"vclez", "(1U)1", "Sh">;
|
||||
def SCALAR_CMLTH : SInst<"vclt", "(1U)11", "Sh">;
|
||||
def SCALAR_CMLTZH : SInst<"vcltz", "(1U)1", "Sh">;
|
||||
|
||||
// Absolute Compare Mask Greater Than Or Equal
|
||||
def SCALAR_FACGEH : IInst<"vcage", "bss", "Sh">;
|
||||
def SCALAR_FACLEH : IInst<"vcale", "bss", "Sh">;
|
||||
def SCALAR_FACGEH : IInst<"vcage", "(1U)11", "Sh">;
|
||||
def SCALAR_FACLEH : IInst<"vcale", "(1U)11", "Sh">;
|
||||
|
||||
// Absolute Compare Mask Greater Than
|
||||
def SCALAR_FACGT : IInst<"vcagt", "bss", "Sh">;
|
||||
def SCALAR_FACLT : IInst<"vcalt", "bss", "Sh">;
|
||||
def SCALAR_FACGT : IInst<"vcagt", "(1U)11", "Sh">;
|
||||
def SCALAR_FACLT : IInst<"vcalt", "(1U)11", "Sh">;
|
||||
|
||||
// Scalar Absolute Value
|
||||
def SCALAR_ABSH : SInst<"vabs", "ss", "Sh">;
|
||||
def SCALAR_ABSH : SInst<"vabs", "11", "Sh">;
|
||||
|
||||
// Scalar Absolute Difference
|
||||
def SCALAR_ABDH: IInst<"vabd", "sss", "Sh">;
|
||||
def SCALAR_ABDH: IInst<"vabd", "111", "Sh">;
|
||||
|
||||
// Add/Sub
|
||||
def VADDSH : SInst<"vadd", "sss", "Sh">;
|
||||
def VSUBHS : SInst<"vsub", "sss", "Sh">;
|
||||
def VADDSH : SInst<"vadd", "111", "Sh">;
|
||||
def VSUBHS : SInst<"vsub", "111", "Sh">;
|
||||
|
||||
// Max/Min
|
||||
def VMAXHS : SInst<"vmax", "sss", "Sh">;
|
||||
def VMINHS : SInst<"vmin", "sss", "Sh">;
|
||||
def FMAXNMHS : SInst<"vmaxnm", "sss", "Sh">;
|
||||
def FMINNMHS : SInst<"vminnm", "sss", "Sh">;
|
||||
def VMAXHS : SInst<"vmax", "111", "Sh">;
|
||||
def VMINHS : SInst<"vmin", "111", "Sh">;
|
||||
def FMAXNMHS : SInst<"vmaxnm", "111", "Sh">;
|
||||
def FMINNMHS : SInst<"vminnm", "111", "Sh">;
|
||||
|
||||
// Multiplication/Division
|
||||
def VMULHS : SInst<"vmul", "sss", "Sh">;
|
||||
def MULXHS : SInst<"vmulx", "sss", "Sh">;
|
||||
def FDIVHS : SInst<"vdiv", "sss", "Sh">;
|
||||
def VMULHS : SInst<"vmul", "111", "Sh">;
|
||||
def MULXHS : SInst<"vmulx", "111", "Sh">;
|
||||
def FDIVHS : SInst<"vdiv", "111", "Sh">;
|
||||
|
||||
// Vector fused multiply-add operations
|
||||
def VFMAHS : SInst<"vfma", "ssss", "Sh">;
|
||||
def VFMSHS : SInst<"vfms", "ssss", "Sh">;
|
||||
def VFMAHS : SInst<"vfma", "1111", "Sh">;
|
||||
def VFMSHS : SInst<"vfms", "1111", "Sh">;
|
||||
}
|
||||
|
|
|
|||
1004
clang/include/clang/Basic/arm_mve.td
Normal file
1004
clang/include/clang/Basic/arm_mve.td
Normal file
File diff suppressed because it is too large
Load diff
516
clang/include/clang/Basic/arm_mve_defs.td
Normal file
516
clang/include/clang/Basic/arm_mve_defs.td
Normal file
|
|
@ -0,0 +1,516 @@
|
|||
//===- arm_mve_defs.td - definitions and infrastructure for arm_mve.td ----===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The definitions in this file are designed to work in close conjunction with
|
||||
// clang/utils/TableGen/MveEmitter.cpp. Comments in there will probably be
|
||||
// useful as well.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Forward declarations.
|
||||
class Type;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Dummy record used as the dag operator for the argument list of an intrinsic.
|
||||
//
|
||||
// We store arguments as a dag rather than a list<Type> so that we can give
|
||||
// each one a name, to be used in codegen. For example, (args Vector:$a,
|
||||
// Scalar:$b) defines the names $a and $b which the specification of the code
|
||||
// for that intrinsic can refer to.
|
||||
|
||||
def args;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Family of nodes for use in the codegen dag for an intrinsic, corresponding
|
||||
// to function calls that return LLVM IR nodes.
|
||||
class IRBuilderParam<int index_> { int index = index_; }
|
||||
class IRBuilderAddrParam<int index_> : IRBuilderParam<index_>;
|
||||
class IRBuilderIntParam<int index_, string type_> : IRBuilderParam<index_> {
|
||||
string type = type_;
|
||||
}
|
||||
class IRBuilderBase {
|
||||
// The prefix of the function call, including an open parenthesis.
|
||||
string prefix;
|
||||
|
||||
// Any parameters that have types that have to be treated specially by the
|
||||
// Tablegen back end. Generally these will be types other than llvm::Value *,
|
||||
// although not all other types need special treatment (e.g. llvm::Type *).
|
||||
list<IRBuilderParam> special_params = [];
|
||||
}
|
||||
class IRBuilder<string func> : IRBuilderBase {
|
||||
// The usual case: a method called on the code gen function's instance of
|
||||
// llvm::IRBuilder.
|
||||
let prefix = "Builder." # func # "(";
|
||||
}
|
||||
class IRFunction<string func> : IRBuilderBase {
|
||||
// Some other function that doesn't use the IRBuilder at all.
|
||||
let prefix = func # "(";
|
||||
}
|
||||
class CGHelperFn<string func> : IRBuilderBase {
|
||||
// A helper function defined in CGBuiltin.cpp, which takes the IRBuilder as
|
||||
// an argument.
|
||||
let prefix = func # "(Builder, ";
|
||||
}
|
||||
def add: IRBuilder<"CreateAdd">;
|
||||
def mul: IRBuilder<"CreateMul">;
|
||||
def not: IRBuilder<"CreateNot">;
|
||||
def or: IRBuilder<"CreateOr">;
|
||||
def and: IRBuilder<"CreateAnd">;
|
||||
def xor: IRBuilder<"CreateXor">;
|
||||
def sub: IRBuilder<"CreateSub">;
|
||||
def shl: IRBuilder<"CreateShl">;
|
||||
def lshr: IRBuilder<"CreateLShr">;
|
||||
def immshr: CGHelperFn<"MVEImmediateShr"> {
|
||||
let special_params = [IRBuilderIntParam<1, "unsigned">,
|
||||
IRBuilderIntParam<2, "bool">];
|
||||
}
|
||||
def fadd: IRBuilder<"CreateFAdd">;
|
||||
def fmul: IRBuilder<"CreateFMul">;
|
||||
def fsub: IRBuilder<"CreateFSub">;
|
||||
def load: IRBuilder<"CreateLoad"> {
|
||||
let special_params = [IRBuilderAddrParam<0>];
|
||||
}
|
||||
def store: IRBuilder<"CreateStore"> {
|
||||
let special_params = [IRBuilderAddrParam<1>];
|
||||
}
|
||||
def xval: IRBuilder<"CreateExtractValue"> {
|
||||
let special_params = [IRBuilderIntParam<1, "unsigned">];
|
||||
}
|
||||
def ielt_const: IRBuilder<"CreateInsertElement"> {
|
||||
let special_params = [IRBuilderIntParam<2, "uint64_t">];
|
||||
}
|
||||
def ielt_var: IRBuilder<"CreateInsertElement">;
|
||||
def xelt_var: IRBuilder<"CreateExtractElement">;
|
||||
def trunc: IRBuilder<"CreateTrunc">;
|
||||
def bitcast: IRBuilder<"CreateBitCast">;
|
||||
def extend: CGHelperFn<"SignOrZeroExtend"> {
|
||||
let special_params = [IRBuilderIntParam<2, "bool">];
|
||||
}
|
||||
def zeroinit: IRFunction<"llvm::Constant::getNullValue">;
|
||||
def undef: IRFunction<"UndefValue::get">;
|
||||
def icmp_eq: IRBuilder<"CreateICmpEQ">;
|
||||
def icmp_ne: IRBuilder<"CreateICmpNE">;
|
||||
def icmp_ugt: IRBuilder<"CreateICmpUGT">;
|
||||
def icmp_uge: IRBuilder<"CreateICmpUGE">;
|
||||
def icmp_ult: IRBuilder<"CreateICmpULT">;
|
||||
def icmp_ule: IRBuilder<"CreateICmpULE">;
|
||||
def icmp_sgt: IRBuilder<"CreateICmpSGT">;
|
||||
def icmp_sge: IRBuilder<"CreateICmpSGE">;
|
||||
def icmp_slt: IRBuilder<"CreateICmpSLT">;
|
||||
def icmp_sle: IRBuilder<"CreateICmpSLE">;
|
||||
def fcmp_eq: IRBuilder<"CreateFCmpOEQ">;
|
||||
def fcmp_ne: IRBuilder<"CreateFCmpUNE">; // not O: it must return true on NaNs
|
||||
def fcmp_gt: IRBuilder<"CreateFCmpOGT">;
|
||||
def fcmp_ge: IRBuilder<"CreateFCmpOGE">;
|
||||
def fcmp_lt: IRBuilder<"CreateFCmpOLT">;
|
||||
def fcmp_le: IRBuilder<"CreateFCmpOLE">;
|
||||
def splat: CGHelperFn<"ARMMVEVectorSplat">;
|
||||
def select: IRBuilder<"CreateSelect">;
|
||||
|
||||
// A node that makes an Address out of a pointer-typed Value, by
|
||||
// providing an alignment as the second argument.
|
||||
def address;
|
||||
|
||||
// Another node class you can use in the codegen dag. This one corresponds to
|
||||
// an IR intrinsic function, which has to be specialized to a particular list
|
||||
// of types.
|
||||
class IRIntBase<string name_, list<Type> params_ = [], bit appendKind_ = 0> {
|
||||
string intname = name_; // base name of the intrinsic
|
||||
list<Type> params = params_; // list of parameter types
|
||||
|
||||
// If this flag is set, then the IR intrinsic name will get a suffix _s, _u
|
||||
// or _f depending on whether the main parameter type of the ACLE intrinsic
|
||||
// being generated is a signed integer, unsigned integer, or float. Mostly
|
||||
// this is useful for signed vs unsigned integers, because the ACLE
|
||||
// intrinsics and the source-level integer types distinguish them, but at IR
|
||||
// level the distinction has moved from the type system into the operations
|
||||
// and you just have i32 or i16 etc. So when an IR intrinsic has to vary with
|
||||
// signedness, you set this bit, and then you can still put the signed and
|
||||
// unsigned versions in the same subclass of Intrinsic, and the Tablegen
|
||||
// backend will take care of adding _s or _u as appropriate in each instance.
|
||||
bit appendKind = appendKind_;
|
||||
}
|
||||
|
||||
// Mostly we'll be using @llvm.arm.mve.* intrinsics, so here's a trivial
|
||||
// subclass that puts on that prefix.
|
||||
class IRInt<string name, list<Type> params = [], bit appendKind = 0>
|
||||
: IRIntBase<"arm_mve_" # name, params, appendKind>;
|
||||
|
||||
// The 'seq' node in a codegen dag specifies a set of IR operations to be
|
||||
// performed in order. It has the special ability to define extra variable
|
||||
// names, on top of the ones that refer to the intrinsic's parameters. For
|
||||
// example:
|
||||
//
|
||||
// (seq (foo this, that):$a,
|
||||
// (bar this, $a):$b
|
||||
// (add $a, $b))
|
||||
//
|
||||
// defines the name $a to refer to the return value of the 'foo' operation;
|
||||
// then the 'bar' operation uses $a as one of its arguments, and the return
|
||||
// value of that is assigned the name $b; finally, $a and $b are added to give
|
||||
// the return value of the seq construction as a whole.
|
||||
def seq;
|
||||
|
||||
// Another magic operation is 'unsignedflag', which you give a scalar
|
||||
// _type_ as an argument, and it expands into 1 for an unsigned type
|
||||
// and 0 for a signed (or floating) one.
|
||||
def unsignedflag;
|
||||
|
||||
// If you put CustomCodegen<"foo"> in an intrinsic's codegen field, it
|
||||
// indicates that the IR generation for that intrinsic is done by handwritten
|
||||
// C++ and not autogenerated at all. The effect in the MVE builtin codegen
|
||||
// function is to break out of the main switch and fall through to the
|
||||
// manual-codegen cases below it, having set the CustomCodeGenType enumerated
|
||||
// variable to the value given by the 'type' string here.
|
||||
class CustomCodegen<string type_> { string type = type_; }
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// System for building up complex instances of Type from simple ones.
|
||||
|
||||
// ComplexType is used to represent any more complicated type: vectors,
|
||||
// multivectors, pointers etc. Its dag argument specifies how the type should
|
||||
// be constructed from simpler types. The operator of the dag will always be an
|
||||
// instance of ComplexTypeOp, defined below.
|
||||
class ComplexType<dag spec_>: Type { dag spec = spec_; }
|
||||
|
||||
// Operators you can use in the ComplexType spec dag. These are an intermediate
|
||||
// layer, interpreted by MveEmitter::getType() in the Tablegen backend, and
|
||||
// only used in the definitions below. Actual intrinsic definitions in
|
||||
// arm_mve.td will use the defs defined below here.
|
||||
class ComplexTypeOp;
|
||||
def CTO_Parameter: ComplexTypeOp;
|
||||
def CTO_Vec: ComplexTypeOp;
|
||||
def CTO_Pred: ComplexTypeOp;
|
||||
class CTO_Tuple<int n_>: ComplexTypeOp { int n = n_; }
|
||||
class CTO_Pointer<bit const_>: ComplexTypeOp { bit const = const_; }
|
||||
def CTO_CopyKind: ComplexTypeOp;
|
||||
class CTO_ScaleSize<int num_, int denom_>: ComplexTypeOp {
|
||||
int num = num_;
|
||||
int denom = denom_;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Instances of Type intended to be used directly in the specification of an
|
||||
// intrinsic in arm_mve.td.
|
||||
|
||||
// The type Void can be used for the return type of an intrinsic, and as the
|
||||
// parameter type for intrinsics that aren't actually parameterised by any kind
|
||||
// of _s32 / _f16 / _u8 suffix.
|
||||
def Void : Type;
|
||||
|
||||
// A wrapper you can put on an intrinsic's argument type to prevent it from
|
||||
// being automatically promoted to i32 from a smaller integer type.
|
||||
class unpromoted<Type t> : Type { Type underlying_type = t; }
|
||||
|
||||
// Primitive types: base class, and an instance for the set of scalar integer
|
||||
// and floating types that MVE uses.
|
||||
class PrimitiveType<string kind_, int size_>: Type {
|
||||
string kind = kind_;
|
||||
int size = size_;
|
||||
string nameOverride = "";
|
||||
}
|
||||
|
||||
// The type records defined by these foreaches have names like s32, f16, u8.
|
||||
foreach size = [8, 16, 32, 64] in
|
||||
foreach kind = ["u", "s"] in
|
||||
def kind # size: PrimitiveType<kind, size>;
|
||||
foreach size = [16, 32] in
|
||||
foreach kind = ["f"] in
|
||||
def kind # size: PrimitiveType<kind, size>;
|
||||
|
||||
// Sometimes we need to refer to a type by a different name in C, when
|
||||
// ACLE defines a function parameter to be something like 'unsigned'
|
||||
// rather than uint32_t.
|
||||
def uint: PrimitiveType<"u", 32> { let nameOverride = "unsigned"; }
|
||||
def sint: PrimitiveType<"s", 32> { let nameOverride = "int"; }
|
||||
|
||||
// VecOf<t> expects t to be a scalar, and gives a 128-bit vector of whatever it
|
||||
// is.
|
||||
class VecOf<Type t>: ComplexType<(CTO_Vec t)>;
|
||||
|
||||
// NarrowedVecOf<t,v> expects t to be a scalar type, and v to be a vector
|
||||
// type. It returns a vector type whose element type is t, and whose lane
|
||||
// count is the same as the lane count of v. (Used as an intermediate value
|
||||
// type in the IR representation of a widening load: you load a vector of
|
||||
// small things out of memory, and then zext/sext them into a full 128-bit
|
||||
// output vector.)
|
||||
class NarrowedVecOf<Type t, Type v>: ComplexType<(CTO_Vec t, v)>;
|
||||
|
||||
// PredOf expects t to be a scalar, and expands to a predicate vector which
|
||||
// (logically speaking) has the same number of lanes as VecOf<t> would.
|
||||
class PredOf<Type t>: ComplexType<(CTO_Pred t)>;
|
||||
|
||||
// Scalar expands to whatever is the main parameter type of the current
|
||||
// intrinsic. Vector and Predicate expand to the vector and predicate types
|
||||
// corresponding to that.
|
||||
def Scalar: ComplexType<(CTO_Parameter)>;
|
||||
def Vector: VecOf<Scalar>;
|
||||
def Predicate: PredOf<Scalar>;
|
||||
|
||||
// MultiVector<n> expands to a type containing n instances of Vector. (There's
|
||||
// no need to define this for a general underlying vector type, since it's only
|
||||
// used by vld2q and friends, which don't need that generality.)
|
||||
class MultiVector<int n>: ComplexType<(CTO_Tuple<n> Vector)>;
|
||||
|
||||
// Ptr<t> and CPtr<t> expand to a pointer to t, or a pointer to const t,
|
||||
// respectively.
|
||||
class Ptr<Type t>: ComplexType<(CTO_Pointer<0> t)>;
|
||||
class CPtr<Type t>: ComplexType<(CTO_Pointer<1> t)>;
|
||||
|
||||
// CopyKind<s,k> expects s and k to be scalar types. It returns a scalar type
|
||||
// whose kind (signed, unsigned or float) matches that of k, and whose size
|
||||
// matches that of s.
|
||||
class CopyKind<Type s, Type k>: ComplexType<(CTO_CopyKind s, k)>;
|
||||
|
||||
// DoubleSize<k> expects k to be a scalar type. It returns a scalar type
|
||||
// whose kind (signed, unsigned or float) matches that of k, and whose size
|
||||
// is double that of k, if possible.
|
||||
class DoubleSize<Type k> : ComplexType<(CTO_ScaleSize<2, 1> k)>;
|
||||
class HalfSize<Type k> : ComplexType<(CTO_ScaleSize<1, 2> k)>;
|
||||
|
||||
// Unsigned<t> expects t to be a scalar type, and expands to the unsigned
|
||||
// integer scalar of the same size. So it returns u16 if you give it s16 or
|
||||
// f16 (or u16 itself). Similarly, Signed<t> makes the type signed.
|
||||
class Unsigned<Type t>: ComplexType<(CTO_CopyKind t, u32)>;
|
||||
class Signed<Type t>: ComplexType<(CTO_CopyKind t, s32)>;
|
||||
|
||||
// UScalar and UVector expand to the unsigned-integer versions of
|
||||
// Scalar and Vector. SScalar and SVector are signed-integer versions.
|
||||
def UScalar: Unsigned<Scalar>;
|
||||
def UVector: VecOf<UScalar>;
|
||||
def SScalar: Signed<Scalar>;
|
||||
def SVector: VecOf<SScalar>;
|
||||
|
||||
// DblVector expands to a vector of scalars of size twice the size of Scalar.
|
||||
// HalfVector, similarly, expands to a vector of half-sized scalars. And
|
||||
// UHalfVector is a vector of half-sized _unsigned integers_.
|
||||
def DblVector: VecOf<DoubleSize<Scalar>>;
|
||||
def HalfVector: VecOf<HalfSize<Scalar>>;
|
||||
def UHalfVector: VecOf<Unsigned<HalfSize<Scalar>>>;
|
||||
|
||||
// Expands to the 32-bit integer of the same signedness as Scalar.
|
||||
def Scalar32: CopyKind<u32, Scalar>;
|
||||
// Expands to the 64-bit integer of the same signedness as Scalar.
|
||||
def Scalar64: CopyKind<u64, Scalar>;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Internal definitions for specifying immediate arguments for an intrinsic.
|
||||
|
||||
class ImmediateBounds;
|
||||
class Immediate<Type type_, ImmediateBounds bounds_>: Type {
|
||||
Type type = type_;
|
||||
ImmediateBounds bounds = bounds_;
|
||||
string extra;
|
||||
string extraarg;
|
||||
}
|
||||
class IB_ConstRange<int lo_, int hi_> : ImmediateBounds {
|
||||
int lo = lo_;
|
||||
int hi = hi_;
|
||||
}
|
||||
def IB_UEltValue : ImmediateBounds;
|
||||
def IB_LaneIndex : ImmediateBounds;
|
||||
class IB_EltBit<int base_, Type type_ = Scalar> : ImmediateBounds {
|
||||
int base = base_;
|
||||
Type type = type_;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// End-user definitions for immediate arguments.
|
||||
|
||||
// imm_simd and imm_simd_restrictive are used for the immediate operands to
|
||||
// intrinsics like vmvnq or vorrq. imm_simd_restrictive has to be an 8-bit
|
||||
// value shifted left by a whole number of bytes; imm_simd_vmvn can also be of
|
||||
// the form 0xXXFF for some byte value XX.
|
||||
def imm_simd_restrictive : Immediate<u32, IB_UEltValue> {
|
||||
let extra = "ShiftedByte";
|
||||
}
|
||||
def imm_simd_vmvn : Immediate<u32, IB_UEltValue> {
|
||||
let extra = "ShiftedByteOrXXFF";
|
||||
}
|
||||
|
||||
// imm_1toN can take any value from 1 to N inclusive, where N is the number of
|
||||
// bits in the main parameter type. (E.g. an immediate shift count, in an
|
||||
// intrinsic that shifts every lane of a vector by the same amount.)
|
||||
//
|
||||
// imm_0toNm1 is the same but with the range offset by 1, i.e. 0 to N-1
|
||||
// inclusive.
|
||||
//
|
||||
// imm_1toHalfN is like imm_1toN, but applied to a half-width type.
|
||||
// (So if Scalar is s16, for example, it'll give you the range 1 to 8.)
|
||||
def imm_1toN : Immediate<sint, IB_EltBit<1>>;
|
||||
def imm_0toNm1 : Immediate<sint, IB_EltBit<0>>;
|
||||
def imm_1toHalfN : Immediate<sint, IB_EltBit<1, HalfSize<Scalar>>>;
|
||||
|
||||
// imm_lane has to be the index of a vector lane in the main vector type, i.e
|
||||
// it can range from 0 to (128 / size of scalar)-1 inclusive. (e.g. vgetq_lane)
|
||||
def imm_lane : Immediate<sint, IB_LaneIndex>;
|
||||
|
||||
// imm_1to32 can be in the range 1 to 32, unconditionally. (e.g. scalar shift
|
||||
// intrinsics)
|
||||
def imm_1to32 : Immediate<sint, IB_ConstRange<1, 32>>;
|
||||
|
||||
// imm_1248 can be 1, 2, 4 or 8. (e.g. vidupq)
|
||||
def imm_1248 : Immediate<u32, IB_ConstRange<1, 8>> {
|
||||
let extra = "Power2";
|
||||
}
|
||||
|
||||
// imm_mem7bit<n> is a valid immediate offset for a load/store intrinsic whose
|
||||
// memory access size is n bytes (e.g. 1 for vldrb_[whatever], 2 for vldrh,
|
||||
// ...). The set of valid immediates for these is {-127*n, ..., -1*n, 0*n, 1*n,
|
||||
// ..., 127*n}.
|
||||
class imm_mem7bit<int membytes>
|
||||
: Immediate<sint, IB_ConstRange<!mul(membytes, -127), !mul(membytes, 127)>> {
|
||||
let extra = !if(!eq(membytes, 1), ?, "Multiple");
|
||||
let extraarg = !cast<string>(membytes);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Specification of ways that the full name of an intrinsic can be mapped to
|
||||
// its shorter polymorphic name.
|
||||
|
||||
class PolymorphicNameType<int nt_, string x_> {
|
||||
int NumTypeSuffixesToDiscard = nt_;
|
||||
string ExtraSuffixToDiscard = x_;
|
||||
}
|
||||
|
||||
// PNT_None: the intrinsic is not polymorphic at all, so its short name is the
|
||||
// same as its long name. (E.g. scalar shift intrinsics such as uqshl.)
|
||||
def PNT_None: PolymorphicNameType<0, ?>;
|
||||
|
||||
// PNT_Type: the usual case, in which the polymorphic name is made by dropping
|
||||
// the type suffix, so it ends up the same as the Tablegen record name. E.g.
|
||||
// vaddq_u16 -> vaddq.
|
||||
def PNT_Type: PolymorphicNameType<1, ?>;
|
||||
|
||||
// PNT_2Type: the polymorphic name is made by dropping _two_ type suffixes.
|
||||
// E.g. vcvtq_f16_u16 -> vcvtq.
|
||||
def PNT_2Type: PolymorphicNameType<2, ?>;
|
||||
|
||||
// PNT_NType: the polymorphic name is made by dropping an "_n" suffix and a
|
||||
// type. E.g. vaddq_n_u16 -> vaddq.
|
||||
def PNT_NType: PolymorphicNameType<1, "n">;
|
||||
|
||||
// PNT_NType: the polymorphic name is made by just dropping an "_n" suffix
|
||||
// (even if it isn't at the end of the name). E.g. vidupq_n_u16 -> vidupq_u16.
|
||||
def PNT_N: PolymorphicNameType<0, "n">;
|
||||
|
||||
// PNT_WBType: the polymorphic name is made by dropping an "_wb" suffix and a
|
||||
// type. E.g. vidupq_m_wb_u16 -> vidupq_m.
|
||||
def PNT_WBType: PolymorphicNameType<1, "wb">;
|
||||
|
||||
// PNT_WB: the polymorphic name is made by just dropping "_wb". E.g.
|
||||
// vidupq_wb_u16 -> vidupq_u16.
|
||||
def PNT_WB: PolymorphicNameType<0, "wb">;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// The main class Intrinsic. Define one of these for each family of ACLE
|
||||
// intrinsics which are the same apart from some final type suffix (e.g.
|
||||
// vaddq_{s8,u8,f16,...}.
|
||||
//
|
||||
// The record's name plus that type suffix is taken to be the full unambiguous
|
||||
// name of the function. Its shorter polymorphic name is constructed from that
|
||||
// in turn, in a way specified by the PolymorphicNameType system above.
|
||||
|
||||
class Intrinsic<Type ret_, dag args_, dag codegen_> {
|
||||
// List of parameter types to suffix to this intrinsic's name. A separate
|
||||
// actual ACLE intrinsic will be generated for each of these. Set it to
|
||||
// [Void] if the intrinsic is not polymorphic at all.
|
||||
list<Type> params;
|
||||
|
||||
// Return type and arguments for the intrinsic.
|
||||
Type ret = ret_;
|
||||
dag args = args_;
|
||||
|
||||
// Specification of how to generate its IR.
|
||||
dag codegen = codegen_;
|
||||
|
||||
// Default to PNT_Type, which is by far the most common case.
|
||||
PolymorphicNameType pnt = PNT_Type;
|
||||
|
||||
// A very few intrinsics _only_ have a polymorphic name.
|
||||
bit polymorphicOnly = 0;
|
||||
|
||||
// True if the builtin has to avoid evaluating its arguments.
|
||||
bit nonEvaluating = 0;
|
||||
|
||||
// Use to override the suffix letter to make e.g.vfooq_p16
|
||||
// with an override suffix letter of "p".
|
||||
string overrideKindLetter = "";
|
||||
}
|
||||
|
||||
// Sometimes you have to use two separate Intrinsic declarations to
|
||||
// declare intrinsics that are logically the same family (e.g. vaddq,
|
||||
// because it needs to expand to an Add or FAdd IR node depending on
|
||||
// type). For that purpose, you can derive from NameOverride to
|
||||
// specify the intrinsic's base name independently of the Tablegen
|
||||
// record name.
|
||||
|
||||
class NameOverride<string basename_> {
|
||||
string basename = basename_;
|
||||
}
|
||||
|
||||
// A wrapper to define both _m and _x versions of a predicated
|
||||
// intrinsic.
|
||||
multiclass IntrinsicMX<Type rettype, dag arguments, dag cg,
|
||||
int wantXVariant = 1,
|
||||
string nameSuffix = "",
|
||||
PolymorphicNameType pnt_x = PNT_Type> {
|
||||
// The _m variant takes an initial parameter called $inactive, which
|
||||
// provides the input value of the output register, i.e. all the
|
||||
// inactive lanes in the predicated operation take their values from
|
||||
// this.
|
||||
def "_m" # nameSuffix:
|
||||
Intrinsic<rettype, !con((args rettype:$inactive), arguments), cg>;
|
||||
|
||||
foreach unusedVar = !if(!eq(wantXVariant, 1), [1], []<int>) in {
|
||||
// The _x variant leaves off that parameter, and simply uses an
|
||||
// undef value of the same type.
|
||||
def "_x" # nameSuffix:
|
||||
Intrinsic<rettype, arguments, (seq (undef rettype):$inactive, cg)> {
|
||||
// Allow overriding of the polymorphic name type, because
|
||||
// sometimes the _m and _x variants polymorph differently
|
||||
// (typically because the type of the inactive parameter can be
|
||||
// used as a disambiguator if it's present).
|
||||
let pnt = pnt_x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Convenience lists of parameter types. 'T' is just a container record, so you
|
||||
// can define a typical intrinsic with 'let Params = T.Usual', or similar,
|
||||
// instead of having to repeat a long list every time.
|
||||
|
||||
def T {
|
||||
list<Type> Signed = [s8, s16, s32];
|
||||
list<Type> Unsigned = [u8, u16, u32];
|
||||
list<Type> Int = Signed # Unsigned;
|
||||
list<Type> Float = [f16, f32];
|
||||
list<Type> Usual = Int # Float;
|
||||
list<Type> Int8 = [s8, u8];
|
||||
list<Type> Int16 = [s16, u16];
|
||||
list<Type> Int32 = [s32, u32];
|
||||
list<Type> Int64 = [s64, u64];
|
||||
list<Type> Poly = [u8, u16]; // Actually p8 and p16
|
||||
list<Type> All8 = Int8;
|
||||
list<Type> All16 = Int16 # [f16];
|
||||
list<Type> All32 = Int32 # [f32];
|
||||
list<Type> All64 = Int64;
|
||||
list<Type> All = Usual # All64;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Container record for DAG constant values. These constants are used because
|
||||
// bit/int class/multiclass parameters cannot be used to produce a dag node:
|
||||
// for example (u32 x) where x is 0 is transformed into (u32 { 0 }) by the
|
||||
// Tablegen parser.
|
||||
def V {
|
||||
dag False = (u32 0);
|
||||
dag True = (u32 1);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue