Vendor import of clang trunk r257626:

https://llvm.org/svn/llvm-project/cfe/trunk@257626
This commit is contained in:
Dimitry Andric 2016-01-13 20:00:46 +00:00
parent 97b17066aa
commit 0414e226b7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=293840
svn path=/vendor/clang/clang-trunk-r257626/; revision=293841; tag=vendor/clang/clang-trunk-r257626
277 changed files with 9465 additions and 1313 deletions

View File

@ -131,6 +131,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<AutoType> AutoTypes; mutable llvm::FoldingSet<AutoType> AutoTypes;
mutable llvm::FoldingSet<AtomicType> AtomicTypes; mutable llvm::FoldingSet<AtomicType> AtomicTypes;
llvm::FoldingSet<AttributedType> AttributedTypes; llvm::FoldingSet<AttributedType> AttributedTypes;
mutable llvm::FoldingSet<PipeType> PipeTypes;
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@ -1079,6 +1080,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// blocks. /// blocks.
QualType getBlockDescriptorType() const; 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 /// Gets the struct used to keep track of the extended descriptor for
/// pointer to blocks. /// pointer to blocks.
QualType getBlockDescriptorExtendedType() const; QualType getBlockDescriptorExtendedType() const;
@ -2279,9 +2283,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// \brief Make an APSInt of the appropriate width and signedness for the /// \brief Make an APSInt of the appropriate width and signedness for the
/// given \p Value and integer \p Type. /// given \p Value and integer \p Type.
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const { llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
llvm::APSInt Res(getIntWidth(Type), // If Type is a signed integer type larger than 64 bits, we need to be sure
!Type->isSignedIntegerOrEnumerationType()); // to sign extend Res appropriately.
llvm::APSInt Res(64, !Type->isSignedIntegerOrEnumerationType());
Res = Value; Res = Value;
unsigned Width = getIntWidth(Type);
if (Width != Res.getBitWidth())
return Res.extOrTrunc(Width);
return Res; return Res;
} }

View File

@ -29,6 +29,7 @@ namespace clang {
class ObjCContainerDecl; class ObjCContainerDecl;
class ObjCInterfaceDecl; class ObjCInterfaceDecl;
class ObjCPropertyDecl; class ObjCPropertyDecl;
class ParmVarDecl;
class QualType; class QualType;
class RecordDecl; class RecordDecl;
class TagDecl; class TagDecl;
@ -88,6 +89,9 @@ class ASTMutationListener {
/// \brief A function template's definition was instantiated. /// \brief A function template's definition was instantiated.
virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {} 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. /// \brief A new objc category class was added for an interface.
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {} const ObjCInterfaceDecl *IFD) {}

View File

@ -1,4 +1,4 @@
//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- C++ -*-===// //===-- BuiltinTypes.def - Metadata about BuiltinTypes ----------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //

View File

@ -2440,10 +2440,9 @@ class IndirectFieldDecl : public ValueDecl,
NamedDecl **Chaining; NamedDecl **Chaining;
unsigned ChainingSize; unsigned ChainingSize;
IndirectFieldDecl(DeclContext *DC, SourceLocation L, IndirectFieldDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T, DeclarationName N, QualType T,
NamedDecl **CH, unsigned CHS) NamedDecl **CH, unsigned CHS);
: ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {}
public: public:
static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC, static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,

View File

@ -113,6 +113,9 @@ class Decl {
/// Tags, declared with 'struct foo;' and referenced with /// Tags, declared with 'struct foo;' and referenced with
/// 'struct foo'. All tags are also types. This is what /// 'struct foo'. All tags are also types. This is what
/// elaborated-type-specifiers look for in C. /// 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, IDNS_Tag = 0x0002,
/// Types, declared with 'struct foo', typedefs, etc. /// Types, declared with 'struct foo', typedefs, etc.
@ -131,7 +134,7 @@ class Decl {
IDNS_Namespace = 0x0010, IDNS_Namespace = 0x0010,
/// Ordinary names. In C, everything that's not a label, tag, /// 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, IDNS_Ordinary = 0x0020,
/// Objective C \@protocol. /// Objective C \@protocol.
@ -160,7 +163,9 @@ class Decl {
/// This declaration is a function-local extern declaration of a /// This declaration is a function-local extern declaration of a
/// variable or function. This may also be IDNS_Ordinary if it /// 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 IDNS_LocalExtern = 0x0800
}; };

View File

@ -1292,6 +1292,7 @@ class CharacterLiteral : public Expr {
enum CharacterKind { enum CharacterKind {
Ascii, Ascii,
Wide, Wide,
UTF8,
UTF16, UTF16,
UTF32 UTF32
}; };

View File

@ -951,15 +951,9 @@ class CXXThrowExpr : public Expr {
/// This wraps up a function call argument that was created from the /// This wraps up a function call argument that was created from the
/// corresponding parameter's default argument, when the call did not /// corresponding parameter's default argument, when the call did not
/// explicitly supply arguments for all of the parameters. /// explicitly supply arguments for all of the parameters.
class CXXDefaultArgExpr final class CXXDefaultArgExpr final : public Expr {
: public Expr,
private llvm::TrailingObjects<CXXDefaultArgExpr, Expr *> {
/// \brief The parameter whose default is being used. /// \brief The parameter whose default is being used.
/// ParmVarDecl *Param;
/// 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;
/// \brief The location where the default argument expression was used. /// \brief The location where the default argument expression was used.
SourceLocation Loc; SourceLocation Loc;
@ -971,16 +965,7 @@ class CXXDefaultArgExpr final
: param->getDefaultArg()->getType(), : param->getDefaultArg()->getType(),
param->getDefaultArg()->getValueKind(), param->getDefaultArg()->getValueKind(),
param->getDefaultArg()->getObjectKind(), false, false, false, false), param->getDefaultArg()->getObjectKind(), false, false, false, false),
Param(param, false), Loc(Loc) { } Param(param), 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;
}
public: public:
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
@ -992,24 +977,15 @@ class CXXDefaultArgExpr final
return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param); 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. // Retrieve the parameter that the argument was created from.
const ParmVarDecl *getParam() const { return Param.getPointer(); } const ParmVarDecl *getParam() const { return Param; }
ParmVarDecl *getParam() { return Param.getPointer(); } ParmVarDecl *getParam() { return Param; }
// Retrieve the actual argument to the function call. // Retrieve the actual argument to the function call.
const Expr *getExpr() const { const Expr *getExpr() const {
if (Param.getInt())
return *getTrailingObjects<Expr *>();
return getParam()->getDefaultArg(); return getParam()->getDefaultArg();
} }
Expr *getExpr() { Expr *getExpr() {
if (Param.getInt())
return *getTrailingObjects<Expr *>();
return getParam()->getDefaultArg(); return getParam()->getDefaultArg();
} }
@ -1033,7 +1009,6 @@ class CXXDefaultArgExpr final
return child_range(child_iterator(), child_iterator()); return child_range(child_iterator(), child_iterator());
} }
friend TrailingObjects;
friend class ASTStmtReader; friend class ASTStmtReader;
friend class ASTStmtWriter; friend class ASTStmtWriter;
}; };

View File

@ -186,6 +186,10 @@ enum CastKind {
/// (bool) f /// (bool) f
CK_FloatingToBoolean, 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. /// CK_FloatingCast - Casting between floating types of different size.
/// (double) f /// (double) f
/// (float) ld /// (float) ld

View File

@ -978,6 +978,8 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); })
#undef DEF_TRAVERSE_TYPE #undef DEF_TRAVERSE_TYPE
// ----------------- TypeLoc traversal ----------------- // ----------------- TypeLoc traversal -----------------
@ -1206,6 +1208,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
#undef DEF_TRAVERSE_TYPELOC #undef DEF_TRAVERSE_TYPELOC
// ----------------- Decl traversal ----------------- // ----------------- Decl traversal -----------------

View File

