Vendor import of clang trunk r257626:
https://llvm.org/svn/llvm-project/cfe/trunk@257626
This commit is contained in:
parent
fc74ff5a07
commit
3a53b69070
@ -131,6 +131,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
mutable llvm::FoldingSet<AutoType> AutoTypes;
|
||||
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
|
||||
llvm::FoldingSet<AttributedType> AttributedTypes;
|
||||
mutable llvm::FoldingSet<PipeType> PipeTypes;
|
||||
|
||||
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
|
||||
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
|
||||
@ -1079,6 +1080,9 @@ public:
|
||||
/// blocks.
|
||||
QualType getBlockDescriptorType() const;
|
||||
|
||||
/// \brief Return pipe type for the specified type.
|
||||
QualType getPipeType(QualType T) const;
|
||||
|
||||
/// Gets the struct used to keep track of the extended descriptor for
|
||||
/// pointer to blocks.
|
||||
QualType getBlockDescriptorExtendedType() const;
|
||||
@ -2279,9 +2283,13 @@ public:
|
||||
/// \brief Make an APSInt of the appropriate width and signedness for the
|
||||
/// given \p Value and integer \p Type.
|
||||
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
|
||||
llvm::APSInt Res(getIntWidth(Type),
|
||||
!Type->isSignedIntegerOrEnumerationType());
|
||||
// If Type is a signed integer type larger than 64 bits, we need to be sure
|
||||
// to sign extend Res appropriately.
|
||||
llvm::APSInt Res(64, !Type->isSignedIntegerOrEnumerationType());
|
||||
Res = Value;
|
||||
unsigned Width = getIntWidth(Type);
|
||||
if (Width != Res.getBitWidth())
|
||||
return Res.extOrTrunc(Width);
|
||||
return Res;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ namespace clang {
|
||||
class ObjCContainerDecl;
|
||||
class ObjCInterfaceDecl;
|
||||
class ObjCPropertyDecl;
|
||||
class ParmVarDecl;
|
||||
class QualType;
|
||||
class RecordDecl;
|
||||
class TagDecl;
|
||||
@ -88,6 +89,9 @@ public:
|
||||
/// \brief A function template's definition was instantiated.
|
||||
virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {}
|
||||
|
||||
/// \brief A default argument was instantiated.
|
||||
virtual void DefaultArgumentInstantiated(const ParmVarDecl *D) {}
|
||||
|
||||
/// \brief A new objc category class was added for an interface.
|
||||
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
|
||||
const ObjCInterfaceDecl *IFD) {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- C++ -*-===//
|
||||
//===-- BuiltinTypes.def - Metadata about BuiltinTypes ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -2440,10 +2440,9 @@ class IndirectFieldDecl : public ValueDecl,
|
||||
NamedDecl **Chaining;
|
||||
unsigned ChainingSize;
|
||||
|
||||
IndirectFieldDecl(DeclContext *DC, SourceLocation L,
|
||||
IndirectFieldDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
DeclarationName N, QualType T,
|
||||
NamedDecl **CH, unsigned CHS)
|
||||
: ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {}
|
||||
NamedDecl **CH, unsigned CHS);
|
||||
|
||||
public:
|
||||
static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
|
@ -113,6 +113,9 @@ public:
|
||||
/// Tags, declared with 'struct foo;' and referenced with
|
||||
/// 'struct foo'. All tags are also types. This is what
|
||||
/// elaborated-type-specifiers look for in C.
|
||||
/// This also contains names that conflict with tags in the
|
||||
/// same scope but that are otherwise ordinary names (non-type
|
||||
/// template parameters and indirect field declarations).
|
||||
IDNS_Tag = 0x0002,
|
||||
|
||||
/// Types, declared with 'struct foo', typedefs, etc.
|
||||
@ -131,7 +134,7 @@ public:
|
||||
IDNS_Namespace = 0x0010,
|
||||
|
||||
/// Ordinary names. In C, everything that's not a label, tag,
|
||||
/// or member ends up here.
|
||||
/// member, or function-local extern ends up here.
|
||||
IDNS_Ordinary = 0x0020,
|
||||
|
||||
/// Objective C \@protocol.
|
||||
@ -160,7 +163,9 @@ public:
|
||||
|
||||
/// This declaration is a function-local extern declaration of a
|
||||
/// variable or function. This may also be IDNS_Ordinary if it
|
||||
/// has been declared outside any function.
|
||||
/// has been declared outside any function. These act mostly like
|
||||
/// invisible friend declarations, but are also visible to unqualified
|
||||
/// lookup within the scope of the declaring function.
|
||||
IDNS_LocalExtern = 0x0800
|
||||
};
|
||||
|
||||
|
@ -1292,6 +1292,7 @@ public:
|
||||
enum CharacterKind {
|
||||
Ascii,
|
||||
Wide,
|
||||
UTF8,
|
||||
UTF16,
|
||||
UTF32
|
||||
};
|
||||
|
@ -951,15 +951,9 @@ public:
|
||||
/// This wraps up a function call argument that was created from the
|
||||
/// corresponding parameter's default argument, when the call did not
|
||||
/// explicitly supply arguments for all of the parameters.
|
||||
class CXXDefaultArgExpr final
|
||||
: public Expr,
|
||||
private llvm::TrailingObjects<CXXDefaultArgExpr, Expr *> {
|
||||
class CXXDefaultArgExpr final : public Expr {
|
||||
/// \brief The parameter whose default is being used.
|
||||
///
|
||||
/// When the bit is set, the subexpression is stored after the
|
||||
/// CXXDefaultArgExpr itself. When the bit is clear, the parameter's
|
||||
/// actual default expression is the subexpression.
|
||||
llvm::PointerIntPair<ParmVarDecl *, 1, bool> Param;
|
||||
ParmVarDecl *Param;
|
||||
|
||||
/// \brief The location where the default argument expression was used.
|
||||
SourceLocation Loc;
|
||||
@ -971,16 +965,7 @@ class CXXDefaultArgExpr final
|
||||
: param->getDefaultArg()->getType(),
|
||||
param->getDefaultArg()->getValueKind(),
|
||||
param->getDefaultArg()->getObjectKind(), false, false, false, false),
|
||||
Param(param, false), Loc(Loc) { }
|
||||
|
||||
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param,
|
||||
Expr *SubExpr)
|
||||
: Expr(SC, SubExpr->getType(),
|
||||
SubExpr->getValueKind(), SubExpr->getObjectKind(),
|
||||
false, false, false, false),
|
||||
Param(param, true), Loc(Loc) {
|
||||
*getTrailingObjects<Expr *>() = SubExpr;
|
||||
}
|
||||
Param(param), Loc(Loc) { }
|
||||
|
||||
public:
|
||||
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
|
||||
@ -992,24 +977,15 @@ public:
|
||||
return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param);
|
||||
}
|
||||
|
||||
// \p Param is the parameter whose default argument is used by this
|
||||
// expression, and \p SubExpr is the expression that will actually be used.
|
||||
static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
|
||||
ParmVarDecl *Param, Expr *SubExpr);
|
||||
|
||||
// Retrieve the parameter that the argument was created from.
|
||||
const ParmVarDecl *getParam() const { return Param.getPointer(); }
|
||||
ParmVarDecl *getParam() { return Param.getPointer(); }
|
||||
const ParmVarDecl *getParam() const { return Param; }
|
||||
ParmVarDecl *getParam() { return Param; }
|
||||
|
||||
// Retrieve the actual argument to the function call.
|
||||
const Expr *getExpr() const {
|
||||
if (Param.getInt())
|
||||
return *getTrailingObjects<Expr *>();
|
||||
return getParam()->getDefaultArg();
|
||||
}
|
||||
Expr *getExpr() {
|
||||
if (Param.getInt())
|
||||
return *getTrailingObjects<Expr *>();
|
||||
return getParam()->getDefaultArg();
|
||||
}
|
||||
|
||||
@ -1033,7 +1009,6 @@ public:
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
friend TrailingObjects;
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
};
|
||||
|
@ -185,7 +185,11 @@ enum CastKind {
|
||||
/// CK_FloatingToBoolean - Floating point to boolean.
|
||||
/// (bool) f
|
||||
CK_FloatingToBoolean,
|
||||
|
||||
|
||||
// CK_BooleanToSignedIntegral - Convert a boolean to -1 or 0 for true and
|
||||
// false, respectively.
|
||||
CK_BooleanToSignedIntegral,
|
||||
|
||||
/// CK_FloatingCast - Casting between floating types of different size.
|
||||
/// (double) f
|
||||
/// (float) ld
|
||||
|
@ -978,6 +978,8 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
|
||||
|
||||
DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
|
||||
|
||||
DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); })
|
||||
|
||||
#undef DEF_TRAVERSE_TYPE
|
||||
|
||||
// ----------------- TypeLoc traversal -----------------
|
||||
@ -1206,6 +1208,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
|
||||
|
||||
#undef DEF_TRAVERSE_TYPELOC
|
||||
|
||||
// ----------------- Decl traversal -----------------
|
||||
|
@ -130,7 +130,7 @@ protected:
|
||||
friend class CharacterLiteral;
|
||||
unsigned : NumExprBits;
|
||||
|
||||
unsigned Kind : 2;
|
||||
unsigned Kind : 3;
|
||||
};
|
||||
|
||||
enum APFloatSemantics {
|
||||
|
@ -1721,6 +1721,7 @@ public:
|
||||
bool isNDRangeT() const; // OpenCL ndrange_t
|
||||
bool isReserveIDT() const; // OpenCL reserve_id_t
|
||||
|
||||
bool isPipeType() const; // OpenCL pipe type
|
||||
bool isOpenCLSpecificType() const; // Any OpenCL specific type
|
||||
|
||||
/// Determines if this type, which must satisfy
|
||||
@ -5015,6 +5016,41 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
|
||||
}
|
||||
};
|
||||
|
||||
/// PipeType - OpenCL20.
|
||||
class PipeType : public Type, public llvm::FoldingSetNode {
|
||||
QualType ElementType;
|
||||
|
||||
PipeType(QualType elemType, QualType CanonicalPtr) :
|
||||
Type(Pipe, CanonicalPtr, elemType->isDependentType(),
|
||||
elemType->isInstantiationDependentType(),
|
||||
elemType->isVariablyModifiedType(),
|
||||
elemType->containsUnexpandedParameterPack()),
|
||||
ElementType(elemType) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
public:
|
||||
|
||||
QualType getElementType() const { return ElementType; }
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getElementType());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
|
||||
ID.AddPointer(T.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == Pipe;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// A qualifier set is used to build a set of qualifiers.
|
||||
class QualifierCollector : public Qualifiers {
|
||||
public:
|
||||
@ -5461,9 +5497,13 @@ inline bool Type::isImageType() const {
|
||||
isImage1dBufferT();
|
||||
}
|
||||
|
||||
inline bool Type::isPipeType() const {
|
||||
return isa<PipeType>(CanonicalType);
|
||||
}
|
||||
|
||||
inline bool Type::isOpenCLSpecificType() const {
|
||||
return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
|
||||
isQueueT() || isNDRangeT() || isReserveIDT();
|
||||
isQueueT() || isNDRangeT() || isReserveIDT() || isPipeType();
|
||||
}
|
||||
|
||||
inline bool Type::isTemplateTypeParmType() const {
|
||||
|
@ -2033,7 +2033,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct PipeTypeLocInfo {
|
||||
SourceLocation KWLoc;
|
||||
};
|
||||
|
||||
class PipeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, PipeTypeLoc, PipeType,
|
||||
PipeTypeLocInfo> {
|
||||
public:
|
||||
TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); }
|
||||
|
||||
SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc()); }
|
||||
|
||||
SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; }
|
||||
void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; }
|
||||
|
||||
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
|
||||
setKWLoc(Loc);
|
||||
}
|
||||
|
||||
QualType getInnerType() const { return this->getTypePtr()->getElementType(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -104,6 +104,7 @@ NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
|
||||
TYPE(ObjCObject, Type)
|
||||
TYPE(ObjCInterface, ObjCObjectType)
|
||||
TYPE(ObjCObjectPointer, Type)
|
||||
TYPE(Pipe, Type)
|
||||
TYPE(Atomic, Type)
|
||||
|
||||
#ifdef LAST_TYPE
|
||||
|
@ -560,10 +560,10 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
|
||||
|
||||
// Metafunction to determine if type T has a member called
|
||||
// getDecl.
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__clang__)
|
||||
// For old versions of MSVC, we use a weird nonstandard __if_exists
|
||||
// statement, since before MSVC2015, it was not standards-conformant
|
||||
// enough to compile the usual code below.
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// For MSVC, we use a weird nonstandard __if_exists statement, as it
|
||||
// is not standards-conformant enough to properly compile the standard
|
||||
// code below. (At least up through MSVC 2015 require this workaround)
|
||||
template <typename T> struct has_getDecl {
|
||||
__if_exists(T::getDecl) {
|
||||
enum { value = 1 };
|
||||
|
@ -22,6 +22,7 @@ def err_drv_unknown_stdin_type_clang_cl : Error<
|
||||
def err_drv_unknown_language : Error<"language not recognized: '%0'">;
|
||||
def err_drv_invalid_arch_name : Error<
|
||||
"invalid arch name '%0'">;
|
||||
def err_drv_cuda_bad_gpu_arch : Error<"Unsupported CUDA gpu architecture: %0">;
|
||||
def err_drv_invalid_thread_model_for_target : Error<
|
||||
"invalid thread model '%0' in '%1' for this target">;
|
||||
def err_drv_invalid_linker_name : Error<
|
||||
|
@ -616,6 +616,7 @@ def Most : DiagGroup<"most", [
|
||||
CharSubscript,
|
||||
Comment,
|
||||
DeleteNonVirtualDtor,
|
||||
ForLoopAnalysis,
|
||||
Format,
|
||||
Implicit,
|
||||
InfiniteRecursion,
|
||||
|
@ -29,7 +29,7 @@ namespace clang {
|
||||
enum {
|
||||
DIAG_START_COMMON = 0,
|
||||
DIAG_START_DRIVER = DIAG_START_COMMON + 300,
|
||||
DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
|
||||
DIAG_START_FRONTEND = DIAG_START_DRIVER + 200,
|
||||
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100,
|
||||
DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
|
||||
DIAG_START_PARSE = DIAG_START_LEX + 300,
|
||||
|
@ -490,6 +490,8 @@ def warn_pragma_diagnostic_unknown_warning :
|
||||
// - #pragma __debug
|
||||
def warn_pragma_debug_unexpected_command : Warning<
|
||||
"unexpected debug command '%0'">, InGroup<IgnoredPragmas>;
|
||||
def warn_pragma_debug_missing_argument : Warning<
|
||||
"missing argument to debug command '%0'">, InGroup<IgnoredPragmas>;
|
||||
|
||||
def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
|
||||
def err_paste_at_start : Error<
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
//==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@ -7643,6 +7642,10 @@ def err_wrong_sampler_addressspace: Error<
|
||||
"sampler type cannot be used with the __local and __global address space qualifiers">;
|
||||
def err_opencl_global_invalid_addr_space : Error<
|
||||
"program scope variable must reside in %0 address space">;
|
||||
def err_missing_actual_pipe_type : Error<
|
||||
"missing actual type specifier for pipe">;
|
||||
def err_reference_pipe_type : Error <
|
||||
"pipes packet types cannot be of reference type">;
|
||||
def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
|
||||
def err_opencl_kernel_attr :
|
||||
Error<"attribute %0 can only be applied to a kernel function">;
|
||||
|
@ -36,6 +36,11 @@ namespace clang {
|
||||
TSS_unsigned
|
||||
};
|
||||
|
||||
enum TypeSpecifiersPipe {
|
||||
TSP_unspecified,
|
||||
TSP_pipe
|
||||
};
|
||||
|
||||
/// \brief Specifies the kind of type.
|
||||
enum TypeSpecifierType {
|
||||
TST_unspecified,
|
||||
|
@ -519,6 +519,8 @@ KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR)
|
||||
// OpenMP Type Traits
|
||||
KEYWORD(__builtin_omp_required_simd_align, KEYALL)
|
||||
|
||||
KEYWORD(pipe , KEYOPENCL)
|
||||
|
||||
// Borland Extensions.
|
||||
KEYWORD(__pascal , KEYALL)
|
||||
|
||||
@ -697,6 +699,11 @@ ANNOTATION(pragma_parser_crash)
|
||||
// handles them.
|
||||
ANNOTATION(pragma_captured)
|
||||
|
||||
// Annotation for #pragma clang __debug dump...
|
||||
// The lexer produces these so that the parser and semantic analysis can
|
||||
// look up and dump the operand.
|
||||
ANNOTATION(pragma_dump)
|
||||
|
||||
// Annotation for #pragma ms_struct...
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
|
@ -299,10 +299,7 @@ public:
|
||||
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
|
||||
return WorkingDirectory;
|
||||
}
|
||||
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
|
||||
WorkingDirectory = Path.str();
|
||||
return std::error_code();
|
||||
}
|
||||
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
|
||||
};
|
||||
|
||||
/// \brief Get a globally unique ID for a virtual file or directory.
|
||||
|
@ -33,12 +33,10 @@ namespace clang {
|
||||
Backend_EmitObj ///< Emit native object files
|
||||
};
|
||||
|
||||
void
|
||||
EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts,
|
||||
const TargetOptions &TOpts, const LangOptions &LOpts,
|
||||
StringRef TDesc, llvm::Module *M, BackendAction Action,
|
||||
raw_pwrite_stream *OS,
|
||||
std::unique_ptr<llvm::FunctionInfoIndex> Index = nullptr);
|
||||
void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts,
|
||||
const TargetOptions &TOpts, const LangOptions &LOpts,
|
||||
StringRef TDesc, llvm::Module *M, BackendAction Action,
|
||||
raw_pwrite_stream *OS);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class StringRef;
|
||||
|
||||
namespace opt {
|
||||
class Arg;
|
||||
}
|
||||
@ -32,6 +35,9 @@ namespace driver {
|
||||
/// single primary output, at least in terms of controlling the
|
||||
/// compilation. Actions can produce auxiliary files, but can only
|
||||
/// produce a single output to feed into subsequent actions.
|
||||
///
|
||||
/// Actions are usually owned by a Compilation, which creates new
|
||||
/// actions via MakeAction().
|
||||
class Action {
|
||||
public:
|
||||
typedef ActionList::size_type size_type;
|
||||
@ -70,27 +76,20 @@ private:
|
||||
|
||||
ActionList Inputs;
|
||||
|
||||
unsigned OwnsInputs : 1;
|
||||
|
||||
protected:
|
||||
Action(ActionClass Kind, types::ID Type)
|
||||
: Kind(Kind), Type(Type), OwnsInputs(true) {}
|
||||
Action(ActionClass Kind, std::unique_ptr<Action> Input, types::ID Type)
|
||||
: Kind(Kind), Type(Type), Inputs(1, Input.release()), OwnsInputs(true) {
|
||||
}
|
||||
Action(ActionClass Kind, std::unique_ptr<Action> Input)
|
||||
: Kind(Kind), Type(Input->getType()), Inputs(1, Input.release()),
|
||||
OwnsInputs(true) {}
|
||||
Action(ActionClass Kind, types::ID Type) : Action(Kind, ActionList(), Type) {}
|
||||
Action(ActionClass Kind, Action *Input, types::ID Type)
|
||||
: Action(Kind, ActionList({Input}), Type) {}
|
||||
Action(ActionClass Kind, Action *Input)
|
||||
: Action(Kind, ActionList({Input}), Input->getType()) {}
|
||||
Action(ActionClass Kind, const ActionList &Inputs, types::ID Type)
|
||||
: Kind(Kind), Type(Type), Inputs(Inputs), OwnsInputs(true) {}
|
||||
: Kind(Kind), Type(Type), Inputs(Inputs) {}
|
||||
|
||||
public:
|
||||
virtual ~Action();
|
||||
|
||||
const char *getClassName() const { return Action::getClassName(getKind()); }
|
||||
|
||||
bool getOwnsInputs() { return OwnsInputs; }
|
||||
void setOwnsInputs(bool Value) { OwnsInputs = Value; }
|
||||
|
||||
ActionClass getKind() const { return Kind; }
|
||||
types::ID getType() const { return Type; }
|
||||
|
||||
@ -126,7 +125,7 @@ class BindArchAction : public Action {
|
||||
const char *ArchName;
|
||||
|
||||
public:
|
||||
BindArchAction(std::unique_ptr<Action> Input, const char *ArchName);
|
||||
BindArchAction(Action *Input, const char *ArchName);
|
||||
|
||||
const char *getArchName() const { return ArchName; }
|
||||
|
||||
@ -137,19 +136,24 @@ public:
|
||||
|
||||
class CudaDeviceAction : public Action {
|
||||
virtual void anchor();
|
||||
/// GPU architecture to bind -- e.g 'sm_35'.
|
||||
/// GPU architecture to bind. Always of the form /sm_\d+/.
|
||||
const char *GpuArchName;
|
||||
/// True when action results are not consumed by the host action (e.g when
|
||||
/// -fsyntax-only or --cuda-device-only options are used).
|
||||
bool AtTopLevel;
|
||||
|
||||
public:
|
||||
CudaDeviceAction(std::unique_ptr<Action> Input, const char *ArchName,
|
||||
bool AtTopLevel);
|
||||
CudaDeviceAction(Action *Input, const char *ArchName, bool AtTopLevel);
|
||||
|
||||
const char *getGpuArchName() const { return GpuArchName; }
|
||||
|
||||
/// Gets the compute_XX that corresponds to getGpuArchName().
|
||||
const char *getComputeArchName() const;
|
||||
|
||||
bool isAtTopLevel() const { return AtTopLevel; }
|
||||
|
||||
static bool IsValidGpuArchName(llvm::StringRef ArchName);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == CudaDeviceClass;
|
||||
}
|
||||
@ -160,9 +164,7 @@ class CudaHostAction : public Action {
|
||||
ActionList DeviceActions;
|
||||
|
||||
public:
|
||||
CudaHostAction(std::unique_ptr<Action> Input,
|
||||
const ActionList &DeviceActions);
|
||||
~CudaHostAction() override;
|
||||
CudaHostAction(Action *Input, const ActionList &DeviceActions);
|
||||
|
||||
const ActionList &getDeviceActions() const { return DeviceActions; }
|
||||
|
||||
@ -172,7 +174,7 @@ public:
|
||||
class JobAction : public Action {
|
||||
virtual void anchor();
|
||||
protected:
|
||||
JobAction(ActionClass Kind, std::unique_ptr<Action> Input, types::ID Type);
|
||||
JobAction(ActionClass Kind, Action *Input, types::ID Type);
|
||||
JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type);
|
||||
|
||||
public:
|
||||
@ -185,7 +187,7 @@ public:
|
||||
class PreprocessJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
PreprocessJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
|
||||
PreprocessJobAction(Action *Input, types::ID OutputType);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == PreprocessJobClass;
|
||||
@ -195,7 +197,7 @@ public:
|
||||
class PrecompileJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
PrecompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
|
||||
PrecompileJobAction(Action *Input, types::ID OutputType);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == PrecompileJobClass;
|
||||
@ -205,7 +207,7 @@ public:
|
||||
class AnalyzeJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
AnalyzeJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
|
||||
AnalyzeJobAction(Action *Input, types::ID OutputType);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == AnalyzeJobClass;
|
||||
@ -215,7 +217,7 @@ public:
|
||||
class MigrateJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
MigrateJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
|
||||
MigrateJobAction(Action *Input, types::ID OutputType);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == MigrateJobClass;
|
||||
@ -225,7 +227,7 @@ public:
|
||||
class CompileJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
CompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
|
||||
CompileJobAction(Action *Input, types::ID OutputType);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == CompileJobClass;
|
||||
@ -235,7 +237,7 @@ public:
|
||||
class BackendJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
BackendJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
|
||||
BackendJobAction(Action *Input, types::ID OutputType);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == BackendJobClass;
|
||||
@ -245,7 +247,7 @@ public:
|
||||
class AssembleJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
AssembleJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
|
||||
AssembleJobAction(Action *Input, types::ID OutputType);
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == AssembleJobClass;
|
||||
@ -285,8 +287,7 @@ public:
|
||||
class VerifyJobAction : public JobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
VerifyJobAction(ActionClass Kind, std::unique_ptr<Action> Input,
|
||||
types::ID Type);
|
||||
VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type);
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == VerifyDebugInfoJobClass ||
|
||||
A->getKind() == VerifyPCHJobClass;
|
||||
@ -296,7 +297,7 @@ public:
|
||||
class VerifyDebugInfoJobAction : public VerifyJobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
VerifyDebugInfoJobAction(std::unique_ptr<Action> Input, types::ID Type);
|
||||
VerifyDebugInfoJobAction(Action *Input, types::ID Type);
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == VerifyDebugInfoJobClass;
|
||||
}
|
||||
@ -305,7 +306,7 @@ public:
|
||||
class VerifyPCHJobAction : public VerifyJobAction {
|
||||
void anchor() override;
|
||||
public:
|
||||
VerifyPCHJobAction(std::unique_ptr<Action> Input, types::ID Type);
|
||||
VerifyPCHJobAction(Action *Input, types::ID Type);
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == VerifyPCHJobClass;
|
||||
}
|
||||
|
@ -48,7 +48,12 @@ class Compilation {
|
||||
/// own argument translation.
|
||||
llvm::opt::DerivedArgList *TranslatedArgs;
|
||||
|
||||
/// The list of actions.
|
||||
/// The list of actions we've created via MakeAction. This is not accessible
|
||||
/// to consumers; it's here just to manage ownership.
|
||||
std::vector<std::unique_ptr<Action>> AllActions;
|
||||
|
||||
/// The list of actions. This is maintained and modified by consumers, via
|
||||
/// getActions().
|
||||
ActionList Actions;
|
||||
|
||||
/// The root list of jobs.
|
||||
@ -105,6 +110,15 @@ public:
|
||||
ActionList &getActions() { return Actions; }
|
||||
const ActionList &getActions() const { return Actions; }
|
||||
|
||||
/// Creates a new Action owned by this Compilation.
|
||||
///
|
||||
/// The new Action is *not* added to the list returned by getActions().
|
||||
template <typename T, typename... Args> T *MakeAction(Args &&... Arg) {
|
||||
T *RawPtr = new T(std::forward<Args>(Arg)...);
|
||||
AllActions.push_back(std::unique_ptr<Action>(RawPtr));
|
||||
return RawPtr;
|
||||
}
|
||||
|
||||
JobList &getJobs() { return Jobs; }
|
||||
const JobList &getJobs() const { return Jobs; }
|
||||
|
||||
|
@ -18,10 +18,10 @@
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo
|
||||
#include <memory>
|
||||
// lands.
|
||||
#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo lands.
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
@ -375,20 +375,16 @@ public:
|
||||
/// ConstructAction - Construct the appropriate action to do for
|
||||
/// \p Phase on the \p Input, taking in to account arguments
|
||||
/// like -fsyntax-only or --analyze.
|
||||
std::unique_ptr<Action>
|
||||
ConstructPhaseAction(const ToolChain &TC, const llvm::opt::ArgList &Args,
|
||||
phases::ID Phase, std::unique_ptr<Action> Input) const;
|
||||
Action *ConstructPhaseAction(Compilation &C, const ToolChain &TC,
|
||||
const llvm::opt::ArgList &Args, phases::ID Phase,
|
||||
Action *Input) const;
|
||||
|
||||
/// BuildJobsForAction - Construct the jobs to perform for the
|
||||
/// action \p A.
|
||||
void BuildJobsForAction(Compilation &C,
|
||||
const Action *A,
|
||||
const ToolChain *TC,
|
||||
const char *BoundArch,
|
||||
bool AtTopLevel,
|
||||
bool MultipleArchs,
|
||||
const char *LinkingOutput,
|
||||
InputInfo &Result) const;
|
||||
/// action \p A and return an InputInfo for the result of running \p A.
|
||||
InputInfo BuildJobsForAction(Compilation &C, const Action *A,
|
||||
const ToolChain *TC, const char *BoundArch,
|
||||
bool AtTopLevel, bool MultipleArchs,
|
||||
const char *LinkingOutput) const;
|
||||
|
||||
/// Returns the default name for linked images (e.g., "a.out").
|
||||
const char *getDefaultImageName() const;
|
||||
|
@ -1906,13 +1906,13 @@ def _ : Joined<["--"], "">, Flags<[Unsupported]>;
|
||||
|
||||
def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group<m_hexagon_Features_Group>;
|
||||
def mv4 : Flag<["-"], "mv4">, Group<m_hexagon_Features_Group>,
|
||||
Alias<mcpu_EQ>, AliasArgs<["v4"]>;
|
||||
Alias<mcpu_EQ>, AliasArgs<["hexagonv4"]>;
|
||||
def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>,
|
||||
AliasArgs<["v5"]>;
|
||||
AliasArgs<["hexagonv5"]>;
|
||||
def mv55 : Flag<["-"], "mv55">, Group<m_hexagon_Features_Group>,
|
||||
Alias<mcpu_EQ>, AliasArgs<["v55"]>;
|
||||
Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>;
|
||||
def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>,
|
||||
Alias<mcpu_EQ>, AliasArgs<["v60"]>;
|
||||
Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>;
|
||||
def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_Group>,
|
||||
Flags<[CC1Option]>, HelpText<"Enable Hexagon Vector eXtensions">;
|
||||
def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, Group<m_hexagon_Features_Group>,
|
||||
|
@ -134,7 +134,7 @@ public:
|
||||
StringRef getOS() const { return Triple.getOSName(); }
|
||||
|
||||
/// \brief Provide the default architecture name (as expected by -arch) for
|
||||
/// this toolchain. Note t
|
||||
/// this toolchain.
|
||||
StringRef getDefaultUniversalArchName() const;
|
||||
|
||||
std::string getTripleString() const {
|
||||
|
@ -166,6 +166,7 @@ public:
|
||||
bool hadError() const { return HadError; }
|
||||
bool isAscii() const { return Kind == tok::char_constant; }
|
||||
bool isWide() const { return Kind == tok::wide_char_constant; }
|
||||
bool isUTF8() const { return Kind == tok::utf8_char_constant; }
|
||||
bool isUTF16() const { return Kind == tok::utf16_char_constant; }
|
||||
bool isUTF32() const { return Kind == tok::utf32_char_constant; }
|
||||
bool isMultiChar() const { return IsMultiChar; }
|
||||
|
@ -501,6 +501,10 @@ private:
|
||||
/// #pragma align...
|
||||
void HandlePragmaAlign();
|
||||
|
||||
/// \brief Handle the annotation token produced for
|
||||
/// #pragma clang __debug dump...
|
||||
void HandlePragmaDump();
|
||||
|
||||
/// \brief Handle the annotation token produced for
|
||||
/// #pragma weak id...
|
||||
void HandlePragmaWeak();
|
||||
@ -1640,13 +1644,22 @@ private:
|
||||
/// A SmallVector of types.
|
||||
typedef SmallVector<ParsedType, 12> TypeVector;
|
||||
|
||||
StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr);
|
||||
StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr,
|
||||
bool AllowOpenMPStandalone = false);
|
||||
enum AllowedContsructsKind {
|
||||
/// \brief Allow any declarations, statements, OpenMP directives.
|
||||
ACK_Any,
|
||||
/// \brief Allow only statements and non-standalone OpenMP directives.
|
||||
ACK_StatementsOpenMPNonStandalone,
|
||||
/// \brief Allow statements and all executable OpenMP directives
|
||||
ACK_StatementsOpenMPAnyExecutable
|
||||
};
|
||||
StmtResult
|
||||
ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
|
||||
ParseStatementOrDeclaration(StmtVector &Stmts, AllowedContsructsKind Allowed,
|
||||
SourceLocation *TrailingElseLoc = nullptr);
|
||||
StmtResult ParseStatementOrDeclarationAfterAttributes(
|
||||
StmtVector &Stmts,
|
||||
bool OnlyStatement,
|
||||
AllowedContsructsKind Allowed,
|
||||
SourceLocation *TrailingElseLoc,
|
||||
ParsedAttributesWithRange &Attrs);
|
||||
StmtResult ParseExprStatement();
|
||||
@ -1674,7 +1687,8 @@ private:
|
||||
StmtResult ParseReturnStatement();
|
||||
StmtResult ParseAsmStatement(bool &msAsm);
|
||||
StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);
|
||||
StmtResult ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement,
|
||||
StmtResult ParsePragmaLoopHint(StmtVector &Stmts,
|
||||
AllowedContsructsKind Allowed,
|
||||
SourceLocation *TrailingElseLoc,
|
||||
ParsedAttributesWithRange &Attrs);
|
||||
|
||||
@ -2439,11 +2453,13 @@ private:
|
||||
bool AllowScopeSpecifier);
|
||||
/// \brief Parses declarative or executable directive.
|
||||
///
|
||||
/// \param StandAloneAllowed true if allowed stand-alone directives,
|
||||
/// false - otherwise
|
||||
/// \param Allowed ACK_Any, if any directives are allowed,
|
||||
/// ACK_StatementsOpenMPAnyExecutable - if any executable directives are
|
||||
/// allowed, ACK_StatementsOpenMPNonStandalone - if only non-standalone
|
||||
/// executable directives are allowed.
|
||||
///
|
||||
StmtResult
|
||||
ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed);
|
||||
ParseOpenMPDeclarativeOrExecutableDirective(AllowedContsructsKind Allowed);
|
||||
/// \brief Parses clause of kind \a CKind for directive of a kind \a Kind.
|
||||
///
|
||||
/// \param DKind Kind of current directive.
|
||||
|
@ -337,6 +337,7 @@ private:
|
||||
unsigned TypeAltiVecPixel : 1;
|
||||
unsigned TypeAltiVecBool : 1;
|
||||
unsigned TypeSpecOwned : 1;
|
||||
unsigned TypeSpecPipe : 1;
|
||||
|
||||
// type-qualifiers
|
||||
unsigned TypeQualifiers : 4; // Bitwise OR of TQ.
|
||||
@ -385,6 +386,7 @@ private:
|
||||
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
|
||||
SourceLocation FS_forceinlineLoc;
|
||||
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc;
|
||||
SourceLocation TQ_pipeLoc;
|
||||
|
||||
WrittenBuiltinSpecs writtenBS;
|
||||
void SaveWrittenBuiltinSpecs();
|
||||
@ -420,6 +422,7 @@ public:
|
||||
TypeAltiVecPixel(false),
|
||||
TypeAltiVecBool(false),
|
||||
TypeSpecOwned(false),
|
||||
TypeSpecPipe(false),
|
||||
TypeQualifiers(TQ_unspecified),
|
||||
FS_inline_specified(false),
|
||||
FS_forceinline_specified(false),
|
||||
@ -473,6 +476,7 @@ public:
|
||||
bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
|
||||
bool isTypeSpecOwned() const { return TypeSpecOwned; }
|
||||
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
|
||||
bool isTypeSpecPipe() const { return TypeSpecPipe; }
|
||||
|
||||
ParsedType getRepAsType() const {
|
||||
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
|
||||
@ -532,6 +536,7 @@ public:
|
||||
SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
|
||||
SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
|
||||
SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; }
|
||||
SourceLocation getPipeLoc() const { return TQ_pipeLoc; }
|
||||
|
||||
/// \brief Clear out all of the type qualifiers.
|
||||
void ClearTypeQualifiers() {
|
||||
@ -540,6 +545,7 @@ public:
|
||||
TQ_restrictLoc = SourceLocation();
|
||||
TQ_volatileLoc = SourceLocation();
|
||||
TQ_atomicLoc = SourceLocation();
|
||||
TQ_pipeLoc = SourceLocation();
|
||||
}
|
||||
|
||||
// function-specifier
|
||||
@ -643,6 +649,9 @@ public:
|
||||
bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
|
||||
const char *&PrevSpec, unsigned &DiagID,
|
||||
const PrintingPolicy &Policy);
|
||||
bool SetTypePipe(bool isPipe, SourceLocation Loc,
|
||||
const char *&PrevSpec, unsigned &DiagID,
|
||||
const PrintingPolicy &Policy);
|
||||
bool SetTypeSpecError();
|
||||
void UpdateDeclRep(Decl *Rep) {
|
||||
assert(isDeclRep((TST) TypeSpecType));
|
||||
@ -1081,7 +1090,7 @@ typedef SmallVector<Token, 4> CachedTokens;
|
||||
/// This is intended to be a small value object.
|
||||
struct DeclaratorChunk {
|
||||
enum {
|
||||
Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren
|
||||
Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren, Pipe
|
||||
} Kind;
|
||||
|
||||
/// Loc - The place where this type was defined.
|
||||
@ -1409,6 +1418,13 @@ struct DeclaratorChunk {
|
||||
}
|
||||
};
|
||||
|
||||
struct PipeTypeInfo : TypeInfoCommon {
|
||||
/// The access writes.
|
||||
unsigned AccessWrites : 3;
|
||||
|
||||
void destroy() {}
|
||||
};
|
||||
|
||||
union {
|
||||
TypeInfoCommon Common;
|
||||
PointerTypeInfo Ptr;
|
||||
@ -1417,6 +1433,7 @@ struct DeclaratorChunk {
|
||||
FunctionTypeInfo Fun;
|
||||
BlockPointerTypeInfo Cls;
|
||||
MemberPointerTypeInfo Mem;
|
||||
PipeTypeInfo PipeInfo;
|
||||
};
|
||||
|
||||
void destroy() {
|
||||
@ -1428,6 +1445,7 @@ struct DeclaratorChunk {
|
||||
case DeclaratorChunk::Array: return Arr.destroy();
|
||||
case DeclaratorChunk::MemberPointer: return Mem.destroy();
|
||||
case DeclaratorChunk::Paren: return;
|
||||
case DeclaratorChunk::Pipe: return PipeInfo.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1526,6 +1544,17 @@ struct DeclaratorChunk {
|
||||
return I;
|
||||
}
|
||||
|
||||
/// \brief Return a DeclaratorChunk for a block.
|
||||
static DeclaratorChunk getPipe(unsigned TypeQuals,
|
||||
SourceLocation Loc) {
|
||||
DeclaratorChunk I;
|
||||
I.Kind = Pipe;
|
||||
I.Loc = Loc;
|
||||
I.Cls.TypeQuals = TypeQuals;
|
||||
I.Cls.AttrList = 0;
|
||||
return I;
|
||||
}
|
||||
|
||||
static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
|
||||
unsigned TypeQuals,
|
||||
SourceLocation Loc) {
|
||||
@ -2026,6 +2055,7 @@ public:
|
||||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("Invalid type chunk");
|
||||
|
@ -515,6 +515,7 @@ public:
|
||||
configure();
|
||||
}
|
||||
|
||||
void dump();
|
||||
void print(raw_ostream &);
|
||||
|
||||
/// Suppress the diagnostics that would normally fire because of this
|
||||
|
@ -570,8 +570,8 @@ namespace clang {
|
||||
/// This conversion candidate is not viable because its result
|
||||
/// type is not implicitly convertible to the desired type.
|
||||
ovl_fail_bad_final_conversion,
|
||||
|
||||
/// This conversion function template specialization candidate is not
|
||||
|
||||
/// This conversion function template specialization candidate is not
|
||||
/// viable because the final conversion was not an exact match.
|
||||
ovl_fail_final_conversion_not_exact,
|
||||
|
||||
@ -582,7 +582,10 @@ namespace clang {
|
||||
|
||||
/// This candidate function was not viable because an enable_if
|
||||
/// attribute disabled it.
|
||||
ovl_fail_enable_if
|
||||
ovl_fail_enable_if,
|
||||
|
||||
/// This candidate was not viable because its address could not be taken.
|
||||
ovl_fail_addr_not_available
|
||||
};
|
||||
|
||||
/// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
|
||||
|
@ -1269,6 +1269,8 @@ public:
|
||||
SourceLocation Loc, DeclarationName Entity);
|
||||
QualType BuildParenType(QualType T);
|
||||
QualType BuildAtomicType(QualType T, SourceLocation Loc);
|
||||
QualType BuildPipeType(QualType T,
|
||||
SourceLocation Loc);
|
||||
|
||||
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
|
||||
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
|
||||
@ -2548,7 +2550,8 @@ public:
|
||||
MultiExprArg Args,
|
||||
SourceLocation RParenLoc,
|
||||
Expr *ExecConfig,
|
||||
bool AllowTypoCorrection=true);
|
||||
bool AllowTypoCorrection=true,
|
||||
bool CalleesAddressIsTaken=false);
|
||||
|
||||
bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
|
||||
MultiExprArg Args, SourceLocation RParenLoc,
|
||||
@ -7626,6 +7629,9 @@ public:
|
||||
void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
|
||||
StringLiteral *SegmentName);
|
||||
|
||||
/// \brief Called on #pragma clang __debug dump II
|
||||
void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
|
||||
|
||||
/// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
|
||||
void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value);
|
||||
|
||||
@ -8583,6 +8589,10 @@ public:
|
||||
bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
|
||||
CastKind &Kind);
|
||||
|
||||
/// \brief Prepare `SplattedExpr` for a vector splat operation, adding
|
||||
/// implicit casts if necessary.
|
||||
ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
|
||||
|
||||
// CheckExtVectorCast - check type constraints for extended vectors.
|
||||
// Since vectors are an extension, there are no C standard reference for this.
|
||||
// We allow casting between vectors and integer datatypes of the same size,
|
||||
|
@ -907,7 +907,9 @@ namespace clang {
|
||||
/// \brief A DecayedType record.
|
||||
TYPE_DECAYED = 41,
|
||||
/// \brief An AdjustedType record.
|
||||
TYPE_ADJUSTED = 42
|
||||
TYPE_ADJUSTED = 42,
|
||||
/// \brief A PipeType record.
|
||||
TYPE_PIPE = 43
|
||||
};
|
||||
|
||||
/// \brief The type IDs for special types constructed by semantic
|
||||
|
@ -871,6 +871,7 @@ public:
|
||||
const FunctionDecl *Delete) override;
|
||||
void CompletedImplicitDefinition(const FunctionDecl *D) override;
|
||||
void StaticDataMemberInstantiated(const VarDecl *D) override;
|
||||
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
|
||||
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
|
||||
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
|
||||
const ObjCInterfaceDecl *IFD) override;
|
||||
|
@ -80,7 +80,7 @@ class MemRegion : public llvm::FoldingSetNode {
|
||||
public:
|
||||
enum Kind {
|
||||
// Memory spaces.
|
||||
GenericMemSpaceRegionKind,
|
||||
CodeSpaceRegionKind,
|
||||
StackLocalsSpaceRegionKind,
|
||||
StackArgumentsSpaceRegionKind,
|
||||
HeapSpaceRegionKind,
|
||||
@ -89,29 +89,29 @@ public:
|
||||
GlobalInternalSpaceRegionKind,
|
||||
GlobalSystemSpaceRegionKind,
|
||||
GlobalImmutableSpaceRegionKind,
|
||||
BEG_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind,
|
||||
BEGIN_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind,
|
||||
END_NON_STATIC_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
|
||||
BEG_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind,
|
||||
BEGIN_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind,
|
||||
END_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
|
||||
BEG_MEMSPACES = GenericMemSpaceRegionKind,
|
||||
BEGIN_MEMSPACES = CodeSpaceRegionKind,
|
||||
END_MEMSPACES = GlobalImmutableSpaceRegionKind,
|
||||
// Untyped regions.
|
||||
SymbolicRegionKind,
|
||||
AllocaRegionKind,
|
||||
// Typed regions.
|
||||
BEG_TYPED_REGIONS,
|
||||
FunctionTextRegionKind = BEG_TYPED_REGIONS,
|
||||
BlockTextRegionKind,
|
||||
BEGIN_TYPED_REGIONS,
|
||||
FunctionCodeRegionKind = BEGIN_TYPED_REGIONS,
|
||||
BlockCodeRegionKind,
|
||||
BlockDataRegionKind,
|
||||
BEG_TYPED_VALUE_REGIONS,
|
||||
CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS,
|
||||
BEGIN_TYPED_VALUE_REGIONS,
|
||||
CompoundLiteralRegionKind = BEGIN_TYPED_VALUE_REGIONS,
|
||||
CXXThisRegionKind,
|
||||
StringRegionKind,
|
||||
ObjCStringRegionKind,
|
||||
ElementRegionKind,
|
||||
// Decl Regions.
|
||||
BEG_DECL_REGIONS,
|
||||
VarRegionKind = BEG_DECL_REGIONS,
|
||||
BEGIN_DECL_REGIONS,
|
||||
VarRegionKind = BEGIN_DECL_REGIONS,
|
||||
FieldRegionKind,
|
||||
ObjCIvarRegionKind,
|
||||
END_DECL_REGIONS = ObjCIvarRegionKind,
|
||||
@ -193,12 +193,9 @@ public:
|
||||
/// for example, the set of global variables, the stack frame, etc.
|
||||
class MemSpaceRegion : public MemRegion {
|
||||
protected:
|
||||
friend class MemRegionManager;
|
||||
|
||||
MemRegionManager *Mgr;
|
||||
|
||||
MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind)
|
||||
: MemRegion(k), Mgr(mgr) {
|
||||
MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) {
|
||||
assert(classof(this));
|
||||
}
|
||||
|
||||
@ -211,10 +208,26 @@ public:
|
||||
|
||||
static bool classof(const MemRegion *R) {
|
||||
Kind k = R->getKind();
|
||||
return k >= BEG_MEMSPACES && k <= END_MEMSPACES;
|
||||
return k >= BEGIN_MEMSPACES && k <= END_MEMSPACES;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// CodeSpaceRegion - The memory space that holds the executable code of
|
||||
/// functions and blocks.
|
||||
class CodeSpaceRegion : public MemSpaceRegion {
|
||||
friend class MemRegionManager;
|
||||
|
||||
CodeSpaceRegion(MemRegionManager *mgr)
|
||||
: MemSpaceRegion(mgr, CodeSpaceRegionKind) {}
|
||||
|
||||
public:
|
||||
void dumpToStream(raw_ostream &os) const override;
|
||||
|
||||
static bool classof(const MemRegion *R) {
|
||||
return R->getKind() == CodeSpaceRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
class GlobalsSpaceRegion : public MemSpaceRegion {
|
||||
virtual void anchor();
|
||||
protected:
|
||||
@ -223,7 +236,7 @@ protected:
|
||||
public:
|
||||
static bool classof(const MemRegion *R) {
|
||||
Kind k = R->getKind();
|
||||
return k >= BEG_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
|
||||
return k >= BEGIN_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
|
||||
}
|
||||
};
|
||||
|
||||
@ -259,17 +272,15 @@ public:
|
||||
/// RegionStoreManager::invalidateRegions (instead of finding all the dependent
|
||||
/// globals, we invalidate the whole parent region).
|
||||
class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
|
||||
friend class MemRegionManager;
|
||||
|
||||
protected:
|
||||
NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
|
||||
: GlobalsSpaceRegion(mgr, k) {}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
static bool classof(const MemRegion *R) {
|
||||
Kind k = R->getKind();
|
||||
return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES &&
|
||||
return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES &&
|
||||
k <= END_NON_STATIC_GLOBAL_MEMSPACES;
|
||||
}
|
||||
};
|
||||
@ -357,7 +368,7 @@ public:
|
||||
return R->getKind() == UnknownSpaceRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class StackSpaceRegion : public MemSpaceRegion {
|
||||
private:
|
||||
const StackFrameContext *SFC;
|
||||
@ -368,18 +379,18 @@ protected:
|
||||
assert(classof(this));
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
const StackFrameContext *getStackFrame() const { return SFC; }
|
||||
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const override;
|
||||
|
||||
static bool classof(const MemRegion *R) {
|
||||
Kind k = R->getKind();
|
||||
return k >= StackLocalsSpaceRegionKind &&
|
||||
k <= StackArgumentsSpaceRegionKind;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class StackLocalsSpaceRegion : public StackSpaceRegion {
|
||||
virtual void anchor();
|
||||
friend class MemRegionManager;
|
||||
@ -491,7 +502,7 @@ public:
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
unsigned k = R->getKind();
|
||||
return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS;
|
||||
return k >= BEGIN_TYPED_REGIONS && k <= END_TYPED_REGIONS;
|
||||
}
|
||||
};
|
||||
|
||||
@ -523,7 +534,7 @@ public:
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
unsigned k = R->getKind();
|
||||
return k >= BEG_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
|
||||
return k >= BEGIN_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
|
||||
}
|
||||
};
|
||||
|
||||
@ -538,16 +549,16 @@ public:
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
Kind k = R->getKind();
|
||||
return k >= FunctionTextRegionKind && k <= BlockTextRegionKind;
|
||||
return k >= FunctionCodeRegionKind && k <= BlockCodeRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
/// FunctionTextRegion - A region that represents code texts of function.
|
||||
class FunctionTextRegion : public CodeTextRegion {
|
||||
/// FunctionCodeRegion - A region that represents code texts of function.
|
||||
class FunctionCodeRegion : public CodeTextRegion {
|
||||
const NamedDecl *FD;
|
||||
public:
|
||||
FunctionTextRegion(const NamedDecl *fd, const MemRegion* sreg)
|
||||
: CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {
|
||||
FunctionCodeRegion(const NamedDecl *fd, const MemRegion* sreg)
|
||||
: CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
|
||||
assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
|
||||
}
|
||||
|
||||
@ -577,27 +588,27 @@ public:
|
||||
const MemRegion*);
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
return R->getKind() == FunctionTextRegionKind;
|
||||
return R->getKind() == FunctionCodeRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// BlockTextRegion - A region that represents code texts of blocks (closures).
|
||||
/// Blocks are represented with two kinds of regions. BlockTextRegions
|
||||
/// BlockCodeRegion - A region that represents code texts of blocks (closures).
|
||||
/// Blocks are represented with two kinds of regions. BlockCodeRegions
|
||||
/// represent the "code", while BlockDataRegions represent instances of blocks,
|
||||
/// which correspond to "code+data". The distinction is important, because
|
||||
/// like a closure a block captures the values of externally referenced
|
||||
/// variables.
|
||||
class BlockTextRegion : public CodeTextRegion {
|
||||
class BlockCodeRegion : public CodeTextRegion {
|
||||
friend class MemRegionManager;
|
||||
|
||||
const BlockDecl *BD;
|
||||
AnalysisDeclContext *AC;
|
||||
CanQualType locTy;
|
||||
|
||||
BlockTextRegion(const BlockDecl *bd, CanQualType lTy,
|
||||
BlockCodeRegion(const BlockDecl *bd, CanQualType lTy,
|
||||
AnalysisDeclContext *ac, const MemRegion* sreg)
|
||||
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
|
||||
: CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {}
|
||||
|
||||
public:
|
||||
QualType getLocationType() const override {
|
||||
@ -619,32 +630,32 @@ public:
|
||||
const MemRegion*);
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
return R->getKind() == BlockTextRegionKind;
|
||||
return R->getKind() == BlockCodeRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
/// BlockDataRegion - A region that represents a block instance.
|
||||
/// Blocks are represented with two kinds of regions. BlockTextRegions
|
||||
/// Blocks are represented with two kinds of regions. BlockCodeRegions
|
||||
/// represent the "code", while BlockDataRegions represent instances of blocks,
|
||||
/// which correspond to "code+data". The distinction is important, because
|
||||
/// like a closure a block captures the values of externally referenced
|
||||
/// variables.
|
||||
class BlockDataRegion : public TypedRegion {
|
||||
friend class MemRegionManager;
|
||||
const BlockTextRegion *BC;
|
||||
const BlockCodeRegion *BC;
|
||||
const LocationContext *LC; // Can be null */
|
||||
unsigned BlockCount;
|
||||
void *ReferencedVars;
|
||||
void *OriginalVars;
|
||||
|
||||
BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
|
||||
BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
|
||||
unsigned count, const MemRegion *sreg)
|
||||
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
|
||||
BlockCount(count),
|
||||
ReferencedVars(nullptr), OriginalVars(nullptr) {}
|
||||
|
||||
public:
|
||||
const BlockTextRegion *getCodeRegion() const { return BC; }
|
||||
const BlockCodeRegion *getCodeRegion() const { return BC; }
|
||||
|
||||
const BlockDecl *getDecl() const { return BC->getDecl(); }
|
||||
|
||||
@ -691,7 +702,7 @@ public:
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const override;
|
||||
|
||||
static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
|
||||
static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *,
|
||||
const LocationContext *, unsigned,
|
||||
const MemRegion *);
|
||||
|
||||
@ -856,7 +867,7 @@ public:
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
unsigned k = R->getKind();
|
||||
return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS;
|
||||
return k >= BEGIN_DECL_REGIONS && k <= END_DECL_REGIONS;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1138,7 +1149,7 @@ class MemRegionManager {
|
||||
|
||||
HeapSpaceRegion *heap;
|
||||
UnknownSpaceRegion *unknown;
|
||||
MemSpaceRegion *code;
|
||||
CodeSpaceRegion *code;
|
||||
|
||||
public:
|
||||
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a)
|
||||
@ -1174,9 +1185,9 @@ public:
|
||||
|
||||
/// getUnknownRegion - Retrieve the memory region associated with unknown
|
||||
/// memory space.
|
||||
const MemSpaceRegion *getUnknownRegion();
|
||||
const UnknownSpaceRegion *getUnknownRegion();
|
||||
|
||||
const MemSpaceRegion *getCodeRegion();
|
||||
const CodeSpaceRegion *getCodeRegion();
|
||||
|
||||
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
|
||||
const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
|
||||
@ -1262,8 +1273,8 @@ public:
|
||||
baseReg->isVirtual());
|
||||
}
|
||||
|
||||
const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD);
|
||||
const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
|
||||
const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD);
|
||||
const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,
|
||||
CanQualType locTy,
|
||||
AnalysisDeclContext *AC);
|
||||
|
||||
@ -1271,7 +1282,7 @@ public:
|
||||
/// of a block. Unlike many other MemRegions, the LocationContext*
|
||||
/// argument is allowed to be NULL for cases where we have no known
|
||||
/// context.
|
||||
const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
|
||||
const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc,
|
||||
const LocationContext *lc,
|
||||
unsigned blockCount);
|
||||
|
||||
|
@ -83,7 +83,11 @@ public:
|
||||
}
|
||||
|
||||
SVal evalCast(SVal val, QualType castTy, QualType originalType);
|
||||
|
||||
|
||||
// Handles casts of type CK_IntegralCast.
|
||||
SVal evalIntegralCast(ProgramStateRef state, SVal val, QualType castTy,
|
||||
QualType originalType);
|
||||
|
||||
virtual SVal evalMinus(NonLoc val) = 0;
|
||||
|
||||
virtual SVal evalComplement(NonLoc val) = 0;
|
||||
|
@ -45,8 +45,8 @@ class SVal {
|
||||
public:
|
||||
enum BaseKind {
|
||||
// The enumerators must be representable using 2 bits.
|
||||
UndefinedKind = 0, // for subclass UndefinedVal (an uninitialized value)
|
||||
UnknownKind = 1, // for subclass UnknownVal (a void value)
|
||||
UndefinedValKind = 0, // for subclass UndefinedVal (an uninitialized value)
|
||||
UnknownValKind = 1, // for subclass UnknownVal (a void value)
|
||||
LocKind = 2, // for subclass Loc (an L-value)
|
||||
NonLocKind = 3 // for subclass NonLoc (an R-value that's not
|
||||
// an L-value)
|
||||
@ -115,19 +115,19 @@ public:
|
||||
}
|
||||
|
||||
inline bool isUnknown() const {
|
||||
return getRawKind() == UnknownKind;
|
||||
return getRawKind() == UnknownValKind;
|
||||
}
|
||||
|
||||
inline bool isUndef() const {
|
||||
return getRawKind() == UndefinedKind;
|
||||
return getRawKind() == UndefinedValKind;
|
||||
}
|
||||
|
||||
inline bool isUnknownOrUndef() const {
|
||||
return getRawKind() <= UnknownKind;
|
||||
return getRawKind() <= UnknownValKind;
|
||||
}
|
||||
|
||||
inline bool isValid() const {
|
||||
return getRawKind() > UnknownKind;
|
||||
return getRawKind() > UnknownValKind;
|
||||
}
|
||||
|
||||
bool isConstant() const;
|
||||
@ -190,12 +190,12 @@ public:
|
||||
|
||||
class UndefinedVal : public SVal {
|
||||
public:
|
||||
UndefinedVal() : SVal(UndefinedKind) {}
|
||||
UndefinedVal() : SVal(UndefinedValKind) {}
|
||||
|
||||
private:
|
||||
friend class SVal;
|
||||
static bool isKind(const SVal& V) {
|
||||
return V.getBaseKind() == UndefinedKind;
|
||||
return V.getBaseKind() == UndefinedValKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -223,12 +223,12 @@ private:
|
||||
|
||||
class UnknownVal : public DefinedOrUnknownSVal {
|
||||
public:
|
||||
explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
|
||||
explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {}
|
||||
|
||||
private:
|
||||
friend class SVal;
|
||||
static bool isKind(const SVal &V) {
|
||||
return V.getBaseKind() == UnknownKind;
|
||||
return V.getBaseKind() == UnknownValKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -465,7 +465,7 @@ private:
|
||||
|
||||
namespace loc {
|
||||
|
||||
enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
|
||||
enum Kind { GotoLabelKind, MemRegionValKind, ConcreteIntKind };
|
||||
|
||||
class GotoLabel : public Loc {
|
||||
public:
|
||||
@ -490,7 +490,7 @@ private:
|
||||
|
||||
class MemRegionVal : public Loc {
|
||||
public:
|
||||
explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
|
||||
explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {}
|
||||
|
||||
/// \brief Get the underlining region.
|
||||
const MemRegion* getRegion() const {
|
||||
@ -518,11 +518,11 @@ private:
|
||||
MemRegionVal() {}
|
||||
static bool isKind(const SVal& V) {
|
||||
return V.getBaseKind() == LocKind &&
|
||||
V.getSubKind() == MemRegionKind;
|
||||
V.getSubKind() == MemRegionValKind;
|
||||
}
|
||||
|
||||
static bool isKind(const Loc& V) {
|
||||
return V.getSubKind() == MemRegionKind;
|
||||
return V.getSubKind() == MemRegionValKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -42,14 +42,22 @@ namespace ento {
|
||||
class SymExpr : public llvm::FoldingSetNode {
|
||||
virtual void anchor();
|
||||
public:
|
||||
enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
|
||||
MetadataKind,
|
||||
BEGIN_SYMBOLS = RegionValueKind,
|
||||
END_SYMBOLS = MetadataKind,
|
||||
SymIntKind, IntSymKind, SymSymKind,
|
||||
BEGIN_BINARYSYMEXPRS = SymIntKind,
|
||||
END_BINARYSYMEXPRS = SymSymKind,
|
||||
CastSymbolKind };
|
||||
enum Kind {
|
||||
SymbolRegionValueKind,
|
||||
SymbolConjuredKind,
|
||||
SymbolDerivedKind,
|
||||
SymbolExtentKind,
|
||||
SymbolMetadataKind,
|
||||
BEGIN_SYMBOLS = SymbolRegionValueKind,
|
||||
END_SYMBOLS = SymbolMetadataKind,
|
||||
SymIntExprKind,
|
||||
IntSymExprKind,
|
||||
SymSymExprKind,
|
||||
BEGIN_BINARYSYMEXPRS = SymIntExprKind,
|
||||
END_BINARYSYMEXPRS = SymSymExprKind,
|
||||
SymbolCastKind
|
||||
};
|
||||
|
||||
private:
|
||||
Kind K;
|
||||
|
||||
@ -126,12 +134,12 @@ class SymbolRegionValue : public SymbolData {
|
||||
|
||||
public:
|
||||
SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
|
||||
: SymbolData(RegionValueKind, sym), R(r) {}
|
||||
: SymbolData(SymbolRegionValueKind, sym), R(r) {}
|
||||
|
||||
const TypedValueRegion* getRegion() const { return R; }
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
|
||||
profile.AddInteger((unsigned) RegionValueKind);
|
||||
profile.AddInteger((unsigned) SymbolRegionValueKind);
|
||||
profile.AddPointer(R);
|
||||
}
|
||||
|
||||
@ -145,7 +153,7 @@ public:
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymExpr *SE) {
|
||||
return SE->getKind() == RegionValueKind;
|
||||
return SE->getKind() == SymbolRegionValueKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -160,11 +168,9 @@ class SymbolConjured : public SymbolData {
|
||||
|
||||
public:
|
||||
SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
|
||||
QualType t, unsigned count,
|
||||
const void *symbolTag)
|
||||
: SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
|
||||
LCtx(lctx),
|
||||
SymbolTag(symbolTag) {}
|
||||
QualType t, unsigned count, const void *symbolTag)
|
||||
: SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
|
||||
LCtx(lctx), SymbolTag(symbolTag) {}
|
||||
|
||||
const Stmt *getStmt() const { return S; }
|
||||
unsigned getCount() const { return Count; }
|
||||
@ -177,7 +183,7 @@ public:
|
||||
static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
|
||||
QualType T, unsigned Count, const LocationContext *LCtx,
|
||||
const void *SymbolTag) {
|
||||
profile.AddInteger((unsigned) ConjuredKind);
|
||||
profile.AddInteger((unsigned) SymbolConjuredKind);
|
||||
profile.AddPointer(S);
|
||||
profile.AddPointer(LCtx);
|
||||
profile.Add(T);
|
||||
@ -191,7 +197,7 @@ public:
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymExpr *SE) {
|
||||
return SE->getKind() == ConjuredKind;
|
||||
return SE->getKind() == SymbolConjuredKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -203,7 +209,7 @@ class SymbolDerived : public SymbolData {
|
||||
|
||||
public:
|
||||
SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
|
||||
: SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {}
|
||||
: SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {}
|
||||
|
||||
SymbolRef getParentSymbol() const { return parentSymbol; }
|
||||
const TypedValueRegion *getRegion() const { return R; }
|
||||
@ -214,7 +220,7 @@ public:
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
|
||||
const TypedValueRegion *r) {
|
||||
profile.AddInteger((unsigned) DerivedKind);
|
||||
profile.AddInteger((unsigned) SymbolDerivedKind);
|
||||
profile.AddPointer(r);
|
||||
profile.AddPointer(parent);
|
||||
}
|
||||
@ -225,7 +231,7 @@ public:
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymExpr *SE) {
|
||||
return SE->getKind() == DerivedKind;
|
||||
return SE->getKind() == SymbolDerivedKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -237,7 +243,7 @@ class SymbolExtent : public SymbolData {
|
||||
|
||||
public:
|
||||
SymbolExtent(SymbolID sym, const SubRegion *r)
|
||||
: SymbolData(ExtentKind, sym), R(r) {}
|
||||
: SymbolData(SymbolExtentKind, sym), R(r) {}
|
||||
|
||||
const SubRegion *getRegion() const { return R; }
|
||||
|
||||
@ -246,7 +252,7 @@ public:
|
||||
void dumpToStream(raw_ostream &os) const override;
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
|
||||
profile.AddInteger((unsigned) ExtentKind);
|
||||
profile.AddInteger((unsigned) SymbolExtentKind);
|
||||
profile.AddPointer(R);
|
||||
}
|
||||
|
||||
@ -256,7 +262,7 @@ public:
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymExpr *SE) {
|
||||
return SE->getKind() == ExtentKind;
|
||||
return SE->getKind() == SymbolExtentKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -273,7 +279,7 @@ class SymbolMetadata : public SymbolData {
|
||||
public:
|
||||
SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
|
||||
unsigned count, const void *tag)
|
||||
: SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
|
||||
: SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
|
||||
|
||||
const MemRegion *getRegion() const { return R; }
|
||||
const Stmt *getStmt() const { return S; }
|
||||
@ -287,7 +293,7 @@ public:
|
||||
static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
|
||||
const Stmt *S, QualType T, unsigned Count,
|
||||
const void *Tag) {
|
||||
profile.AddInteger((unsigned) MetadataKind);
|
||||
profile.AddInteger((unsigned) SymbolMetadataKind);
|
||||
profile.AddPointer(R);
|
||||
profile.AddPointer(S);
|
||||
profile.Add(T);
|
||||
@ -301,7 +307,7 @@ public:
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymExpr *SE) {
|
||||
return SE->getKind() == MetadataKind;
|
||||
return SE->getKind() == SymbolMetadataKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -315,7 +321,7 @@ class SymbolCast : public SymExpr {
|
||||
|
||||
public:
|
||||
SymbolCast(const SymExpr *In, QualType From, QualType To) :
|
||||
SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { }
|
||||
SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { }
|
||||
|
||||
QualType getType() const override { return ToTy; }
|
||||
|
||||
@ -325,7 +331,7 @@ public:
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID& ID,
|
||||
const SymExpr *In, QualType From, QualType To) {
|
||||
ID.AddInteger((unsigned) CastSymbolKind);
|
||||
ID.AddInteger((unsigned) SymbolCastKind);
|
||||
ID.AddPointer(In);
|
||||
ID.Add(From);
|
||||
ID.Add(To);
|
||||
@ -337,7 +343,7 @@ public:
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymExpr *SE) {
|
||||
return SE->getKind() == CastSymbolKind;
|
||||
return SE->getKind() == SymbolCastKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -372,7 +378,7 @@ class SymIntExpr : public BinarySymExpr {
|
||||
public:
|
||||
SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
|
||||
const llvm::APSInt& rhs, QualType t)
|
||||
: BinarySymExpr(SymIntKind, op, t), LHS(lhs), RHS(rhs) {}
|
||||
: BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {}
|
||||
|
||||
void dumpToStream(raw_ostream &os) const override;
|
||||
|
||||
@ -382,7 +388,7 @@ public:
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
|
||||
BinaryOperator::Opcode op, const llvm::APSInt& rhs,
|
||||
QualType t) {
|
||||
ID.AddInteger((unsigned) SymIntKind);
|
||||
ID.AddInteger((unsigned) SymIntExprKind);
|
||||
ID.AddPointer(lhs);
|
||||
ID.AddInteger(op);
|
||||
ID.AddPointer(&rhs);
|
||||
@ -395,7 +401,7 @@ public:
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymExpr *SE) {
|
||||
return SE->getKind() == SymIntKind;
|
||||
return SE->getKind() == SymIntExprKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -407,7 +413,7 @@ class IntSymExpr : public BinarySymExpr {
|
||||
public:
|
||||
IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op,
|
||||
const SymExpr *rhs, QualType t)
|
||||
: BinarySymExpr(IntSymKind, op, t), LHS(lhs), RHS(rhs) {}
|
||||
: BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) {}
|
||||
|
||||
void dumpToStream(raw_ostream &os) const override;
|
||||
|
||||
@ -417,7 +423,7 @@ public:
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs,
|
||||
BinaryOperator::Opcode op, const SymExpr *rhs,
|
||||
QualType t) {
|
||||
ID.AddInteger((unsigned) IntSymKind);
|
||||
ID.AddInteger((unsigned) IntSymExprKind);
|
||||
ID.AddPointer(&lhs);
|
||||
ID.AddInteger(op);
|
||||
ID.AddPointer(rhs);
|
||||
@ -430,7 +436,7 @@ public:
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymExpr *SE) {
|
||||
return SE->getKind() == IntSymKind;
|
||||
return SE->getKind() == IntSymExprKind;
|
||||
}
|
||||
};
|
||||
|
||||
@ -442,7 +448,7 @@ class SymSymExpr : public BinarySymExpr {
|
||||
public:
|
||||
SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
|
||||
QualType t)
|
||||
: BinarySymExpr(SymSymKind, op, t), LHS(lhs), RHS(rhs) {}
|
||||
: BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) {}
|
||||
|
||||
const SymExpr *getLHS() const { return LHS; }
|
||||
const SymExpr *getRHS() const { return RHS; }
|
||||
@ -451,7 +457,7 @@ public:
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
|
||||
BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
|
||||
ID.AddInteger((unsigned) SymSymKind);
|
||||
ID.AddInteger((unsigned) SymSymExprKind);
|
||||
ID.AddPointer(lhs);
|
||||
ID.AddInteger(op);
|
||||
ID.AddPointer(rhs);
|
||||
@ -464,7 +470,7 @@ public:
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymExpr *SE) {
|
||||
return SE->getKind() == SymSymKind;
|
||||
return SE->getKind() == SymSymExprKind;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1836,6 +1836,13 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
|
||||
Align = static_cast<unsigned>(Width);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Type::Pipe: {
|
||||
TypeInfo Info = getTypeInfo(cast<PipeType>(T)->getElementType());
|
||||
Width = Info.Width;
|
||||
Align = Info.Align;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2663,6 +2670,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
|
||||
case Type::FunctionProto:
|
||||
case Type::BlockPointer:
|
||||
case Type::MemberPointer:
|
||||
case Type::Pipe:
|
||||
return type;
|
||||
|
||||
// These types can be variably-modified. All these modifications
|
||||
@ -3117,6 +3125,32 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
|
||||
return QualType(FTP, 0);
|
||||
}
|
||||
|
||||
/// Return pipe type for the specified type.
|
||||
QualType ASTContext::getPipeType(QualType T) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
PipeType::Profile(ID, T);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(PT, 0);
|
||||
|
||||
// If the pipe element type isn't canonical, this won't be a canonical type
|
||||
// either, so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T.isCanonical()) {
|
||||
Canonical = getPipeType(getCanonicalType(T));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!NewIP && "Shouldn't be in the map!");
|
||||
(void)NewIP;
|
||||
}
|
||||
PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical);
|
||||
Types.push_back(New);
|
||||
PipeTypes.InsertNode(New, InsertPos);
|
||||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
|
||||
if (!isa<CXXRecordDecl>(D)) return false;
|
||||
@ -5857,6 +5891,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
case Type::Auto:
|
||||
return;
|
||||
|
||||
case Type::Pipe:
|
||||
#define ABSTRACT_TYPE(KIND, BASE)
|
||||
#define TYPE(KIND, BASE)
|
||||
#define DEPENDENT_TYPE(KIND, BASE) \
|
||||
@ -7792,6 +7827,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
|
||||
|
||||
return QualType();
|
||||
}
|
||||
case Type::Pipe:
|
||||
{
|
||||
// Merge two pointer types, while trying to preserve typedef info
|
||||
QualType LHSValue = LHS->getAs<PipeType>()->getElementType();
|
||||
QualType RHSValue = RHS->getAs<PipeType>()->getElementType();
|
||||
if (Unqualified) {
|
||||
LHSValue = LHSValue.getUnqualifiedType();
|
||||
RHSValue = RHSValue.getUnqualifiedType();
|
||||
}
|
||||
QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
|
||||
Unqualified);
|
||||
if (ResultType.isNull()) return QualType();
|
||||
if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
|
||||
return LHS;
|
||||
if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
|
||||
return RHS;
|
||||
return getPipeType(ResultType);
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("Invalid Type::Class!");
|
||||
|
@ -1055,6 +1055,7 @@ void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) {
|
||||
dumpType(D->getUnderlyingType());
|
||||
if (D->isModulePrivate())
|
||||
OS << " __module_private__";
|
||||
dumpTypeAsChild(D->getUnderlyingType());
|
||||
}
|
||||
|
||||
void ASTDumper::VisitEnumDecl(const EnumDecl *D) {
|
||||
@ -1226,6 +1227,7 @@ void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
|
||||
void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
|
||||
dumpName(D);
|
||||
dumpType(D->getUnderlyingType());
|
||||
dumpTypeAsChild(D->getUnderlyingType());
|
||||
}
|
||||
|
||||
void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
|
||||
@ -1419,6 +1421,8 @@ void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D)
|
||||
void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
|
||||
OS << ' ';
|
||||
dumpBareDeclRef(D->getTargetDecl());
|
||||
if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
|
||||
dumpTypeAsChild(TD->getTypeForDecl());
|
||||
}
|
||||
|
||||
void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
|
||||
|
@ -878,6 +878,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
break;
|
||||
}
|
||||
|
||||
case Type::Pipe: {
|
||||
if (!IsStructurallyEquivalent(Context,
|
||||
cast<PipeType>(T1)->getElementType(),
|
||||
cast<PipeType>(T2)->getElementType()))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
} // end switch
|
||||
|
||||
return true;
|
||||
|
@ -1184,7 +1184,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
|
||||
return LinkageInfo::none();
|
||||
|
||||
const Decl *OuterD = getOutermostFuncOrBlockContext(D);
|
||||
if (!OuterD)
|
||||
if (!OuterD || OuterD->isInvalidDecl())
|
||||
return LinkageInfo::none();
|
||||
|
||||
LinkageInfo LV;
|
||||
@ -4024,16 +4024,26 @@ EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
||||
|
||||
void IndirectFieldDecl::anchor() { }
|
||||
|
||||
IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, DeclarationName N,
|
||||
QualType T, NamedDecl **CH, unsigned CHS)
|
||||
: ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {
|
||||
// In C++, indirect field declarations conflict with tag declarations in the
|
||||
// same scope, so add them to IDNS_Tag so that tag redeclaration finds them.
|
||||
if (C.getLangOpts().CPlusPlus)
|
||||
IdentifierNamespace |= IDNS_Tag;
|
||||
}
|
||||
|
||||
IndirectFieldDecl *
|
||||
IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T, NamedDecl **CH,
|
||||
unsigned CHS) {
|
||||
return new (C, DC) IndirectFieldDecl(DC, L, Id, T, CH, CHS);
|
||||
return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH, CHS);
|
||||
}
|
||||
|
||||
IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
|
||||
unsigned ID) {
|
||||
return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(),
|
||||
return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(),
|
||||
DeclarationName(), QualType(), nullptr,
|
||||
0);
|
||||
}
|
||||
|
@ -569,7 +569,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
case Var:
|
||||
case ImplicitParam:
|
||||
case ParmVar:
|
||||
case NonTypeTemplateParm:
|
||||
case ObjCMethod:
|
||||
case ObjCProperty:
|
||||
case MSProperty:
|
||||
@ -579,6 +578,12 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
case IndirectField:
|
||||
return IDNS_Ordinary | IDNS_Member;
|
||||
|
||||
case NonTypeTemplateParm:
|
||||
// Non-type template parameters are not found by lookups that ignore
|
||||
// non-types, but they are found by redeclaration lookups for tag types,
|
||||
// so we include them in the tag namespace.
|
||||
return IDNS_Ordinary | IDNS_Tag;
|
||||
|
||||
case ObjCCompatibleAlias:
|
||||
case ObjCInterface:
|
||||
return IDNS_Ordinary | IDNS_Type;
|
||||
|
@ -1553,6 +1553,7 @@ bool CastExpr::CastConsistency() const {
|
||||
case CK_ToVoid:
|
||||
case CK_VectorSplat:
|
||||
case CK_IntegralCast:
|
||||
case CK_BooleanToSignedIntegral:
|
||||
case CK_IntegralToFloating:
|
||||
case CK_FloatingToIntegral:
|
||||
case CK_FloatingCast:
|
||||
@ -1646,6 +1647,8 @@ const char *CastExpr::getCastKindName() const {
|
||||
return "VectorSplat";
|
||||
case CK_IntegralCast:
|
||||
return "IntegralCast";
|
||||
case CK_BooleanToSignedIntegral:
|
||||
return "BooleanToSignedIntegral";
|
||||
case CK_IntegralToBoolean:
|
||||
return "IntegralToBoolean";
|
||||
case CK_IntegralToFloating:
|
||||
|
@ -763,14 +763,6 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const {
|
||||
return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier();
|
||||
}
|
||||
|
||||
CXXDefaultArgExpr *
|
||||
CXXDefaultArgExpr::Create(const ASTContext &C, SourceLocation Loc,
|
||||
ParmVarDecl *Param, Expr *SubExpr) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(1));
|
||||
return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param,
|
||||
SubExpr);
|
||||
}
|
||||
|
||||
CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc,
|
||||
FieldDecl *Field, QualType T)
|
||||
: Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C),
|
||||
|
@ -7781,12 +7781,16 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
|
||||
case CK_PointerToBoolean:
|
||||
case CK_IntegralToBoolean:
|
||||
case CK_FloatingToBoolean:
|
||||
case CK_BooleanToSignedIntegral:
|
||||
case CK_FloatingComplexToBoolean:
|
||||
case CK_IntegralComplexToBoolean: {
|
||||
bool BoolResult;
|
||||
if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info))
|
||||
return false;
|
||||
return Success(BoolResult, E);
|
||||
uint64_t IntResult = BoolResult;
|
||||
if (BoolResult && E->getCastKind() == CK_BooleanToSignedIntegral)
|
||||
IntResult = (uint64_t)-1;
|
||||
return Success(IntResult, E);
|
||||
}
|
||||
|
||||
case CK_IntegralCast: {
|
||||
@ -8223,6 +8227,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
|
||||
case CK_ToVoid:
|
||||
case CK_VectorSplat:
|
||||
case CK_IntegralCast:
|
||||
case CK_BooleanToSignedIntegral:
|
||||
case CK_IntegralToBoolean:
|
||||
case CK_IntegralToFloating:
|
||||
case CK_FloatingToIntegral:
|
||||
|
@ -1509,6 +1509,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
|
||||
case Type::ObjCInterface:
|
||||
case Type::ObjCObjectPointer:
|
||||
case Type::Atomic:
|
||||
case Type::Pipe:
|
||||
llvm_unreachable("type is illegal as a nested name specifier");
|
||||
|
||||
case Type::SubstTemplateTypeParmPack:
|
||||
@ -2682,6 +2683,13 @@ void CXXNameMangler::mangleType(const AtomicType *T) {
|
||||
mangleType(T->getValueType());
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleType(const PipeType *T) {
|
||||
// Pipe type mangling rules are described in SPIR 2.0 specification
|
||||
// A.1 Data types and A.3 Summary of changes
|
||||
// <type> ::= 8ocl_pipe
|
||||
Out << "8ocl_pipe";
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleIntegerLiteral(QualType T,
|
||||
const llvm::APSInt &Value) {
|
||||
// <expr-primary> ::= L <type> <value number> E # integer literal
|
||||
|
@ -2428,6 +2428,15 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
|
||||
mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
|
||||
}
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers,
|
||||
SourceRange Range) {
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
|
||||
"cannot mangle this OpenCL pipe type yet");
|
||||
Diags.Report(Range.getBegin(), DiagID)
|
||||
<< Range;
|
||||
}
|
||||
|
||||
void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D,
|
||||
raw_ostream &Out) {
|
||||
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
|
||||
|
@ -1552,7 +1552,8 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
|
||||
FieldAlign = 1;
|
||||
|
||||
// But, if there's an 'aligned' attribute on the field, honor that.
|
||||
if (unsigned ExplicitFieldAlign = D->getMaxAlignment()) {
|
||||
unsigned ExplicitFieldAlign = D->getMaxAlignment();
|
||||
if (ExplicitFieldAlign) {
|
||||
FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
|
||||
UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
|
||||
}
|
||||
@ -1601,6 +1602,10 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
|
||||
(AllowPadding &&
|
||||
(FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) {
|
||||
FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
|
||||
} else if (ExplicitFieldAlign) {
|
||||
// TODO: figure it out what needs to be done on targets that don't honor
|
||||
// bit-field type alignment like ARM APCS ABI.
|
||||
FieldOffset = llvm::RoundUpToAlignment(FieldOffset, ExplicitFieldAlign);
|
||||
}
|
||||
|
||||
// Repeat the computation for diagnostic purposes.
|
||||
@ -1609,6 +1614,9 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
|
||||
(UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
|
||||
UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
|
||||
UnpackedFieldAlign);
|
||||
else if (ExplicitFieldAlign)
|
||||
UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
|
||||
ExplicitFieldAlign);
|
||||
}
|
||||
|
||||
// If we're using external layout, give the external layout a chance
|
||||
|
@ -1165,6 +1165,7 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
|
||||
switch (Node->getKind()) {
|
||||
case CharacterLiteral::Ascii: break; // no prefix.
|
||||
case CharacterLiteral::Wide: OS << 'L'; break;
|
||||
case CharacterLiteral::UTF8: OS << "u8"; break;
|
||||
case CharacterLiteral::UTF16: OS << 'u'; break;
|
||||
case CharacterLiteral::UTF32: OS << 'U'; break;
|
||||
}
|
||||
|
@ -2614,7 +2614,7 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
|
||||
case OCLQueue:
|
||||
return "queue_t";
|
||||
case OCLNDRange:
|
||||
return "event_t";
|
||||
return "ndrange_t";
|
||||
case OCLReserveID:
|
||||
return "reserve_id_t";
|
||||
case OMPArraySection:
|
||||
@ -3361,6 +3361,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
|
||||
return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
|
||||
case Type::Atomic:
|
||||
return Cache::get(cast<AtomicType>(T)->getValueType());
|
||||
case Type::Pipe:
|
||||
return Cache::get(cast<PipeType>(T)->getElementType());
|
||||
}
|
||||
|
||||
llvm_unreachable("unhandled type class");
|
||||
@ -3443,6 +3445,8 @@ static LinkageInfo computeLinkageInfo(const Type *T) {
|
||||
return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType());
|
||||
case Type::Atomic:
|
||||
return computeLinkageInfo(cast<AtomicType>(T)->getValueType());
|
||||
case Type::Pipe:
|
||||
return computeLinkageInfo(cast<PipeType>(T)->getElementType());
|
||||
}
|
||||
|
||||
llvm_unreachable("unhandled type class");
|
||||
@ -3601,6 +3605,7 @@ bool Type::canHaveNullability() const {
|
||||
case Type::ObjCObject:
|
||||
case Type::ObjCInterface:
|
||||
case Type::Atomic:
|
||||
case Type::Pipe:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("bad type kind!");
|
||||
|
@ -193,6 +193,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
|
||||
case Type::ObjCObject:
|
||||
case Type::ObjCInterface:
|
||||
case Type::Atomic:
|
||||
case Type::Pipe:
|
||||
CanPrefixQualifiers = true;
|
||||
break;
|
||||
|
||||
@ -859,6 +860,15 @@ void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
|
||||
}
|
||||
void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
|
||||
|
||||
void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
|
||||
IncludeStrongLifetimeRAII Strong(Policy);
|
||||
|
||||
OS << "pipe";
|
||||
spaceBeforePlaceHolder(OS);
|
||||
}
|
||||
|
||||
void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {
|
||||
}
|
||||
/// Appends the given scope to the end of a string.
|
||||
void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
|
||||
if (DC->isTranslationUnit()) return;
|
||||
|
@ -223,7 +223,24 @@ protected:
|
||||
|
||||
public:
|
||||
DarwinTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {
|
||||
this->TLSSupported = Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 7);
|
||||
// By default, no TLS, and we whitelist permitted architecture/OS
|
||||
// combinations.
|
||||
this->TLSSupported = false;
|
||||
|
||||
if (Triple.isMacOSX())
|
||||
this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7);
|
||||
else if (Triple.isiOS()) {
|
||||
// 64-bit iOS supported it from 8 onwards, 32-bit from 9 onwards.
|
||||
if (Triple.getArch() == llvm::Triple::x86_64 ||
|
||||
Triple.getArch() == llvm::Triple::aarch64)
|
||||
this->TLSSupported = !Triple.isOSVersionLT(8);
|
||||
else if (Triple.getArch() == llvm::Triple::x86 ||
|
||||
Triple.getArch() == llvm::Triple::arm ||
|
||||
Triple.getArch() == llvm::Triple::thumb)
|
||||
this->TLSSupported = !Triple.isOSVersionLT(9);
|
||||
} else if (Triple.isWatchOS())
|
||||
this->TLSSupported = !Triple.isOSVersionLT(2);
|
||||
|
||||
this->MCountName = "\01mcount";
|
||||
}
|
||||
|
||||
@ -7281,7 +7298,7 @@ public:
|
||||
explicit WebAssembly32TargetInfo(const llvm::Triple &T)
|
||||
: WebAssemblyTargetInfo(T) {
|
||||
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
|
||||
DataLayoutString = "e-p:32:32-i64:64-n32:64-S128";
|
||||
DataLayoutString = "e-m:e-p:32:32-i64:64-n32:64-S128";
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -7299,7 +7316,7 @@ public:
|
||||
LongAlign = LongWidth = 64;
|
||||
PointerAlign = PointerWidth = 64;
|
||||
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
|
||||
DataLayoutString = "e-p:64:64-i64:64-n32:64-S128";
|
||||
DataLayoutString = "e-m:e-p:64:64-i64:64-n32:64-S128";
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -658,6 +658,23 @@ directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
|
||||
EC = make_error_code(llvm::errc::not_a_directory);
|
||||
return directory_iterator(std::make_shared<InMemoryDirIterator>());
|
||||
}
|
||||
|
||||
std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) {
|
||||
SmallString<128> Path;
|
||||
P.toVector(Path);
|
||||
|
||||
// Fix up relative paths. This just prepends the current working directory.
|
||||
std::error_code EC = makeAbsolute(Path);
|
||||
assert(!EC);
|
||||
(void)EC;
|
||||
|
||||
if (useNormalizedPaths())
|
||||
llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
|
||||
|
||||
if (!Path.empty())
|
||||
WorkingDirectory = Path.str();
|
||||
return std::error_code();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/MC/SubtargetFeature.h"
|
||||
#include "llvm/Object/FunctionIndexObjectFile.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/PrettyStackTrace.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
@ -54,7 +55,6 @@ class EmitAssemblyHelper {
|
||||
const clang::TargetOptions &TargetOpts;
|
||||
const LangOptions &LangOpts;
|
||||
Module *TheModule;
|
||||
std::unique_ptr<FunctionInfoIndex> FunctionIndex;
|
||||
|
||||
Timer CodeGenerationTime;
|
||||
|
||||
@ -97,7 +97,7 @@ private:
|
||||
return PerFunctionPasses;
|
||||
}
|
||||
|
||||
void CreatePasses();
|
||||
void CreatePasses(FunctionInfoIndex *FunctionIndex);
|
||||
|
||||
/// Generates the TargetMachine.
|
||||
/// Returns Null if it is unable to create the target machine.
|
||||
@ -117,12 +117,11 @@ private:
|
||||
public:
|
||||
EmitAssemblyHelper(DiagnosticsEngine &_Diags, const CodeGenOptions &CGOpts,
|
||||
const clang::TargetOptions &TOpts,
|
||||
const LangOptions &LOpts, Module *M,
|
||||
std::unique_ptr<FunctionInfoIndex> Index)
|
||||
const LangOptions &LOpts, Module *M)
|
||||
: Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts),
|
||||
TheModule(M), FunctionIndex(std::move(Index)),
|
||||
CodeGenerationTime("Code Generation Time"), CodeGenPasses(nullptr),
|
||||
PerModulePasses(nullptr), PerFunctionPasses(nullptr) {}
|
||||
TheModule(M), CodeGenerationTime("Code Generation Time"),
|
||||
CodeGenPasses(nullptr), PerModulePasses(nullptr),
|
||||
PerFunctionPasses(nullptr) {}
|
||||
|
||||
~EmitAssemblyHelper() {
|
||||
delete CodeGenPasses;
|
||||
@ -278,7 +277,7 @@ static void addSymbolRewriterPass(const CodeGenOptions &Opts,
|
||||
MPM->add(createRewriteSymbolsPass(DL));
|
||||
}
|
||||
|
||||
void EmitAssemblyHelper::CreatePasses() {
|
||||
void EmitAssemblyHelper::CreatePasses(FunctionInfoIndex *FunctionIndex) {
|
||||
if (CodeGenOpts.DisableLLVMPasses)
|
||||
return;
|
||||
|
||||
@ -332,9 +331,8 @@ void EmitAssemblyHelper::CreatePasses() {
|
||||
|
||||
// If we are performing a ThinLTO importing compile, invoke the LTO
|
||||
// pipeline and pass down the in-memory function index.
|
||||
if (!CodeGenOpts.ThinLTOIndexFile.empty()) {
|
||||
assert(FunctionIndex && "Expected non-empty function index");
|
||||
PMBuilder.FunctionIndex = FunctionIndex.get();
|
||||
if (FunctionIndex) {
|
||||
PMBuilder.FunctionIndex = FunctionIndex;
|
||||
PMBuilder.populateLTOPassManager(*MPM);
|
||||
return;
|
||||
}
|
||||
@ -642,7 +640,28 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
|
||||
return;
|
||||
if (TM)
|
||||
TheModule->setDataLayout(TM->createDataLayout());
|
||||
CreatePasses();
|
||||
|
||||
// If we are performing a ThinLTO importing compile, load the function
|
||||
// index into memory and pass it into CreatePasses, which will add it
|
||||
// to the PassManagerBuilder and invoke LTO passes.
|
||||
std::unique_ptr<FunctionInfoIndex> FunctionIndex;
|
||||
if (!CodeGenOpts.ThinLTOIndexFile.empty()) {
|
||||
ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
|
||||
llvm::getFunctionIndexForFile(CodeGenOpts.ThinLTOIndexFile,
|
||||
[&](const DiagnosticInfo &DI) {
|
||||
TheModule->getContext().diagnose(DI);
|
||||
});
|
||||
if (std::error_code EC = IndexOrErr.getError()) {
|
||||
std::string Error = EC.message();
|
||||
errs() << "Error loading index file '" << CodeGenOpts.ThinLTOIndexFile
|
||||
<< "': " << Error << "\n";
|
||||
return;
|
||||
}
|
||||
FunctionIndex = std::move(IndexOrErr.get());
|
||||
assert(FunctionIndex && "Expected non-empty function index");
|
||||
}
|
||||
|
||||
CreatePasses(FunctionIndex.get());
|
||||
|
||||
switch (Action) {
|
||||
case Backend_EmitNothing:
|
||||
@ -695,10 +714,8 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
|
||||
const clang::TargetOptions &TOpts,
|
||||
const LangOptions &LOpts, StringRef TDesc,
|
||||
Module *M, BackendAction Action,
|
||||
raw_pwrite_stream *OS,
|
||||
std::unique_ptr<FunctionInfoIndex> Index) {
|
||||
EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M,
|
||||
std::move(Index));
|
||||
raw_pwrite_stream *OS) {
|
||||
EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M);
|
||||
|
||||
AsmHelper.EmitAssembly(Action, OS);
|
||||
|
||||
|
@ -2025,6 +2025,11 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
|
||||
return getOrCreateType(Ty->getValueType(), U);
|
||||
}
|
||||
|
||||
llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty,
|
||||
llvm::DIFile *U) {
|
||||
return getOrCreateType(Ty->getElementType(), U);
|
||||
}
|
||||
|
||||
llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
|
||||
const EnumDecl *ED = Ty->getDecl();
|
||||
|
||||
@ -2284,6 +2289,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
|
||||
case Type::Atomic:
|
||||
return CreateType(cast<AtomicType>(Ty), Unit);
|
||||
|
||||
case Type::Pipe:
|
||||
return CreateType(cast<PipeType>(Ty), Unit);
|
||||
|
||||
case Type::TemplateSpecialization:
|
||||
return CreateType(cast<TemplateSpecializationType>(Ty), Unit);
|
||||
|
||||
|
@ -168,6 +168,7 @@ class CGDebugInfo {
|
||||
llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit);
|
||||
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
|
||||
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
|
||||
llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
|
||||
/// Get enumeration type.
|
||||
llvm::DIType *CreateEnumType(const EnumType *Ty);
|
||||
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
|
||||
|
@ -3365,6 +3365,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
||||
case CK_PointerToBoolean:
|
||||
case CK_VectorSplat:
|
||||
case CK_IntegralCast:
|
||||
case CK_BooleanToSignedIntegral:
|
||||
case CK_IntegralToBoolean:
|
||||
case CK_IntegralToFloating:
|
||||
case CK_FloatingToIntegral:
|
||||
|
@ -721,6 +721,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
|
||||
case CK_ToVoid:
|
||||
case CK_VectorSplat:
|
||||
case CK_IntegralCast:
|
||||
case CK_BooleanToSignedIntegral:
|
||||
case CK_IntegralToBoolean:
|
||||
case CK_IntegralToFloating:
|
||||
case CK_FloatingToIntegral:
|
||||
|
@ -462,6 +462,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
|
||||
case CK_ToVoid:
|
||||
case CK_VectorSplat:
|
||||
case CK_IntegralCast:
|
||||
case CK_BooleanToSignedIntegral:
|
||||
case CK_IntegralToBoolean:
|
||||
case CK_IntegralToFloating:
|
||||
case CK_FloatingToIntegral:
|
||||
|
@ -735,6 +735,7 @@ public:
|
||||
case CK_PointerToBoolean:
|
||||
case CK_NullToPointer:
|
||||
case CK_IntegralCast:
|
||||
case CK_BooleanToSignedIntegral:
|
||||
case CK_IntegralToPointer:
|
||||
case CK_IntegralToBoolean:
|
||||
case CK_IntegralToFloating:
|
||||
|
@ -811,14 +811,15 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
|
||||
|
||||
// A scalar can be splatted to an extended vector of the same element type
|
||||
if (DstType->isExtVectorType() && !SrcType->isVectorType()) {
|
||||
// Cast the scalar to element type
|
||||
QualType EltTy = DstType->getAs<ExtVectorType>()->getElementType();
|
||||
llvm::Value *Elt = EmitScalarConversion(
|
||||
Src, SrcType, EltTy, Loc, CGF.getContext().getLangOpts().OpenCL);
|
||||
// Sema should add casts to make sure that the source expression's type is
|
||||
// the same as the vector's element type (sans qualifiers)
|
||||
assert(DstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
|
||||
SrcType.getTypePtr() &&
|
||||
"Splatted expr doesn't match with vector element type?");
|
||||
|
||||
// Splat the element across to all elements
|
||||
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
|
||||
return Builder.CreateVectorSplat(NumElements, Elt, "splat");
|
||||
return Builder.CreateVectorSplat(NumElements, Src, "splat");
|
||||
}
|
||||
|
||||
// Allow bitcast from vector to integer/fp of the same size.
|
||||
@ -1541,15 +1542,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
|
||||
}
|
||||
case CK_VectorSplat: {
|
||||
llvm::Type *DstTy = ConvertType(DestTy);
|
||||
// Need an IgnoreImpCasts here as by default a boolean will be promoted to
|
||||
// an int, which will not perform the sign extension, so if we know we are
|
||||
// going to cast to a vector we have to strip the implicit cast off.
|
||||
Value *Elt = Visit(const_cast<Expr*>(E->IgnoreImpCasts()));
|
||||
Elt = EmitScalarConversion(Elt, E->IgnoreImpCasts()->getType(),
|
||||
DestTy->getAs<VectorType>()->getElementType(),
|
||||
CE->getExprLoc(),
|
||||
CGF.getContext().getLangOpts().OpenCL);
|
||||
|
||||
Value *Elt = Visit(const_cast<Expr*>(E));
|
||||
// Splat the element across to all elements
|
||||
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
|
||||
return Builder.CreateVectorSplat(NumElements, Elt, "splat");
|
||||
@ -1561,6 +1554,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
|
||||
case CK_FloatingCast:
|
||||
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
|
||||
CE->getExprLoc());
|
||||
case CK_BooleanToSignedIntegral:
|
||||
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
|
||||
CE->getExprLoc(),
|
||||
/*TreatBooleanAsSigned=*/true);
|
||||
case CK_IntegralToBoolean:
|
||||
return EmitIntToBoolConversion(Visit(E));
|
||||
case CK_PointerToBoolean:
|
||||
|
@ -99,3 +99,14 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
|
||||
llvm::StructType::create(Ctx, "opencl.reserve_id_t"), 0);
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Type *CGOpenCLRuntime::getPipeType() {
|
||||
if (!PipeTy){
|
||||
uint32_t PipeAddrSpc =
|
||||
CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
|
||||
PipeTy = llvm::PointerType::get(llvm::StructType::create(
|
||||
CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc);
|
||||
}
|
||||
|
||||
return PipeTy;
|
||||
}
|
||||
|
@ -32,9 +32,10 @@ class CodeGenModule;
|
||||
class CGOpenCLRuntime {
|
||||
protected:
|
||||
CodeGenModule &CGM;
|
||||
llvm::Type *PipeTy;
|
||||
|
||||
public:
|
||||
CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
|
||||
CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr) {}
|
||||
virtual ~CGOpenCLRuntime();
|
||||
|
||||
/// Emit the IR required for a work-group-local variable declaration, and add
|
||||
@ -44,6 +45,8 @@ public:
|
||||
const VarDecl &D);
|
||||
|
||||
virtual llvm::Type *convertOpenCLSpecificType(const Type *T);
|
||||
|
||||
virtual llvm::Type *getPipeType();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ public:
|
||||
|
||||
protected:
|
||||
CGOpenMPRegionKind RegionKind;
|
||||
const RegionCodeGenTy &CodeGen;
|
||||
RegionCodeGenTy CodeGen;
|
||||
OpenMPDirectiveKind Kind;
|
||||
bool HasCancel;
|
||||
};
|
||||
|
@ -335,7 +335,7 @@ private:
|
||||
public:
|
||||
/// \brief Kind of a given entry. Currently, only target regions are
|
||||
/// supported.
|
||||
enum OffloadingEntryInfoKinds {
|
||||
enum OffloadingEntryInfoKinds : unsigned {
|
||||
// Entry is a target region.
|
||||
OFFLOAD_ENTRY_INFO_TARGET_REGION = 0,
|
||||
// Invalid entry info.
|
||||
@ -955,7 +955,7 @@ public:
|
||||
/// \brief Emit the target regions enclosed in \a GD function definition or
|
||||
/// the function itself in case it is a valid device function. Returns true if
|
||||
/// \a GD was dealt with successfully.
|
||||
/// \param FD Function to scan.
|
||||
/// \param GD Function to scan.
|
||||
virtual bool emitTargetFunctions(GlobalDecl GD);
|
||||
|
||||
/// \brief Emit the global variable if it is a valid device global variable.
|
||||
|
@ -26,12 +26,10 @@
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/DiagnosticInfo.h"
|
||||
#include "llvm/IR/DiagnosticPrinter.h"
|
||||
#include "llvm/IR/FunctionInfo.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IRReader/IRReader.h"
|
||||
#include "llvm/Linker/Linker.h"
|
||||
#include "llvm/Object/FunctionIndexObjectFile.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
@ -781,43 +779,11 @@ void CodeGenAction::ExecuteAction() {
|
||||
TheModule->setTargetTriple(TargetOpts.Triple);
|
||||
}
|
||||
|
||||
auto DiagHandler = [&](const DiagnosticInfo &DI) {
|
||||
TheModule->getContext().diagnose(DI);
|
||||
};
|
||||
|
||||
// If we are performing ThinLTO importing compilation (indicated by
|
||||
// a non-empty index file option), then we need promote to global scope
|
||||
// and rename any local values that are potentially exported to other
|
||||
// modules. Do this early so that the rest of the compilation sees the
|
||||
// promoted symbols.
|
||||
std::unique_ptr<FunctionInfoIndex> Index;
|
||||
if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) {
|
||||
ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
|
||||
llvm::getFunctionIndexForFile(CI.getCodeGenOpts().ThinLTOIndexFile,
|
||||
DiagHandler);
|
||||
if (std::error_code EC = IndexOrErr.getError()) {
|
||||
std::string Error = EC.message();
|
||||
errs() << "Error loading index file '"
|
||||
<< CI.getCodeGenOpts().ThinLTOIndexFile << "': " << Error
|
||||
<< "\n";
|
||||
return;
|
||||
}
|
||||
Index = std::move(IndexOrErr.get());
|
||||
assert(Index);
|
||||
// Currently this requires creating a new Module object.
|
||||
std::unique_ptr<llvm::Module> RenamedModule =
|
||||
renameModuleForThinLTO(std::move(TheModule), Index.get());
|
||||
if (!RenamedModule)
|
||||
return;
|
||||
|
||||
TheModule = std::move(RenamedModule);
|
||||
}
|
||||
|
||||
LLVMContext &Ctx = TheModule->getContext();
|
||||
Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler);
|
||||
EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts,
|
||||
CI.getLangOpts(), CI.getTarget().getDataLayoutString(),
|
||||
TheModule.get(), BA, OS, std::move(Index));
|
||||
TheModule.get(), BA, OS);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
|
||||
if (CGM.getCodeGenOpts().ReciprocalMath) {
|
||||
FMF.setAllowReciprocal();
|
||||
}
|
||||
Builder.SetFastMathFlags(FMF);
|
||||
Builder.setFastMathFlags(FMF);
|
||||
}
|
||||
|
||||
CodeGenFunction::~CodeGenFunction() {
|
||||
@ -195,6 +195,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
|
||||
case Type::FunctionNoProto:
|
||||
case Type::Enum:
|
||||
case Type::ObjCObjectPointer:
|
||||
case Type::Pipe:
|
||||
return TEK_Scalar;
|
||||
|
||||
// Complexes.
|
||||
@ -511,7 +512,8 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
|
||||
typeQuals += typeQuals.empty() ? "volatile" : " volatile";
|
||||
} else {
|
||||
uint32_t AddrSpc = 0;
|
||||
if (ty->isImageType())
|
||||
bool isPipe = ty->isPipeType();
|
||||
if (ty->isImageType() || isPipe)
|
||||
AddrSpc =
|
||||
CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
|
||||
|
||||
@ -519,7 +521,11 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
|
||||
llvm::ConstantAsMetadata::get(Builder.getInt32(AddrSpc)));
|
||||
|
||||
// Get argument type name.
|
||||
std::string typeName = ty.getUnqualifiedType().getAsString(Policy);
|
||||
std::string typeName;
|
||||
if (isPipe)
|
||||
typeName = cast<PipeType>(ty)->getElementType().getAsString(Policy);
|
||||
else
|
||||
typeName = ty.getUnqualifiedType().getAsString(Policy);
|
||||
|
||||
// Turn "unsigned type" to "utype"
|
||||
std::string::size_type pos = typeName.find("unsigned");
|
||||
@ -528,7 +534,12 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
|
||||
|
||||
argTypeNames.push_back(llvm::MDString::get(Context, typeName));
|
||||
|
||||
std::string baseTypeName =
|
||||
std::string baseTypeName;
|
||||
if (isPipe)
|
||||
baseTypeName =
|
||||
cast<PipeType>(ty)->getElementType().getCanonicalType().getAsString(Policy);
|
||||
else
|
||||
baseTypeName =
|
||||
ty.getUnqualifiedType().getCanonicalType().getAsString(Policy);
|
||||
|
||||
// Turn "unsigned type" to "utype"
|
||||
@ -543,12 +554,16 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
|
||||
typeQuals = "const";
|
||||
if (ty.isVolatileQualified())
|
||||
typeQuals += typeQuals.empty() ? "volatile" : " volatile";
|
||||
if (isPipe)
|
||||
typeQuals = "pipe";
|
||||
}
|
||||
|
||||
argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals));
|
||||
|
||||
// Get image access qualifier:
|
||||
if (ty->isImageType()) {
|
||||
// Get image and pipe access qualifier:
|
||||
// FIXME: now image and pipe share the same access qualifier maybe we can
|
||||
// refine it to OpenCL access qualifier and also handle write_read
|
||||
if (ty->isImageType()|| ty->isPipeType()) {
|
||||
const OpenCLImageAccessAttr *A = parm->getAttr<OpenCLImageAccessAttr>();
|
||||
if (A && A->isWriteOnly())
|
||||
accessQuals.push_back(llvm::MDString::get(Context, "write_only"));
|
||||
@ -1727,6 +1742,10 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
|
||||
case Type::Atomic:
|
||||
type = cast<AtomicType>(ty)->getValueType();
|
||||
break;
|
||||
|
||||
case Type::Pipe:
|
||||
type = cast<PipeType>(ty)->getElementType();
|
||||
break;
|
||||
}
|
||||
} while (type->isVariablyModifiedType());
|
||||
}
|
||||
|
@ -615,7 +615,20 @@ void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const {
|
||||
}
|
||||
|
||||
StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
|
||||
StringRef &FoundStr = MangledDeclNames[GD.getCanonicalDecl()];
|
||||
GlobalDecl CanonicalGD = GD.getCanonicalDecl();
|
||||
|
||||
// Some ABIs don't have constructor variants. Make sure that base and
|
||||
// complete constructors get mangled the same.
|
||||
if (const auto *CD = dyn_cast<CXXConstructorDecl>(CanonicalGD.getDecl())) {
|
||||
if (!getTarget().getCXXABI().hasConstructorVariants()) {
|
||||
CXXCtorType OrigCtorType = GD.getCtorType();
|
||||
assert(OrigCtorType == Ctor_Base || OrigCtorType == Ctor_Complete);
|
||||
if (OrigCtorType == Ctor_Base)
|
||||
CanonicalGD = GlobalDecl(CD, Ctor_Complete);
|
||||
}
|
||||
}
|
||||
|
||||
StringRef &FoundStr = MangledDeclNames[CanonicalGD];
|
||||
if (!FoundStr.empty())
|
||||
return FoundStr;
|
||||
|
||||
|
@ -699,7 +699,7 @@ CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name,
|
||||
|
||||
setFuncName(Name, Linkage);
|
||||
CGM.getCoverageMapping()->addFunctionMappingRecord(
|
||||
FuncNameVar, FuncName, FunctionHash, CoverageMapping);
|
||||
FuncNameVar, FuncName, FunctionHash, CoverageMapping, false);
|
||||
}
|
||||
|
||||
void CodeGenPGO::computeRegionCounts(const Decl *D) {
|
||||
|
@ -628,6 +628,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Type::Pipe: {
|
||||
ResultType = CGM.getOpenCLRuntime().getPipeType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(ResultType && "Didn't convert a type?");
|
||||
|
@ -910,11 +910,11 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
|
||||
}
|
||||
|
||||
void CoverageMappingModuleGen::addFunctionMappingRecord(
|
||||
llvm::GlobalVariable *NamePtr, StringRef NameValue,
|
||||
uint64_t FuncHash, const std::string &CoverageMapping) {
|
||||
llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
|
||||
const std::string &CoverageMapping, bool isUsed) {
|
||||
llvm::LLVMContext &Ctx = CGM.getLLVMContext();
|
||||
if (!FunctionRecordTy) {
|
||||
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
|
||||
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
|
||||
llvm::Type *FunctionRecordTypes[] = {
|
||||
#include "llvm/ProfileData/InstrProfData.inc"
|
||||
};
|
||||
@ -929,6 +929,9 @@ void CoverageMappingModuleGen::addFunctionMappingRecord(
|
||||
};
|
||||
FunctionRecords.push_back(llvm::ConstantStruct::get(
|
||||
FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
|
||||
if (!isUsed)
|
||||
FunctionNames.push_back(
|
||||
llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
|
||||
CoverageMappings += CoverageMapping;
|
||||
|
||||
if (CGM.getCodeGenOpts().DumpCoverageMapping) {
|
||||
@ -1023,6 +1026,17 @@ void CoverageMappingModuleGen::emit() {
|
||||
|
||||
// Make sure the data doesn't get deleted.
|
||||
CGM.addUsedGlobal(CovData);
|
||||
// Create the deferred function records array
|
||||
if (!FunctionNames.empty()) {
|
||||
auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx),
|
||||
FunctionNames.size());
|
||||
auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
|
||||
// This variable will *NOT* be emitted to the object file. It is used
|
||||
// to pass the list of names referenced to codegen.
|
||||
new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true,
|
||||
llvm::GlobalValue::InternalLinkage, NamesArrVal,
|
||||
llvm::getCoverageNamesVarName());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {
|
||||
|
@ -54,6 +54,7 @@ class CoverageMappingModuleGen {
|
||||
CoverageSourceInfo &SourceInfo;
|
||||
llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries;
|
||||
std::vector<llvm::Constant *> FunctionRecords;
|
||||
std::vector<llvm::Constant *> FunctionNames;
|
||||
llvm::StructType *FunctionRecordTy;
|
||||
std::string CoverageMappings;
|
||||
|
||||
@ -70,7 +71,8 @@ public:
|
||||
void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,
|
||||
StringRef FunctionNameValue,
|
||||
uint64_t FunctionHash,
|
||||
const std::string &CoverageMapping);
|
||||
const std::string &CoverageMapping,
|
||||
bool isUsed = true);
|
||||
|
||||
/// \brief Emit the coverage mapping data for a translation unit.
|
||||
void emit();
|
||||
|
@ -2715,6 +2715,9 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
|
||||
case Type::Auto:
|
||||
llvm_unreachable("Undeduced auto type shouldn't get here");
|
||||
|
||||
case Type::Pipe:
|
||||
llvm_unreachable("Pipe types shouldn't get here");
|
||||
|
||||
case Type::Builtin:
|
||||
// GCC treats vector and complex types as fundamental types.
|
||||
case Type::Vector:
|
||||
@ -2939,6 +2942,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
|
||||
case Type::Auto:
|
||||
llvm_unreachable("Undeduced auto type shouldn't get here");
|
||||
|
||||
case Type::Pipe:
|
||||
llvm_unreachable("Pipe type shouldn't get here");
|
||||
|
||||
case Type::ConstantArray:
|
||||
case Type::IncompleteArray:
|
||||
case Type::VariableArray:
|
||||
|
@ -59,8 +59,10 @@ class PCHContainerGenerator : public ASTConsumer {
|
||||
struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> {
|
||||
clang::CodeGen::CGDebugInfo &DI;
|
||||
ASTContext &Ctx;
|
||||
DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx)
|
||||
: DI(DI), Ctx(Ctx) {}
|
||||
bool SkipTagDecls;
|
||||
DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx,
|
||||
bool SkipTagDecls)
|
||||
: DI(DI), Ctx(Ctx), SkipTagDecls(SkipTagDecls) {}
|
||||
|
||||
/// Determine whether this type can be represented in DWARF.
|
||||
static bool CanRepresent(const Type *Ty) {
|
||||
@ -75,6 +77,12 @@ class PCHContainerGenerator : public ASTConsumer {
|
||||
}
|
||||
|
||||
bool VisitTypeDecl(TypeDecl *D) {
|
||||
// TagDecls may be deferred until after all decls have been merged and we
|
||||
// know the complete type. Pure forward declarations will be skipped, but
|
||||
// they don't need to be emitted into the module anyway.
|
||||
if (SkipTagDecls && isa<TagDecl>(D))
|
||||
return true;
|
||||
|
||||
QualType QualTy = Ctx.getTypeDeclType(D);
|
||||
if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
|
||||
DI.getOrCreateStandaloneType(QualTy, D->getLocation());
|
||||
@ -165,7 +173,7 @@ public:
|
||||
// Collect debug info for all decls in this group.
|
||||
for (auto *I : D)
|
||||
if (!I->isFromASTFile()) {
|
||||
DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
|
||||
DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx, true);
|
||||
DTV.TraverseDecl(I);
|
||||
}
|
||||
return true;
|
||||
@ -179,6 +187,11 @@ public:
|
||||
if (Diags.hasErrorOccurred())
|
||||
return;
|
||||
|
||||
if (D->isFromASTFile())
|
||||
return;
|
||||
|
||||
DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx, false);
|
||||
DTV.TraverseDecl(D);
|
||||
Builder->UpdateCompletedType(D);
|
||||
}
|
||||
|
||||
|
@ -8,17 +8,14 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Driver/Action.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include <cassert>
|
||||
using namespace clang::driver;
|
||||
using namespace llvm::opt;
|
||||
|
||||
Action::~Action() {
|
||||
if (OwnsInputs) {
|
||||
for (iterator it = begin(), ie = end(); it != ie; ++it)
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
Action::~Action() {}
|
||||
|
||||
const char *Action::getClassName(ActionClass AC) {
|
||||
switch (AC) {
|
||||
@ -51,33 +48,53 @@ InputAction::InputAction(const Arg &_Input, types::ID _Type)
|
||||
|
||||
void BindArchAction::anchor() {}
|
||||
|
||||
BindArchAction::BindArchAction(std::unique_ptr<Action> Input,
|
||||
const char *_ArchName)
|
||||
: Action(BindArchClass, std::move(Input)), ArchName(_ArchName) {}
|
||||
BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
|
||||
: Action(BindArchClass, Input), ArchName(_ArchName) {}
|
||||
|
||||
// Converts CUDA GPU architecture, e.g. "sm_21", to its corresponding virtual
|
||||
// compute arch, e.g. "compute_20". Returns null if the input arch is null or
|
||||
// doesn't match an existing arch.
|
||||
static const char* GpuArchToComputeName(const char *ArchName) {
|
||||
if (!ArchName)
|
||||
return nullptr;
|
||||
return llvm::StringSwitch<const char *>(ArchName)
|
||||
.Cases("sm_20", "sm_21", "compute_20")
|
||||
.Case("sm_30", "compute_30")
|
||||
.Case("sm_32", "compute_32")
|
||||
.Case("sm_35", "compute_35")
|
||||
.Case("sm_37", "compute_37")
|
||||
.Case("sm_50", "compute_50")
|
||||
.Case("sm_52", "compute_52")
|
||||
.Case("sm_53", "compute_53")
|
||||
.Default(nullptr);
|
||||
}
|
||||
|
||||
void CudaDeviceAction::anchor() {}
|
||||
|
||||
CudaDeviceAction::CudaDeviceAction(std::unique_ptr<Action> Input,
|
||||
const char *ArchName, bool AtTopLevel)
|
||||
: Action(CudaDeviceClass, std::move(Input)), GpuArchName(ArchName),
|
||||
AtTopLevel(AtTopLevel) {}
|
||||
CudaDeviceAction::CudaDeviceAction(Action *Input, const char *ArchName,
|
||||
bool AtTopLevel)
|
||||
: Action(CudaDeviceClass, Input), GpuArchName(ArchName),
|
||||
AtTopLevel(AtTopLevel) {
|
||||
assert(IsValidGpuArchName(GpuArchName));
|
||||
}
|
||||
|
||||
const char *CudaDeviceAction::getComputeArchName() const {
|
||||
return GpuArchToComputeName(GpuArchName);
|
||||
}
|
||||
|
||||
bool CudaDeviceAction::IsValidGpuArchName(llvm::StringRef ArchName) {
|
||||
return GpuArchToComputeName(ArchName.data()) != nullptr;
|
||||
}
|
||||
|
||||
void CudaHostAction::anchor() {}
|
||||
|
||||
CudaHostAction::CudaHostAction(std::unique_ptr<Action> Input,
|
||||
const ActionList &DeviceActions)
|
||||
: Action(CudaHostClass, std::move(Input)), DeviceActions(DeviceActions) {}
|
||||
|
||||
CudaHostAction::~CudaHostAction() {
|
||||
for (auto &DA : DeviceActions)
|
||||
delete DA;
|
||||
}
|
||||
CudaHostAction::CudaHostAction(Action *Input, const ActionList &DeviceActions)
|
||||
: Action(CudaHostClass, Input), DeviceActions(DeviceActions) {}
|
||||
|
||||
void JobAction::anchor() {}
|
||||
|
||||
JobAction::JobAction(ActionClass Kind, std::unique_ptr<Action> Input,
|
||||
types::ID Type)
|
||||
: Action(Kind, std::move(Input), Type) {}
|
||||
JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
|
||||
: Action(Kind, Input, Type) {}
|
||||
|
||||
JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
|
||||
: Action(Kind, Inputs, Type) {
|
||||
@ -85,45 +102,38 @@ JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
|
||||
|
||||
void PreprocessJobAction::anchor() {}
|
||||
|
||||
PreprocessJobAction::PreprocessJobAction(std::unique_ptr<Action> Input,
|
||||
types::ID OutputType)
|
||||
: JobAction(PreprocessJobClass, std::move(Input), OutputType) {}
|
||||
PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
|
||||
: JobAction(PreprocessJobClass, Input, OutputType) {}
|
||||
|
||||
void PrecompileJobAction::anchor() {}
|
||||
|
||||
PrecompileJobAction::PrecompileJobAction(std::unique_ptr<Action> Input,
|
||||
types::ID OutputType)
|
||||
: JobAction(PrecompileJobClass, std::move(Input), OutputType) {}
|
||||
PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
|
||||
: JobAction(PrecompileJobClass, Input, OutputType) {}
|
||||
|
||||
void AnalyzeJobAction::anchor() {}
|
||||
|
||||
AnalyzeJobAction::AnalyzeJobAction(std::unique_ptr<Action> Input,
|
||||
types::ID OutputType)
|
||||
: JobAction(AnalyzeJobClass, std::move(Input), OutputType) {}
|
||||
AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
|
||||
: JobAction(AnalyzeJobClass, Input, OutputType) {}
|
||||
|
||||
void MigrateJobAction::anchor() {}
|
||||
|
||||
MigrateJobAction::MigrateJobAction(std::unique_ptr<Action> Input,
|
||||
types::ID OutputType)
|
||||
: JobAction(MigrateJobClass, std::move(Input), OutputType) {}
|
||||
MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
|
||||
: JobAction(MigrateJobClass, Input, OutputType) {}
|
||||
|
||||
void CompileJobAction::anchor() {}
|
||||
|
||||
CompileJobAction::CompileJobAction(std::unique_ptr<Action> Input,
|
||||
types::ID OutputType)
|
||||
: JobAction(CompileJobClass, std::move(Input), OutputType) {}
|
||||
CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
|
||||
: JobAction(CompileJobClass, Input, OutputType) {}
|
||||
|
||||
void BackendJobAction::anchor() {}
|
||||
|
||||
BackendJobAction::BackendJobAction(std::unique_ptr<Action> Input,
|
||||
types::ID OutputType)
|
||||
: JobAction(BackendJobClass, std::move(Input), OutputType) {}
|
||||
BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
|
||||
: JobAction(BackendJobClass, Input, OutputType) {}
|
||||
|
||||
void AssembleJobAction::anchor() {}
|
||||
|
||||
AssembleJobAction::AssembleJobAction(std::unique_ptr<Action> Input,
|
||||
types::ID OutputType)
|
||||
: JobAction(AssembleJobClass, std::move(Input), OutputType) {}
|
||||
AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
|
||||
: JobAction(AssembleJobClass, Input, OutputType) {}
|
||||
|
||||
void LinkJobAction::anchor() {}
|
||||
|
||||
@ -145,21 +155,20 @@ DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
|
||||
|
||||
void VerifyJobAction::anchor() {}
|
||||
|
||||
VerifyJobAction::VerifyJobAction(ActionClass Kind,
|
||||
std::unique_ptr<Action> Input, types::ID Type)
|
||||
: JobAction(Kind, std::move(Input), Type) {
|
||||
VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
|
||||
types::ID Type)
|
||||
: JobAction(Kind, Input, Type) {
|
||||
assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
|
||||
"ActionClass is not a valid VerifyJobAction");
|
||||
}
|
||||
|
||||
void VerifyDebugInfoJobAction::anchor() {}
|
||||
|
||||
VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(
|
||||
std::unique_ptr<Action> Input, types::ID Type)
|
||||
: VerifyJobAction(VerifyDebugInfoJobClass, std::move(Input), Type) {}
|
||||
VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
|
||||
types::ID Type)
|
||||
: VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
|
||||
|
||||
void VerifyPCHJobAction::anchor() {}
|
||||
|
||||
VerifyPCHJobAction::VerifyPCHJobAction(std::unique_ptr<Action> Input,
|
||||
types::ID Type)
|
||||
: VerifyJobAction(VerifyPCHJobClass, std::move(Input), Type) {}
|
||||
VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
|
||||
: VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
|
||||
|
@ -40,11 +40,6 @@ Compilation::~Compilation() {
|
||||
if (it->second != TranslatedArgs)
|
||||
delete it->second;
|
||||
|
||||
// Free the actions, if built.
|
||||
for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
|
||||
it != ie; ++it)
|
||||
delete *it;
|
||||
|
||||
// Free redirections of stdout/stderr.
|
||||
if (Redirects) {
|
||||
delete Redirects[1];
|
||||
@ -208,7 +203,8 @@ void Compilation::initCompilationForDiagnostics() {
|
||||
ForDiagnostics = true;
|
||||
|
||||
// Free actions and jobs.
|
||||
DeleteContainerPointers(Actions);
|
||||
Actions.clear();
|
||||
AllActions.clear();
|
||||
Jobs.clear();
|
||||
|
||||
// Clear temporary/results file lists.
|
||||
|
@ -1049,19 +1049,15 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
|
||||
<< types::getTypeName(Act->getType());
|
||||
|
||||
ActionList Inputs;
|
||||
for (unsigned i = 0, e = Archs.size(); i != e; ++i) {
|
||||
Inputs.push_back(
|
||||
new BindArchAction(std::unique_ptr<Action>(Act), Archs[i]));
|
||||
if (i != 0)
|
||||
Inputs.back()->setOwnsInputs(false);
|
||||
}
|
||||
for (unsigned i = 0, e = Archs.size(); i != e; ++i)
|
||||
Inputs.push_back(C.MakeAction<BindArchAction>(Act, Archs[i]));
|
||||
|
||||
// Lipo if necessary, we do it this way because we need to set the arch flag
|
||||
// so that -Xarch_ gets overwritten.
|
||||
if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)
|
||||
Actions.append(Inputs.begin(), Inputs.end());
|
||||
else
|
||||
Actions.push_back(new LipoJobAction(Inputs, Act->getType()));
|
||||
Actions.push_back(C.MakeAction<LipoJobAction>(Inputs, Act->getType()));
|
||||
|
||||
// Handle debug info queries.
|
||||
Arg *A = Args.getLastArg(options::OPT_g_Group);
|
||||
@ -1077,15 +1073,16 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
|
||||
ActionList Inputs;
|
||||
Inputs.push_back(Actions.back());
|
||||
Actions.pop_back();
|
||||
Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
|
||||
Actions.push_back(
|
||||
C.MakeAction<DsymutilJobAction>(Inputs, types::TY_dSYM));
|
||||
}
|
||||
|
||||
// Verify the debug info output.
|
||||
if (Args.hasArg(options::OPT_verify_debug_info)) {
|
||||
std::unique_ptr<Action> VerifyInput(Actions.back());
|
||||
Action* LastAction = Actions.back();
|
||||
Actions.pop_back();
|
||||
Actions.push_back(new VerifyDebugInfoJobAction(std::move(VerifyInput),
|
||||
types::TY_Nothing));
|
||||
Actions.push_back(C.MakeAction<VerifyDebugInfoJobAction>(
|
||||
LastAction, types::TY_Nothing));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1283,26 +1280,29 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
|
||||
// Actions and /p Current is released. Otherwise the function creates
|
||||
// and returns a new CudaHostAction which wraps /p Current and device
|
||||
// side actions.
|
||||
static std::unique_ptr<Action>
|
||||
buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg,
|
||||
std::unique_ptr<Action> HostAction, ActionList &Actions) {
|
||||
static Action *buildCudaActions(Compilation &C, DerivedArgList &Args,
|
||||
const Arg *InputArg, Action *HostAction,
|
||||
ActionList &Actions) {
|
||||
Arg *PartialCompilationArg = Args.getLastArg(options::OPT_cuda_host_only,
|
||||
options::OPT_cuda_device_only);
|
||||
// Host-only compilation case.
|
||||
if (PartialCompilationArg &&
|
||||
PartialCompilationArg->getOption().matches(options::OPT_cuda_host_only))
|
||||
return std::unique_ptr<Action>(
|
||||
new CudaHostAction(std::move(HostAction), {}));
|
||||
return C.MakeAction<CudaHostAction>(HostAction, ActionList());
|
||||
|
||||
// Collect all cuda_gpu_arch parameters, removing duplicates.
|
||||
SmallVector<const char *, 4> GpuArchList;
|
||||
llvm::StringSet<> GpuArchNames;
|
||||
for (Arg *A : Args) {
|
||||
if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) {
|
||||
A->claim();
|
||||
if (GpuArchNames.insert(A->getValue()).second)
|
||||
GpuArchList.push_back(A->getValue());
|
||||
}
|
||||
if (!A->getOption().matches(options::OPT_cuda_gpu_arch_EQ))
|
||||
continue;
|
||||
A->claim();
|
||||
|
||||
const auto& Arch = A->getValue();
|
||||
if (!CudaDeviceAction::IsValidGpuArchName(Arch))
|
||||
C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << Arch;
|
||||
else if (GpuArchNames.insert(Arch).second)
|
||||
GpuArchList.push_back(Arch);
|
||||
}
|
||||
|
||||
// Default to sm_20 which is the lowest common denominator for supported GPUs.
|
||||
@ -1325,13 +1325,10 @@ buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg,
|
||||
"Failed to create actions for all devices");
|
||||
|
||||
// Check whether any of device actions stopped before they could generate PTX.
|
||||
bool PartialCompilation = false;
|
||||
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
|
||||
if (CudaDeviceActions[I]->getKind() != Action::BackendJobClass) {
|
||||
PartialCompilation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool PartialCompilation =
|
||||
llvm::any_of(CudaDeviceActions, [](const Action *a) {
|
||||
return a->getKind() != Action::BackendJobClass;
|
||||
});
|
||||
|
||||
// Figure out what to do with device actions -- pass them as inputs to the
|
||||
// host action or run each of them independently.
|
||||
@ -1350,12 +1347,12 @@ buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg,
|
||||
}
|
||||
|
||||
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
|
||||
Actions.push_back(new CudaDeviceAction(
|
||||
std::unique_ptr<Action>(CudaDeviceActions[I]), GpuArchList[I],
|
||||
/* AtTopLevel */ true));
|
||||
Actions.push_back(C.MakeAction<CudaDeviceAction>(CudaDeviceActions[I],
|
||||
GpuArchList[I],
|
||||
/* AtTopLevel */ true));
|
||||
// Kill host action in case of device-only compilation.
|
||||
if (DeviceOnlyCompilation)
|
||||
HostAction.reset(nullptr);
|
||||
return nullptr;
|
||||
return HostAction;
|
||||
}
|
||||
|
||||
@ -1363,13 +1360,12 @@ buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg,
|
||||
// with AtTopLevel=false and become inputs for the host action.
|
||||
ActionList DeviceActions;
|
||||
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
|
||||
DeviceActions.push_back(new CudaDeviceAction(
|
||||
std::unique_ptr<Action>(CudaDeviceActions[I]), GpuArchList[I],
|
||||
/* AtTopLevel */ false));
|
||||
DeviceActions.push_back(
|
||||
C.MakeAction<CudaDeviceAction>(CudaDeviceActions[I], GpuArchList[I],
|
||||
/* AtTopLevel */ false));
|
||||
// Return a new host action that incorporates original host action and all
|
||||
// device actions.
|
||||
return std::unique_ptr<Action>(
|
||||
new CudaHostAction(std::move(HostAction), DeviceActions));
|
||||
return C.MakeAction<CudaHostAction>(HostAction, DeviceActions);
|
||||
}
|
||||
|
||||
void Driver::BuildActions(Compilation &C, const ToolChain &TC,
|
||||
@ -1470,15 +1466,14 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
|
||||
continue;
|
||||
}
|
||||
|
||||
phases::ID CudaInjectionPhase = FinalPhase;
|
||||
for (const auto &Phase : PL)
|
||||
if (Phase <= FinalPhase && Phase == phases::Compile) {
|
||||
CudaInjectionPhase = Phase;
|
||||
break;
|
||||
}
|
||||
phases::ID CudaInjectionPhase =
|
||||
(phases::Compile < FinalPhase &&
|
||||
llvm::find(PL, phases::Compile) != PL.end())
|
||||
? phases::Compile
|
||||
: FinalPhase;
|
||||
|
||||
// Build the pipeline for this file.
|
||||
std::unique_ptr<Action> Current(new InputAction(*InputArg, InputType));
|
||||
Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
|
||||
for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end();
|
||||
i != e; ++i) {
|
||||
phases::ID Phase = *i;
|
||||
@ -1490,7 +1485,8 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
|
||||
// Queue linker inputs.
|
||||
if (Phase == phases::Link) {
|
||||
assert((i + 1) == e && "linking must be final compilation step.");
|
||||
LinkerInputs.push_back(Current.release());
|
||||
LinkerInputs.push_back(Current);
|
||||
Current = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1501,11 +1497,10 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
|
||||
continue;
|
||||
|
||||
// Otherwise construct the appropriate action.
|
||||
Current = ConstructPhaseAction(TC, Args, Phase, std::move(Current));
|
||||
Current = ConstructPhaseAction(C, TC, Args, Phase, Current);
|
||||
|
||||
if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase) {
|
||||
Current =
|
||||
buildCudaActions(C, Args, InputArg, std::move(Current), Actions);
|
||||
Current = buildCudaActions(C, Args, InputArg, Current, Actions);
|
||||
if (!Current)
|
||||
break;
|
||||
}
|
||||
@ -1516,12 +1511,13 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
|
||||
|
||||
// If we ended with something, add to the output list.
|
||||
if (Current)
|
||||
Actions.push_back(Current.release());
|
||||
Actions.push_back(Current);
|
||||
}
|
||||
|
||||
// Add a link action if necessary.
|
||||
if (!LinkerInputs.empty())
|
||||
Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image));
|
||||
Actions.push_back(
|
||||
C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image));
|
||||
|
||||
// If we are linking, claim any options which are obviously only used for
|
||||
// compilation.
|
||||
@ -1538,10 +1534,9 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
|
||||
Args.ClaimAllArgs(options::OPT_cuda_host_only);
|
||||
}
|
||||
|
||||
std::unique_ptr<Action>
|
||||
Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
|
||||
phases::ID Phase,
|
||||
std::unique_ptr<Action> Input) const {
|
||||
Action *Driver::ConstructPhaseAction(Compilation &C, const ToolChain &TC,
|
||||
const ArgList &Args, phases::ID Phase,
|
||||
Action *Input) const {
|
||||
llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
|
||||
// Build the appropriate action.
|
||||
switch (Phase) {
|
||||
@ -1561,7 +1556,7 @@ Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
|
||||
assert(OutputTy != types::TY_INVALID &&
|
||||
"Cannot preprocess this input type!");
|
||||
}
|
||||
return llvm::make_unique<PreprocessJobAction>(std::move(Input), OutputTy);
|
||||
return C.MakeAction<PreprocessJobAction>(Input, OutputTy);
|
||||
}
|
||||
case phases::Precompile: {
|
||||
types::ID OutputTy = types::TY_PCH;
|
||||
@ -1569,53 +1564,43 @@ Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
|
||||
// Syntax checks should not emit a PCH file
|
||||
OutputTy = types::TY_Nothing;
|
||||
}
|
||||
return llvm::make_unique<PrecompileJobAction>(std::move(Input), OutputTy);
|
||||
return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
|
||||
}
|
||||
case phases::Compile: {
|
||||
if (Args.hasArg(options::OPT_fsyntax_only))
|
||||
return llvm::make_unique<CompileJobAction>(std::move(Input),
|
||||
types::TY_Nothing);
|
||||
return C.MakeAction<CompileJobAction>(Input, types::TY_Nothing);
|
||||
if (Args.hasArg(options::OPT_rewrite_objc))
|
||||
return llvm::make_unique<CompileJobAction>(std::move(Input),
|
||||
types::TY_RewrittenObjC);
|
||||
return C.MakeAction<CompileJobAction>(Input, types::TY_RewrittenObjC);
|
||||
if (Args.hasArg(options::OPT_rewrite_legacy_objc))
|
||||
return llvm::make_unique<CompileJobAction>(std::move(Input),
|
||||
types::TY_RewrittenLegacyObjC);
|
||||
return C.MakeAction<CompileJobAction>(Input,
|
||||
types::TY_RewrittenLegacyObjC);
|
||||
if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto))
|
||||
return llvm::make_unique<AnalyzeJobAction>(std::move(Input),
|
||||
types::TY_Plist);
|
||||
return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist);
|
||||
if (Args.hasArg(options::OPT__migrate))
|
||||
return llvm::make_unique<MigrateJobAction>(std::move(Input),
|
||||
types::TY_Remap);
|
||||
return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap);
|
||||
if (Args.hasArg(options::OPT_emit_ast))
|
||||
return llvm::make_unique<CompileJobAction>(std::move(Input),
|
||||
types::TY_AST);
|
||||
return C.MakeAction<CompileJobAction>(Input, types::TY_AST);
|
||||
if (Args.hasArg(options::OPT_module_file_info))
|
||||
return llvm::make_unique<CompileJobAction>(std::move(Input),
|
||||
types::TY_ModuleFile);
|
||||
return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);
|
||||
if (Args.hasArg(options::OPT_verify_pch))
|
||||
return llvm::make_unique<VerifyPCHJobAction>(std::move(Input),
|
||||
types::TY_Nothing);
|
||||
return llvm::make_unique<CompileJobAction>(std::move(Input),
|
||||
types::TY_LLVM_BC);
|
||||
return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
|
||||
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
|
||||
}
|
||||
case phases::Backend: {
|
||||
if (isUsingLTO()) {
|
||||
types::ID Output =
|
||||
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
|
||||
return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
|
||||
return C.MakeAction<BackendJobAction>(Input, Output);
|
||||
}
|
||||
if (Args.hasArg(options::OPT_emit_llvm)) {
|
||||
types::ID Output =
|
||||
Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
|
||||
return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
|
||||
return C.MakeAction<BackendJobAction>(Input, Output);
|
||||
}
|
||||
return llvm::make_unique<BackendJobAction>(std::move(Input),
|
||||
types::TY_PP_Asm);
|
||||
return C.MakeAction<BackendJobAction>(Input, types::TY_PP_Asm);
|
||||
}
|
||||
case phases::Assemble:
|
||||
return llvm::make_unique<AssembleJobAction>(std::move(Input),
|
||||
types::TY_Object);
|
||||
return C.MakeAction<AssembleJobAction>(Input, types::TY_Object);
|
||||
}
|
||||
|
||||
llvm_unreachable("invalid phase in ConstructPhaseAction");
|
||||
@ -1662,12 +1647,11 @@ void Driver::BuildJobs(Compilation &C) const {
|
||||
LinkingOutput = getDefaultImageName();
|
||||
}
|
||||
|
||||
InputInfo II;
|
||||
BuildJobsForAction(C, A, &C.getDefaultToolChain(),
|
||||
/*BoundArch*/ nullptr,
|
||||
/*AtTopLevel*/ true,
|
||||
/*MultipleArchs*/ ArchNames.size() > 1,
|
||||
/*LinkingOutput*/ LinkingOutput, II);
|
||||
/*LinkingOutput*/ LinkingOutput);
|
||||
}
|
||||
|
||||
// If the user passed -Qunused-arguments or there were errors, don't warn
|
||||
@ -1795,21 +1779,19 @@ static const Tool *selectToolForJob(Compilation &C, bool SaveTemps,
|
||||
return ToolForJob;
|
||||
}
|
||||
|
||||
void Driver::BuildJobsForAction(Compilation &C, const Action *A,
|
||||
const ToolChain *TC, const char *BoundArch,
|
||||
bool AtTopLevel, bool MultipleArchs,
|
||||
const char *LinkingOutput,
|
||||
InputInfo &Result) const {
|
||||
InputInfo Driver::BuildJobsForAction(Compilation &C, const Action *A,
|
||||
const ToolChain *TC, const char *BoundArch,
|
||||
bool AtTopLevel, bool MultipleArchs,
|
||||
const char *LinkingOutput) const {
|
||||
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
|
||||
|
||||
InputInfoList CudaDeviceInputInfos;
|
||||
if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {
|
||||
InputInfo II;
|
||||
// Append outputs of device jobs to the input list.
|
||||
for (const Action *DA : CHA->getDeviceActions()) {
|
||||
BuildJobsForAction(C, DA, TC, nullptr, AtTopLevel,
|
||||
/*MultipleArchs*/ false, LinkingOutput, II);
|
||||
CudaDeviceInputInfos.push_back(II);
|
||||
CudaDeviceInputInfos.push_back(
|
||||
BuildJobsForAction(C, DA, TC, nullptr, AtTopLevel,
|
||||
/*MultipleArchs*/ false, LinkingOutput));
|
||||
}
|
||||
// Override current action with a real host compile action and continue
|
||||
// processing it.
|
||||
@ -1823,11 +1805,9 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
|
||||
Input.claim();
|
||||
if (Input.getOption().matches(options::OPT_INPUT)) {
|
||||
const char *Name = Input.getValue();
|
||||
Result = InputInfo(Name, A->getType(), Name);
|
||||
} else {
|
||||
Result = InputInfo(&Input, A->getType(), "");
|
||||
return InputInfo(A, Name, /* BaseInput = */ Name);
|
||||
}
|
||||
return;
|
||||
return InputInfo(A, &Input, /* BaseInput = */ "");
|
||||
}
|
||||
|
||||
if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
|
||||
@ -1841,19 +1821,17 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
|
||||
else
|
||||
TC = &C.getDefaultToolChain();
|
||||
|
||||
BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel,
|
||||
MultipleArchs, LinkingOutput, Result);
|
||||
return;
|
||||
return BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel,
|
||||
MultipleArchs, LinkingOutput);
|
||||
}
|
||||
|
||||
if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {
|
||||
// Initial processing of CudaDeviceAction carries host params.
|
||||
// Call BuildJobsForAction() again, now with correct device parameters.
|
||||
assert(CDA->getGpuArchName() && "No GPU name in device action.");
|
||||
BuildJobsForAction(C, *CDA->begin(), C.getCudaDeviceToolChain(),
|
||||
CDA->getGpuArchName(), CDA->isAtTopLevel(),
|
||||
/*MultipleArchs*/ true, LinkingOutput, Result);
|
||||
return;
|
||||
return BuildJobsForAction(C, *CDA->begin(), C.getCudaDeviceToolChain(),
|
||||
CDA->getGpuArchName(), CDA->isAtTopLevel(),
|
||||
/*MultipleArchs*/ true, LinkingOutput);
|
||||
}
|
||||
|
||||
const ActionList *Inputs = &A->getInputs();
|
||||
@ -1863,16 +1841,15 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
|
||||
const Tool *T =
|
||||
selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA);
|
||||
if (!T)
|
||||
return;
|
||||
return InputInfo();
|
||||
|
||||
// If we've collapsed action list that contained CudaHostAction we
|
||||
// need to build jobs for device-side inputs it may have held.
|
||||
if (CollapsedCHA) {
|
||||
InputInfo II;
|
||||
for (const Action *DA : CollapsedCHA->getDeviceActions()) {
|
||||
BuildJobsForAction(C, DA, TC, "", AtTopLevel,
|
||||
/*MultipleArchs*/ false, LinkingOutput, II);
|
||||
CudaDeviceInputInfos.push_back(II);
|
||||
CudaDeviceInputInfos.push_back(
|
||||
BuildJobsForAction(C, DA, TC, "", AtTopLevel,
|
||||
/*MultipleArchs*/ false, LinkingOutput));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1882,14 +1859,11 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
|
||||
// Treat dsymutil and verify sub-jobs as being at the top-level too, they
|
||||
// shouldn't get temporary output names.
|
||||
// FIXME: Clean this up.
|
||||
bool SubJobAtTopLevel = false;
|
||||
if (AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A)))
|
||||
SubJobAtTopLevel = true;
|
||||
|
||||
InputInfo II;
|
||||
BuildJobsForAction(C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
|
||||
LinkingOutput, II);
|
||||
InputInfos.push_back(II);
|
||||
bool SubJobAtTopLevel =
|
||||
AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A));
|
||||
InputInfos.push_back(BuildJobsForAction(C, Input, TC, BoundArch,
|
||||
SubJobAtTopLevel, MultipleArchs,
|
||||
LinkingOutput));
|
||||
}
|
||||
|
||||
// Always use the first input as the base input.
|
||||
@ -1905,12 +1879,13 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
|
||||
InputInfos.append(CudaDeviceInputInfos.begin(), CudaDeviceInputInfos.end());
|
||||
|
||||
// Determine the place to write output to, if any.
|
||||
InputInfo Result;
|
||||
if (JA->getType() == types::TY_Nothing)
|
||||
Result = InputInfo(A->getType(), BaseInput);
|
||||
Result = InputInfo(A, BaseInput);
|
||||
else
|
||||
Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
|
||||
AtTopLevel, MultipleArchs),
|
||||
A->getType(), BaseInput);
|
||||
Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
|
||||
AtTopLevel, MultipleArchs),
|
||||
BaseInput);
|
||||
|
||||
if (CCCPrintBindings && !CCGenDiagnostics) {
|
||||
llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"'
|
||||
@ -1925,6 +1900,7 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
|
||||
T->ConstructJob(C, *JA, Result, InputInfos,
|
||||
C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
const char *Driver::getDefaultImageName() const {
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef LLVM_CLANG_LIB_DRIVER_INPUTINFO_H
|
||||
#define LLVM_CLANG_LIB_DRIVER_INPUTINFO_H
|
||||
|
||||
#include "clang/Driver/Action.h"
|
||||
#include "clang/Driver/Types.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include <cassert>
|
||||
@ -38,21 +39,36 @@ class InputInfo {
|
||||
const llvm::opt::Arg *InputArg;
|
||||
} Data;
|
||||
Class Kind;
|
||||
const Action* Act;
|
||||
types::ID Type;
|
||||
const char *BaseInput;
|
||||
|
||||
public:
|
||||
InputInfo() {}
|
||||
InputInfo(types::ID _Type, const char *_BaseInput)
|
||||
: Kind(Nothing), Type(_Type), BaseInput(_BaseInput) {
|
||||
static types::ID GetActionType(const Action *A) {
|
||||
return A != nullptr ? A->getType() : types::TY_Nothing;
|
||||
}
|
||||
InputInfo(const char *_Filename, types::ID _Type, const char *_BaseInput)
|
||||
: Kind(Filename), Type(_Type), BaseInput(_BaseInput) {
|
||||
|
||||
public:
|
||||
InputInfo() : InputInfo(nullptr, nullptr) {}
|
||||
InputInfo(const Action *A, const char *_BaseInput)
|
||||
: Kind(Nothing), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {}
|
||||
|
||||
InputInfo(types::ID _Type, const char *_Filename, const char *_BaseInput)
|
||||
: Kind(Filename), Act(nullptr), Type(_Type), BaseInput(_BaseInput) {
|
||||
Data.Filename = _Filename;
|
||||
}
|
||||
InputInfo(const llvm::opt::Arg *_InputArg, types::ID _Type,
|
||||
InputInfo(const Action *A, const char *_Filename, const char *_BaseInput)
|
||||
: Kind(Filename), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {
|
||||
Data.Filename = _Filename;
|
||||
}
|
||||
|
||||
InputInfo(types::ID _Type, const llvm::opt::Arg *_InputArg,
|
||||
const char *_BaseInput)
|
||||
: Kind(InputArg), Type(_Type), BaseInput(_BaseInput) {
|
||||
: Kind(InputArg), Act(nullptr), Type(_Type), BaseInput(_BaseInput) {
|
||||
Data.InputArg = _InputArg;
|
||||
}
|
||||
InputInfo(const Action *A, const llvm::opt::Arg *_InputArg,
|
||||
const char *_BaseInput)
|
||||
: Kind(InputArg), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {
|
||||
Data.InputArg = _InputArg;
|
||||
}
|
||||
|
||||
@ -61,6 +77,9 @@ public:
|
||||
bool isInputArg() const { return Kind == InputArg; }
|
||||
types::ID getType() const { return Type; }
|
||||
const char *getBaseInput() const { return BaseInput; }
|
||||
/// The action for which this InputInfo was created. May be null.
|
||||
const Action *getAction() const { return Act; }
|
||||
void setAction(const Action *A) { Act = A; }
|
||||
|
||||
const char *getFilename() const {
|
||||
assert(isFilename() && "Invalid accessor.");
|
||||
|
@ -634,6 +634,96 @@ SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
|
||||
return Res;
|
||||
}
|
||||
|
||||
static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
|
||||
bool SupportsForcingFramePointer,
|
||||
const char *ExpandChar, const OptTable &Opts) {
|
||||
assert(A->getOption().matches(options::OPT__SLASH_O));
|
||||
|
||||
StringRef OptStr = A->getValue();
|
||||
for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
|
||||
const char &OptChar = *(OptStr.data() + I);
|
||||
switch (OptChar) {
|
||||
default:
|
||||
break;
|
||||
case '1':
|
||||
case '2':
|
||||
case 'x':
|
||||
case 'd':
|
||||
if (&OptChar == ExpandChar) {
|
||||
if (OptChar == 'd') {
|
||||
DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
|
||||
} else {
|
||||
if (OptChar == '1') {
|
||||
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
|
||||
} else if (OptChar == '2' || OptChar == 'x') {
|
||||
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
|
||||
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
|
||||
}
|
||||
if (SupportsForcingFramePointer)
|
||||
DAL.AddFlagArg(A,
|
||||
Opts.getOption(options::OPT_fomit_frame_pointer));
|
||||
if (OptChar == '1' || OptChar == '2')
|
||||
DAL.AddFlagArg(A,
|
||||
Opts.getOption(options::OPT_ffunction_sections));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
if (I + 1 != E && isdigit(OptStr[I + 1]))
|
||||
++I;
|
||||
break;
|
||||
case 'g':
|
||||
break;
|
||||
case 'i':
|
||||
if (I + 1 != E && OptStr[I + 1] == '-') {
|
||||
++I;
|
||||
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
|
||||
} else {
|
||||
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
|
||||
break;
|
||||
case 't':
|
||||
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
|
||||
break;
|
||||
case 'y': {
|
||||
bool OmitFramePointer = true;
|
||||
if (I + 1 != E && OptStr[I + 1] == '-') {
|
||||
OmitFramePointer = false;
|
||||
++I;
|
||||
}
|
||||
if (SupportsForcingFramePointer) {
|
||||
if (OmitFramePointer)
|
||||
DAL.AddFlagArg(A,
|
||||
Opts.getOption(options::OPT_fomit_frame_pointer));
|
||||
else
|
||||
DAL.AddFlagArg(
|
||||
A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
|
||||
const OptTable &Opts) {
|
||||
assert(A->getOption().matches(options::OPT_D));
|
||||
|
||||
StringRef Val = A->getValue();
|
||||
size_t Hash = Val.find('#');
|
||||
if (Hash == StringRef::npos || Hash > Val.find('=')) {
|
||||
DAL.append(A);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string NewVal = Val;
|
||||
NewVal[Hash] = '=';
|
||||
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
|
||||
}
|
||||
|
||||
llvm::opt::DerivedArgList *
|
||||
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
|
||||
const char *BoundArch) const {
|
||||
@ -664,81 +754,18 @@ MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
|
||||
}
|
||||
}
|
||||
|
||||
// The -O flag actually takes an amalgam of other options. For example,
|
||||
// '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
|
||||
for (Arg *A : Args) {
|
||||
if (!A->getOption().matches(options::OPT__SLASH_O)) {
|
||||
if (A->getOption().matches(options::OPT__SLASH_O)) {
|
||||
// The -O flag actually takes an amalgam of other options. For example,
|
||||
// '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
|
||||
TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
|
||||
} else if (A->getOption().matches(options::OPT_D)) {
|
||||
// Translate -Dfoo#bar into -Dfoo=bar.
|
||||
TranslateDArg(A, *DAL, Opts);
|
||||
} else {
|
||||
DAL->append(A);
|
||||
continue;
|
||||
}
|
||||
|
||||
StringRef OptStr = A->getValue();
|
||||
for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
|
||||
const char &OptChar = *(OptStr.data() + I);
|
||||
switch (OptChar) {
|
||||
default:
|
||||
break;
|
||||
case '1':
|
||||
case '2':
|
||||
case 'x':
|
||||
case 'd':
|
||||
if (&OptChar == ExpandChar) {
|
||||
if (OptChar == 'd') {
|
||||
DAL->AddFlagArg(A, Opts.getOption(options::OPT_O0));
|
||||
} else {
|
||||
if (OptChar == '1') {
|
||||
DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
|
||||
} else if (OptChar == '2' || OptChar == 'x') {
|
||||
DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
|
||||
DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
|
||||
}
|
||||
if (SupportsForcingFramePointer)
|
||||
DAL->AddFlagArg(A,
|
||||
Opts.getOption(options::OPT_fomit_frame_pointer));
|
||||
if (OptChar == '1' || OptChar == '2')
|
||||
DAL->AddFlagArg(A,
|
||||
Opts.getOption(options::OPT_ffunction_sections));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
if (I + 1 != E && isdigit(OptStr[I + 1]))
|
||||
++I;
|
||||
break;
|
||||
case 'g':
|
||||
break;
|
||||
case 'i':
|
||||
if (I + 1 != E && OptStr[I + 1] == '-') {
|
||||
++I;
|
||||
DAL->AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
|
||||
} else {
|
||||
DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
|
||||
break;
|
||||
case 't':
|
||||
DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
|
||||
break;
|
||||
case 'y': {
|
||||
bool OmitFramePointer = true;
|
||||
if (I + 1 != E && OptStr[I + 1] == '-') {
|
||||
OmitFramePointer = false;
|
||||
++I;
|
||||
}
|
||||
if (SupportsForcingFramePointer) {
|
||||
if (OmitFramePointer)
|
||||
DAL->AddFlagArg(A,
|
||||
Opts.getOption(options::OPT_fomit_frame_pointer));
|
||||
else
|
||||
DAL->AddFlagArg(
|
||||
A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DAL;
|
||||
}
|
||||
|
@ -66,17 +66,23 @@ MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
: ToolChain(D, Triple, Args) {
|
||||
getProgramPaths().push_back(getDriver().getInstalledDir());
|
||||
|
||||
// On Windows if there is no sysroot we search for gcc on the PATH.
|
||||
if (getDriver().SysRoot.size())
|
||||
Base = getDriver().SysRoot;
|
||||
// In Windows there aren't any standard install locations, we search
|
||||
// for gcc on the PATH. In Linux the base is always /usr.
|
||||
#ifdef LLVM_ON_WIN32
|
||||
if (getDriver().SysRoot.size())
|
||||
Base = getDriver().SysRoot;
|
||||
else if (llvm::ErrorOr<std::string> GPPName =
|
||||
llvm::sys::findProgramByName("gcc"))
|
||||
Base = llvm::sys::path::parent_path(
|
||||
llvm::sys::path::parent_path(GPPName.get()));
|
||||
#endif
|
||||
if (!Base.size())
|
||||
else
|
||||
Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
|
||||
#else
|
||||
if (getDriver().SysRoot.size())
|
||||
Base = getDriver().SysRoot;
|
||||
else
|
||||
Base = "/usr";
|
||||
#endif
|
||||
|
||||
Base += llvm::sys::path::get_separator();
|
||||
findGccLibDir();
|
||||
|
@ -526,7 +526,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
|
||||
// no environment variable defined, see if we can set the default based
|
||||
// on -isysroot.
|
||||
if (OSXTarget.empty() && iOSTarget.empty() && WatchOSTarget.empty() &&
|
||||
Args.hasArg(options::OPT_isysroot)) {
|
||||
TvOSTarget.empty() && Args.hasArg(options::OPT_isysroot)) {
|
||||
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
|
||||
StringRef isysroot = A->getValue();
|
||||
// Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
|
||||
@ -2716,13 +2716,8 @@ const StringRef HexagonToolChain::GetDefaultCPU() {
|
||||
|
||||
const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
|
||||
Arg *CpuArg = nullptr;
|
||||
|
||||
for (auto &A : Args) {
|
||||
if (A->getOption().matches(options::OPT_mcpu_EQ)) {
|
||||
CpuArg = A;
|
||||
A->claim();
|
||||
}
|
||||
}
|
||||
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ, options::OPT_march_EQ))
|
||||
CpuArg = A;
|
||||
|
||||
StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
|
||||
if (CPU.startswith("hexagon"))
|
||||
|
@ -730,9 +730,6 @@ public:
|
||||
// Until dtrace (via CTF) and LLDB can deal with distributed debug info,
|
||||
// FreeBSD defaults to standalone/full debug info.
|
||||
bool GetDefaultStandaloneDebug() const override { return true; }
|
||||
llvm::DebuggerKind getDefaultDebuggerTuning() const override {
|
||||
return llvm::DebuggerKind::LLDB;
|
||||
}
|
||||
|
||||
protected:
|
||||
Tool *buildAssembler() const override;
|
||||
|
@ -2069,6 +2069,16 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
|
||||
CmdArgs.push_back("-machine-sink-split=0");
|
||||
}
|
||||
|
||||
void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
|
||||
ArgStringList &CmdArgs) const {
|
||||
// Default to "hidden" visibility.
|
||||
if (!Args.hasArg(options::OPT_fvisibility_EQ,
|
||||
options::OPT_fvisibility_ms_compat)) {
|
||||
CmdArgs.push_back("-fvisibility");
|
||||
CmdArgs.push_back("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
|
||||
static bool DecodeAArch64Features(const Driver &D, StringRef text,
|
||||
std::vector<const char *> &Features) {
|
||||
@ -2970,7 +2980,7 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
|
||||
ExtractArgs.push_back(OutFile);
|
||||
|
||||
const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy"));
|
||||
InputInfo II(Output.getFilename(), types::TY_Object, Output.getFilename());
|
||||
InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename());
|
||||
|
||||
// First extract the dwo sections.
|
||||
C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs, II));
|
||||
@ -3253,8 +3263,9 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
|
||||
// ToolChain.getTriple() and Triple?
|
||||
bool PIE = ToolChain.isPIEDefault();
|
||||
bool PIC = PIE || ToolChain.isPICDefault();
|
||||
// The Darwin default to use PIC does not apply when using -static.
|
||||
if (ToolChain.getTriple().isOSDarwin() && Args.hasArg(options::OPT_static))
|
||||
// The Darwin/MachO default to use PIC does not apply when using -static.
|
||||
if (ToolChain.getTriple().isOSBinFormatMachO() &&
|
||||
Args.hasArg(options::OPT_static))
|
||||
PIE = PIC = false;
|
||||
bool IsPICLevelTwo = PIC;
|
||||
|
||||
@ -4015,6 +4026,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
case llvm::Triple::hexagon:
|
||||
AddHexagonTargetArgs(Args, CmdArgs);
|
||||
break;
|
||||
|
||||
case llvm::Triple::wasm32:
|
||||
case llvm::Triple::wasm64:
|
||||
AddWebAssemblyTargetArgs(Args, CmdArgs);
|
||||
break;
|
||||
}
|
||||
|
||||
// The 'g' groups options involve a somewhat intricate sequence of decisions
|
||||
@ -4176,8 +4192,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
CmdArgs.push_back("-generate-type-units");
|
||||
}
|
||||
|
||||
// CloudABI uses -ffunction-sections and -fdata-sections by default.
|
||||
bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI;
|
||||
// CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by
|
||||
// default.
|
||||
bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI ||
|
||||
Triple.getArch() == llvm::Triple::wasm32 ||
|
||||
Triple.getArch() == llvm::Triple::wasm64;
|
||||
|
||||
if (Args.hasFlag(options::OPT_ffunction_sections,
|
||||
options::OPT_fno_function_sections, UseSeparateSections)) {
|
||||
@ -6040,8 +6059,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
// doesn't handle that so rather than warning about unused flags that are
|
||||
// actually used, we'll lie by omission instead.
|
||||
// FIXME: Stop lying and consume only the appropriate driver flags
|
||||
for (const Arg *A : Args.filtered(options::OPT_W_Group))
|
||||
A->claim();
|
||||
Args.ClaimAllArgs(options::OPT_W_Group);
|
||||
|
||||
CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
|
||||
getToolChain().getDriver());
|
||||
@ -6078,6 +6096,12 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
||||
for (const auto &A : Args) {
|
||||
if (forwardToGCC(A->getOption())) {
|
||||
// It is unfortunate that we have to claim here, as this means
|
||||
// we will basically never report anything interesting for
|
||||
// platforms using a generic gcc, even if we are just using gcc
|
||||
// to get to the assembler.
|
||||
A->claim();
|
||||
|
||||
// Don't forward any -g arguments to assembly steps.
|
||||
if (isa<AssembleJobAction>(JA) &&
|
||||
A->getOption().matches(options::OPT_g_Group))
|
||||
@ -6088,11 +6112,6 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
A->getOption().matches(options::OPT_W_Group))
|
||||
continue;
|
||||
|
||||
// It is unfortunate that we have to claim here, as this means
|
||||
// we will basically never report anything interesting for
|
||||
// platforms using a generic gcc, even if we are just using gcc
|
||||
// to get to the assembler.
|
||||
A->claim();
|
||||
A->render(Args, CmdArgs);
|
||||
}
|
||||
}
|
||||
@ -6502,10 +6521,6 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
||||
std::string Linker = getToolChain().GetProgramPath(getShortName());
|
||||
ArgStringList CmdArgs;
|
||||
CmdArgs.push_back("-flavor");
|
||||
CmdArgs.push_back("old-gnu");
|
||||
CmdArgs.push_back("-target");
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString()));
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
CmdArgs.push_back("-o");
|
||||
CmdArgs.push_back(Output.getFilename());
|
||||
@ -6534,6 +6549,14 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
ArgStringList CmdArgs;
|
||||
CmdArgs.push_back("-flavor");
|
||||
CmdArgs.push_back("ld");
|
||||
|
||||
// Enable garbage collection of unused input sections by default, since code
|
||||
// size is of particular importance. This is significantly facilitated by
|
||||
// the enabling of -ffunction-sections and -fdata-sections in
|
||||
// Clang::ConstructJob.
|
||||
if (areOptimizationsEnabled(Args))
|
||||
CmdArgs.push_back("--gc-sections");
|
||||
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
CmdArgs.push_back("-o");
|
||||
CmdArgs.push_back(Output.getFilename());
|
||||
@ -8965,7 +8988,7 @@ void nacltools::AssemblerARM::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
const char *LinkingOutput) const {
|
||||
const toolchains::NaClToolChain &ToolChain =
|
||||
static_cast<const toolchains::NaClToolChain &>(getToolChain());
|
||||
InputInfo NaClMacros(ToolChain.GetNaClArmMacrosPath(), types::TY_PP_Asm,
|
||||
InputInfo NaClMacros(types::TY_PP_Asm, ToolChain.GetNaClArmMacrosPath(),
|
||||
"nacl-arm-macros.s");
|
||||
InputInfoList NewInputs;
|
||||
NewInputs.push_back(NaClMacros);
|
||||
|
@ -82,6 +82,8 @@ private:
|
||||
llvm::opt::ArgStringList &CmdArgs) const;
|
||||
void AddHexagonTargetArgs(const llvm::opt::ArgList &Args,
|
||||
llvm::opt::ArgStringList &CmdArgs) const;
|
||||
void AddWebAssemblyTargetArgs(const llvm::opt::ArgList &Args,
|
||||
llvm::opt::ArgStringList &CmdArgs) const;
|
||||
|
||||
enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile };
|
||||
|
||||
@ -238,7 +240,7 @@ namespace amdgpu {
|
||||
|
||||
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
|
||||
public:
|
||||
Linker(const ToolChain &TC) : GnuTool("amdgpu::Linker", "lld", TC) {}
|
||||
Linker(const ToolChain &TC) : GnuTool("amdgpu::Linker", "ld.lld", TC) {}
|
||||
bool isLinkJob() const override { return true; }
|
||||
bool hasIntegratedCPP() const override { return false; }
|
||||
void ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
@ -1077,6 +1077,9 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
|
||||
case CK_BuiltinFnToFnPtr:
|
||||
case CK_ZeroToOCLEvent:
|
||||
return false;
|
||||
|
||||
case CK_BooleanToSignedIntegral:
|
||||
llvm_unreachable("OpenCL-specific cast in Objective-C?");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,12 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
|
||||
if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection)
|
||||
return true;
|
||||
if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) ||
|
||||
(Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName)) ||
|
||||
(Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) &&
|
||||
// FIXME: This is a temporary workaround for the case where clang-format
|
||||
// sets BreakBeforeParameter to avoid bin packing and this creates a
|
||||
// completely unnecessary line break after a template type that isn't
|
||||
// line-wrapped.
|
||||
(Previous.NestingLevel == 1 || Style.BinPackParameters)) ||
|
||||
(Style.BreakBeforeTernaryOperators && Current.is(TT_ConditionalExpr) &&
|
||||
Previous.isNot(tok::question)) ||
|
||||
(!Style.BreakBeforeTernaryOperators &&
|
||||
@ -177,13 +182,15 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
|
||||
return true;
|
||||
|
||||
unsigned NewLineColumn = getNewLineColumn(State);
|
||||
if (Current.isMemberAccess() &&
|
||||
State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit &&
|
||||
(State.Column > NewLineColumn ||
|
||||
Current.NestingLevel < State.StartOfLineLevel))
|
||||
return true;
|
||||
|
||||
if (State.Column <= NewLineColumn)
|
||||
return false;
|
||||
|
||||
if (Current.isMemberAccess() &&
|
||||
State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit)
|
||||
return true;
|
||||
|
||||
if (Style.AlwaysBreakBeforeMultilineStrings &&
|
||||
(NewLineColumn == State.FirstIndent + Style.ContinuationIndentWidth ||
|
||||
Previous.is(tok::comma) || Current.NestingLevel < 2) &&
|
||||
@ -383,7 +390,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
|
||||
State.Stack.back().LastSpace = State.Column;
|
||||
State.Stack.back().NestedBlockIndent = State.Column;
|
||||
} else if (!Current.isOneOf(tok::comment, tok::caret) &&
|
||||
(Previous.is(tok::comma) ||
|
||||
((Previous.is(tok::comma) &&
|
||||
!Previous.is(TT_OverloadedOperator)) ||
|
||||
(Previous.is(tok::colon) && Previous.is(TT_ObjCMethodExpr)))) {
|
||||
State.Stack.back().LastSpace = State.Column;
|
||||
} else if ((Previous.isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
|
||||
@ -860,7 +868,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
|
||||
(!SkipFirstExtraIndent && *I > prec::Assignment &&
|
||||
!Current.isTrailingComment()))
|
||||
NewParenState.Indent += Style.ContinuationIndentWidth;
|
||||
if ((Previous && !Previous->opensScope()) || *I > prec::Comma)
|
||||
if ((Previous && !Previous->opensScope()) || *I != prec::Comma)
|
||||
NewParenState.BreakBeforeParameter = false;
|
||||
State.Stack.push_back(NewParenState);
|
||||
SkipFirstExtraIndent = false;
|
||||
@ -906,8 +914,12 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
|
||||
NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth;
|
||||
}
|
||||
const FormatToken *NextNoComment = Current.getNextNonComment();
|
||||
bool EndsInComma = Current.MatchingParen &&
|
||||
Current.MatchingParen->Previous &&
|
||||
Current.MatchingParen->Previous->is(tok::comma);
|
||||
AvoidBinPacking =
|
||||
Current.isOneOf(TT_ArrayInitializerLSquare, TT_DictLiteral) ||
|
||||
(Current.is(TT_ArrayInitializerLSquare) && EndsInComma) ||
|
||||
Current.is(TT_DictLiteral) ||
|
||||
Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments ||
|
||||
(NextNoComment && NextNoComment->is(TT_DesignatedInitializerPeriod));
|
||||
if (Current.ParameterCount > 1)
|
||||
|
@ -583,6 +583,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
|
||||
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
|
||||
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
|
||||
GoogleStyle.BreakBeforeTernaryOperators = false;
|
||||
GoogleStyle.CommentPragmas = "@(export|visibility) {";
|
||||
GoogleStyle.MaxEmptyLinesToKeep = 3;
|
||||
GoogleStyle.SpacesInContainerLiterals = false;
|
||||
} else if (Language == FormatStyle::LK_Proto) {
|
||||
@ -1238,6 +1239,8 @@ private:
|
||||
FormatTok->Type = TT_ImplicitStringLiteral;
|
||||
break;
|
||||
}
|
||||
if (FormatTok->Type == TT_ImplicitStringLiteral)
|
||||
break;
|
||||
}
|
||||
|
||||
if (FormatTok->is(TT_ImplicitStringLiteral))
|
||||
@ -1901,8 +1904,9 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
|
||||
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
|
||||
new DiagnosticOptions);
|
||||
SourceManager SourceMgr(Diagnostics, Files);
|
||||
InMemoryFileSystem->addFile(FileName, 0,
|
||||
llvm::MemoryBuffer::getMemBuffer(Code, FileName));
|
||||
InMemoryFileSystem->addFile(
|
||||
FileName, 0, llvm::MemoryBuffer::getMemBuffer(
|
||||
Code, FileName, /*RequiresNullTerminator=*/false));
|
||||
FileID ID = SourceMgr.createFileID(Files.getFile(FileName), SourceLocation(),
|
||||
clang::SrcMgr::C_User);
|
||||
SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID);
|
||||
|
@ -119,7 +119,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (Left->Previous &&
|
||||
if (Left->is(TT_OverloadedOperatorLParen)) {
|
||||
Contexts.back().IsExpression = false;
|
||||
} else if (Left->Previous &&
|
||||
(Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
|
||||
tok::kw_if, tok::kw_while, tok::l_paren,
|
||||
tok::comma) ||
|
||||
@ -132,9 +134,7 @@ private:
|
||||
// This is a parameter list of a lambda expression.
|
||||
Contexts.back().IsExpression = false;
|
||||
} else if (Line.InPPDirective &&
|
||||
(!Left->Previous ||
|
||||
!Left->Previous->isOneOf(tok::identifier,
|
||||
TT_OverloadedOperator))) {
|
||||
(!Left->Previous || !Left->Previous->is(tok::identifier))) {
|
||||
Contexts.back().IsExpression = true;
|
||||
} else if (Contexts[Contexts.size() - 2].CaretFound) {
|
||||
// This is the parameter list of an ObjC block.
|
||||
@ -199,6 +199,18 @@ private:
|
||||
Left->MatchingParen = CurrentToken;
|
||||
CurrentToken->MatchingParen = Left;
|
||||
|
||||
if (CurrentToken->Next && CurrentToken->Next->is(tok::l_brace) &&
|
||||
Left->Previous && Left->Previous->is(tok::l_paren)) {
|
||||
// Detect the case where macros are used to generate lambdas or
|
||||
// function bodies, e.g.:
|
||||
// auto my_lambda = MARCO((Type *type, int i) { .. body .. });
|
||||
for (FormatToken *Tok = Left; Tok != CurrentToken; Tok = Tok->Next) {
|
||||
if (Tok->is(TT_BinaryOperator) &&
|
||||
Tok->isOneOf(tok::star, tok::amp, tok::ampamp))
|
||||
Tok->Type = TT_PointerOrReference;
|
||||
}
|
||||
}
|
||||
|
||||
if (StartsObjCMethodExpr) {
|
||||
CurrentToken->Type = TT_ObjCMethodExpr;
|
||||
if (Contexts.back().FirstObjCSelectorName) {
|
||||
@ -568,7 +580,8 @@ private:
|
||||
if (CurrentToken->isOneOf(tok::star, tok::amp))
|
||||
CurrentToken->Type = TT_PointerOrReference;
|
||||
consumeToken();
|
||||
if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator))
|
||||
if (CurrentToken &&
|
||||
CurrentToken->Previous->isOneOf(TT_BinaryOperator, tok::comma))
|
||||
CurrentToken->Previous->Type = TT_OverloadedOperator;
|
||||
}
|
||||
if (CurrentToken) {
|
||||
@ -1713,7 +1726,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
|
||||
if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma))
|
||||
return 100;
|
||||
if (Left.is(TT_JsTypeColon))
|
||||
return 100;
|
||||
return 35;
|
||||
}
|
||||
|
||||
if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
|
||||
@ -2058,14 +2071,14 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
||||
if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||
|
||||
Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
|
||||
return true;
|
||||
if (Right.is(TT_OverloadedOperatorLParen))
|
||||
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
|
||||
if (Left.is(tok::comma))
|
||||
return true;
|
||||
if (Right.is(tok::comma))
|
||||
return false;
|
||||
if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen))
|
||||
return true;
|
||||
if (Right.is(TT_OverloadedOperatorLParen))
|
||||
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
|
||||
if (Right.is(tok::colon)) {
|
||||
if (Line.First->isOneOf(tok::kw_case, tok::kw_default) ||
|
||||
!Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi))
|
||||
|
@ -315,6 +315,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
|
||||
// definitions, too.
|
||||
unsigned StoredPosition = Tokens->getPosition();
|
||||
FormatToken *Tok = FormatTok;
|
||||
const FormatToken *PrevTok = getPreviousToken();
|
||||
// Keep a stack of positions of lbrace tokens. We will
|
||||
// update information about whether an lbrace starts a
|
||||
// braced init list or a different block during the loop.
|
||||
@ -331,47 +332,53 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
|
||||
|
||||
switch (Tok->Tok.getKind()) {
|
||||
case tok::l_brace:
|
||||
Tok->BlockKind = BK_Unknown;
|
||||
if (Style.Language == FormatStyle::LK_JavaScript && PrevTok &&
|
||||
PrevTok->is(tok::colon))
|
||||
// In TypeScript's TypeMemberLists, there can be semicolons between the
|
||||
// individual members.
|
||||
Tok->BlockKind = BK_BracedInit;
|
||||
else
|
||||
Tok->BlockKind = BK_Unknown;
|
||||
LBraceStack.push_back(Tok);
|
||||
break;
|
||||
case tok::r_brace:
|
||||
if (!LBraceStack.empty()) {
|
||||
if (LBraceStack.back()->BlockKind == BK_Unknown) {
|
||||
bool ProbablyBracedList = false;
|
||||
if (Style.Language == FormatStyle::LK_Proto) {
|
||||
ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
|
||||
} else {
|
||||
// Using OriginalColumn to distinguish between ObjC methods and
|
||||
// binary operators is a bit hacky.
|
||||
bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
|
||||
NextTok->OriginalColumn == 0;
|
||||
if (LBraceStack.empty())
|
||||
break;
|
||||
if (LBraceStack.back()->BlockKind == BK_Unknown) {
|
||||
bool ProbablyBracedList = false;
|
||||
if (Style.Language == FormatStyle::LK_Proto) {
|
||||
ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
|
||||
} else {
|
||||
// Using OriginalColumn to distinguish between ObjC methods and
|
||||
// binary operators is a bit hacky.
|
||||
bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
|
||||
NextTok->OriginalColumn == 0;
|
||||
|
||||
// If there is a comma, semicolon or right paren after the closing
|
||||
// brace, we assume this is a braced initializer list. Note that
|
||||
// regardless how we mark inner braces here, we will overwrite the
|
||||
// BlockKind later if we parse a braced list (where all blocks
|
||||
// inside are by default braced lists), or when we explicitly detect
|
||||
// blocks (for example while parsing lambdas).
|
||||
//
|
||||
// We exclude + and - as they can be ObjC visibility modifiers.
|
||||
ProbablyBracedList =
|
||||
NextTok->isOneOf(tok::comma, tok::period, tok::colon,
|
||||
tok::r_paren, tok::r_square, tok::l_brace,
|
||||
tok::l_square, tok::l_paren, tok::ellipsis) ||
|
||||
(NextTok->is(tok::semi) &&
|
||||
(!ExpectClassBody || LBraceStack.size() != 1)) ||
|
||||
(NextTok->isBinaryOperator() && !NextIsObjCMethod);
|
||||
}
|
||||
if (ProbablyBracedList) {
|
||||
Tok->BlockKind = BK_BracedInit;
|
||||
LBraceStack.back()->BlockKind = BK_BracedInit;
|
||||
} else {
|
||||
Tok->BlockKind = BK_Block;
|
||||
LBraceStack.back()->BlockKind = BK_Block;
|
||||
}
|
||||
// If there is a comma, semicolon or right paren after the closing
|
||||
// brace, we assume this is a braced initializer list. Note that
|
||||
// regardless how we mark inner braces here, we will overwrite the
|
||||
// BlockKind later if we parse a braced list (where all blocks
|
||||
// inside are by default braced lists), or when we explicitly detect
|
||||
// blocks (for example while parsing lambdas).
|
||||
//
|
||||
// We exclude + and - as they can be ObjC visibility modifiers.
|
||||
ProbablyBracedList =
|
||||
NextTok->isOneOf(tok::comma, tok::period, tok::colon,
|
||||
tok::r_paren, tok::r_square, tok::l_brace,
|
||||
tok::l_square, tok::l_paren, tok::ellipsis) ||
|
||||
(NextTok->is(tok::semi) &&
|
||||
(!ExpectClassBody || LBraceStack.size() != 1)) ||
|
||||
(NextTok->isBinaryOperator() && !NextIsObjCMethod);
|
||||
}
|
||||
if (ProbablyBracedList) {
|
||||
Tok->BlockKind = BK_BracedInit;
|
||||
LBraceStack.back()->BlockKind = BK_BracedInit;
|
||||
} else {
|
||||
Tok->BlockKind = BK_Block;
|
||||
LBraceStack.back()->BlockKind = BK_Block;
|
||||
}
|
||||
LBraceStack.pop_back();
|
||||
}
|
||||
LBraceStack.pop_back();
|
||||
break;
|
||||
case tok::at:
|
||||
case tok::semi:
|
||||
@ -381,14 +388,16 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
|
||||
case tok::kw_switch:
|
||||
case tok::kw_try:
|
||||
case tok::kw___try:
|
||||
if (!LBraceStack.empty())
|
||||
if (!LBraceStack.empty() && LBraceStack.back()->BlockKind == BK_Unknown)
|
||||
LBraceStack.back()->BlockKind = BK_Block;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
PrevTok = Tok;
|
||||
Tok = NextTok;
|
||||
} while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty());
|
||||
|
||||
// Assume other blocks for all unclosed opening braces.
|
||||
for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) {
|
||||
if (LBraceStack[i]->BlockKind == BK_Unknown)
|
||||
@ -841,6 +850,8 @@ void UnwrappedLineParser::parseStructuralElement() {
|
||||
// This does not apply for Java and JavaScript.
|
||||
if (Style.Language == FormatStyle::LK_Java ||
|
||||
Style.Language == FormatStyle::LK_JavaScript) {
|
||||
if (FormatTok->is(tok::semi))
|
||||
nextToken();
|
||||
addUnwrappedLine();
|
||||
return;
|
||||
}
|
||||
@ -986,13 +997,11 @@ bool UnwrappedLineParser::tryToParseLambda() {
|
||||
nextToken();
|
||||
return false;
|
||||
}
|
||||
// FIXME: This is a dirty way to access the previous token. Find a better
|
||||
// solution.
|
||||
if (!Line->Tokens.empty() &&
|
||||
(Line->Tokens.back().Tok->isOneOf(tok::identifier, tok::kw_operator,
|
||||
tok::kw_new, tok::kw_delete) ||
|
||||
Line->Tokens.back().Tok->closesScope() ||
|
||||
Line->Tokens.back().Tok->isSimpleTypeSpecifier())) {
|
||||
const FormatToken* Previous = getPreviousToken();
|
||||
if (Previous &&
|
||||
(Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
|
||||
tok::kw_delete) ||
|
||||
Previous->closesScope() || Previous->isSimpleTypeSpecifier())) {
|
||||
nextToken();
|
||||
return false;
|
||||
}
|
||||
@ -1174,6 +1183,14 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
|
||||
nextToken();
|
||||
return !HasError;
|
||||
case tok::semi:
|
||||
// JavaScript (or more precisely TypeScript) can have semicolons in braced
|
||||
// lists (in so-called TypeMemberLists). Thus, the semicolon cannot be
|
||||
// used for error recovery if we have otherwise determined that this is
|
||||
// a braced list.
|
||||
if (Style.Language == FormatStyle::LK_JavaScript) {
|
||||
nextToken();
|
||||
break;
|
||||
}
|
||||
HasError = true;
|
||||
if (!ContinueOnSemicolons)
|
||||
return !HasError;
|
||||
@ -1792,18 +1809,22 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Consume the "abstract" in "export abstract class".
|
||||
if (FormatTok->is(Keywords.kw_abstract))
|
||||
nextToken();
|
||||
|
||||
if (FormatTok->isOneOf(tok::kw_const, tok::kw_class, tok::kw_enum,
|
||||
Keywords.kw_let, Keywords.kw_var))
|
||||
Keywords.kw_interface, Keywords.kw_let,
|
||||
Keywords.kw_var))
|
||||
return; // Fall through to parsing the corresponding structure.
|
||||
|
||||
if (FormatTok->is(tok::l_brace)) {
|
||||
FormatTok->BlockKind = BK_Block;
|
||||
parseBracedList();
|
||||
}
|
||||
|
||||
while (!eof() && FormatTok->isNot(tok::semi) &&
|
||||
FormatTok->isNot(tok::l_brace)) {
|
||||
nextToken();
|
||||
while (!eof() && FormatTok->isNot(tok::semi)) {
|
||||
if (FormatTok->is(tok::l_brace)) {
|
||||
FormatTok->BlockKind = BK_Block;
|
||||
parseBracedList();
|
||||
} else {
|
||||
nextToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1877,6 +1898,14 @@ void UnwrappedLineParser::nextToken() {
|
||||
readToken();
|
||||
}
|
||||
|
||||
const FormatToken *UnwrappedLineParser::getPreviousToken() {
|
||||
// FIXME: This is a dirty way to access the previous token. Find a better
|
||||
// solution.
|
||||
if (!Line || Line->Tokens.empty())
|
||||
return nullptr;
|
||||
return Line->Tokens.back().Tok;
|
||||
}
|
||||
|
||||
void UnwrappedLineParser::readToken() {
|
||||
bool CommentsInCurrentLine = true;
|
||||
do {
|
||||
|
@ -110,6 +110,7 @@ private:
|
||||
void addUnwrappedLine();
|
||||
bool eof() const;
|
||||
void nextToken();
|
||||
const FormatToken *getPreviousToken();
|
||||
void readToken();
|
||||
void flushComments(bool NewlineBeforeNext);
|
||||
void pushToken(FormatToken *Tok);
|
||||
|
@ -30,7 +30,7 @@ WhitespaceManager::Change::Change(
|
||||
unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
|
||||
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
|
||||
StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective,
|
||||
bool IsStartOfDeclName)
|
||||
bool IsStartOfDeclName, bool IsInsideToken)
|
||||
: CreateReplacement(CreateReplacement),
|
||||
OriginalWhitespaceRange(OriginalWhitespaceRange),
|
||||
StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
|
||||
@ -38,8 +38,8 @@ WhitespaceManager::Change::Change(
|
||||
CurrentLinePrefix(CurrentLinePrefix), Kind(Kind),
|
||||
ContinuesPPDirective(ContinuesPPDirective),
|
||||
IsStartOfDeclName(IsStartOfDeclName), IndentLevel(IndentLevel),
|
||||
Spaces(Spaces), IsTrailingComment(false), TokenLength(0),
|
||||
PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
|
||||
Spaces(Spaces), IsInsideToken(IsInsideToken), IsTrailingComment(false),
|
||||
TokenLength(0), PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
|
||||
StartOfBlockComment(nullptr), IndentationOffset(0) {}
|
||||
|
||||
void WhitespaceManager::reset() {
|
||||
@ -55,20 +55,23 @@ void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
|
||||
return;
|
||||
Tok.Decision = (Newlines > 0) ? FD_Break : FD_Continue;
|
||||
Changes.push_back(
|
||||
Change(true, Tok.WhitespaceRange, IndentLevel, Spaces, StartOfTokenColumn,
|
||||
Newlines, "", "", Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst,
|
||||
Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName)));
|
||||
Change(/*CreateReplacement=*/true, Tok.WhitespaceRange, IndentLevel,
|
||||
Spaces, StartOfTokenColumn, Newlines, "", "", Tok.Tok.getKind(),
|
||||
InPPDirective && !Tok.IsFirst,
|
||||
Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
|
||||
/*IsInsideToken=*/false));
|
||||
}
|
||||
|
||||
void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
|
||||
bool InPPDirective) {
|
||||
if (Tok.Finalized)
|
||||
return;
|
||||
Changes.push_back(
|
||||
Change(false, Tok.WhitespaceRange, /*IndentLevel=*/0,
|
||||
/*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "",
|
||||
Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst,
|
||||
Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName)));
|
||||
Changes.push_back(Change(
|
||||
/*CreateReplacement=*/false, Tok.WhitespaceRange, /*IndentLevel=*/0,
|
||||
/*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "",
|
||||
Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst,
|
||||
Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
|
||||
/*IsInsideToken=*/false));
|
||||
}
|
||||
|
||||
void WhitespaceManager::replaceWhitespaceInToken(
|
||||
@ -81,15 +84,10 @@ void WhitespaceManager::replaceWhitespaceInToken(
|
||||
Changes.push_back(Change(
|
||||
true, SourceRange(Start, Start.getLocWithOffset(ReplaceChars)),
|
||||
IndentLevel, Spaces, std::max(0, Spaces), Newlines, PreviousPostfix,
|
||||
CurrentPrefix,
|
||||
// If we don't add a newline this change doesn't start a comment. Thus,
|
||||
// when we align line comments, we don't need to treat this change as one.
|
||||
// FIXME: We still need to take this change in account to properly
|
||||
// calculate the new length of the comment and to calculate the changes
|
||||
// for which to do the alignment when aligning comments.
|
||||
Tok.is(TT_LineComment) && Newlines > 0 ? tok::comment : tok::unknown,
|
||||
CurrentPrefix, Tok.is(TT_LineComment) ? tok::comment : tok::unknown,
|
||||
InPPDirective && !Tok.IsFirst,
|
||||
Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName)));
|
||||
Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
|
||||
/*IsInsideToken=*/Newlines == 0));
|
||||
}
|
||||
|
||||
const tooling::Replacements &WhitespaceManager::generateReplacements() {
|
||||
@ -109,6 +107,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
|
||||
|
||||
void WhitespaceManager::calculateLineBreakInformation() {
|
||||
Changes[0].PreviousEndOfTokenColumn = 0;
|
||||
Change *LastOutsideTokenChange = &Changes[0];
|
||||
for (unsigned i = 1, e = Changes.size(); i != e; ++i) {
|
||||
unsigned OriginalWhitespaceStart =
|
||||
SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin());
|
||||
@ -119,11 +118,20 @@ void WhitespaceManager::calculateLineBreakInformation() {
|
||||
Changes[i].PreviousLinePostfix.size() +
|
||||
Changes[i - 1].CurrentLinePrefix.size();
|
||||
|
||||
// If there are multiple changes in this token, sum up all the changes until
|
||||
// the end of the line.
|
||||
if (Changes[i - 1].IsInsideToken)
|
||||
LastOutsideTokenChange->TokenLength +=
|
||||
Changes[i - 1].TokenLength + Changes[i - 1].Spaces;
|
||||
else
|
||||
LastOutsideTokenChange = &Changes[i - 1];
|
||||
|
||||
Changes[i].PreviousEndOfTokenColumn =
|
||||
Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength;
|
||||
|
||||
Changes[i - 1].IsTrailingComment =
|
||||
(Changes[i].NewlinesBefore > 0 || Changes[i].Kind == tok::eof) &&
|
||||
(Changes[i].NewlinesBefore > 0 || Changes[i].Kind == tok::eof ||
|
||||
(Changes[i].IsInsideToken && Changes[i].Kind == tok::comment)) &&
|
||||
Changes[i - 1].Kind == tok::comment;
|
||||
}
|
||||
// FIXME: The last token is currently not always an eof token; in those
|
||||
@ -133,6 +141,10 @@ void WhitespaceManager::calculateLineBreakInformation() {
|
||||
|
||||
const WhitespaceManager::Change *LastBlockComment = nullptr;
|
||||
for (auto &Change : Changes) {
|
||||
// Reset the IsTrailingComment flag for changes inside of trailing comments
|
||||
// so they don't get realigned later.
|
||||
if (Change.IsInsideToken)
|
||||
Change.IsTrailingComment = false;
|
||||
Change.StartOfBlockComment = nullptr;
|
||||
Change.IndentationOffset = 0;
|
||||
if (Change.Kind == tok::comment) {
|
||||
@ -342,6 +354,12 @@ void WhitespaceManager::alignTrailingComments() {
|
||||
|
||||
unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
|
||||
unsigned ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
|
||||
|
||||
// If we don't create a replacement for this change, we have to consider
|
||||
// it to be immovable.
|
||||
if (!Changes[i].CreateReplacement)
|
||||
ChangeMaxColumn = ChangeMinColumn;
|
||||
|
||||
if (i + 1 != e && Changes[i + 1].ContinuesPPDirective)
|
||||
ChangeMaxColumn -= 2;
|
||||
// If this comment follows an } in column 0, it probably documents the
|
||||
|
@ -109,7 +109,8 @@ public:
|
||||
unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
|
||||
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
|
||||
StringRef CurrentLinePrefix, tok::TokenKind Kind,
|
||||
bool ContinuesPPDirective, bool IsStartOfDeclName);
|
||||
bool ContinuesPPDirective, bool IsStartOfDeclName,
|
||||
bool IsInsideToken);
|
||||
|
||||
bool CreateReplacement;
|
||||
// Changes might be in the middle of a token, so we cannot just keep the
|
||||
@ -139,6 +140,10 @@ public:
|
||||
// comments. Uncompensated negative offset is truncated to 0.
|
||||
int Spaces;
|
||||
|
||||
// If this change is inside of a token but not at the start of the token or
|
||||
// directly after a newline.
|
||||
bool IsInsideToken;
|
||||
|
||||
// \c IsTrailingComment, \c TokenLength, \c PreviousEndOfTokenColumn and
|
||||
// \c EscapedNewlineColumn will be calculated in
|
||||
// \c calculateLineBreakInformation.
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===---
|
||||
//===--- CompilerInvocation.cpp -------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -2202,8 +2202,11 @@ std::string CompilerInvocation::getModuleHash() const {
|
||||
code = hash_combine(code, I->first, I->second);
|
||||
}
|
||||
|
||||
// Extend the signature with the sysroot.
|
||||
code = hash_combine(code, hsOpts.Sysroot, hsOpts.UseBuiltinIncludes,
|
||||
// Extend the signature with the sysroot and other header search options.
|
||||
code = hash_combine(code, hsOpts.Sysroot,
|
||||
hsOpts.ModuleFormat,
|
||||
hsOpts.UseDebugInfo,
|
||||
hsOpts.UseBuiltinIncludes,
|
||||
hsOpts.UseStandardSystemIncludes,
|
||||
hsOpts.UseStandardCXXIncludes,
|
||||
hsOpts.UseLibcxx);
|
||||
|
@ -187,15 +187,17 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
|
||||
return std::error_code();
|
||||
|
||||
// Add includes for each of these headers.
|
||||
for (Module::Header &H : Module->Headers[Module::HK_Normal]) {
|
||||
Module->addTopHeader(H.Entry);
|
||||
// Use the path as specified in the module map file. We'll look for this
|
||||
// file relative to the module build directory (the directory containing
|
||||
// the module map file) so this will find the same file that we found
|
||||
// while parsing the module map.
|
||||
if (std::error_code Err = addHeaderInclude(H.NameAsWritten, Includes,
|
||||
LangOpts, Module->IsExternC))
|
||||
return Err;
|
||||
for (auto HK : {Module::HK_Normal, Module::HK_Private}) {
|
||||
for (Module::Header &H : Module->Headers[HK]) {
|
||||
Module->addTopHeader(H.Entry);
|
||||
// Use the path as specified in the module map file. We'll look for this
|
||||
// file relative to the module build directory (the directory containing
|
||||
// the module map file) so this will find the same file that we found
|
||||
// while parsing the module map.
|
||||
if (std::error_code Err = addHeaderInclude(H.NameAsWritten, Includes,
|
||||
LangOpts, Module->IsExternC))
|
||||
return Err;
|
||||
}
|
||||
}
|
||||
// Note that Module->PrivateHeaders will not be a TopHeader.
|
||||
|
||||
|
@ -119,6 +119,7 @@ public:
|
||||
const FunctionDecl *Delete) override;
|
||||
void CompletedImplicitDefinition(const FunctionDecl *D) override;
|
||||
void StaticDataMemberInstantiated(const VarDecl *D) override;
|
||||
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
|
||||
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
|
||||
const ObjCInterfaceDecl *IFD) override;
|
||||
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
|
||||
@ -193,6 +194,11 @@ void MultiplexASTMutationListener::StaticDataMemberInstantiated(
|
||||
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
|
||||
Listeners[i]->StaticDataMemberInstantiated(D);
|
||||
}
|
||||
void MultiplexASTMutationListener::DefaultArgumentInstantiated(
|
||||
const ParmVarDecl *D) {
|
||||
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
|
||||
Listeners[i]->DefaultArgumentInstantiated(D);
|
||||
}
|
||||
void MultiplexASTMutationListener::AddedObjCCategoryToInterface(
|
||||
const ObjCCategoryDecl *CatD,
|
||||
const ObjCInterfaceDecl *IFD) {
|
||||
|
@ -1891,6 +1891,22 @@ static vector float __ATTRS_o_ai vec_ctf(vector unsigned int __a, int __b) {
|
||||
return __builtin_altivec_vcfux((vector int)__a, __b);
|
||||
}
|
||||
|
||||
#ifdef __VSX__
|
||||
static vector double __ATTRS_o_ai vec_ctf(vector unsigned long long __a,
|
||||
int __b) {
|
||||
vector double __ret = __builtin_convertvector(__a, vector double);
|
||||
__ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
static vector double __ATTRS_o_ai vec_ctf(vector signed long long __a,
|
||||
int __b) {
|
||||
vector double __ret = __builtin_convertvector(__a, vector double);
|
||||
__ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52);
|
||||
return __ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vec_vcfsx */
|
||||
|
||||
static vector float __attribute__((__always_inline__))
|
||||
@ -1907,11 +1923,18 @@ vec_vcfux(vector unsigned int __a, int __b) {
|
||||
|
||||
/* vec_cts */
|
||||
|
||||
static vector int __attribute__((__always_inline__))
|
||||
vec_cts(vector float __a, int __b) {
|
||||
static vector int __ATTRS_o_ai vec_cts(vector float __a, int __b) {
|
||||
return __builtin_altivec_vctsxs(__a, __b);
|
||||
}
|
||||
|
||||
#ifdef __VSX__
|
||||
static vector signed long long __ATTRS_o_ai vec_cts(vector double __a,
|
||||
int __b) {
|
||||
__a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52);
|
||||
return __builtin_convertvector(__a, vector signed long long);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vec_vctsxs */
|
||||
|
||||
static vector int __attribute__((__always_inline__))
|
||||
@ -1921,11 +1944,18 @@ vec_vctsxs(vector float __a, int __b) {
|
||||
|
||||
/* vec_ctu */
|
||||
|
||||
static vector unsigned int __attribute__((__always_inline__))
|
||||
vec_ctu(vector float __a, int __b) {
|
||||
static vector unsigned int __ATTRS_o_ai vec_ctu(vector float __a, int __b) {
|
||||
return __builtin_altivec_vctuxs(__a, __b);
|
||||
}
|
||||
|
||||
#ifdef __VSX__
|
||||
static vector unsigned long long __ATTRS_o_ai vec_ctu(vector double __a,
|
||||
int __b) {
|
||||
__a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52);
|
||||
return __builtin_convertvector(__a, vector unsigned long long);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vec_vctuxs */
|
||||
|
||||
static vector unsigned int __attribute__((__always_inline__))
|
||||
|
@ -153,8 +153,7 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
|
||||
auto FileName = llvm::sys::path::filename(ModuleMapPath);
|
||||
|
||||
llvm::hash_code Hash =
|
||||
llvm::hash_combine(DirName.lower(), FileName.lower(),
|
||||
HSOpts->ModuleFormat, HSOpts->UseDebugInfo);
|
||||
llvm::hash_combine(DirName.lower(), FileName.lower());
|
||||
|
||||
SmallString<128> HashStr;
|
||||
llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user