@ -130,7 +130,7 @@ class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt {
friend class CharacterLiteral; friend class CharacterLiteral;
unsigned : NumExprBits; unsigned : NumExprBits;
unsigned Kind : 2; unsigned Kind : 3;
}; };
enum APFloatSemantics { enum APFloatSemantics {

View File

@ -1721,6 +1721,7 @@ class Type : public ExtQualsTypeCommonBase {
bool isNDRangeT() const; // OpenCL ndrange_t bool isNDRangeT() const; // OpenCL ndrange_t
bool isReserveIDT() const; // OpenCL reserve_id_t bool isReserveIDT() const; // OpenCL reserve_id_t
bool isPipeType() const; // OpenCL pipe type
bool isOpenCLSpecificType() const; // Any OpenCL specific type bool isOpenCLSpecificType() const; // Any OpenCL specific type
/// Determines if this type, which must satisfy /// 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. /// A qualifier set is used to build a set of qualifiers.
class QualifierCollector : public Qualifiers { class QualifierCollector : public Qualifiers {
public: public:
@ -5461,9 +5497,13 @@ inline bool Type::isImageType() const {
isImage1dBufferT(); isImage1dBufferT();
} }
inline bool Type::isPipeType() const {
return isa<PipeType>(CanonicalType);
}
inline bool Type::isOpenCLSpecificType() const { inline bool Type::isOpenCLSpecificType() const {
return isSamplerT() || isEventT() || isImageType() || isClkEventT() || return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
isQueueT() || isNDRangeT() || isReserveIDT(); isQueueT() || isNDRangeT() || isReserveIDT() || isPipeType();
} }
inline bool Type::isTemplateTypeParmType() const { inline bool Type::isTemplateTypeParmType() const {

View File

@ -2033,7 +2033,26 @@ class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc,
} }
}; };
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 #endif

View File

@ -104,6 +104,7 @@ NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
TYPE(ObjCObject, Type) TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type) TYPE(ObjCObjectPointer, Type)
TYPE(Pipe, Type)
TYPE(Atomic, Type) TYPE(Atomic, Type)
#ifdef LAST_TYPE #ifdef LAST_TYPE

View File

@ -560,10 +560,10 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
// Metafunction to determine if type T has a member called // Metafunction to determine if type T has a member called
// getDecl. // getDecl.
#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__clang__) #if defined(_MSC_VER) && !defined(__clang__)
// For old versions of MSVC, we use a weird nonstandard __if_exists // For MSVC, we use a weird nonstandard __if_exists statement, as it
// statement, since before MSVC2015, it was not standards-conformant // is not standards-conformant enough to properly compile the standard
// enough to compile the usual code below. // code below. (At least up through MSVC 2015 require this workaround)
template <typename T> struct has_getDecl { template <typename T> struct has_getDecl {
__if_exists(T::getDecl) { __if_exists(T::getDecl) {
enum { value = 1 }; enum { value = 1 };

View File

@ -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_unknown_language : Error<"language not recognized: '%0'">;
def err_drv_invalid_arch_name : Error< def err_drv_invalid_arch_name : Error<
"invalid arch name '%0'">; "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< def err_drv_invalid_thread_model_for_target : Error<
"invalid thread model '%0' in '%1' for this target">; "invalid thread model '%0' in '%1' for this target">;
def err_drv_invalid_linker_name : Error< def err_drv_invalid_linker_name : Error<

View File

@ -616,6 +616,7 @@ def Most : DiagGroup<"most", [
CharSubscript, CharSubscript,
Comment, Comment,
DeleteNonVirtualDtor, DeleteNonVirtualDtor,
ForLoopAnalysis,
Format, Format,
Implicit, Implicit,
InfiniteRecursion, InfiniteRecursion,

View File

@ -29,7 +29,7 @@ namespace clang {
enum { enum {
DIAG_START_COMMON = 0, DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + 300, 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_SERIALIZATION = DIAG_START_FRONTEND + 100,
DIAG_START_LEX = DIAG_START_SERIALIZATION + 120, DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
DIAG_START_PARSE = DIAG_START_LEX + 300, DIAG_START_PARSE = DIAG_START_LEX + 300,

View File

@ -490,6 +490,8 @@ def warn_pragma_diagnostic_unknown_warning :
// - #pragma __debug // - #pragma __debug
def warn_pragma_debug_unexpected_command : Warning< def warn_pragma_debug_unexpected_command : Warning<
"unexpected debug command '%0'">, InGroup<IgnoredPragmas>; "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_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
def err_paste_at_start : Error< def err_paste_at_start : Error<

View File

@ -1,4 +1,3 @@
//==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===// //==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===//
// //
// The LLVM Compiler Infrastructure // 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">; "sampler type cannot be used with the __local and __global address space qualifiers">;
def err_opencl_global_invalid_addr_space : Error< def err_opencl_global_invalid_addr_space : Error<
"program scope variable must reside in %0 address space">; "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_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
def err_opencl_kernel_attr : def err_opencl_kernel_attr :
Error<"attribute %0 can only be applied to a kernel function">; Error<"attribute %0 can only be applied to a kernel function">;

View File

@ -36,6 +36,11 @@ namespace clang {
TSS_unsigned TSS_unsigned
}; };
enum TypeSpecifiersPipe {
TSP_unspecified,
TSP_pipe
};
/// \brief Specifies the kind of type. /// \brief Specifies the kind of type.
enum TypeSpecifierType { enum TypeSpecifierType {
TST_unspecified, TST_unspecified,

View File

@ -519,6 +519,8 @@ KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR)
// OpenMP Type Traits // OpenMP Type Traits
KEYWORD(__builtin_omp_required_simd_align, KEYALL) KEYWORD(__builtin_omp_required_simd_align, KEYALL)
KEYWORD(pipe , KEYOPENCL)
// Borland Extensions. // Borland Extensions.
KEYWORD(__pascal , KEYALL) KEYWORD(__pascal , KEYALL)
@ -697,6 +699,11 @@ ANNOTATION(pragma_parser_crash)
// handles them. // handles them.
ANNOTATION(pragma_captured) 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... // Annotation for #pragma ms_struct...
// The lexer produces these so that they only take effect when the parser // The lexer produces these so that they only take effect when the parser
// handles them. // handles them.

View File

@ -299,10 +299,7 @@ class InMemoryFileSystem : public FileSystem {
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override { llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
return WorkingDirectory; return WorkingDirectory;
} }
std::error_code setCurrentWorkingDirectory(const Twine &Path) override { std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
WorkingDirectory = Path.str();
return std::error_code();
}
}; };
/// \brief Get a globally unique ID for a virtual file or directory. /// \brief Get a globally unique ID for a virtual file or directory.

View File

@ -33,12 +33,10 @@ namespace clang {
Backend_EmitObj ///< Emit native object files Backend_EmitObj ///< Emit native object files
}; };
void void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts,
EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts,
const TargetOptions &TOpts, const LangOptions &LOpts, const TargetOptions &TOpts, const LangOptions &LOpts,
StringRef TDesc, llvm::Module *M, BackendAction Action, StringRef TDesc, llvm::Module *M, BackendAction Action,
raw_pwrite_stream *OS, raw_pwrite_stream *OS);
std::unique_ptr<llvm::FunctionInfoIndex> Index = nullptr);
} }
#endif #endif

View File

@ -15,6 +15,9 @@
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
namespace llvm { namespace llvm {
class StringRef;
namespace opt { namespace opt {
class Arg; class Arg;
} }
@ -32,6 +35,9 @@ namespace driver {
/// single primary output, at least in terms of controlling the /// single primary output, at least in terms of controlling the
/// compilation. Actions can produce auxiliary files, but can only /// compilation. Actions can produce auxiliary files, but can only
/// produce a single output to feed into subsequent actions. /// produce a single output to feed into subsequent actions.
///
/// Actions are usually owned by a Compilation, which creates new
/// actions via MakeAction().
class Action { class Action {
public: public:
typedef ActionList::size_type size_type; typedef ActionList::size_type size_type;
@ -70,27 +76,20 @@ class Action {
ActionList Inputs; ActionList Inputs;
unsigned OwnsInputs : 1;
protected: protected:
Action(ActionClass Kind, types::ID Type) Action(ActionClass Kind, types::ID Type) : Action(Kind, ActionList(), Type) {}
: Kind(Kind), Type(Type), OwnsInputs(true) {} Action(ActionClass Kind, Action *Input, types::ID Type)
Action(ActionClass Kind, std::unique_ptr<Action> Input, types::ID Type) : Action(Kind, ActionList({Input}), Type) {}
: Kind(Kind), Type(Type), Inputs(1, Input.release()), OwnsInputs(true) { Action(ActionClass Kind, Action *Input)
} : Action(Kind, ActionList({Input}), Input->getType()) {}
Action(ActionClass Kind, std::unique_ptr<Action> Input)
: Kind(Kind), Type(Input->getType()), Inputs(1, Input.release()),
OwnsInputs(true) {}
Action(ActionClass Kind, const ActionList &Inputs, types::ID Type) Action(ActionClass Kind, const ActionList &Inputs, types::ID Type)
: Kind(Kind), Type(Type), Inputs(Inputs), OwnsInputs(true) {} : Kind(Kind), Type(Type), Inputs(Inputs) {}
public: public:
virtual ~Action(); virtual ~Action();
const char *getClassName() const { return Action::getClassName(getKind()); } const char *getClassName() const { return Action::getClassName(getKind()); }
bool getOwnsInputs() { return OwnsInputs; }
void setOwnsInputs(bool Value) { OwnsInputs = Value; }
ActionClass getKind() const { return Kind; } ActionClass getKind() const { return Kind; }
types::ID getType() const { return Type; } types::ID getType() const { return Type; }
@ -126,7 +125,7 @@ class BindArchAction : public Action {
const char *ArchName; const char *ArchName;
public: public:
BindArchAction(std::unique_ptr<Action> Input, const char *ArchName); BindArchAction(Action *Input, const char *ArchName);
const char *getArchName() const { return ArchName; } const char *getArchName() const { return ArchName; }
@ -137,19 +136,24 @@ class BindArchAction : public Action {
class CudaDeviceAction : public Action { class CudaDeviceAction : public Action {
virtual void anchor(); virtual void anchor();
/// GPU architecture to bind -- e.g 'sm_35'. /// GPU architecture to bind. Always of the form /sm_\d+/.
const char *GpuArchName; const char *GpuArchName;
/// True when action results are not consumed by the host action (e.g when /// True when action results are not consumed by the host action (e.g when
/// -fsyntax-only or --cuda-device-only options are used). /// -fsyntax-only or --cuda-device-only options are used).
bool AtTopLevel; bool AtTopLevel;
public: public:
CudaDeviceAction(std::unique_ptr<Action> Input, const char *ArchName, CudaDeviceAction(Action *Input, const char *ArchName, bool AtTopLevel);
bool AtTopLevel);
const char *getGpuArchName() const { return GpuArchName; } const char *getGpuArchName() const { return GpuArchName; }
/// Gets the compute_XX that corresponds to getGpuArchName().
const char *getComputeArchName() const;
bool isAtTopLevel() const { return AtTopLevel; } bool isAtTopLevel() const { return AtTopLevel; }
static bool IsValidGpuArchName(llvm::StringRef ArchName);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == CudaDeviceClass; return A->getKind() == CudaDeviceClass;
} }
@ -160,9 +164,7 @@ class CudaHostAction : public Action {
ActionList DeviceActions; ActionList DeviceActions;
public: public:
CudaHostAction(std::unique_ptr<Action> Input, CudaHostAction(Action *Input, const ActionList &DeviceActions);
const ActionList &DeviceActions);
~CudaHostAction() override;
const ActionList &getDeviceActions() const { return DeviceActions; } const ActionList &getDeviceActions() const { return DeviceActions; }
@ -172,7 +174,7 @@ class CudaHostAction : public Action {
class JobAction : public Action { class JobAction : public Action {
virtual void anchor(); virtual void anchor();
protected: 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); JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type);
public: public:
@ -185,7 +187,7 @@ class JobAction : public Action {
class PreprocessJobAction : public JobAction { class PreprocessJobAction : public JobAction {
void anchor() override; void anchor() override;
public: public:
PreprocessJobAction(std::unique_ptr<Action> Input, types::ID OutputType); PreprocessJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == PreprocessJobClass; return A->getKind() == PreprocessJobClass;
@ -195,7 +197,7 @@ class PreprocessJobAction : public JobAction {
class PrecompileJobAction : public JobAction { class PrecompileJobAction : public JobAction {
void anchor() override; void anchor() override;
public: public:
PrecompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType); PrecompileJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == PrecompileJobClass; return A->getKind() == PrecompileJobClass;
@ -205,7 +207,7 @@ class PrecompileJobAction : public JobAction {
class AnalyzeJobAction : public JobAction { class AnalyzeJobAction : public JobAction {
void anchor() override; void anchor() override;
public: public:
AnalyzeJobAction(std::unique_ptr<Action> Input, types::ID OutputType); AnalyzeJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == AnalyzeJobClass; return A->getKind() == AnalyzeJobClass;
@ -215,7 +217,7 @@ class AnalyzeJobAction : public JobAction {
class MigrateJobAction : public JobAction { class MigrateJobAction : public JobAction {
void anchor() override; void anchor() override;
public: public:
MigrateJobAction(std::unique_ptr<Action> Input, types::ID OutputType); MigrateJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == MigrateJobClass; return A->getKind() == MigrateJobClass;
@ -225,7 +227,7 @@ class MigrateJobAction : public JobAction {
class CompileJobAction : public JobAction { class CompileJobAction : public JobAction {
void anchor() override; void anchor() override;
public: public:
CompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType); CompileJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == CompileJobClass; return A->getKind() == CompileJobClass;
@ -235,7 +237,7 @@ class CompileJobAction : public JobAction {
class BackendJobAction : public JobAction { class BackendJobAction : public JobAction {
void anchor() override; void anchor() override;
public: public:
BackendJobAction(std::unique_ptr<Action> Input, types::ID OutputType); BackendJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == BackendJobClass; return A->getKind() == BackendJobClass;
@ -245,7 +247,7 @@ class BackendJobAction : public JobAction {
class AssembleJobAction : public JobAction { class AssembleJobAction : public JobAction {
void anchor() override; void anchor() override;
public: public:
AssembleJobAction(std::unique_ptr<Action> Input, types::ID OutputType); AssembleJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == AssembleJobClass; return A->getKind() == AssembleJobClass;
@ -285,8 +287,7 @@ class DsymutilJobAction : public JobAction {
class VerifyJobAction : public JobAction { class VerifyJobAction : public JobAction {
void anchor() override; void anchor() override;
public: public:
VerifyJobAction(ActionClass Kind, std::unique_ptr<Action> Input, VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type);
types::ID Type);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == VerifyDebugInfoJobClass || return A->getKind() == VerifyDebugInfoJobClass ||
A->getKind() == VerifyPCHJobClass; A->getKind() == VerifyPCHJobClass;
@ -296,7 +297,7 @@ class VerifyJobAction : public JobAction {
class VerifyDebugInfoJobAction : public VerifyJobAction { class VerifyDebugInfoJobAction : public VerifyJobAction {
void anchor() override; void anchor() override;
public: public:
VerifyDebugInfoJobAction(std::unique_ptr<Action> Input, types::ID Type); VerifyDebugInfoJobAction(Action *Input, types::ID Type);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == VerifyDebugInfoJobClass; return A->getKind() == VerifyDebugInfoJobClass;
} }
@ -305,7 +306,7 @@ class VerifyDebugInfoJobAction : public VerifyJobAction {
class VerifyPCHJobAction : public VerifyJobAction { class VerifyPCHJobAction : public VerifyJobAction {
void anchor() override; void anchor() override;
public: public:
VerifyPCHJobAction(std::unique_ptr<Action> Input, types::ID Type); VerifyPCHJobAction(Action *Input, types::ID Type);
static bool classof(const Action *A) { static bool classof(const Action *A) {
return A->getKind() == VerifyPCHJobClass; return A->getKind() == VerifyPCHJobClass;
} }

View File

@ -48,7 +48,12 @@ class Compilation {
/// own argument translation. /// own argument translation.
llvm::opt::DerivedArgList *TranslatedArgs; 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; ActionList Actions;
/// The root list of jobs. /// The root list of jobs.
@ -105,6 +110,15 @@ class Compilation {
ActionList &getActions() { return Actions; } ActionList &getActions() { return Actions; }
const ActionList &getActions() const { 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; } JobList &getJobs() { return Jobs; }
const JobList &getJobs() const { return Jobs; } const JobList &getJobs() const { return Jobs; }

View File

@ -18,10 +18,10 @@
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo #include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo lands.
#include <memory>
// lands.
#include <list> #include <list>
#include <memory>
#include <set> #include <set>
#include <string> #include <string>
@ -375,20 +375,16 @@ class Driver {
/// ConstructAction - Construct the appropriate action to do for /// ConstructAction - Construct the appropriate action to do for
/// \p Phase on the \p Input, taking in to account arguments /// \p Phase on the \p Input, taking in to account arguments
/// like -fsyntax-only or --analyze. /// like -fsyntax-only or --analyze.
std::unique_ptr<Action> Action *ConstructPhaseAction(Compilation &C, const ToolChain &TC,
ConstructPhaseAction(const ToolChain &TC, const llvm::opt::ArgList &Args, const llvm::opt::ArgList &Args, phases::ID Phase,
phases::ID Phase, std::unique_ptr<Action> Input) const; Action *Input) const;
/// BuildJobsForAction - Construct the jobs to perform for the /// BuildJobsForAction - Construct the jobs to perform for the
/// action \p A. /// action \p A and return an InputInfo for the result of running \p A.
void BuildJobsForAction(Compilation &C, InputInfo BuildJobsForAction(Compilation &C, const Action *A,
const Action *A, const ToolChain *TC, const char *BoundArch,
const ToolChain *TC, bool AtTopLevel, bool MultipleArchs,
const char *BoundArch, const char *LinkingOutput) const;
bool AtTopLevel,
bool MultipleArchs,
const char *LinkingOutput,
InputInfo &Result) const;
/// Returns the default name for linked images (e.g., "a.out"). /// Returns the default name for linked images (e.g., "a.out").
const char *getDefaultImageName() const; const char *getDefaultImageName() const;

View File

@ -1906,13 +1906,13 @@ def _ : Joined<["--"], "">, Flags<[Unsupported]>;
def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group<m_hexagon_Features_Group>; def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group<m_hexagon_Features_Group>;
def mv4 : Flag<["-"], "mv4">, 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>, 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>, 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>, 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>, def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Enable Hexagon Vector eXtensions">; Flags<[CC1Option]>, HelpText<"Enable Hexagon Vector eXtensions">;
def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, Group<m_hexagon_Features_Group>, def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, Group<m_hexagon_Features_Group>,

View File

@ -134,7 +134,7 @@ class ToolChain {
StringRef getOS() const { return Triple.getOSName(); } StringRef getOS() const { return Triple.getOSName(); }
/// \brief Provide the default architecture name (as expected by -arch) for /// \brief Provide the default architecture name (as expected by -arch) for
/// this toolchain. Note t /// this toolchain.
StringRef getDefaultUniversalArchName() const; StringRef getDefaultUniversalArchName() const;
std::string getTripleString() const { std::string getTripleString() const {

View File

@ -166,6 +166,7 @@ class CharLiteralParser {
bool hadError() const { return HadError; } bool hadError() const { return HadError; }
bool isAscii() const { return Kind == tok::char_constant; } bool isAscii() const { return Kind == tok::char_constant; }
bool isWide() const { return Kind == tok::wide_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 isUTF16() const { return Kind == tok::utf16_char_constant; }
bool isUTF32() const { return Kind == tok::utf32_char_constant; } bool isUTF32() const { return Kind == tok::utf32_char_constant; }
bool isMultiChar() const { return IsMultiChar; } bool isMultiChar() const { return IsMultiChar; }

View File

@ -501,6 +501,10 @@ class Parser : public CodeCompletionHandler {
/// #pragma align... /// #pragma align...
void HandlePragmaAlign(); void HandlePragmaAlign();
/// \brief Handle the annotation token produced for
/// #pragma clang __debug dump...
void HandlePragmaDump();
/// \brief Handle the annotation token produced for /// \brief Handle the annotation token produced for
/// #pragma weak id... /// #pragma weak id...
void HandlePragmaWeak(); void HandlePragmaWeak();
@ -1640,13 +1644,22 @@ class Parser : public CodeCompletionHandler {
/// A SmallVector of types. /// A SmallVector of types.
typedef SmallVector<ParsedType, 12> TypeVector; 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 StmtResult
ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, ParseStatementOrDeclaration(StmtVector &Stmts, AllowedContsructsKind Allowed,
SourceLocation *TrailingElseLoc = nullptr); SourceLocation *TrailingElseLoc = nullptr);
StmtResult ParseStatementOrDeclarationAfterAttributes( StmtResult ParseStatementOrDeclarationAfterAttributes(
StmtVector &Stmts, StmtVector &Stmts,
bool OnlyStatement, AllowedContsructsKind Allowed,
SourceLocation *TrailingElseLoc, SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs); ParsedAttributesWithRange &Attrs);
StmtResult ParseExprStatement(); StmtResult ParseExprStatement();
@ -1674,7 +1687,8 @@ class Parser : public CodeCompletionHandler {
StmtResult ParseReturnStatement(); StmtResult ParseReturnStatement();
StmtResult ParseAsmStatement(bool &msAsm); StmtResult ParseAsmStatement(bool &msAsm);
StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc); StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);
StmtResult ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement, StmtResult ParsePragmaLoopHint(StmtVector &Stmts,
AllowedContsructsKind Allowed,
SourceLocation *TrailingElseLoc, SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs); ParsedAttributesWithRange &Attrs);
@ -2439,11 +2453,13 @@ class Parser : public CodeCompletionHandler {
bool AllowScopeSpecifier); bool AllowScopeSpecifier);
/// \brief Parses declarative or executable directive. /// \brief Parses declarative or executable directive.
/// ///
/// \param StandAloneAllowed true if allowed stand-alone directives, /// \param Allowed ACK_Any, if any directives are allowed,
/// false - otherwise /// ACK_StatementsOpenMPAnyExecutable - if any executable directives are
/// allowed, ACK_StatementsOpenMPNonStandalone - if only non-standalone
/// executable directives are allowed.
/// ///
StmtResult StmtResult
ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed); ParseOpenMPDeclarativeOrExecutableDirective(AllowedContsructsKind Allowed);
/// \brief Parses clause of kind \a CKind for directive of a kind \a Kind. /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind.
/// ///
/// \param DKind Kind of current directive. /// \param DKind Kind of current directive.

View File

@ -337,6 +337,7 @@ class DeclSpec {
unsigned TypeAltiVecPixel : 1; unsigned TypeAltiVecPixel : 1;
unsigned TypeAltiVecBool : 1; unsigned TypeAltiVecBool : 1;
unsigned TypeSpecOwned : 1; unsigned TypeSpecOwned : 1;
unsigned TypeSpecPipe : 1;
// type-qualifiers // type-qualifiers
unsigned TypeQualifiers : 4; // Bitwise OR of TQ. unsigned TypeQualifiers : 4; // Bitwise OR of TQ.
@ -385,6 +386,7 @@ class DeclSpec {
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
SourceLocation FS_forceinlineLoc; SourceLocation FS_forceinlineLoc;
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc; SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc;
SourceLocation TQ_pipeLoc;
WrittenBuiltinSpecs writtenBS; WrittenBuiltinSpecs writtenBS;
void SaveWrittenBuiltinSpecs(); void SaveWrittenBuiltinSpecs();
@ -420,6 +422,7 @@ class DeclSpec {
TypeAltiVecPixel(false), TypeAltiVecPixel(false),
TypeAltiVecBool(false), TypeAltiVecBool(false),
TypeSpecOwned(false), TypeSpecOwned(false),
TypeSpecPipe(false),
TypeQualifiers(TQ_unspecified), TypeQualifiers(TQ_unspecified),
FS_inline_specified(false), FS_inline_specified(false),
FS_forceinline_specified(false), FS_forceinline_specified(false),
@ -473,6 +476,7 @@ class DeclSpec {
bool isTypeAltiVecBool() const { return TypeAltiVecBool; } bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
bool isTypeSpecOwned() const { return TypeSpecOwned; } bool isTypeSpecOwned() const { return TypeSpecOwned; }
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); } bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
bool isTypeSpecPipe() const { return TypeSpecPipe; }
ParsedType getRepAsType() const { ParsedType getRepAsType() const {
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type"); assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
@ -532,6 +536,7 @@ class DeclSpec {
SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; } SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; } SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; } SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; }
SourceLocation getPipeLoc() const { return TQ_pipeLoc; }
/// \brief Clear out all of the type qualifiers. /// \brief Clear out all of the type qualifiers.
void ClearTypeQualifiers() { void ClearTypeQualifiers() {
@ -540,6 +545,7 @@ class DeclSpec {
TQ_restrictLoc = SourceLocation(); TQ_restrictLoc = SourceLocation();
TQ_volatileLoc = SourceLocation(); TQ_volatileLoc = SourceLocation();
TQ_atomicLoc = SourceLocation(); TQ_atomicLoc = SourceLocation();
TQ_pipeLoc = SourceLocation();
} }
// function-specifier // function-specifier
@ -643,6 +649,9 @@ class DeclSpec {
bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc, bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID, const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy); const PrintingPolicy &Policy);
bool SetTypePipe(bool isPipe, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy);
bool SetTypeSpecError(); bool SetTypeSpecError();
void UpdateDeclRep(Decl *Rep) { void UpdateDeclRep(Decl *Rep) {
assert(isDeclRep((TST) TypeSpecType)); assert(isDeclRep((TST) TypeSpecType));
@ -1081,7 +1090,7 @@ typedef SmallVector<Token, 4> CachedTokens;
/// This is intended to be a small value object. /// This is intended to be a small value object.
struct DeclaratorChunk { struct DeclaratorChunk {
enum { enum {
Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren, Pipe
} Kind; } Kind;
/// Loc - The place where this type was defined. /// 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 { union {
TypeInfoCommon Common; TypeInfoCommon Common;
PointerTypeInfo Ptr; PointerTypeInfo Ptr;
@ -1417,6 +1433,7 @@ struct DeclaratorChunk {
FunctionTypeInfo Fun; FunctionTypeInfo Fun;
BlockPointerTypeInfo Cls; BlockPointerTypeInfo Cls;
MemberPointerTypeInfo Mem; MemberPointerTypeInfo Mem;
PipeTypeInfo PipeInfo;
}; };
void destroy() { void destroy() {
@ -1428,6 +1445,7 @@ struct DeclaratorChunk {
case DeclaratorChunk::Array: return Arr.destroy(); case DeclaratorChunk::Array: return Arr.destroy();
case DeclaratorChunk::MemberPointer: return Mem.destroy(); case DeclaratorChunk::MemberPointer: return Mem.destroy();
case DeclaratorChunk::Paren: return; case DeclaratorChunk::Paren: return;
case DeclaratorChunk::Pipe: return PipeInfo.destroy();
} }
} }
@ -1526,6 +1544,17 @@ struct DeclaratorChunk {
return I; 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, static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
unsigned TypeQuals, unsigned TypeQuals,
SourceLocation Loc) { SourceLocation Loc) {
@ -2026,6 +2055,7 @@ class Declarator {
case DeclaratorChunk::Array: case DeclaratorChunk::Array:
case DeclaratorChunk::BlockPointer: case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer: case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
return false; return false;
} }
llvm_unreachable("Invalid type chunk"); llvm_unreachable("Invalid type chunk");

View File

@ -515,6 +515,7 @@ class LookupResult {
configure(); configure();
} }
void dump();
void print(raw_ostream &); void print(raw_ostream &);
/// Suppress the diagnostics that would normally fire because of this /// Suppress the diagnostics that would normally fire because of this

View File

@ -582,7 +582,10 @@ namespace clang {
/// This candidate function was not viable because an enable_if /// This candidate function was not viable because an enable_if
/// attribute disabled it. /// 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). /// OverloadCandidate - A single candidate in an overload set (C++ 13.3).

View File

@ -1269,6 +1269,8 @@ class Sema {
SourceLocation Loc, DeclarationName Entity); SourceLocation Loc, DeclarationName Entity);
QualType BuildParenType(QualType T); QualType BuildParenType(QualType T);
QualType BuildAtomicType(QualType T, SourceLocation Loc); QualType BuildAtomicType(QualType T, SourceLocation Loc);
QualType BuildPipeType(QualType T,
SourceLocation Loc);
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S); TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy); TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
@ -2548,7 +2550,8 @@ class Sema {
MultiExprArg Args, MultiExprArg Args,
SourceLocation RParenLoc, SourceLocation RParenLoc,
Expr *ExecConfig, Expr *ExecConfig,
bool AllowTypoCorrection=true); bool AllowTypoCorrection=true,
bool CalleesAddressIsTaken=false);
bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
MultiExprArg Args, SourceLocation RParenLoc, MultiExprArg Args, SourceLocation RParenLoc,
@ -7626,6 +7629,9 @@ class Sema {
void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
StringLiteral *SegmentName); 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 /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value); void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value);
@ -8583,6 +8589,10 @@ class Sema {
bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind); 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. // CheckExtVectorCast - check type constraints for extended vectors.
// Since vectors are an extension, there are no C standard reference for this. // 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, // We allow casting between vectors and integer datatypes of the same size,

View File

@ -907,7 +907,9 @@ namespace clang {
/// \brief A DecayedType record. /// \brief A DecayedType record.
TYPE_DECAYED = 41, TYPE_DECAYED = 41,
/// \brief An AdjustedType record. /// \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 /// \brief The type IDs for special types constructed by semantic

View File

@ -871,6 +871,7 @@ class ASTWriter : public ASTDeserializationListener,
const FunctionDecl *Delete) override; const FunctionDecl *Delete) override;
void CompletedImplicitDefinition(const FunctionDecl *D) override; void CompletedImplicitDefinition(const FunctionDecl *D) override;
void StaticDataMemberInstantiated(const VarDecl *D) override; void StaticDataMemberInstantiated(const VarDecl *D) override;
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) override; const ObjCInterfaceDecl *IFD) override;

View File

@ -80,7 +80,7 @@ class MemRegion : public llvm::FoldingSetNode {
public: public:
enum Kind { enum Kind {
// Memory spaces. // Memory spaces.
GenericMemSpaceRegionKind, CodeSpaceRegionKind,
StackLocalsSpaceRegionKind, StackLocalsSpaceRegionKind,
StackArgumentsSpaceRegionKind, StackArgumentsSpaceRegionKind,
HeapSpaceRegionKind, HeapSpaceRegionKind,
@ -89,29 +89,29 @@ class MemRegion : public llvm::FoldingSetNode {
GlobalInternalSpaceRegionKind, GlobalInternalSpaceRegionKind,
GlobalSystemSpaceRegionKind, GlobalSystemSpaceRegionKind,
GlobalImmutableSpaceRegionKind, GlobalImmutableSpaceRegionKind,
BEG_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind, BEGIN_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind,
END_NON_STATIC_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind, END_NON_STATIC_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
BEG_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind, BEGIN_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind,
END_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind, END_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
BEG_MEMSPACES = GenericMemSpaceRegionKind, BEGIN_MEMSPACES = CodeSpaceRegionKind,
END_MEMSPACES = GlobalImmutableSpaceRegionKind, END_MEMSPACES = GlobalImmutableSpaceRegionKind,
// Untyped regions. // Untyped regions.
SymbolicRegionKind, SymbolicRegionKind,
AllocaRegionKind, AllocaRegionKind,
// Typed regions. // Typed regions.
BEG_TYPED_REGIONS, BEGIN_TYPED_REGIONS,
FunctionTextRegionKind = BEG_TYPED_REGIONS, FunctionCodeRegionKind = BEGIN_TYPED_REGIONS,
BlockTextRegionKind, BlockCodeRegionKind,
BlockDataRegionKind, BlockDataRegionKind,
BEG_TYPED_VALUE_REGIONS, BEGIN_TYPED_VALUE_REGIONS,
CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS, CompoundLiteralRegionKind = BEGIN_TYPED_VALUE_REGIONS,
CXXThisRegionKind, CXXThisRegionKind,
StringRegionKind, StringRegionKind,
ObjCStringRegionKind, ObjCStringRegionKind,
ElementRegionKind, ElementRegionKind,
// Decl Regions. // Decl Regions.
BEG_DECL_REGIONS, BEGIN_DECL_REGIONS,
VarRegionKind = BEG_DECL_REGIONS, VarRegionKind = BEGIN_DECL_REGIONS,
FieldRegionKind, FieldRegionKind,
ObjCIvarRegionKind, ObjCIvarRegionKind,
END_DECL_REGIONS = ObjCIvarRegionKind, END_DECL_REGIONS = ObjCIvarRegionKind,
@ -193,12 +193,9 @@ class MemRegion : public llvm::FoldingSetNode {
/// for example, the set of global variables, the stack frame, etc. /// for example, the set of global variables, the stack frame, etc.
class MemSpaceRegion : public MemRegion { class MemSpaceRegion : public MemRegion {
protected: protected:
friend class MemRegionManager;
MemRegionManager *Mgr; MemRegionManager *Mgr;
MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind) MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) {
: MemRegion(k), Mgr(mgr) {
assert(classof(this)); assert(classof(this));
} }
@ -211,7 +208,23 @@ class MemSpaceRegion : public MemRegion {
static bool classof(const MemRegion *R) { static bool classof(const MemRegion *R) {
Kind k = R->getKind(); 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;
} }
}; };
@ -223,7 +236,7 @@ class GlobalsSpaceRegion : public MemSpaceRegion {
public: public:
static bool classof(const MemRegion *R) { static bool classof(const MemRegion *R) {
Kind k = R->getKind(); Kind k = R->getKind();
return k >= BEG_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES; return k >= BEGIN_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
} }
}; };
@ -259,8 +272,6 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
/// RegionStoreManager::invalidateRegions (instead of finding all the dependent /// RegionStoreManager::invalidateRegions (instead of finding all the dependent
/// globals, we invalidate the whole parent region). /// globals, we invalidate the whole parent region).
class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion { class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
friend class MemRegionManager;
protected: protected:
NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k) NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
: GlobalsSpaceRegion(mgr, k) {} : GlobalsSpaceRegion(mgr, k) {}
@ -269,7 +280,7 @@ class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
static bool classof(const MemRegion *R) { static bool classof(const MemRegion *R) {
Kind k = R->getKind(); Kind k = R->getKind();
return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES && return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES &&
k <= END_NON_STATIC_GLOBAL_MEMSPACES; k <= END_NON_STATIC_GLOBAL_MEMSPACES;
} }
}; };
@ -491,7 +502,7 @@ class TypedRegion : public SubRegion {
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
unsigned k = R->getKind(); 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 @@ class TypedValueRegion : public TypedRegion {
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
unsigned k = R->getKind(); 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 @@ class CodeTextRegion : public TypedRegion {
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
Kind k = R->getKind(); Kind k = R->getKind();
return k >= FunctionTextRegionKind && k <= BlockTextRegionKind; return k >= FunctionCodeRegionKind && k <= BlockCodeRegionKind;
} }
}; };
/// FunctionTextRegion - A region that represents code texts of function. /// FunctionCodeRegion - A region that represents code texts of function.
class FunctionTextRegion : public CodeTextRegion { class FunctionCodeRegion : public CodeTextRegion {
const NamedDecl *FD; const NamedDecl *FD;
public: public:
FunctionTextRegion(const NamedDecl *fd, const MemRegion* sreg) FunctionCodeRegion(const NamedDecl *fd, const MemRegion* sreg)
: CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) { : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd)); assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
} }
@ -577,27 +588,27 @@ class FunctionTextRegion : public CodeTextRegion {
const MemRegion*); const MemRegion*);
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
return R->getKind() == FunctionTextRegionKind; return R->getKind() == FunctionCodeRegionKind;
} }
}; };
/// BlockTextRegion - A region that represents code texts of blocks (closures). /// BlockCodeRegion - A region that represents code texts of blocks (closures).
/// 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, /// represent the "code", while BlockDataRegions represent instances of blocks,
/// which correspond to "code+data". The distinction is important, because /// which correspond to "code+data". The distinction is important, because
/// like a closure a block captures the values of externally referenced /// like a closure a block captures the values of externally referenced
/// variables. /// variables.
class BlockTextRegion : public CodeTextRegion { class BlockCodeRegion : public CodeTextRegion {
friend class MemRegionManager; friend class MemRegionManager;
const BlockDecl *BD; const BlockDecl *BD;
AnalysisDeclContext *AC; AnalysisDeclContext *AC;
CanQualType locTy; CanQualType locTy;
BlockTextRegion(const BlockDecl *bd, CanQualType lTy, BlockCodeRegion(const BlockDecl *bd, CanQualType lTy,
AnalysisDeclContext *ac, const MemRegion* sreg) AnalysisDeclContext *ac, const MemRegion* sreg)
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {}
public: public:
QualType getLocationType() const override { QualType getLocationType() const override {
@ -619,32 +630,32 @@ class BlockTextRegion : public CodeTextRegion {
const MemRegion*); const MemRegion*);
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
return R->getKind() == BlockTextRegionKind; return R->getKind() == BlockCodeRegionKind;
} }
}; };
/// BlockDataRegion - A region that represents a block instance. /// 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, /// represent the "code", while BlockDataRegions represent instances of blocks,
/// which correspond to "code+data". The distinction is important, because /// which correspond to "code+data". The distinction is important, because
/// like a closure a block captures the values of externally referenced /// like a closure a block captures the values of externally referenced
/// variables. /// variables.
class BlockDataRegion : public TypedRegion { class BlockDataRegion : public TypedRegion {
friend class MemRegionManager; friend class MemRegionManager;
const BlockTextRegion *BC; const BlockCodeRegion *BC;
const LocationContext *LC; // Can be null */ const LocationContext *LC; // Can be null */
unsigned BlockCount; unsigned BlockCount;
void *ReferencedVars; void *ReferencedVars;
void *OriginalVars; void *OriginalVars;
BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc, BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
unsigned count, const MemRegion *sreg) unsigned count, const MemRegion *sreg)
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
BlockCount(count), BlockCount(count),
ReferencedVars(nullptr), OriginalVars(nullptr) {} ReferencedVars(nullptr), OriginalVars(nullptr) {}
public: public:
const BlockTextRegion *getCodeRegion() const { return BC; } const BlockCodeRegion *getCodeRegion() const { return BC; }
const BlockDecl *getDecl() const { return BC->getDecl(); } const BlockDecl *getDecl() const { return BC->getDecl(); }
@ -691,7 +702,7 @@ class BlockDataRegion : public TypedRegion {
void Profile(llvm::FoldingSetNodeID& ID) const override; 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 LocationContext *, unsigned,
const MemRegion *); const MemRegion *);
@ -856,7 +867,7 @@ class DeclRegion : public TypedValueRegion {
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
unsigned k = R->getKind(); 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; HeapSpaceRegion *heap;
UnknownSpaceRegion *unknown; UnknownSpaceRegion *unknown;
MemSpaceRegion *code; CodeSpaceRegion *code;
public: public:
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a)
@ -1174,9 +1185,9 @@ class MemRegionManager {
/// getUnknownRegion - Retrieve the memory region associated with unknown /// getUnknownRegion - Retrieve the memory region associated with unknown
/// memory space. /// memory space.
const MemSpaceRegion *getUnknownRegion(); const UnknownSpaceRegion *getUnknownRegion();
const MemSpaceRegion *getCodeRegion(); const CodeSpaceRegion *getCodeRegion();
/// getAllocaRegion - Retrieve a region associated with a call to alloca(). /// getAllocaRegion - Retrieve a region associated with a call to alloca().
const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt, const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
@ -1262,8 +1273,8 @@ class MemRegionManager {
baseReg->isVirtual()); baseReg->isVirtual());
} }
const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD); const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD);
const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,
CanQualType locTy, CanQualType locTy,
AnalysisDeclContext *AC); AnalysisDeclContext *AC);
@ -1271,7 +1282,7 @@ class MemRegionManager {
/// of a block. Unlike many other MemRegions, the LocationContext* /// of a block. Unlike many other MemRegions, the LocationContext*
/// argument is allowed to be NULL for cases where we have no known /// argument is allowed to be NULL for cases where we have no known
/// context. /// context.
const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc, const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc,
const LocationContext *lc, const LocationContext *lc,
unsigned blockCount); unsigned blockCount);

View File

@ -84,6 +84,10 @@ class SValBuilder {
SVal evalCast(SVal val, QualType castTy, QualType originalType); 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 evalMinus(NonLoc val) = 0;
virtual SVal evalComplement(NonLoc val) = 0; virtual SVal evalComplement(NonLoc val) = 0;

View File

@ -45,8 +45,8 @@ class SVal {
public: public:
enum BaseKind { enum BaseKind {
// The enumerators must be representable using 2 bits. // The enumerators must be representable using 2 bits.
UndefinedKind = 0, // for subclass UndefinedVal (an uninitialized value) UndefinedValKind = 0, // for subclass UndefinedVal (an uninitialized value)
UnknownKind = 1, // for subclass UnknownVal (a void value) UnknownValKind = 1, // for subclass UnknownVal (a void value)
LocKind = 2, // for subclass Loc (an L-value) LocKind = 2, // for subclass Loc (an L-value)
NonLocKind = 3 // for subclass NonLoc (an R-value that's not NonLocKind = 3 // for subclass NonLoc (an R-value that's not
// an L-value) // an L-value)
@ -115,19 +115,19 @@ class SVal {
} }
inline bool isUnknown() const { inline bool isUnknown() const {
return getRawKind() == UnknownKind; return getRawKind() == UnknownValKind;
} }
inline bool isUndef() const { inline bool isUndef() const {
return getRawKind() == UndefinedKind; return getRawKind() == UndefinedValKind;
} }
inline bool isUnknownOrUndef() const { inline bool isUnknownOrUndef() const {
return getRawKind() <= UnknownKind; return getRawKind() <= UnknownValKind;
} }
inline bool isValid() const { inline bool isValid() const {
return getRawKind() > UnknownKind; return getRawKind() > UnknownValKind;
} }
bool isConstant() const; bool isConstant() const;
@ -190,12 +190,12 @@ class SVal {
class UndefinedVal : public SVal { class UndefinedVal : public SVal {
public: public:
UndefinedVal() : SVal(UndefinedKind) {} UndefinedVal() : SVal(UndefinedValKind) {}
private: private:
friend class SVal; friend class SVal;
static bool isKind(const SVal& V) { static bool isKind(const SVal& V) {
return V.getBaseKind() == UndefinedKind; return V.getBaseKind() == UndefinedValKind;
} }
}; };
@ -223,12 +223,12 @@ class DefinedOrUnknownSVal : public SVal {
class UnknownVal : public DefinedOrUnknownSVal { class UnknownVal : public DefinedOrUnknownSVal {
public: public:
explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {} explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {}
private: private:
friend class SVal; friend class SVal;
static bool isKind(const SVal &V) { static bool isKind(const SVal &V) {
return V.getBaseKind() == UnknownKind; return V.getBaseKind() == UnknownValKind;
} }
}; };
@ -465,7 +465,7 @@ class LazyCompoundVal : public NonLoc {
namespace loc { namespace loc {
enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind }; enum Kind { GotoLabelKind, MemRegionValKind, ConcreteIntKind };
class GotoLabel : public Loc { class GotoLabel : public Loc {
public: public:
@ -490,7 +490,7 @@ class GotoLabel : public Loc {
class MemRegionVal : public Loc { class MemRegionVal : public Loc {
public: public:
explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {} explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {}
/// \brief Get the underlining region. /// \brief Get the underlining region.
const MemRegion* getRegion() const { const MemRegion* getRegion() const {
@ -518,11 +518,11 @@ class MemRegionVal : public Loc {
MemRegionVal() {} MemRegionVal() {}
static bool isKind(const SVal& V) { static bool isKind(const SVal& V) {
return V.getBaseKind() == LocKind && return V.getBaseKind() == LocKind &&
V.getSubKind() == MemRegionKind; V.getSubKind() == MemRegionValKind;
} }
static bool isKind(const Loc& V) { static bool isKind(const Loc& V) {
return V.getSubKind() == MemRegionKind; return V.getSubKind() == MemRegionValKind;
} }
}; };

View File

@ -42,14 +42,22 @@ namespace ento {
class SymExpr : public llvm::FoldingSetNode { class SymExpr : public llvm::FoldingSetNode {
virtual void anchor(); virtual void anchor();
public: public:
enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind, enum Kind {
MetadataKind, SymbolRegionValueKind,
BEGIN_SYMBOLS = RegionValueKind, SymbolConjuredKind,
END_SYMBOLS = MetadataKind, SymbolDerivedKind,
SymIntKind, IntSymKind, SymSymKind, SymbolExtentKind,
BEGIN_BINARYSYMEXPRS = SymIntKind, SymbolMetadataKind,
END_BINARYSYMEXPRS = SymSymKind, BEGIN_SYMBOLS = SymbolRegionValueKind,
CastSymbolKind }; END_SYMBOLS = SymbolMetadataKind,
SymIntExprKind,
IntSymExprKind,
SymSymExprKind,
BEGIN_BINARYSYMEXPRS = SymIntExprKind,
END_BINARYSYMEXPRS = SymSymExprKind,
SymbolCastKind
};
private: private:
Kind K; Kind K;
@ -126,12 +134,12 @@ class SymbolRegionValue : public SymbolData {
public: public:
SymbolRegionValue(SymbolID sym, const TypedValueRegion *r) SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
: SymbolData(RegionValueKind, sym), R(r) {} : SymbolData(SymbolRegionValueKind, sym), R(r) {}
const TypedValueRegion* getRegion() const { return R; } const TypedValueRegion* getRegion() const { return R; }
static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) { static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
profile.AddInteger((unsigned) RegionValueKind); profile.AddInteger((unsigned) SymbolRegionValueKind);
profile.AddPointer(R); profile.AddPointer(R);
} }
@ -145,7 +153,7 @@ class SymbolRegionValue : public SymbolData {
// Implement isa<T> support. // Implement isa<T> support.
static inline bool classof(const SymExpr *SE) { static inline bool classof(const SymExpr *SE) {
return SE->getKind() == RegionValueKind; return SE->getKind() == SymbolRegionValueKind;
} }
}; };
@ -160,11 +168,9 @@ class SymbolConjured : public SymbolData {
public: public:
SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx, SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
QualType t, unsigned count, QualType t, unsigned count, const void *symbolTag)
const void *symbolTag) : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
: SymbolData(ConjuredKind, sym), S(s), T(t), Count(count), LCtx(lctx), SymbolTag(symbolTag) {}
LCtx(lctx),
SymbolTag(symbolTag) {}
const Stmt *getStmt() const { return S; } const Stmt *getStmt() const { return S; }
unsigned getCount() const { return Count; } unsigned getCount() const { return Count; }
@ -177,7 +183,7 @@ class SymbolConjured : public SymbolData {
static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S, static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
QualType T, unsigned Count, const LocationContext *LCtx, QualType T, unsigned Count, const LocationContext *LCtx,
const void *SymbolTag) { const void *SymbolTag) {
profile.AddInteger((unsigned) ConjuredKind); profile.AddInteger((unsigned) SymbolConjuredKind);
profile.AddPointer(S); profile.AddPointer(S);
profile.AddPointer(LCtx); profile.AddPointer(LCtx);
profile.Add(T); profile.Add(T);
@ -191,7 +197,7 @@ class SymbolConjured : public SymbolData {
// Implement isa<T> support. // Implement isa<T> support.
static inline bool classof(const SymExpr *SE) { static inline bool classof(const SymExpr *SE) {
return SE->getKind() == ConjuredKind; return SE->getKind() == SymbolConjuredKind;
} }
}; };
@ -203,7 +209,7 @@ class SymbolDerived : public SymbolData {
public: public:
SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r) 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; } SymbolRef getParentSymbol() const { return parentSymbol; }
const TypedValueRegion *getRegion() const { return R; } const TypedValueRegion *getRegion() const { return R; }
@ -214,7 +220,7 @@ class SymbolDerived : public SymbolData {
static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent, static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
const TypedValueRegion *r) { const TypedValueRegion *r) {
profile.AddInteger((unsigned) DerivedKind); profile.AddInteger((unsigned) SymbolDerivedKind);
profile.AddPointer(r); profile.AddPointer(r);
profile.AddPointer(parent); profile.AddPointer(parent);
} }
@ -225,7 +231,7 @@ class SymbolDerived : public SymbolData {
// Implement isa<T> support. // Implement isa<T> support.
static inline bool classof(const SymExpr *SE) { static inline bool classof(const SymExpr *SE) {
return SE->getKind() == DerivedKind; return SE->getKind() == SymbolDerivedKind;
} }
}; };
@ -237,7 +243,7 @@ class SymbolExtent : public SymbolData {
public: public:
SymbolExtent(SymbolID sym, const SubRegion *r) SymbolExtent(SymbolID sym, const SubRegion *r)
: SymbolData(ExtentKind, sym), R(r) {} : SymbolData(SymbolExtentKind, sym), R(r) {}
const SubRegion *getRegion() const { return R; } const SubRegion *getRegion() const { return R; }
@ -246,7 +252,7 @@ class SymbolExtent : public SymbolData {
void dumpToStream(raw_ostream &os) const override; void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) { static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
profile.AddInteger((unsigned) ExtentKind); profile.AddInteger((unsigned) SymbolExtentKind);
profile.AddPointer(R); profile.AddPointer(R);
} }
@ -256,7 +262,7 @@ class SymbolExtent : public SymbolData {
// Implement isa<T> support. // Implement isa<T> support.
static inline bool classof(const SymExpr *SE) { static inline bool classof(const SymExpr *SE) {
return SE->getKind() == ExtentKind; return SE->getKind() == SymbolExtentKind;
} }
}; };
@ -273,7 +279,7 @@ class SymbolMetadata : public SymbolData {
public: public:
SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t, SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
unsigned count, const void *tag) 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 MemRegion *getRegion() const { return R; }
const Stmt *getStmt() const { return S; } const Stmt *getStmt() const { return S; }
@ -287,7 +293,7 @@ class SymbolMetadata : public SymbolData {
static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R, static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
const Stmt *S, QualType T, unsigned Count, const Stmt *S, QualType T, unsigned Count,
const void *Tag) { const void *Tag) {
profile.AddInteger((unsigned) MetadataKind); profile.AddInteger((unsigned) SymbolMetadataKind);
profile.AddPointer(R); profile.AddPointer(R);
profile.AddPointer(S); profile.AddPointer(S);
profile.Add(T); profile.Add(T);
@ -301,7 +307,7 @@ class SymbolMetadata : public SymbolData {
// Implement isa<T> support. // Implement isa<T> support.
static inline bool classof(const SymExpr *SE) { static inline bool classof(const SymExpr *SE) {
return SE->getKind() == MetadataKind; return SE->getKind() == SymbolMetadataKind;
} }
}; };
@ -315,7 +321,7 @@ class SymbolCast : public SymExpr {
public: public:
SymbolCast(const SymExpr *In, QualType From, QualType To) : 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; } QualType getType() const override { return ToTy; }
@ -325,7 +331,7 @@ class SymbolCast : public SymExpr {
static void Profile(llvm::FoldingSetNodeID& ID, static void Profile(llvm::FoldingSetNodeID& ID,
const SymExpr *In, QualType From, QualType To) { const SymExpr *In, QualType From, QualType To) {
ID.AddInteger((unsigned) CastSymbolKind); ID.AddInteger((unsigned) SymbolCastKind);
ID.AddPointer(In); ID.AddPointer(In);
ID.Add(From); ID.Add(From);
ID.Add(To); ID.Add(To);
@ -337,7 +343,7 @@ class SymbolCast : public SymExpr {
// Implement isa<T> support. // Implement isa<T> support.
static inline bool classof(const SymExpr *SE) { static inline bool classof(const SymExpr *SE) {
return SE->getKind() == CastSymbolKind; return SE->getKind() == SymbolCastKind;
} }
}; };
@ -372,7 +378,7 @@ class SymIntExpr : public BinarySymExpr {
public: public:
SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType t) 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; void dumpToStream(raw_ostream &os) const override;
@ -382,7 +388,7 @@ class SymIntExpr : public BinarySymExpr {
static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
BinaryOperator::Opcode op, const llvm::APSInt& rhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs,
QualType t) { QualType t) {
ID.AddInteger((unsigned) SymIntKind); ID.AddInteger((unsigned) SymIntExprKind);
ID.AddPointer(lhs); ID.AddPointer(lhs);
ID.AddInteger(op); ID.AddInteger(op);
ID.AddPointer(&rhs); ID.AddPointer(&rhs);
@ -395,7 +401,7 @@ class SymIntExpr : public BinarySymExpr {
// Implement isa<T> support. // Implement isa<T> support.
static inline bool classof(const SymExpr *SE) { static inline bool classof(const SymExpr *SE) {
return SE->getKind() == SymIntKind; return SE->getKind() == SymIntExprKind;
} }
}; };
@ -407,7 +413,7 @@ class IntSymExpr : public BinarySymExpr {
public: public:
IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op, IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType t) 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; void dumpToStream(raw_ostream &os) const override;
@ -417,7 +423,7 @@ class IntSymExpr : public BinarySymExpr {
static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs, static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs,
BinaryOperator::Opcode op, const SymExpr *rhs, BinaryOperator::Opcode op, const SymExpr *rhs,
QualType t) { QualType t) {
ID.AddInteger((unsigned) IntSymKind); ID.AddInteger((unsigned) IntSymExprKind);
ID.AddPointer(&lhs); ID.AddPointer(&lhs);
ID.AddInteger(op); ID.AddInteger(op);
ID.AddPointer(rhs); ID.AddPointer(rhs);
@ -430,7 +436,7 @@ class IntSymExpr : public BinarySymExpr {
// Implement isa<T> support. // Implement isa<T> support.
static inline bool classof(const SymExpr *SE) { static inline bool classof(const SymExpr *SE) {
return SE->getKind() == IntSymKind; return SE->getKind() == IntSymExprKind;
} }
}; };
@ -442,7 +448,7 @@ class SymSymExpr : public BinarySymExpr {
public: public:
SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
QualType t) 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 *getLHS() const { return LHS; }
const SymExpr *getRHS() const { return RHS; } const SymExpr *getRHS() const { return RHS; }
@ -451,7 +457,7 @@ class SymSymExpr : public BinarySymExpr {
static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
ID.AddInteger((unsigned) SymSymKind); ID.AddInteger((unsigned) SymSymExprKind);
ID.AddPointer(lhs); ID.AddPointer(lhs);
ID.AddInteger(op); ID.AddInteger(op);
ID.AddPointer(rhs); ID.AddPointer(rhs);
@ -464,7 +470,7 @@ class SymSymExpr : public BinarySymExpr {
// Implement isa<T> support. // Implement isa<T> support.
static inline bool classof(const SymExpr *SE) { static inline bool classof(const SymExpr *SE) {
return SE->getKind() == SymSymKind; return SE->getKind() == SymSymExprKind;
} }
}; };

View File

@ -1836,6 +1836,13 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Align = static_cast<unsigned>(Width); 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::FunctionProto:
case Type::BlockPointer: case Type::BlockPointer:
case Type::MemberPointer: case Type::MemberPointer:
case Type::Pipe:
return type; return type;
// These types can be variably-modified. All these modifications // 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 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 #ifndef NDEBUG
static bool NeedsInjectedClassNameType(const RecordDecl *D) { static bool NeedsInjectedClassNameType(const RecordDecl *D) {
if (!isa<CXXRecordDecl>(D)) return false; if (!isa<CXXRecordDecl>(D)) return false;
@ -5857,6 +5891,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
case Type::Auto: case Type::Auto:
return; return;
case Type::Pipe:
#define ABSTRACT_TYPE(KIND, BASE) #define ABSTRACT_TYPE(KIND, BASE)
#define TYPE(KIND, BASE) #define TYPE(KIND, BASE)
#define DEPENDENT_TYPE(KIND, BASE) \ #define DEPENDENT_TYPE(KIND, BASE) \
@ -7792,6 +7827,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return QualType(); 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!"); llvm_unreachable("Invalid Type::Class!");

View File

@ -1055,6 +1055,7 @@ void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) {
dumpType(D->getUnderlyingType()); dumpType(D->getUnderlyingType());
if (D->isModulePrivate()) if (D->isModulePrivate())
OS << " __module_private__"; OS << " __module_private__";
dumpTypeAsChild(D->getUnderlyingType());
} }
void ASTDumper::VisitEnumDecl(const EnumDecl *D) { void ASTDumper::VisitEnumDecl(const EnumDecl *D) {
@ -1226,6 +1227,7 @@ void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
dumpName(D); dumpName(D);
dumpType(D->getUnderlyingType()); dumpType(D->getUnderlyingType());
dumpTypeAsChild(D->getUnderlyingType());
} }
void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
@ -1419,6 +1421,8 @@ void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D)
void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
OS << ' '; OS << ' ';
dumpBareDeclRef(D->getTargetDecl()); dumpBareDeclRef(D->getTargetDecl());
if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
dumpTypeAsChild(TD->getTypeForDecl());
} }
void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {

View File

@ -878,6 +878,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break; break;
} }
case Type::Pipe: {
if (!IsStructurallyEquivalent(Context,
cast<PipeType>(T1)->getElementType(),
cast<PipeType>(T2)->getElementType()))
return false;
break;
}
} // end switch } // end switch
return true; return true;

View File

@ -1184,7 +1184,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
return LinkageInfo::none(); return LinkageInfo::none();
const Decl *OuterD = getOutermostFuncOrBlockContext(D); const Decl *OuterD = getOutermostFuncOrBlockContext(D);
if (!OuterD) if (!OuterD || OuterD->isInvalidDecl())
return LinkageInfo::none(); return LinkageInfo::none();
LinkageInfo LV; LinkageInfo LV;
@ -4024,16 +4024,26 @@ EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
void IndirectFieldDecl::anchor() { } 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 *
IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, NamedDecl **CH, IdentifierInfo *Id, QualType T, NamedDecl **CH,
unsigned CHS) { 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, IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
unsigned ID) { unsigned ID) {
return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(), return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(),
DeclarationName(), QualType(), nullptr, DeclarationName(), QualType(), nullptr,
0); 0);
} }

View File

@ -569,7 +569,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Var: case Var:
case ImplicitParam: case ImplicitParam:
case ParmVar: case ParmVar:
case NonTypeTemplateParm:
case ObjCMethod: case ObjCMethod:
case ObjCProperty: case ObjCProperty:
case MSProperty: case MSProperty:
@ -579,6 +578,12 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case IndirectField: case IndirectField:
return IDNS_Ordinary | IDNS_Member; 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 ObjCCompatibleAlias:
case ObjCInterface: case ObjCInterface:
return IDNS_Ordinary | IDNS_Type; return IDNS_Ordinary | IDNS_Type;

View File

@ -1553,6 +1553,7 @@ bool CastExpr::CastConsistency() const {
case CK_ToVoid: case CK_ToVoid:
case CK_VectorSplat: case CK_VectorSplat:
case CK_IntegralCast: case CK_IntegralCast:
case CK_BooleanToSignedIntegral:
case CK_IntegralToFloating: case CK_IntegralToFloating:
case CK_FloatingToIntegral: case CK_FloatingToIntegral:
case CK_FloatingCast: case CK_FloatingCast:
@ -1646,6 +1647,8 @@ const char *CastExpr::getCastKindName() const {
return "VectorSplat"; return "VectorSplat";
case CK_IntegralCast: case CK_IntegralCast:
return "IntegralCast"; return "IntegralCast";
case CK_BooleanToSignedIntegral:
return "BooleanToSignedIntegral";
case CK_IntegralToBoolean: case CK_IntegralToBoolean:
return "IntegralToBoolean"; return "IntegralToBoolean";
case CK_IntegralToFloating: case CK_IntegralToFloating:

View File

@ -763,14 +763,6 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const {
return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier(); 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, CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc,
FieldDecl *Field, QualType T) FieldDecl *Field, QualType T)
: Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C), : Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C),

View File

@ -7781,12 +7781,16 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_PointerToBoolean: case CK_PointerToBoolean:
case CK_IntegralToBoolean: case CK_IntegralToBoolean:
case CK_FloatingToBoolean: case CK_FloatingToBoolean:
case CK_BooleanToSignedIntegral:
case CK_FloatingComplexToBoolean: case CK_FloatingComplexToBoolean:
case CK_IntegralComplexToBoolean: { case CK_IntegralComplexToBoolean: {
bool BoolResult; bool BoolResult;
if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info)) if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info))
return false; 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: { case CK_IntegralCast: {
@ -8223,6 +8227,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_ToVoid: case CK_ToVoid:
case CK_VectorSplat: case CK_VectorSplat:
case CK_IntegralCast: case CK_IntegralCast:
case CK_BooleanToSignedIntegral:
case CK_IntegralToBoolean: case CK_IntegralToBoolean:
case CK_IntegralToFloating: case CK_IntegralToFloating:
case CK_FloatingToIntegral: case CK_FloatingToIntegral:

View File

@ -1509,6 +1509,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::ObjCInterface: case Type::ObjCInterface:
case Type::ObjCObjectPointer: case Type::ObjCObjectPointer:
case Type::Atomic: case Type::Atomic:
case Type::Pipe:
llvm_unreachable("type is illegal as a nested name specifier"); llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstTemplateTypeParmPack: case Type::SubstTemplateTypeParmPack:
@ -2682,6 +2683,13 @@ void CXXNameMangler::mangleType(const AtomicType *T) {
mangleType(T->getValueType()); 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, void CXXNameMangler::mangleIntegerLiteral(QualType T,
const llvm::APSInt &Value) { const llvm::APSInt &Value) {
// <expr-primary> ::= L <type> <value number> E # integer literal // <expr-primary> ::= L <type> <value number> E # integer literal

View File

@ -2428,6 +2428,15 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"}); 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, void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D,
raw_ostream &Out) { raw_ostream &Out) {
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) && assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&

View File

@ -1552,7 +1552,8 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
FieldAlign = 1; FieldAlign = 1;
// But, if there's an 'aligned' attribute on the field, honor that. // 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); FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign); UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
} }
@ -1601,6 +1602,10 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
(AllowPadding && (AllowPadding &&
(FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) { (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) {
FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); 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. // Repeat the computation for diagnostic purposes.
@ -1609,6 +1614,9 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
(UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
UnpackedFieldAlign); UnpackedFieldAlign);
else if (ExplicitFieldAlign)
UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
ExplicitFieldAlign);
} }
// If we're using external layout, give the external layout a chance // If we're using external layout, give the external layout a chance

View File

@ -1165,6 +1165,7 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
switch (Node->getKind()) { switch (Node->getKind()) {
case CharacterLiteral::Ascii: break; // no prefix. case CharacterLiteral::Ascii: break; // no prefix.
case CharacterLiteral::Wide: OS << 'L'; break; case CharacterLiteral::Wide: OS << 'L'; break;
case CharacterLiteral::UTF8: OS << "u8"; break;
case CharacterLiteral::UTF16: OS << 'u'; break; case CharacterLiteral::UTF16: OS << 'u'; break;
case CharacterLiteral::UTF32: OS << 'U'; break; case CharacterLiteral::UTF32: OS << 'U'; break;
} }

View File

@ -2614,7 +2614,7 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
case OCLQueue: case OCLQueue:
return "queue_t"; return "queue_t";
case OCLNDRange: case OCLNDRange:
return "event_t"; return "ndrange_t";
case OCLReserveID: case OCLReserveID:
return "reserve_id_t"; return "reserve_id_t";
case OMPArraySection: case OMPArraySection:
@ -3361,6 +3361,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType()); return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
case Type::Atomic: case Type::Atomic:
return Cache::get(cast<AtomicType>(T)->getValueType()); return Cache::get(cast<AtomicType>(T)->getValueType());
case Type::Pipe:
return Cache::get(cast<PipeType>(T)->getElementType());
} }
llvm_unreachable("unhandled type class"); llvm_unreachable("unhandled type class");
@ -3443,6 +3445,8 @@ static LinkageInfo computeLinkageInfo(const Type *T) {
return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType()); return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType());
case Type::Atomic: case Type::Atomic:
return computeLinkageInfo(cast<AtomicType>(T)->getValueType()); return computeLinkageInfo(cast<AtomicType>(T)->getValueType());
case Type::Pipe:
return computeLinkageInfo(cast<PipeType>(T)->getElementType());
} }
llvm_unreachable("unhandled type class"); llvm_unreachable("unhandled type class");
@ -3601,6 +3605,7 @@ bool Type::canHaveNullability() const {
case Type::ObjCObject: case Type::ObjCObject:
case Type::ObjCInterface: case Type::ObjCInterface:
case Type::Atomic: case Type::Atomic:
case Type::Pipe:
return false; return false;
} }
llvm_unreachable("bad type kind!"); llvm_unreachable("bad type kind!");

View File

@ -193,6 +193,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::ObjCObject: case Type::ObjCObject:
case Type::ObjCInterface: case Type::ObjCInterface:
case Type::Atomic: case Type::Atomic:
case Type::Pipe:
CanPrefixQualifiers = true; CanPrefixQualifiers = true;
break; 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::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. /// Appends the given scope to the end of a string.
void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) { void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
if (DC->isTranslationUnit()) return; if (DC->isTranslationUnit()) return;

View File

@ -223,7 +223,24 @@ class DarwinTargetInfo : public OSTargetInfo<Target> {
public: public:
DarwinTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { 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"; this->MCountName = "\01mcount";
} }
@ -7281,7 +7298,7 @@ class WebAssembly32TargetInfo : public WebAssemblyTargetInfo {
explicit WebAssembly32TargetInfo(const llvm::Triple &T) explicit WebAssembly32TargetInfo(const llvm::Triple &T)
: WebAssemblyTargetInfo(T) { : WebAssemblyTargetInfo(T) {
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; 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: protected:
@ -7299,7 +7316,7 @@ class WebAssembly64TargetInfo : public WebAssemblyTargetInfo {
LongAlign = LongWidth = 64; LongAlign = LongWidth = 64;
PointerAlign = PointerWidth = 64; PointerAlign = PointerWidth = 64;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 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: protected:

View File

@ -658,6 +658,23 @@ directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
EC = make_error_code(llvm::errc::not_a_directory); EC = make_error_code(llvm::errc::not_a_directory);
return directory_iterator(std::make_shared<InMemoryDirIterator>()); 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();
}
} }
} }

View File

@ -28,6 +28,7 @@
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h" #include "llvm/IR/Verifier.h"
#include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetRegistry.h"
@ -54,7 +55,6 @@ class EmitAssemblyHelper {
const clang::TargetOptions &TargetOpts; const clang::TargetOptions &TargetOpts;
const LangOptions &LangOpts; const LangOptions &LangOpts;
Module *TheModule; Module *TheModule;
std::unique_ptr<FunctionInfoIndex> FunctionIndex;
Timer CodeGenerationTime; Timer CodeGenerationTime;
@ -97,7 +97,7 @@ class EmitAssemblyHelper {
return PerFunctionPasses; return PerFunctionPasses;
} }
void CreatePasses(); void CreatePasses(FunctionInfoIndex *FunctionIndex);
/// Generates the TargetMachine. /// Generates the TargetMachine.
/// Returns Null if it is unable to create the target machine. /// Returns Null if it is unable to create the target machine.
@ -117,12 +117,11 @@ class EmitAssemblyHelper {
public: public:
EmitAssemblyHelper(DiagnosticsEngine &_Diags, const CodeGenOptions &CGOpts, EmitAssemblyHelper(DiagnosticsEngine &_Diags, const CodeGenOptions &CGOpts,
const clang::TargetOptions &TOpts, const clang::TargetOptions &TOpts,
const LangOptions &LOpts, Module *M, const LangOptions &LOpts, Module *M)
std::unique_ptr<FunctionInfoIndex> Index)
: Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts), : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts),
TheModule(M), FunctionIndex(std::move(Index)), TheModule(M), CodeGenerationTime("Code Generation Time"),
CodeGenerationTime("Code Generation Time"), CodeGenPasses(nullptr), CodeGenPasses(nullptr), PerModulePasses(nullptr),
PerModulePasses(nullptr), PerFunctionPasses(nullptr) {} PerFunctionPasses(nullptr) {}
~EmitAssemblyHelper() { ~EmitAssemblyHelper() {
delete CodeGenPasses; delete CodeGenPasses;
@ -278,7 +277,7 @@ static void addSymbolRewriterPass(const CodeGenOptions &Opts,
MPM->add(createRewriteSymbolsPass(DL)); MPM->add(createRewriteSymbolsPass(DL));
} }
void EmitAssemblyHelper::CreatePasses() { void EmitAssemblyHelper::CreatePasses(FunctionInfoIndex *FunctionIndex) {
if (CodeGenOpts.DisableLLVMPasses) if (CodeGenOpts.DisableLLVMPasses)
return; return;
@ -332,9 +331,8 @@ void EmitAssemblyHelper::CreatePasses() {
// If we are performing a ThinLTO importing compile, invoke the LTO // If we are performing a ThinLTO importing compile, invoke the LTO
// pipeline and pass down the in-memory function index. // pipeline and pass down the in-memory function index.
if (!CodeGenOpts.ThinLTOIndexFile.empty()) { if (FunctionIndex) {
assert(FunctionIndex && "Expected non-empty function index"); PMBuilder.FunctionIndex = FunctionIndex;
PMBuilder.FunctionIndex = FunctionIndex.get();
PMBuilder.populateLTOPassManager(*MPM); PMBuilder.populateLTOPassManager(*MPM);
return; return;
} }
@ -642,7 +640,28 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
return; return;
if (TM) if (TM)
TheModule->setDataLayout(TM->createDataLayout()); 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) { switch (Action) {
case Backend_EmitNothing: case Backend_EmitNothing:
@ -695,10 +714,8 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
const clang::TargetOptions &TOpts, const clang::TargetOptions &TOpts,
const LangOptions &LOpts, StringRef TDesc, const LangOptions &LOpts, StringRef TDesc,
Module *M, BackendAction Action, Module *M, BackendAction Action,
raw_pwrite_stream *OS, raw_pwrite_stream *OS) {
std::unique_ptr<FunctionInfoIndex> Index) { EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M);
EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M,
std::move(Index));
AsmHelper.EmitAssembly(Action, OS); AsmHelper.EmitAssembly(Action, OS);

View File

@ -2025,6 +2025,11 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
return getOrCreateType(Ty->getValueType(), 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) { llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl(); const EnumDecl *ED = Ty->getDecl();
@ -2284,6 +2289,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Atomic: case Type::Atomic:
return CreateType(cast<AtomicType>(Ty), Unit); return CreateType(cast<AtomicType>(Ty), Unit);
case Type::Pipe:
return CreateType(cast<PipeType>(Ty), Unit);
case Type::TemplateSpecialization: case Type::TemplateSpecialization:
return CreateType(cast<TemplateSpecializationType>(Ty), Unit); return CreateType(cast<TemplateSpecializationType>(Ty), Unit);

View File

@ -168,6 +168,7 @@ class CGDebugInfo {
llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit); llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit);
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const AtomicType *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. /// Get enumeration type.
llvm::DIType *CreateEnumType(const EnumType *Ty); llvm::DIType *CreateEnumType(const EnumType *Ty);
llvm::DIType *CreateTypeDefinition(const EnumType *Ty); llvm::DIType *CreateTypeDefinition(const EnumType *Ty);

View File

@ -3365,6 +3365,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_PointerToBoolean: case CK_PointerToBoolean:
case CK_VectorSplat: case CK_VectorSplat:
case CK_IntegralCast: case CK_IntegralCast:
case CK_BooleanToSignedIntegral:
case CK_IntegralToBoolean: case CK_IntegralToBoolean:
case CK_IntegralToFloating: case CK_IntegralToFloating:
case CK_FloatingToIntegral: case CK_FloatingToIntegral:

View File

@ -721,6 +721,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
case CK_ToVoid: case CK_ToVoid:
case CK_VectorSplat: case CK_VectorSplat:
case CK_IntegralCast: case CK_IntegralCast:
case CK_BooleanToSignedIntegral:
case CK_IntegralToBoolean: case CK_IntegralToBoolean:
case CK_IntegralToFloating: case CK_IntegralToFloating:
case CK_FloatingToIntegral: case CK_FloatingToIntegral:

View File

@ -462,6 +462,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
case CK_ToVoid: case CK_ToVoid:
case CK_VectorSplat: case CK_VectorSplat:
case CK_IntegralCast: case CK_IntegralCast:
case CK_BooleanToSignedIntegral:
case CK_IntegralToBoolean: case CK_IntegralToBoolean:
case CK_IntegralToFloating: case CK_IntegralToFloating:
case CK_FloatingToIntegral: case CK_FloatingToIntegral:

View File

@ -735,6 +735,7 @@ class ConstExprEmitter :
case CK_PointerToBoolean: case CK_PointerToBoolean:
case CK_NullToPointer: case CK_NullToPointer:
case CK_IntegralCast: case CK_IntegralCast:
case CK_BooleanToSignedIntegral:
case CK_IntegralToPointer: case CK_IntegralToPointer:
case CK_IntegralToBoolean: case CK_IntegralToBoolean:
case CK_IntegralToFloating: case CK_IntegralToFloating:

View File

@ -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 // A scalar can be splatted to an extended vector of the same element type
if (DstType->isExtVectorType() && !SrcType->isVectorType()) { if (DstType->isExtVectorType() && !SrcType->isVectorType()) {
// Cast the scalar to element type // Sema should add casts to make sure that the source expression's type is
QualType EltTy = DstType->getAs<ExtVectorType>()->getElementType(); // the same as the vector's element type (sans qualifiers)
llvm::Value *Elt = EmitScalarConversion( assert(DstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
Src, SrcType, EltTy, Loc, CGF.getContext().getLangOpts().OpenCL); SrcType.getTypePtr() &&
"Splatted expr doesn't match with vector element type?");
// Splat the element across to all elements // Splat the element across to all elements
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements(); 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. // Allow bitcast from vector to integer/fp of the same size.
@ -1541,15 +1542,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
} }
case CK_VectorSplat: { case CK_VectorSplat: {
llvm::Type *DstTy = ConvertType(DestTy); llvm::Type *DstTy = ConvertType(DestTy);
// Need an IgnoreImpCasts here as by default a boolean will be promoted to Value *Elt = Visit(const_cast<Expr*>(E));
// 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);
// Splat the element across to all elements // Splat the element across to all elements
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements(); unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
return Builder.CreateVectorSplat(NumElements, Elt, "splat"); return Builder.CreateVectorSplat(NumElements, Elt, "splat");
@ -1561,6 +1554,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_FloatingCast: case CK_FloatingCast:
return EmitScalarConversion(Visit(E), E->getType(), DestTy, return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc()); CE->getExprLoc());
case CK_BooleanToSignedIntegral:
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc(),
/*TreatBooleanAsSigned=*/true);
case CK_IntegralToBoolean: case CK_IntegralToBoolean:
return EmitIntToBoolConversion(Visit(E)); return EmitIntToBoolConversion(Visit(E));
case CK_PointerToBoolean: case CK_PointerToBoolean:

View File

@ -99,3 +99,14 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
llvm::StructType::create(Ctx, "opencl.reserve_id_t"), 0); 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;
}

View File

@ -32,9 +32,10 @@ class CodeGenModule;
class CGOpenCLRuntime { class CGOpenCLRuntime {
protected: protected:
CodeGenModule &CGM; CodeGenModule &CGM;
llvm::Type *PipeTy;
public: public:
CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {} CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr) {}
virtual ~CGOpenCLRuntime(); virtual ~CGOpenCLRuntime();
/// Emit the IR required for a work-group-local variable declaration, and add /// Emit the IR required for a work-group-local variable declaration, and add
@ -44,6 +45,8 @@ class CGOpenCLRuntime {
const VarDecl &D); const VarDecl &D);
virtual llvm::Type *convertOpenCLSpecificType(const Type *T); virtual llvm::Type *convertOpenCLSpecificType(const Type *T);
virtual llvm::Type *getPipeType();
}; };
} }

View File

@ -84,7 +84,7 @@ class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
protected: protected:
CGOpenMPRegionKind RegionKind; CGOpenMPRegionKind RegionKind;
const RegionCodeGenTy &CodeGen; RegionCodeGenTy CodeGen;
OpenMPDirectiveKind Kind; OpenMPDirectiveKind Kind;
bool HasCancel; bool HasCancel;
}; };

View File

@ -335,7 +335,7 @@ class CGOpenMPRuntime {
public: public:
/// \brief Kind of a given entry. Currently, only target regions are /// \brief Kind of a given entry. Currently, only target regions are
/// supported. /// supported.
enum OffloadingEntryInfoKinds { enum OffloadingEntryInfoKinds : unsigned {
// Entry is a target region. // Entry is a target region.
OFFLOAD_ENTRY_INFO_TARGET_REGION = 0, OFFLOAD_ENTRY_INFO_TARGET_REGION = 0,
// Invalid entry info. // Invalid entry info.
@ -955,7 +955,7 @@ class CGOpenMPRuntime {
/// \brief Emit the target regions enclosed in \a GD function definition or /// \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 /// the function itself in case it is a valid device function. Returns true if
/// \a GD was dealt with successfully. /// \a GD was dealt with successfully.
/// \param FD Function to scan. /// \param GD Function to scan.
virtual bool emitTargetFunctions(GlobalDecl GD); virtual bool emitTargetFunctions(GlobalDecl GD);
/// \brief Emit the global variable if it is a valid device global variable. /// \brief Emit the global variable if it is a valid device global variable.

View File

@ -26,12 +26,10 @@
#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/FunctionInfo.h"
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h" #include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h" #include "llvm/Linker/Linker.h"
#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h" #include "llvm/Support/SourceMgr.h"
@ -781,43 +779,11 @@ void CodeGenAction::ExecuteAction() {
TheModule->setTargetTriple(TargetOpts.Triple); 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(); LLVMContext &Ctx = TheModule->getContext();
Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler); Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler);
EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts, EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts,
CI.getLangOpts(), CI.getTarget().getDataLayoutString(), CI.getLangOpts(), CI.getTarget().getDataLayoutString(),
TheModule.get(), BA, OS, std::move(Index)); TheModule.get(), BA, OS);
return; return;
} }

View File

@ -79,7 +79,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
if (CGM.getCodeGenOpts().ReciprocalMath) { if (CGM.getCodeGenOpts().ReciprocalMath) {
FMF.setAllowReciprocal(); FMF.setAllowReciprocal();
} }
Builder.SetFastMathFlags(FMF); Builder.setFastMathFlags(FMF);
} }
CodeGenFunction::~CodeGenFunction() { CodeGenFunction::~CodeGenFunction() {
@ -195,6 +195,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
case Type::FunctionNoProto: case Type::FunctionNoProto:
case Type::Enum: case Type::Enum:
case Type::ObjCObjectPointer: case Type::ObjCObjectPointer:
case Type::Pipe:
return TEK_Scalar; return TEK_Scalar;
// Complexes. // Complexes.
@ -511,7 +512,8 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
typeQuals += typeQuals.empty() ? "volatile" : " volatile"; typeQuals += typeQuals.empty() ? "volatile" : " volatile";
} else { } else {
uint32_t AddrSpc = 0; uint32_t AddrSpc = 0;
if (ty->isImageType()) bool isPipe = ty->isPipeType();
if (ty->isImageType() || isPipe)
AddrSpc = AddrSpc =
CGM.getContext().getTargetAddressSpace(LangAS::opencl_global); 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))); llvm::ConstantAsMetadata::get(Builder.getInt32(AddrSpc)));
// Get argument type name. // 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" // Turn "unsigned type" to "utype"
std::string::size_type pos = typeName.find("unsigned"); 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)); 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); ty.getUnqualifiedType().getCanonicalType().getAsString(Policy);
// Turn "unsigned type" to "utype" // Turn "unsigned type" to "utype"
@ -543,12 +554,16 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
typeQuals = "const"; typeQuals = "const";
if (ty.isVolatileQualified()) if (ty.isVolatileQualified())
typeQuals += typeQuals.empty() ? "volatile" : " volatile"; typeQuals += typeQuals.empty() ? "volatile" : " volatile";
if (isPipe)
typeQuals = "pipe";
} }
argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals)); argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals));
// Get image access qualifier: // Get image and pipe access qualifier:
if (ty->isImageType()) { // 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>(); const OpenCLImageAccessAttr *A = parm->getAttr<OpenCLImageAccessAttr>();
if (A && A->isWriteOnly()) if (A && A->isWriteOnly())
accessQuals.push_back(llvm::MDString::get(Context, "write_only")); accessQuals.push_back(llvm::MDString::get(Context, "write_only"));
@ -1727,6 +1742,10 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::Atomic: case Type::Atomic:
type = cast<AtomicType>(ty)->getValueType(); type = cast<AtomicType>(ty)->getValueType();
break; break;
case Type::Pipe:
type = cast<PipeType>(ty)->getElementType();
break;
} }
} while (type->isVariablyModifiedType()); } while (type->isVariablyModifiedType());
} }

View File

@ -615,7 +615,20 @@ void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const {
} }
StringRef CodeGenModule::getMangledName(GlobalDecl GD) { 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()) if (!FoundStr.empty())
return FoundStr; return FoundStr;

View File

@ -699,7 +699,7 @@ CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name,
setFuncName(Name, Linkage); setFuncName(Name, Linkage);
CGM.getCoverageMapping()->addFunctionMappingRecord( CGM.getCoverageMapping()->addFunctionMappingRecord(
FuncNameVar, FuncName, FunctionHash, CoverageMapping); FuncNameVar, FuncName, FunctionHash, CoverageMapping, false);
} }
void CodeGenPGO::computeRegionCounts(const Decl *D) { void CodeGenPGO::computeRegionCounts(const Decl *D) {

View File

@ -628,6 +628,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
} }
break; break;
} }
case Type::Pipe: {
ResultType = CGM.getOpenCLRuntime().getPipeType();
break;
}
} }
assert(ResultType && "Didn't convert a type?"); assert(ResultType && "Didn't convert a type?");

View File

@ -910,11 +910,11 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
} }
void CoverageMappingModuleGen::addFunctionMappingRecord( void CoverageMappingModuleGen::addFunctionMappingRecord(
llvm::GlobalVariable *NamePtr, StringRef NameValue, llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
uint64_t FuncHash, const std::string &CoverageMapping) { const std::string &CoverageMapping, bool isUsed) {
llvm::LLVMContext &Ctx = CGM.getLLVMContext(); llvm::LLVMContext &Ctx = CGM.getLLVMContext();
if (!FunctionRecordTy) { if (!FunctionRecordTy) {
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
llvm::Type *FunctionRecordTypes[] = { llvm::Type *FunctionRecordTypes[] = {
#include "llvm/ProfileData/InstrProfData.inc" #include "llvm/ProfileData/InstrProfData.inc"
}; };
@ -929,6 +929,9 @@ void CoverageMappingModuleGen::addFunctionMappingRecord(
}; };
FunctionRecords.push_back(llvm::ConstantStruct::get( FunctionRecords.push_back(llvm::ConstantStruct::get(
FunctionRecordTy, makeArrayRef(FunctionRecordVals))); FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
if (!isUsed)
FunctionNames.push_back(
llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
CoverageMappings += CoverageMapping; CoverageMappings += CoverageMapping;
if (CGM.getCodeGenOpts().DumpCoverageMapping) { if (CGM.getCodeGenOpts().DumpCoverageMapping) {
@ -1023,6 +1026,17 @@ void CoverageMappingModuleGen::emit() {
// Make sure the data doesn't get deleted. // Make sure the data doesn't get deleted.
CGM.addUsedGlobal(CovData); 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) { unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {

View File

@ -54,6 +54,7 @@ class CoverageMappingModuleGen {
CoverageSourceInfo &SourceInfo; CoverageSourceInfo &SourceInfo;
llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries; llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries;
std::vector<llvm::Constant *> FunctionRecords; std::vector<llvm::Constant *> FunctionRecords;
std::vector<llvm::Constant *> FunctionNames;
llvm::StructType *FunctionRecordTy; llvm::StructType *FunctionRecordTy;
std::string CoverageMappings; std::string CoverageMappings;
@ -70,7 +71,8 @@ class CoverageMappingModuleGen {
void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName, void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,
StringRef FunctionNameValue, StringRef FunctionNameValue,
uint64_t FunctionHash, uint64_t FunctionHash,
const std::string &CoverageMapping); const std::string &CoverageMapping,
bool isUsed = true);
/// \brief Emit the coverage mapping data for a translation unit. /// \brief Emit the coverage mapping data for a translation unit.
void emit(); void emit();

View File

@ -2715,6 +2715,9 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
case Type::Auto: case Type::Auto:
llvm_unreachable("Undeduced auto type shouldn't get here"); llvm_unreachable("Undeduced auto type shouldn't get here");
case Type::Pipe:
llvm_unreachable("Pipe types shouldn't get here");
case Type::Builtin: case Type::Builtin:
// GCC treats vector and complex types as fundamental types. // GCC treats vector and complex types as fundamental types.
case Type::Vector: case Type::Vector:
@ -2939,6 +2942,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
case Type::Auto: case Type::Auto:
llvm_unreachable("Undeduced auto type shouldn't get here"); 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::ConstantArray:
case Type::IncompleteArray: case Type::IncompleteArray:
case Type::VariableArray: case Type::VariableArray:

View File

@ -59,8 +59,10 @@ class PCHContainerGenerator : public ASTConsumer {
struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> { struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> {
clang::CodeGen::CGDebugInfo &DI; clang::CodeGen::CGDebugInfo &DI;
ASTContext &Ctx; ASTContext &Ctx;
DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx) bool SkipTagDecls;
: DI(DI), Ctx(Ctx) {} DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx,
bool SkipTagDecls)
: DI(DI), Ctx(Ctx), SkipTagDecls(SkipTagDecls) {}
/// Determine whether this type can be represented in DWARF. /// Determine whether this type can be represented in DWARF.
static bool CanRepresent(const Type *Ty) { static bool CanRepresent(const Type *Ty) {
@ -75,6 +77,12 @@ class PCHContainerGenerator : public ASTConsumer {
} }
bool VisitTypeDecl(TypeDecl *D) { 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); QualType QualTy = Ctx.getTypeDeclType(D);
if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
DI.getOrCreateStandaloneType(QualTy, D->getLocation()); DI.getOrCreateStandaloneType(QualTy, D->getLocation());
@ -165,7 +173,7 @@ class PCHContainerGenerator : public ASTConsumer {
// Collect debug info for all decls in this group. // Collect debug info for all decls in this group.
for (auto *I : D) for (auto *I : D)
if (!I->isFromASTFile()) { if (!I->isFromASTFile()) {
DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx, true);
DTV.TraverseDecl(I); DTV.TraverseDecl(I);
} }
return true; return true;
@ -179,6 +187,11 @@ class PCHContainerGenerator : public ASTConsumer {
if (Diags.hasErrorOccurred()) if (Diags.hasErrorOccurred())
return; return;
if (D->isFromASTFile())
return;
DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx, false);
DTV.TraverseDecl(D);
Builder->UpdateCompletedType(D); Builder->UpdateCompletedType(D);
} }

View File

@ -8,17 +8,14 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "clang/Driver/Action.h" #include "clang/Driver/Action.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Regex.h"
#include <cassert> #include <cassert>
using namespace clang::driver; using namespace clang::driver;
using namespace llvm::opt; using namespace llvm::opt;
Action::~Action() { Action::~Action() {}
if (OwnsInputs) {
for (iterator it = begin(), ie = end(); it != ie; ++it)
delete *it;
}
}
const char *Action::getClassName(ActionClass AC) { const char *Action::getClassName(ActionClass AC) {
switch (AC) { switch (AC) {
@ -51,33 +48,53 @@ InputAction::InputAction(const Arg &_Input, types::ID _Type)
void BindArchAction::anchor() {} void BindArchAction::anchor() {}
BindArchAction::BindArchAction(std::unique_ptr<Action> Input, BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
const char *_ArchName) : Action(BindArchClass, Input), ArchName(_ArchName) {}
: Action(BindArchClass, std::move(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() {} void CudaDeviceAction::anchor() {}
CudaDeviceAction::CudaDeviceAction(std::unique_ptr<Action> Input, CudaDeviceAction::CudaDeviceAction(Action *Input, const char *ArchName,
const char *ArchName, bool AtTopLevel) bool AtTopLevel)
: Action(CudaDeviceClass, std::move(Input)), GpuArchName(ArchName), : Action(CudaDeviceClass, Input), GpuArchName(ArchName),
AtTopLevel(AtTopLevel) {} 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() {} void CudaHostAction::anchor() {}
CudaHostAction::CudaHostAction(std::unique_ptr<Action> Input, CudaHostAction::CudaHostAction(Action *Input, const ActionList &DeviceActions)
const ActionList &DeviceActions) : Action(CudaHostClass, Input), DeviceActions(DeviceActions) {}
: Action(CudaHostClass, std::move(Input)), DeviceActions(DeviceActions) {}
CudaHostAction::~CudaHostAction() {
for (auto &DA : DeviceActions)
delete DA;
}
void JobAction::anchor() {} void JobAction::anchor() {}
JobAction::JobAction(ActionClass Kind, std::unique_ptr<Action> Input, JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
types::ID Type) : Action(Kind, Input, Type) {}
: Action(Kind, std::move(Input), Type) {}
JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type) JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
: Action(Kind, Inputs, Type) { : Action(Kind, Inputs, Type) {
@ -85,45 +102,38 @@ JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
void PreprocessJobAction::anchor() {} void PreprocessJobAction::anchor() {}
PreprocessJobAction::PreprocessJobAction(std::unique_ptr<Action> Input, PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
types::ID OutputType) : JobAction(PreprocessJobClass, Input, OutputType) {}
: JobAction(PreprocessJobClass, std::move(Input), OutputType) {}
void PrecompileJobAction::anchor() {} void PrecompileJobAction::anchor() {}
PrecompileJobAction::PrecompileJobAction(std::unique_ptr<Action> Input, PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
types::ID OutputType) : JobAction(PrecompileJobClass, Input, OutputType) {}
: JobAction(PrecompileJobClass, std::move(Input), OutputType) {}
void AnalyzeJobAction::anchor() {} void AnalyzeJobAction::anchor() {}
AnalyzeJobAction::AnalyzeJobAction(std::unique_ptr<Action> Input, AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
types::ID OutputType) : JobAction(AnalyzeJobClass, Input, OutputType) {}
: JobAction(AnalyzeJobClass, std::move(Input), OutputType) {}
void MigrateJobAction::anchor() {} void MigrateJobAction::anchor() {}
MigrateJobAction::MigrateJobAction(std::unique_ptr<Action> Input, MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
types::ID OutputType) : JobAction(MigrateJobClass, Input, OutputType) {}
: JobAction(MigrateJobClass, std::move(Input), OutputType) {}
void CompileJobAction::anchor() {} void CompileJobAction::anchor() {}
CompileJobAction::CompileJobAction(std::unique_ptr<Action> Input, CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
types::ID OutputType) : JobAction(CompileJobClass, Input, OutputType) {}
: JobAction(CompileJobClass, std::move(Input), OutputType) {}
void BackendJobAction::anchor() {} void BackendJobAction::anchor() {}
BackendJobAction::BackendJobAction(std::unique_ptr<Action> Input, BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
types::ID OutputType) : JobAction(BackendJobClass, Input, OutputType) {}
: JobAction(BackendJobClass, std::move(Input), OutputType) {}
void AssembleJobAction::anchor() {} void AssembleJobAction::anchor() {}
AssembleJobAction::AssembleJobAction(std::unique_ptr<Action> Input, AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
types::ID OutputType) : JobAction(AssembleJobClass, Input, OutputType) {}
: JobAction(AssembleJobClass, std::move(Input), OutputType) {}
void LinkJobAction::anchor() {} void LinkJobAction::anchor() {}
@ -145,21 +155,20 @@ DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
void VerifyJobAction::anchor() {} void VerifyJobAction::anchor() {}
VerifyJobAction::VerifyJobAction(ActionClass Kind, VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
std::unique_ptr<Action> Input, types::ID Type) types::ID Type)
: JobAction(Kind, std::move(Input), Type) { : JobAction(Kind, Input, Type) {
assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) && assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
"ActionClass is not a valid VerifyJobAction"); "ActionClass is not a valid VerifyJobAction");
} }
void VerifyDebugInfoJobAction::anchor() {} void VerifyDebugInfoJobAction::anchor() {}
VerifyDebugInfoJobAction::VerifyDebugInfoJobAction( VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
std::unique_ptr<Action> Input, types::ID Type) types::ID Type)
: VerifyJobAction(VerifyDebugInfoJobClass, std::move(Input), Type) {} : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
void VerifyPCHJobAction::anchor() {} void VerifyPCHJobAction::anchor() {}
VerifyPCHJobAction::VerifyPCHJobAction(std::unique_ptr<Action> Input, VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
types::ID Type) : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
: VerifyJobAction(VerifyPCHJobClass, std::move(Input), Type) {}

View File

@ -40,11 +40,6 @@ Compilation::~Compilation() {
if (it->second != TranslatedArgs) if (it->second != TranslatedArgs)
delete it->second; 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. // Free redirections of stdout/stderr.
if (Redirects) { if (Redirects) {
delete Redirects[1]; delete Redirects[1];
@ -208,7 +203,8 @@ void Compilation::initCompilationForDiagnostics() {
ForDiagnostics = true; ForDiagnostics = true;
// Free actions and jobs. // Free actions and jobs.
DeleteContainerPointers(Actions); Actions.clear();
AllActions.clear();
Jobs.clear(); Jobs.clear();
// Clear temporary/results file lists. // Clear temporary/results file lists.

View File

@ -1049,19 +1049,15 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
<< types::getTypeName(Act->getType()); << types::getTypeName(Act->getType());
ActionList Inputs; ActionList Inputs;
for (unsigned i = 0, e = Archs.size(); i != e; ++i) { for (unsigned i = 0, e = Archs.size(); i != e; ++i)
Inputs.push_back( Inputs.push_back(C.MakeAction<BindArchAction>(Act, Archs[i]));
new BindArchAction(std::unique_ptr<Action>(Act), Archs[i]));
if (i != 0)
Inputs.back()->setOwnsInputs(false);
}
// Lipo if necessary, we do it this way because we need to set the arch flag // Lipo if necessary, we do it this way because we need to set the arch flag
// so that -Xarch_ gets overwritten. // so that -Xarch_ gets overwritten.
if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing) if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)
Actions.append(Inputs.begin(), Inputs.end()); Actions.append(Inputs.begin(), Inputs.end());
else else
Actions.push_back(new LipoJobAction(Inputs, Act->getType())); Actions.push_back(C.MakeAction<LipoJobAction>(Inputs, Act->getType()));
// Handle debug info queries. // Handle debug info queries.
Arg *A = Args.getLastArg(options::OPT_g_Group); Arg *A = Args.getLastArg(options::OPT_g_Group);
@ -1077,15 +1073,16 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
ActionList Inputs; ActionList Inputs;
Inputs.push_back(Actions.back()); Inputs.push_back(Actions.back());
Actions.pop_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. // Verify the debug info output.
if (Args.hasArg(options::OPT_verify_debug_info)) { if (Args.hasArg(options::OPT_verify_debug_info)) {
std::unique_ptr<Action> VerifyInput(Actions.back()); Action* LastAction = Actions.back();
Actions.pop_back(); Actions.pop_back();
Actions.push_back(new VerifyDebugInfoJobAction(std::move(VerifyInput), Actions.push_back(C.MakeAction<VerifyDebugInfoJobAction>(
types::TY_Nothing)); 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 // Actions and /p Current is released. Otherwise the function creates
// and returns a new CudaHostAction which wraps /p Current and device // and returns a new CudaHostAction which wraps /p Current and device
// side actions. // side actions.
static std::unique_ptr<Action> static Action *buildCudaActions(Compilation &C, DerivedArgList &Args,
buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg, const Arg *InputArg, Action *HostAction,
std::unique_ptr<Action> HostAction, ActionList &Actions) { ActionList &Actions) {
Arg *PartialCompilationArg = Args.getLastArg(options::OPT_cuda_host_only, Arg *PartialCompilationArg = Args.getLastArg(options::OPT_cuda_host_only,
options::OPT_cuda_device_only); options::OPT_cuda_device_only);
// Host-only compilation case. // Host-only compilation case.
if (PartialCompilationArg && if (PartialCompilationArg &&
PartialCompilationArg->getOption().matches(options::OPT_cuda_host_only)) PartialCompilationArg->getOption().matches(options::OPT_cuda_host_only))
return std::unique_ptr<Action>( return C.MakeAction<CudaHostAction>(HostAction, ActionList());
new CudaHostAction(std::move(HostAction), {}));
// Collect all cuda_gpu_arch parameters, removing duplicates. // Collect all cuda_gpu_arch parameters, removing duplicates.
SmallVector<const char *, 4> GpuArchList; SmallVector<const char *, 4> GpuArchList;
llvm::StringSet<> GpuArchNames; llvm::StringSet<> GpuArchNames;
for (Arg *A : Args) { for (Arg *A : Args) {
if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) { if (!A->getOption().matches(options::OPT_cuda_gpu_arch_EQ))
continue;
A->claim(); A->claim();
if (GpuArchNames.insert(A->getValue()).second)
GpuArchList.push_back(A->getValue()); 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. // 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"); "Failed to create actions for all devices");
// Check whether any of device actions stopped before they could generate PTX. // Check whether any of device actions stopped before they could generate PTX.
bool PartialCompilation = false; bool PartialCompilation =
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { llvm::any_of(CudaDeviceActions, [](const Action *a) {
if (CudaDeviceActions[I]->getKind() != Action::BackendJobClass) { return a->getKind() != Action::BackendJobClass;
PartialCompilation = true; });
break;
}
}
// Figure out what to do with device actions -- pass them as inputs to the // Figure out what to do with device actions -- pass them as inputs to the
// host action or run each of them independently. // 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) for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
Actions.push_back(new CudaDeviceAction( Actions.push_back(C.MakeAction<CudaDeviceAction>(CudaDeviceActions[I],
std::unique_ptr<Action>(CudaDeviceActions[I]), GpuArchList[I], GpuArchList[I],
/* AtTopLevel */ true)); /* AtTopLevel */ true));
// Kill host action in case of device-only compilation. // Kill host action in case of device-only compilation.
if (DeviceOnlyCompilation) if (DeviceOnlyCompilation)
HostAction.reset(nullptr); return nullptr;
return HostAction; return HostAction;
} }
@ -1363,13 +1360,12 @@ buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg,
// with AtTopLevel=false and become inputs for the host action. // with AtTopLevel=false and become inputs for the host action.
ActionList DeviceActions; ActionList DeviceActions;
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
DeviceActions.push_back(new CudaDeviceAction( DeviceActions.push_back(
std::unique_ptr<Action>(CudaDeviceActions[I]), GpuArchList[I], C.MakeAction<CudaDeviceAction>(CudaDeviceActions[I], GpuArchList[I],
/* AtTopLevel */ false)); /* AtTopLevel */ false));
// Return a new host action that incorporates original host action and all // Return a new host action that incorporates original host action and all
// device actions. // device actions.
return std::unique_ptr<Action>( return C.MakeAction<CudaHostAction>(HostAction, DeviceActions);
new CudaHostAction(std::move(HostAction), DeviceActions));
} }
void Driver::BuildActions(Compilation &C, const ToolChain &TC, void Driver::BuildActions(Compilation &C, const ToolChain &TC,
@ -1470,15 +1466,14 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
continue; continue;
} }
phases::ID CudaInjectionPhase = FinalPhase; phases::ID CudaInjectionPhase =
for (const auto &Phase : PL) (phases::Compile < FinalPhase &&
if (Phase <= FinalPhase && Phase == phases::Compile) { llvm::find(PL, phases::Compile) != PL.end())
CudaInjectionPhase = Phase; ? phases::Compile
break; : FinalPhase;
}
// Build the pipeline for this file. // 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(); for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end();
i != e; ++i) { i != e; ++i) {
phases::ID Phase = *i; phases::ID Phase = *i;
@ -1490,7 +1485,8 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
// Queue linker inputs. // Queue linker inputs.
if (Phase == phases::Link) { if (Phase == phases::Link) {
assert((i + 1) == e && "linking must be final compilation step."); assert((i + 1) == e && "linking must be final compilation step.");
LinkerInputs.push_back(Current.release()); LinkerInputs.push_back(Current);
Current = nullptr;
break; break;
} }
@ -1501,11 +1497,10 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
continue; continue;
// Otherwise construct the appropriate action. // 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) { if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase) {
Current = Current = buildCudaActions(C, Args, InputArg, Current, Actions);
buildCudaActions(C, Args, InputArg, std::move(Current), Actions);
if (!Current) if (!Current)
break; break;
} }
@ -1516,12 +1511,13 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
// If we ended with something, add to the output list. // If we ended with something, add to the output list.
if (Current) if (Current)
Actions.push_back(Current.release()); Actions.push_back(Current);
} }
// Add a link action if necessary. // Add a link action if necessary.
if (!LinkerInputs.empty()) 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 // If we are linking, claim any options which are obviously only used for
// compilation. // compilation.
@ -1538,10 +1534,9 @@ void Driver::BuildActions(Compilation &C, const ToolChain &TC,
Args.ClaimAllArgs(options::OPT_cuda_host_only); Args.ClaimAllArgs(options::OPT_cuda_host_only);
} }
std::unique_ptr<Action> Action *Driver::ConstructPhaseAction(Compilation &C, const ToolChain &TC,
Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args, const ArgList &Args, phases::ID Phase,
phases::ID Phase, Action *Input) const {
std::unique_ptr<Action> Input) const {
llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
// Build the appropriate action. // Build the appropriate action.
switch (Phase) { switch (Phase) {
@ -1561,7 +1556,7 @@ Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
assert(OutputTy != types::TY_INVALID && assert(OutputTy != types::TY_INVALID &&
"Cannot preprocess this input type!"); "Cannot preprocess this input type!");
} }
return llvm::make_unique<PreprocessJobAction>(std::move(Input), OutputTy); return C.MakeAction<PreprocessJobAction>(Input, OutputTy);
} }
case phases::Precompile: { case phases::Precompile: {
types::ID OutputTy = types::TY_PCH; 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 // Syntax checks should not emit a PCH file
OutputTy = types::TY_Nothing; OutputTy = types::TY_Nothing;
} }
return llvm::make_unique<PrecompileJobAction>(std::move(Input), OutputTy); return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
} }
case phases::Compile: { case phases::Compile: {
if (Args.hasArg(options::OPT_fsyntax_only)) if (Args.hasArg(options::OPT_fsyntax_only))
return llvm::make_unique<CompileJobAction>(std::move(Input), return C.MakeAction<CompileJobAction>(Input, types::TY_Nothing);
types::TY_Nothing);
if (Args.hasArg(options::OPT_rewrite_objc)) if (Args.hasArg(options::OPT_rewrite_objc))
return llvm::make_unique<CompileJobAction>(std::move(Input), return C.MakeAction<CompileJobAction>(Input, types::TY_RewrittenObjC);
types::TY_RewrittenObjC);
if (Args.hasArg(options::OPT_rewrite_legacy_objc)) if (Args.hasArg(options::OPT_rewrite_legacy_objc))
return llvm::make_unique<CompileJobAction>(std::move(Input), return C.MakeAction<CompileJobAction>(Input,
types::TY_RewrittenLegacyObjC); types::TY_RewrittenLegacyObjC);
if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto))
return llvm::make_unique<AnalyzeJobAction>(std::move(Input), return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist);
types::TY_Plist);
if (Args.hasArg(options::OPT__migrate)) if (Args.hasArg(options::OPT__migrate))
return llvm::make_unique<MigrateJobAction>(std::move(Input), return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap);
types::TY_Remap);
if (Args.hasArg(options::OPT_emit_ast)) if (Args.hasArg(options::OPT_emit_ast))
return llvm::make_unique<CompileJobAction>(std::move(Input), return C.MakeAction<CompileJobAction>(Input, types::TY_AST);
types::TY_AST);
if (Args.hasArg(options::OPT_module_file_info)) if (Args.hasArg(options::OPT_module_file_info))
return llvm::make_unique<CompileJobAction>(std::move(Input), return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);
types::TY_ModuleFile);
if (Args.hasArg(options::OPT_verify_pch)) if (Args.hasArg(options::OPT_verify_pch))
return llvm::make_unique<VerifyPCHJobAction>(std::move(Input), return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
types::TY_Nothing); return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
return llvm::make_unique<CompileJobAction>(std::move(Input),
types::TY_LLVM_BC);
} }
case phases::Backend: { case phases::Backend: {
if (isUsingLTO()) { if (isUsingLTO()) {
types::ID Output = types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; 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)) { if (Args.hasArg(options::OPT_emit_llvm)) {
types::ID Output = types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC; 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), return C.MakeAction<BackendJobAction>(Input, types::TY_PP_Asm);
types::TY_PP_Asm);
} }
case phases::Assemble: case phases::Assemble:
return llvm::make_unique<AssembleJobAction>(std::move(Input), return C.MakeAction<AssembleJobAction>(Input, types::TY_Object);
types::TY_Object);
} }
llvm_unreachable("invalid phase in ConstructPhaseAction"); llvm_unreachable("invalid phase in ConstructPhaseAction");
@ -1662,12 +1647,11 @@ void Driver::BuildJobs(Compilation &C) const {
LinkingOutput = getDefaultImageName(); LinkingOutput = getDefaultImageName();
} }
InputInfo II;
BuildJobsForAction(C, A, &C.getDefaultToolChain(), BuildJobsForAction(C, A, &C.getDefaultToolChain(),
/*BoundArch*/ nullptr, /*BoundArch*/ nullptr,
/*AtTopLevel*/ true, /*AtTopLevel*/ true,
/*MultipleArchs*/ ArchNames.size() > 1, /*MultipleArchs*/ ArchNames.size() > 1,
/*LinkingOutput*/ LinkingOutput, II); /*LinkingOutput*/ LinkingOutput);
} }
// If the user passed -Qunused-arguments or there were errors, don't warn // 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; return ToolForJob;
} }
void Driver::BuildJobsForAction(Compilation &C, const Action *A, InputInfo Driver::BuildJobsForAction(Compilation &C, const Action *A,
const ToolChain *TC, const char *BoundArch, const ToolChain *TC, const char *BoundArch,
bool AtTopLevel, bool MultipleArchs, bool AtTopLevel, bool MultipleArchs,
const char *LinkingOutput, const char *LinkingOutput) const {
InputInfo &Result) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
InputInfoList CudaDeviceInputInfos; InputInfoList CudaDeviceInputInfos;
if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) { if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {
InputInfo II;
// Append outputs of device jobs to the input list. // Append outputs of device jobs to the input list.
for (const Action *DA : CHA->getDeviceActions()) { for (const Action *DA : CHA->getDeviceActions()) {
CudaDeviceInputInfos.push_back(
BuildJobsForAction(C, DA, TC, nullptr, AtTopLevel, BuildJobsForAction(C, DA, TC, nullptr, AtTopLevel,
/*MultipleArchs*/ false, LinkingOutput, II); /*MultipleArchs*/ false, LinkingOutput));
CudaDeviceInputInfos.push_back(II);
} }
// Override current action with a real host compile action and continue // Override current action with a real host compile action and continue
// processing it. // processing it.
@ -1823,11 +1805,9 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
Input.claim(); Input.claim();
if (Input.getOption().matches(options::OPT_INPUT)) { if (Input.getOption().matches(options::OPT_INPUT)) {
const char *Name = Input.getValue(); const char *Name = Input.getValue();
Result = InputInfo(Name, A->getType(), Name); return InputInfo(A, Name, /* BaseInput = */ Name);
} else {
Result = InputInfo(&Input, A->getType(), "");
} }
return; return InputInfo(A, &Input, /* BaseInput = */ "");
} }
if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) { if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
@ -1841,19 +1821,17 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
else else
TC = &C.getDefaultToolChain(); TC = &C.getDefaultToolChain();
BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel, return BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel,
MultipleArchs, LinkingOutput, Result); MultipleArchs, LinkingOutput);
return;
} }
if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) { if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {
// Initial processing of CudaDeviceAction carries host params. // Initial processing of CudaDeviceAction carries host params.
// Call BuildJobsForAction() again, now with correct device parameters. // Call BuildJobsForAction() again, now with correct device parameters.
assert(CDA->getGpuArchName() && "No GPU name in device action."); assert(CDA->getGpuArchName() && "No GPU name in device action.");
BuildJobsForAction(C, *CDA->begin(), C.getCudaDeviceToolChain(), return BuildJobsForAction(C, *CDA->begin(), C.getCudaDeviceToolChain(),
CDA->getGpuArchName(), CDA->isAtTopLevel(), CDA->getGpuArchName(), CDA->isAtTopLevel(),
/*MultipleArchs*/ true, LinkingOutput, Result); /*MultipleArchs*/ true, LinkingOutput);
return;
} }
const ActionList *Inputs = &A->getInputs(); const ActionList *Inputs = &A->getInputs();
@ -1863,16 +1841,15 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
const Tool *T = const Tool *T =
selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA); selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA);
if (!T) if (!T)
return; return InputInfo();
// If we've collapsed action list that contained CudaHostAction we // If we've collapsed action list that contained CudaHostAction we
// need to build jobs for device-side inputs it may have held. // need to build jobs for device-side inputs it may have held.
if (CollapsedCHA) { if (CollapsedCHA) {
InputInfo II;
for (const Action *DA : CollapsedCHA->getDeviceActions()) { for (const Action *DA : CollapsedCHA->getDeviceActions()) {
CudaDeviceInputInfos.push_back(
BuildJobsForAction(C, DA, TC, "", AtTopLevel, BuildJobsForAction(C, DA, TC, "", AtTopLevel,
/*MultipleArchs*/ false, LinkingOutput, II); /*MultipleArchs*/ false, LinkingOutput));
CudaDeviceInputInfos.push_back(II);
} }
} }
@ -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 // Treat dsymutil and verify sub-jobs as being at the top-level too, they
// shouldn't get temporary output names. // shouldn't get temporary output names.
// FIXME: Clean this up. // FIXME: Clean this up.
bool SubJobAtTopLevel = false; bool SubJobAtTopLevel =
if (AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A))) AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A));
SubJobAtTopLevel = true; InputInfos.push_back(BuildJobsForAction(C, Input, TC, BoundArch,
SubJobAtTopLevel, MultipleArchs,
InputInfo II; LinkingOutput));
BuildJobsForAction(C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
LinkingOutput, II);
InputInfos.push_back(II);
} }
// Always use the first input as the base input. // 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()); InputInfos.append(CudaDeviceInputInfos.begin(), CudaDeviceInputInfos.end());
// Determine the place to write output to, if any. // Determine the place to write output to, if any.
InputInfo Result;
if (JA->getType() == types::TY_Nothing) if (JA->getType() == types::TY_Nothing)
Result = InputInfo(A->getType(), BaseInput); Result = InputInfo(A, BaseInput);
else else
Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, BoundArch, Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
AtTopLevel, MultipleArchs), AtTopLevel, MultipleArchs),
A->getType(), BaseInput); BaseInput);
if (CCCPrintBindings && !CCGenDiagnostics) { if (CCCPrintBindings && !CCGenDiagnostics) {
llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"' llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"'
@ -1925,6 +1900,7 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
T->ConstructJob(C, *JA, Result, InputInfos, T->ConstructJob(C, *JA, Result, InputInfos,
C.getArgsForToolChain(TC, BoundArch), LinkingOutput); C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
} }
return Result;
} }
const char *Driver::getDefaultImageName() const { const char *Driver::getDefaultImageName() const {

View File

@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_LIB_DRIVER_INPUTINFO_H #ifndef LLVM_CLANG_LIB_DRIVER_INPUTINFO_H
#define LLVM_CLANG_LIB_DRIVER_INPUTINFO_H #define LLVM_CLANG_LIB_DRIVER_INPUTINFO_H
#include "clang/Driver/Action.h"
#include "clang/Driver/Types.h" #include "clang/Driver/Types.h"
#include "llvm/Option/Arg.h" #include "llvm/Option/Arg.h"
#include <cassert> #include <cassert>
@ -38,21 +39,36 @@ class InputInfo {
const llvm::opt::Arg *InputArg; const llvm::opt::Arg *InputArg;
} Data; } Data;
Class Kind; Class Kind;
const Action* Act;
types::ID Type; types::ID Type;
const char *BaseInput; const char *BaseInput;
public: static types::ID GetActionType(const Action *A) {
InputInfo() {} return A != nullptr ? A->getType() : types::TY_Nothing;
InputInfo(types::ID _Type, const char *_BaseInput)
: Kind(Nothing), Type(_Type), BaseInput(_BaseInput) {
} }
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; 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) 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; Data.InputArg = _InputArg;
} }
@ -61,6 +77,9 @@ class InputInfo {
bool isInputArg() const { return Kind == InputArg; } bool isInputArg() const { return Kind == InputArg; }
types::ID getType() const { return Type; } types::ID getType() const { return Type; }
const char *getBaseInput() const { return BaseInput; } 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 { const char *getFilename() const {
assert(isFilename() && "Invalid accessor."); assert(isFilename() && "Invalid accessor.");

View File

@ -634,6 +634,96 @@ SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
return Res; 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 * llvm::opt::DerivedArgList *
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
const char *BoundArch) const { const char *BoundArch) const {
@ -664,81 +754,18 @@ MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
} }
} }
for (Arg *A : Args) {
if (A->getOption().matches(options::OPT__SLASH_O)) {
// The -O flag actually takes an amalgam of other options. For example, // The -O flag actually takes an amalgam of other options. For example,
// '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'. // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
for (Arg *A : Args) { TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
if (!A->getOption().matches(options::OPT__SLASH_O)) { } else if (A->getOption().matches(options::OPT_D)) {
// Translate -Dfoo#bar into -Dfoo=bar.
TranslateDArg(A, *DAL, Opts);
} else {
DAL->append(A); 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; return DAL;
} }

View File

@ -66,17 +66,23 @@ MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) { : ToolChain(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir()); getProgramPaths().push_back(getDriver().getInstalledDir());
// On Windows if there is no sysroot we search for gcc on the PATH. // 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()) if (getDriver().SysRoot.size())
Base = getDriver().SysRoot; Base = getDriver().SysRoot;
#ifdef LLVM_ON_WIN32
else if (llvm::ErrorOr<std::string> GPPName = else if (llvm::ErrorOr<std::string> GPPName =
llvm::sys::findProgramByName("gcc")) llvm::sys::findProgramByName("gcc"))
Base = llvm::sys::path::parent_path( Base = llvm::sys::path::parent_path(
llvm::sys::path::parent_path(GPPName.get())); llvm::sys::path::parent_path(GPPName.get()));
#endif else
if (!Base.size())
Base = llvm::sys::path::parent_path(getDriver().getInstalledDir()); 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(); Base += llvm::sys::path::get_separator();
findGccLibDir(); findGccLibDir();

View File

@ -526,7 +526,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
// no environment variable defined, see if we can set the default based // no environment variable defined, see if we can set the default based
// on -isysroot. // on -isysroot.
if (OSXTarget.empty() && iOSTarget.empty() && WatchOSTarget.empty() && 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)) { if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef isysroot = A->getValue(); StringRef isysroot = A->getValue();
// Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk // 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) { const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
Arg *CpuArg = nullptr; Arg *CpuArg = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ, options::OPT_march_EQ))
for (auto &A : Args) {
if (A->getOption().matches(options::OPT_mcpu_EQ)) {
CpuArg = A; CpuArg = A;
A->claim();
}
}
StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU(); StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
if (CPU.startswith("hexagon")) if (CPU.startswith("hexagon"))

View File

@ -730,9 +730,6 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
// Until dtrace (via CTF) and LLDB can deal with distributed debug info, // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
// FreeBSD defaults to standalone/full debug info. // FreeBSD defaults to standalone/full debug info.
bool GetDefaultStandaloneDebug() const override { return true; } bool GetDefaultStandaloneDebug() const override { return true; }
llvm::DebuggerKind getDefaultDebuggerTuning() const override {
return llvm::DebuggerKind::LLDB;
}
protected: protected:
Tool *buildAssembler() const override; Tool *buildAssembler() const override;

View File

@ -2069,6 +2069,16 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
CmdArgs.push_back("-machine-sink-split=0"); 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+... // Decode AArch64 features from string like +[no]featureA+[no]featureB+...
static bool DecodeAArch64Features(const Driver &D, StringRef text, static bool DecodeAArch64Features(const Driver &D, StringRef text,
std::vector<const char *> &Features) { std::vector<const char *> &Features) {
@ -2970,7 +2980,7 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
ExtractArgs.push_back(OutFile); ExtractArgs.push_back(OutFile);
const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy")); 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. // First extract the dwo sections.
C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs, II)); 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? // ToolChain.getTriple() and Triple?
bool PIE = ToolChain.isPIEDefault(); bool PIE = ToolChain.isPIEDefault();
bool PIC = PIE || ToolChain.isPICDefault(); bool PIC = PIE || ToolChain.isPICDefault();
// The Darwin default to use PIC does not apply when using -static. // The Darwin/MachO default to use PIC does not apply when using -static.
if (ToolChain.getTriple().isOSDarwin() && Args.hasArg(options::OPT_static)) if (ToolChain.getTriple().isOSBinFormatMachO() &&
Args.hasArg(options::OPT_static))
PIE = PIC = false; PIE = PIC = false;
bool IsPICLevelTwo = PIC; bool IsPICLevelTwo = PIC;
@ -4015,6 +4026,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::hexagon: case llvm::Triple::hexagon:
AddHexagonTargetArgs(Args, CmdArgs); AddHexagonTargetArgs(Args, CmdArgs);
break; break;
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
AddWebAssemblyTargetArgs(Args, CmdArgs);
break;
} }
// The 'g' groups options involve a somewhat intricate sequence of decisions // 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"); CmdArgs.push_back("-generate-type-units");
} }
// CloudABI uses -ffunction-sections and -fdata-sections by default. // CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by
bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI; // 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, if (Args.hasFlag(options::OPT_ffunction_sections,
options::OPT_fno_function_sections, UseSeparateSections)) { 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 // doesn't handle that so rather than warning about unused flags that are
// actually used, we'll lie by omission instead. // actually used, we'll lie by omission instead.
// FIXME: Stop lying and consume only the appropriate driver flags // FIXME: Stop lying and consume only the appropriate driver flags
for (const Arg *A : Args.filtered(options::OPT_W_Group)) Args.ClaimAllArgs(options::OPT_W_Group);
A->claim();
CollectArgsForIntegratedAssembler(C, Args, CmdArgs, CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
getToolChain().getDriver()); getToolChain().getDriver());
@ -6078,6 +6096,12 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &A : Args) { for (const auto &A : Args) {
if (forwardToGCC(A->getOption())) { 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. // Don't forward any -g arguments to assembly steps.
if (isa<AssembleJobAction>(JA) && if (isa<AssembleJobAction>(JA) &&
A->getOption().matches(options::OPT_g_Group)) 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)) A->getOption().matches(options::OPT_W_Group))
continue; 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); A->render(Args, CmdArgs);
} }
} }
@ -6502,10 +6521,6 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
std::string Linker = getToolChain().GetProgramPath(getShortName()); std::string Linker = getToolChain().GetProgramPath(getShortName());
ArgStringList CmdArgs; 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); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
CmdArgs.push_back("-o"); CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename()); CmdArgs.push_back(Output.getFilename());
@ -6534,6 +6549,14 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs; ArgStringList CmdArgs;
CmdArgs.push_back("-flavor"); CmdArgs.push_back("-flavor");
CmdArgs.push_back("ld"); 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); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
CmdArgs.push_back("-o"); CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename()); CmdArgs.push_back(Output.getFilename());
@ -8965,7 +8988,7 @@ void nacltools::AssemblerARM::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const { const char *LinkingOutput) const {
const toolchains::NaClToolChain &ToolChain = const toolchains::NaClToolChain &ToolChain =
static_cast<const toolchains::NaClToolChain &>(getToolChain()); 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"); "nacl-arm-macros.s");
InputInfoList NewInputs; InputInfoList NewInputs;
NewInputs.push_back(NaClMacros); NewInputs.push_back(NaClMacros);

View File

@ -82,6 +82,8 @@ class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
llvm::opt::ArgStringList &CmdArgs) const; llvm::opt::ArgStringList &CmdArgs) const;
void AddHexagonTargetArgs(const llvm::opt::ArgList &Args, void AddHexagonTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const; 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 }; enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile };
@ -238,7 +240,7 @@ namespace amdgpu {
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool { class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public: 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 isLinkJob() const override { return true; }
bool hasIntegratedCPP() const override { return false; } bool hasIntegratedCPP() const override { return false; }
void ConstructJob(Compilation &C, const JobAction &JA, void ConstructJob(Compilation &C, const JobAction &JA,

View File

@ -1077,6 +1077,9 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
case CK_BuiltinFnToFnPtr: case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent: case CK_ZeroToOCLEvent:
return false; return false;
case CK_BooleanToSignedIntegral:
llvm_unreachable("OpenCL-specific cast in Objective-C?");
} }
} }

View File

@ -150,7 +150,12 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection) if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection)
return true; return true;
if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || 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) && (Style.BreakBeforeTernaryOperators && Current.is(TT_ConditionalExpr) &&
Previous.isNot(tok::question)) || Previous.isNot(tok::question)) ||
(!Style.BreakBeforeTernaryOperators && (!Style.BreakBeforeTernaryOperators &&
@ -177,13 +182,15 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
return true; return true;
unsigned NewLineColumn = getNewLineColumn(State); 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) if (State.Column <= NewLineColumn)
return false; return false;
if (Current.isMemberAccess() &&
State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit)
return true;
if (Style.AlwaysBreakBeforeMultilineStrings && if (Style.AlwaysBreakBeforeMultilineStrings &&
(NewLineColumn == State.FirstIndent + Style.ContinuationIndentWidth || (NewLineColumn == State.FirstIndent + Style.ContinuationIndentWidth ||
Previous.is(tok::comma) || Current.NestingLevel < 2) && 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().LastSpace = State.Column;
State.Stack.back().NestedBlockIndent = State.Column; State.Stack.back().NestedBlockIndent = State.Column;
} else if (!Current.isOneOf(tok::comment, tok::caret) && } 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)))) { (Previous.is(tok::colon) && Previous.is(TT_ObjCMethodExpr)))) {
State.Stack.back().LastSpace = State.Column; State.Stack.back().LastSpace = State.Column;
} else if ((Previous.isOneOf(TT_BinaryOperator, TT_ConditionalExpr, } else if ((Previous.isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
@ -860,7 +868,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
(!SkipFirstExtraIndent && *I > prec::Assignment && (!SkipFirstExtraIndent && *I > prec::Assignment &&
!Current.isTrailingComment())) !Current.isTrailingComment()))
NewParenState.Indent += Style.ContinuationIndentWidth; NewParenState.Indent += Style.ContinuationIndentWidth;
if ((Previous && !Previous->opensScope()) || *I > prec::Comma) if ((Previous && !Previous->opensScope()) || *I != prec::Comma)
NewParenState.BreakBeforeParameter = false; NewParenState.BreakBeforeParameter = false;
State.Stack.push_back(NewParenState); State.Stack.push_back(NewParenState);
SkipFirstExtraIndent = false; SkipFirstExtraIndent = false;
@ -906,8 +914,12 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth; NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth;
} }
const FormatToken *NextNoComment = Current.getNextNonComment(); const FormatToken *NextNoComment = Current.getNextNonComment();
bool EndsInComma = Current.MatchingParen &&
Current.MatchingParen->Previous &&
Current.MatchingParen->Previous->is(tok::comma);
AvoidBinPacking = AvoidBinPacking =
Current.isOneOf(TT_ArrayInitializerLSquare, TT_DictLiteral) || (Current.is(TT_ArrayInitializerLSquare) && EndsInComma) ||
Current.is(TT_DictLiteral) ||
Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments || Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments ||
(NextNoComment && NextNoComment->is(TT_DesignatedInitializerPeriod)); (NextNoComment && NextNoComment->is(TT_DesignatedInitializerPeriod));
if (Current.ParameterCount > 1) if (Current.ParameterCount > 1)

View File

@ -583,6 +583,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.BreakBeforeTernaryOperators = false; GoogleStyle.BreakBeforeTernaryOperators = false;
GoogleStyle.CommentPragmas = "@(export|visibility) {";
GoogleStyle.MaxEmptyLinesToKeep = 3; GoogleStyle.MaxEmptyLinesToKeep = 3;
GoogleStyle.SpacesInContainerLiterals = false; GoogleStyle.SpacesInContainerLiterals = false;
} else if (Language == FormatStyle::LK_Proto) { } else if (Language == FormatStyle::LK_Proto) {
@ -1238,6 +1239,8 @@ class FormatTokenLexer {
FormatTok->Type = TT_ImplicitStringLiteral; FormatTok->Type = TT_ImplicitStringLiteral;
break; break;
} }
if (FormatTok->Type == TT_ImplicitStringLiteral)
break;
} }
if (FormatTok->is(TT_ImplicitStringLiteral)) if (FormatTok->is(TT_ImplicitStringLiteral))
@ -1901,8 +1904,9 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
new DiagnosticOptions); new DiagnosticOptions);
SourceManager SourceMgr(Diagnostics, Files); SourceManager SourceMgr(Diagnostics, Files);
InMemoryFileSystem->addFile(FileName, 0, InMemoryFileSystem->addFile(
llvm::MemoryBuffer::getMemBuffer(Code, FileName)); FileName, 0, llvm::MemoryBuffer::getMemBuffer(
Code, FileName, /*RequiresNullTerminator=*/false));
FileID ID = SourceMgr.createFileID(Files.getFile(FileName), SourceLocation(), FileID ID = SourceMgr.createFileID(Files.getFile(FileName), SourceLocation(),
clang::SrcMgr::C_User); clang::SrcMgr::C_User);
SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID); SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID);

View File

@ -119,7 +119,9 @@ class AnnotatingParser {
} }
} }
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, (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
tok::kw_if, tok::kw_while, tok::l_paren, tok::kw_if, tok::kw_while, tok::l_paren,
tok::comma) || tok::comma) ||
@ -132,9 +134,7 @@ class AnnotatingParser {
// This is a parameter list of a lambda expression. // This is a parameter list of a lambda expression.
Contexts.back().IsExpression = false; Contexts.back().IsExpression = false;
} else if (Line.InPPDirective && } else if (Line.InPPDirective &&
(!Left->Previous || (!Left->Previous || !Left->Previous->is(tok::identifier))) {
!Left->Previous->isOneOf(tok::identifier,
TT_OverloadedOperator))) {
Contexts.back().IsExpression = true; Contexts.back().IsExpression = true;
} else if (Contexts[Contexts.size() - 2].CaretFound) { } else if (Contexts[Contexts.size() - 2].CaretFound) {
// This is the parameter list of an ObjC block. // This is the parameter list of an ObjC block.
@ -199,6 +199,18 @@ class AnnotatingParser {
Left->MatchingParen = CurrentToken; Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left; 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) { if (StartsObjCMethodExpr) {
CurrentToken->Type = TT_ObjCMethodExpr; CurrentToken->Type = TT_ObjCMethodExpr;
if (Contexts.back().FirstObjCSelectorName) { if (Contexts.back().FirstObjCSelectorName) {
@ -568,7 +580,8 @@ class AnnotatingParser {
if (CurrentToken->isOneOf(tok::star, tok::amp)) if (CurrentToken->isOneOf(tok::star, tok::amp))
CurrentToken->Type = TT_PointerOrReference; CurrentToken->Type = TT_PointerOrReference;
consumeToken(); consumeToken();
if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator)) if (CurrentToken &&
CurrentToken->Previous->isOneOf(TT_BinaryOperator, tok::comma))
CurrentToken->Previous->Type = TT_OverloadedOperator; CurrentToken->Previous->Type = TT_OverloadedOperator;
} }
if (CurrentToken) { if (CurrentToken) {
@ -1713,7 +1726,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma)) if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma))
return 100; return 100;
if (Left.is(TT_JsTypeColon)) if (Left.is(TT_JsTypeColon))
return 100; return 35;
} }
if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next && 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) || if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||
Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow)) Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
return true; return true;
if (Right.is(TT_OverloadedOperatorLParen))
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
if (Left.is(tok::comma)) if (Left.is(tok::comma))
return true; return true;
if (Right.is(tok::comma)) if (Right.is(tok::comma))
return false; return false;
if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen)) if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen))
return true; return true;
if (Right.is(TT_OverloadedOperatorLParen))
return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
if (Right.is(tok::colon)) { if (Right.is(tok::colon)) {
if (Line.First->isOneOf(tok::kw_case, tok::kw_default) || if (Line.First->isOneOf(tok::kw_case, tok::kw_default) ||
!Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi)) !Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi))

View File

@ -315,6 +315,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
// definitions, too. // definitions, too.
unsigned StoredPosition = Tokens->getPosition(); unsigned StoredPosition = Tokens->getPosition();
FormatToken *Tok = FormatTok; FormatToken *Tok = FormatTok;
const FormatToken *PrevTok = getPreviousToken();
// Keep a stack of positions of lbrace tokens. We will // Keep a stack of positions of lbrace tokens. We will
// update information about whether an lbrace starts a // update information about whether an lbrace starts a
// braced init list or a different block during the loop. // braced init list or a different block during the loop.
@ -331,11 +332,18 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
switch (Tok->Tok.getKind()) { switch (Tok->Tok.getKind()) {
case tok::l_brace: case tok::l_brace:
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; Tok->BlockKind = BK_Unknown;
LBraceStack.push_back(Tok); LBraceStack.push_back(Tok);
break; break;
case tok::r_brace: case tok::r_brace:
if (!LBraceStack.empty()) { if (LBraceStack.empty())
break;
if (LBraceStack.back()->BlockKind == BK_Unknown) { if (LBraceStack.back()->BlockKind == BK_Unknown) {
bool ProbablyBracedList = false; bool ProbablyBracedList = false;
if (Style.Language == FormatStyle::LK_Proto) { if (Style.Language == FormatStyle::LK_Proto) {
@ -371,7 +379,6 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
} }
} }
LBraceStack.pop_back(); LBraceStack.pop_back();
}
break; break;
case tok::at: case tok::at:
case tok::semi: case tok::semi:
@ -381,14 +388,16 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
case tok::kw_switch: case tok::kw_switch:
case tok::kw_try: case tok::kw_try:
case tok::kw___try: case tok::kw___try:
if (!LBraceStack.empty()) if (!LBraceStack.empty() && LBraceStack.back()->BlockKind == BK_Unknown)
LBraceStack.back()->BlockKind = BK_Block; LBraceStack.back()->BlockKind = BK_Block;
break; break;
default: default:
break; break;
} }
PrevTok = Tok;
Tok = NextTok; Tok = NextTok;
} while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty()); } while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty());
// Assume other blocks for all unclosed opening braces. // Assume other blocks for all unclosed opening braces.
for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) { for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) {
if (LBraceStack[i]->BlockKind == BK_Unknown) if (LBraceStack[i]->BlockKind == BK_Unknown)
@ -841,6 +850,8 @@ void UnwrappedLineParser::parseStructuralElement() {
// This does not apply for Java and JavaScript. // This does not apply for Java and JavaScript.
if (Style.Language == FormatStyle::LK_Java || if (Style.Language == FormatStyle::LK_Java ||
Style.Language == FormatStyle::LK_JavaScript) { Style.Language == FormatStyle::LK_JavaScript) {
if (FormatTok->is(tok::semi))
nextToken();
addUnwrappedLine(); addUnwrappedLine();
return; return;
} }
@ -986,13 +997,11 @@ bool UnwrappedLineParser::tryToParseLambda() {
nextToken(); nextToken();
return false; return false;
} }
// FIXME: This is a dirty way to access the previous token. Find a better const FormatToken* Previous = getPreviousToken();
// solution. if (Previous &&
if (!Line->Tokens.empty() && (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
(Line->Tokens.back().Tok->isOneOf(tok::identifier, tok::kw_operator, tok::kw_delete) ||
tok::kw_new, tok::kw_delete) || Previous->closesScope() || Previous->isSimpleTypeSpecifier())) {
Line->Tokens.back().Tok->closesScope() ||
Line->Tokens.back().Tok->isSimpleTypeSpecifier())) {
nextToken(); nextToken();
return false; return false;
} }
@ -1174,6 +1183,14 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
nextToken(); nextToken();
return !HasError; return !HasError;
case tok::semi: 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; HasError = true;
if (!ContinueOnSemicolons) if (!ContinueOnSemicolons)
return !HasError; return !HasError;
@ -1792,19 +1809,23 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
return; 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, 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. return; // Fall through to parsing the corresponding structure.
while (!eof() && FormatTok->isNot(tok::semi)) {
if (FormatTok->is(tok::l_brace)) { if (FormatTok->is(tok::l_brace)) {
FormatTok->BlockKind = BK_Block; FormatTok->BlockKind = BK_Block;
parseBracedList(); parseBracedList();
} } else {
while (!eof() && FormatTok->isNot(tok::semi) &&
FormatTok->isNot(tok::l_brace)) {
nextToken(); nextToken();
} }
}
} }
LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line, LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
@ -1877,6 +1898,14 @@ void UnwrappedLineParser::nextToken() {
readToken(); 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() { void UnwrappedLineParser::readToken() {
bool CommentsInCurrentLine = true; bool CommentsInCurrentLine = true;
do { do {

View File

@ -110,6 +110,7 @@ class UnwrappedLineParser {
void addUnwrappedLine(); void addUnwrappedLine();
bool eof() const; bool eof() const;
void nextToken(); void nextToken();
const FormatToken *getPreviousToken();
void readToken(); void readToken();
void flushComments(bool NewlineBeforeNext); void flushComments(bool NewlineBeforeNext);
void pushToken(FormatToken *Tok); void pushToken(FormatToken *Tok);

View File

@ -30,7 +30,7 @@ WhitespaceManager::Change::Change(
unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn, unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix, unsigned NewlinesBefore, StringRef PreviousLinePostfix,
StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective, StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective,
bool IsStartOfDeclName) bool IsStartOfDeclName, bool IsInsideToken)
: CreateReplacement(CreateReplacement), : CreateReplacement(CreateReplacement),
OriginalWhitespaceRange(OriginalWhitespaceRange), OriginalWhitespaceRange(OriginalWhitespaceRange),
StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore), StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
@ -38,8 +38,8 @@ WhitespaceManager::Change::Change(
CurrentLinePrefix(CurrentLinePrefix), Kind(Kind), CurrentLinePrefix(CurrentLinePrefix), Kind(Kind),
ContinuesPPDirective(ContinuesPPDirective), ContinuesPPDirective(ContinuesPPDirective),
IsStartOfDeclName(IsStartOfDeclName), IndentLevel(IndentLevel), IsStartOfDeclName(IsStartOfDeclName), IndentLevel(IndentLevel),
Spaces(Spaces), IsTrailingComment(false), TokenLength(0), Spaces(Spaces), IsInsideToken(IsInsideToken), IsTrailingComment(false),
PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0), TokenLength(0), PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
StartOfBlockComment(nullptr), IndentationOffset(0) {} StartOfBlockComment(nullptr), IndentationOffset(0) {}
void WhitespaceManager::reset() { void WhitespaceManager::reset() {
@ -55,20 +55,23 @@ void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
return; return;
Tok.Decision = (Newlines > 0) ? FD_Break : FD_Continue; Tok.Decision = (Newlines > 0) ? FD_Break : FD_Continue;
Changes.push_back( Changes.push_back(
Change(true, Tok.WhitespaceRange, IndentLevel, Spaces, StartOfTokenColumn, Change(/*CreateReplacement=*/true, Tok.WhitespaceRange, IndentLevel,
Newlines, "", "", Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst, Spaces, StartOfTokenColumn, Newlines, "", "", Tok.Tok.getKind(),
Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName))); InPPDirective && !Tok.IsFirst,
Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
/*IsInsideToken=*/false));
} }
void WhitespaceManager::addUntouchableToken(const FormatToken &Tok, void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
bool InPPDirective) { bool InPPDirective) {
if (Tok.Finalized) if (Tok.Finalized)
return; return;
Changes.push_back( Changes.push_back(Change(
Change(false, Tok.WhitespaceRange, /*IndentLevel=*/0, /*CreateReplacement=*/false, Tok.WhitespaceRange, /*IndentLevel=*/0,
/*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "", /*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "",
Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst, Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst,
Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName))); Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
/*IsInsideToken=*/false));
} }
void WhitespaceManager::replaceWhitespaceInToken( void WhitespaceManager::replaceWhitespaceInToken(
@ -81,15 +84,10 @@ void WhitespaceManager::replaceWhitespaceInToken(
Changes.push_back(Change( Changes.push_back(Change(
true, SourceRange(Start, Start.getLocWithOffset(ReplaceChars)), true, SourceRange(Start, Start.getLocWithOffset(ReplaceChars)),
IndentLevel, Spaces, std::max(0, Spaces), Newlines, PreviousPostfix, IndentLevel, Spaces, std::max(0, Spaces), Newlines, PreviousPostfix,
CurrentPrefix, CurrentPrefix, Tok.is(TT_LineComment) ? tok::comment : tok::unknown,
// 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,
InPPDirective && !Tok.IsFirst, 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() { const tooling::Replacements &WhitespaceManager::generateReplacements() {
@ -109,6 +107,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
void WhitespaceManager::calculateLineBreakInformation() { void WhitespaceManager::calculateLineBreakInformation() {
Changes[0].PreviousEndOfTokenColumn = 0; Changes[0].PreviousEndOfTokenColumn = 0;
Change *LastOutsideTokenChange = &Changes[0];
for (unsigned i = 1, e = Changes.size(); i != e; ++i) { for (unsigned i = 1, e = Changes.size(); i != e; ++i) {
unsigned OriginalWhitespaceStart = unsigned OriginalWhitespaceStart =
SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin()); SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin());
@ -119,11 +118,20 @@ void WhitespaceManager::calculateLineBreakInformation() {
Changes[i].PreviousLinePostfix.size() + Changes[i].PreviousLinePostfix.size() +
Changes[i - 1].CurrentLinePrefix.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].PreviousEndOfTokenColumn =
Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength; Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength;
Changes[i - 1].IsTrailingComment = 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; Changes[i - 1].Kind == tok::comment;
} }
// FIXME: The last token is currently not always an eof token; in those // 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; const WhitespaceManager::Change *LastBlockComment = nullptr;
for (auto &Change : Changes) { 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.StartOfBlockComment = nullptr;
Change.IndentationOffset = 0; Change.IndentationOffset = 0;
if (Change.Kind == tok::comment) { if (Change.Kind == tok::comment) {
@ -342,6 +354,12 @@ void WhitespaceManager::alignTrailingComments() {
unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn; unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
unsigned ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength; 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) if (i + 1 != e && Changes[i + 1].ContinuesPPDirective)
ChangeMaxColumn -= 2; ChangeMaxColumn -= 2;
// If this comment follows an } in column 0, it probably documents the // If this comment follows an } in column 0, it probably documents the

View File

@ -109,7 +109,8 @@ class WhitespaceManager {
unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn, unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix, unsigned NewlinesBefore, StringRef PreviousLinePostfix,
StringRef CurrentLinePrefix, tok::TokenKind Kind, StringRef CurrentLinePrefix, tok::TokenKind Kind,
bool ContinuesPPDirective, bool IsStartOfDeclName); bool ContinuesPPDirective, bool IsStartOfDeclName,
bool IsInsideToken);
bool CreateReplacement; bool CreateReplacement;
// Changes might be in the middle of a token, so we cannot just keep the // Changes might be in the middle of a token, so we cannot just keep the
@ -139,6 +140,10 @@ class WhitespaceManager {
// comments. Uncompensated negative offset is truncated to 0. // comments. Uncompensated negative offset is truncated to 0.
int Spaces; 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 IsTrailingComment, \c TokenLength, \c PreviousEndOfTokenColumn and
// \c EscapedNewlineColumn will be calculated in // \c EscapedNewlineColumn will be calculated in
// \c calculateLineBreakInformation. // \c calculateLineBreakInformation.

View File

@ -1,4 +1,4 @@
//===--- //===--- CompilerInvocation.cpp -------------------------------------------===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -2202,8 +2202,11 @@ std::string CompilerInvocation::getModuleHash() const {
code = hash_combine(code, I->first, I->second); code = hash_combine(code, I->first, I->second);
} }
// Extend the signature with the sysroot. // Extend the signature with the sysroot and other header search options.
code = hash_combine(code, hsOpts.Sysroot, hsOpts.UseBuiltinIncludes, code = hash_combine(code, hsOpts.Sysroot,
hsOpts.ModuleFormat,
hsOpts.UseDebugInfo,
hsOpts.UseBuiltinIncludes,
hsOpts.UseStandardSystemIncludes, hsOpts.UseStandardSystemIncludes,
hsOpts.UseStandardCXXIncludes, hsOpts.UseStandardCXXIncludes,
hsOpts.UseLibcxx); hsOpts.UseLibcxx);

View File

@ -187,7 +187,8 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
return std::error_code(); return std::error_code();
// Add includes for each of these headers. // Add includes for each of these headers.
for (Module::Header &H : Module->Headers[Module::HK_Normal]) { for (auto HK : {Module::HK_Normal, Module::HK_Private}) {
for (Module::Header &H : Module->Headers[HK]) {
Module->addTopHeader(H.Entry); Module->addTopHeader(H.Entry);
// Use the path as specified in the module map file. We'll look for this // 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 // file relative to the module build directory (the directory containing
@ -197,6 +198,7 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
LangOpts, Module->IsExternC)) LangOpts, Module->IsExternC))
return Err; return Err;
} }
}
// Note that Module->PrivateHeaders will not be a TopHeader. // Note that Module->PrivateHeaders will not be a TopHeader.
if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) { if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) {

View File

@ -119,6 +119,7 @@ class MultiplexASTMutationListener : public ASTMutationListener {
const FunctionDecl *Delete) override; const FunctionDecl *Delete) override;
void CompletedImplicitDefinition(const FunctionDecl *D) override; void CompletedImplicitDefinition(const FunctionDecl *D) override;
void StaticDataMemberInstantiated(const VarDecl *D) override; void StaticDataMemberInstantiated(const VarDecl *D) override;
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) override; const ObjCInterfaceDecl *IFD) override;
void FunctionDefinitionInstantiated(const FunctionDecl *D) 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) for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->StaticDataMemberInstantiated(D); 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( void MultiplexASTMutationListener::AddedObjCCategoryToInterface(
const ObjCCategoryDecl *CatD, const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) { const ObjCInterfaceDecl *IFD) {

View File

@ -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); 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 */ /* vec_vcfsx */
static vector float __attribute__((__always_inline__)) static vector float __attribute__((__always_inline__))
@ -1907,11 +1923,18 @@ vec_vcfux(vector unsigned int __a, int __b) {
/* vec_cts */ /* vec_cts */
static vector int __attribute__((__always_inline__)) static vector int __ATTRS_o_ai vec_cts(vector float __a, int __b) {
vec_cts(vector float __a, int __b) {
return __builtin_altivec_vctsxs(__a, __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 */ /* vec_vctsxs */
static vector int __attribute__((__always_inline__)) static vector int __attribute__((__always_inline__))
@ -1921,11 +1944,18 @@ vec_vctsxs(vector float __a, int __b) {
/* vec_ctu */ /* vec_ctu */
static vector unsigned int __attribute__((__always_inline__)) static vector unsigned int __ATTRS_o_ai vec_ctu(vector float __a, int __b) {
vec_ctu(vector float __a, int __b) {
return __builtin_altivec_vctuxs(__a, __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 */ /* vec_vctuxs */
static vector unsigned int __attribute__((__always_inline__)) static vector unsigned int __attribute__((__always_inline__))

View File

@ -153,8 +153,7 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
auto FileName = llvm::sys::path::filename(ModuleMapPath); auto FileName = llvm::sys::path::filename(ModuleMapPath);
llvm::hash_code Hash = llvm::hash_code Hash =
llvm::hash_combine(DirName.lower(), FileName.lower(), llvm::hash_combine(DirName.lower(), FileName.lower());
HSOpts->ModuleFormat, HSOpts->UseDebugInfo);
SmallString<128> HashStr; SmallString<128> HashStr;
llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36); 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