Vendor import of clang trunk r242221:

https://llvm.org/svn/llvm-project/cfe/trunk@242221
This commit is contained in:
Dimitry Andric 2015-08-07 23:02:44 +00:00
parent c192b3dcff
commit 51ece4aae5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=286427
svn path=/vendor/clang/clang-trunk-r242221/; revision=286428; tag=vendor/clang/clang-trunk-r242221
440 changed files with 17513 additions and 3077 deletions

View File

@ -275,6 +275,9 @@ the configuration (without a prefix: ``Auto``).
* ``BS_Linux`` (in configuration: ``Linux``)
Like ``Attach``, but break before braces on function, namespace and
class definitions.
* ``BS_Mozilla`` (in configuration: ``Mozilla``)
Like ``Attach``, but break before braces on enum, function, and record
definitions.
* ``BS_Stroustrup`` (in configuration: ``Stroustrup``)
Like ``Attach``, but break before function definitions, and 'else'.
* ``BS_Allman`` (in configuration: ``Allman``)
@ -394,6 +397,12 @@ the configuration (without a prefix: ``Auto``).
(https://developers.google.com/protocol-buffers/).
**MacroBlockBegin** (``std::string``)
A regular expression matching macros that start a block.
**MacroBlockEnd** (``std::string``)
A regular expression matching macros that end a block.
**MaxEmptyLinesToKeep** (``unsigned``)
The maximum number of consecutive empty lines to keep.

View File

@ -92,7 +92,7 @@ will be assumed, which sets the defaults for the specified architecture.
The system name is generally the OS (linux, darwin), but could be special
like the bare-metal "none".
When a parameter is not important, they can be omitted, or you can
When a parameter is not important, it can be omitted, or you can
choose ``unknown`` and the defaults will be used. If you choose a parameter
that Clang doesn't know, like ``blerg``, it'll ignore and assume
``unknown``, which is not always desired, so be careful.

View File

@ -1991,10 +1991,10 @@ compile time. Partial unrolling replicates the loop body within the loop and
reduces the trip count.
If ``unroll(full)`` is specified the unroller will attempt to fully unroll the
loop if the trip count is known at compile time. If the loop count is not known
or the fully unrolled code size is greater than the limit specified by the
`-pragma-unroll-threshold` command line option the loop will be partially
unrolled subject to the same limit.
loop if the trip count is known at compile time. If the fully unrolled code size
is greater than an internal limit the loop will be partially unrolled up to this
limit. If the loop count is not known at compile time the loop will not be
unrolled.
.. code-block:: c++
@ -2006,7 +2006,7 @@ unrolled subject to the same limit.
The unroll count can be specified explicitly with ``unroll_count(_value_)`` where
_value_ is a positive integer. If this value is greater than the trip count the
loop will be fully unrolled. Otherwise the loop is partially unrolled subject
to the `-pragma-unroll-threshold` limit.
to the same code size limit as with ``unroll(full)``.
.. code-block:: c++

View File

@ -124,20 +124,30 @@ section <pchinternals-chained>`.
AST File Contents
-----------------
Clang's AST files are organized into several different blocks, each of which
contains the serialized representation of a part of Clang's internal
An AST file produced by clang is an object file container with a ``clangast``
(COFF) or ``__clangast`` (ELF and Mach-O) section containing the serialized AST.
Other target-specific sections in the object file container are used to hold
debug information for the data types defined in the AST. Tools built on top of
libclang that do not need debug information may also produce raw AST files that
only contain the serialized AST.
The ``clangast`` section is organized into several different blocks, each of
which contains the serialized representation of a part of Clang's internal
representation. Each of the blocks corresponds to either a block or a record
within `LLVM's bitstream format <http://llvm.org/docs/BitCodeFormat.html>`_.
The contents of each of these logical blocks are described below.
.. image:: PCHLayout.png
For a given AST file, the `llvm-bcanalyzer
<http://llvm.org/docs/CommandGuide/llvm-bcanalyzer.html>`_ utility can be used
to examine the actual structure of the bitstream for the AST file. This
information can be used both to help understand the structure of the AST file
and to isolate areas where AST files can still be optimized, e.g., through the
introduction of abbreviations.
The ``llvm-objdump`` utility provides a ``-raw-clang-ast`` option to extract the
binary contents of the AST section from an object file container.
The `llvm-bcanalyzer <http://llvm.org/docs/CommandGuide/llvm-bcanalyzer.html>`_
utility can be used to examine the actual structure of the bitstream for the AST
section. This information can be used both to help understand the structure of
the AST section and to isolate areas where the AST representation can still be
optimized, e.g., through the introduction of abbreviations.
Metadata Block
^^^^^^^^^^^^^^

View File

@ -1488,6 +1488,45 @@ instrumentation:
profile. As you make changes to your code, clang may no longer be able to
use the profile data. It will warn you when this happens.
Profile generation and use can also be controlled by the GCC-compatible flags
``-fprofile-generate`` and ``-fprofile-use``. Although these flags are
semantically equivalent to their GCC counterparts, they *do not* handle
GCC-compatible profiles. They are only meant to implement GCC's semantics
with respect to profile creation and use.
.. option:: -fprofile-generate[=<dirname>]
Without any other arguments, ``-fprofile-generate`` behaves identically to
``-fprofile-instr-generate``. When given a directory name, it generates the
profile file ``default.profraw`` in the directory named ``dirname``. If
``dirname`` does not exist, it will be created at runtime. The environment
variable ``LLVM_PROFILE_FILE`` can be used to override the directory and
filename for the profile file at runtime. For example,
.. code-block:: console
$ clang++ -O2 -fprofile-generate=yyy/zzz code.cc -o code
When ``code`` is executed, the profile will be written to the file
``yyy/zzz/default.profraw``. This can be altered at runtime via the
``LLVM_PROFILE_FILE`` environment variable:
.. code-block:: console
$ LLVM_PROFILE_FILE=/tmp/myprofile/code.profraw ./code
The above invocation will produce the profile file
``/tmp/myprofile/code.profraw`` instead of ``yyy/zzz/default.profraw``.
Notice that ``LLVM_PROFILE_FILE`` overrides the directory *and* the file
name for the profile file.
.. option:: -fprofile-use[=<pathname>]
Without any other arguments, ``-fprofile-use`` behaves identically to
``-fprofile-instr-use``. Otherwise, if ``pathname`` is the full path to a
profile file, it reads from that file. If ``pathname`` is a directory name,
it reads from ``pathname/default.profdata``.
Controlling Size of Debug Information
-------------------------------------

View File

@ -73,7 +73,7 @@ clang_VirtualFileOverlay_setCaseSensitivity(CXVirtualFileOverlay,
*
* \param options is reserved, always pass 0.
* \param out_buffer_ptr pointer to receive the buffer pointer, which should be
* disposed using \c free().
* disposed using \c clang_free().
* \param out_buffer_size pointer to receive the buffer size.
* \returns 0 for success, non-zero to indicate an error.
*/
@ -82,6 +82,14 @@ clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay, unsigned options,
char **out_buffer_ptr,
unsigned *out_buffer_size);
/**
* \brief free memory allocated by libclang, such as the buffer returned by
* \c CXVirtualFileOverlay() or \c clang_ModuleMapDescriptor_writeToBuffer().
*
* \param buffer memory pointer to free.
*/
CINDEX_LINKAGE void clang_free(void *buffer);
/**
* \brief Dispose a \c CXVirtualFileOverlay object.
*/
@ -122,7 +130,7 @@ clang_ModuleMapDescriptor_setUmbrellaHeader(CXModuleMapDescriptor,
*
* \param options is reserved, always pass 0.
* \param out_buffer_ptr pointer to receive the buffer pointer, which should be
* disposed using \c free().
* disposed using \c clang_free().
* \param out_buffer_size pointer to receive the buffer size.
* \returns 0 for success, non-zero to indicate an error.
*/

View File

@ -236,6 +236,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType ObjCClassRedefinitionType;
QualType ObjCSelRedefinitionType;
/// The identifier 'NSObject'.
IdentifierInfo *NSObjectName = nullptr;
/// The identifier 'NSCopying'.
IdentifierInfo *NSCopyingName = nullptr;
QualType ObjCConstantStringType;
mutable RecordDecl *CFConstantStringTypeDecl;
@ -1189,9 +1195,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
ObjCInterfaceDecl *PrevDecl = nullptr) const;
/// Legacy interface: cannot provide type arguments or __kindof.
QualType getObjCObjectType(QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) const;
QualType getObjCObjectType(QualType Base,
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf) const;
bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
/// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in
@ -1351,6 +1363,24 @@ class ASTContext : public RefCountedBase<ASTContext> {
ObjCSelRedefinitionType = RedefType;
}
/// Retrieve the identifier 'NSObject'.
IdentifierInfo *getNSObjectName() {
if (!NSObjectName) {
NSObjectName = &Idents.get("NSObject");
}
return NSObjectName;
}
/// Retrieve the identifier 'NSCopying'.
IdentifierInfo *getNSCopyingName() {
if (!NSCopyingName) {
NSCopyingName = &Idents.get("NSCopying");
}
return NSCopyingName;
}
/// \brief Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
QualType getObjCInstanceType() {

View File

@ -940,6 +940,9 @@ DEF_TRAVERSE_TYPE(ObjCObjectType, {
// type is itself.
if (T->getBaseType().getTypePtr() != T)
TRY_TO(TraverseType(T->getBaseType()));
for (auto typeArg : T->getTypeArgsAsWritten()) {
TRY_TO(TraverseType(typeArg));
}
})
DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
@ -1166,6 +1169,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
// type is itself.
if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
})
DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
@ -1307,7 +1312,13 @@ DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
})
if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
for (auto typeParam : *typeParamList) {
TRY_TO(TraverseObjCTypeParamDecl(typeParam));
}
}
return true;
})
DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
})
@ -1316,7 +1327,16 @@ DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
})
if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
for (auto typeParam : *typeParamList) {
TRY_TO(TraverseObjCTypeParamDecl(typeParam));
}
}
if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
}
})
DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
})
@ -1335,6 +1355,15 @@ DEF_TRAVERSE_DECL(ObjCMethodDecl, {
return true;
})
DEF_TRAVERSE_DECL(ObjCTypeParamDecl, {
if (D->hasExplicitBound()) {
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the type alias, not something that was written in the
// source.
}
})
DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
if (D->getTypeSourceInfo())
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));

View File

@ -332,10 +332,14 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
SourceRange getReturnTypeSourceRange() const;
/// \brief Determine the type of an expression that sends a message to this
/// function.
QualType getSendResultType() const {
return getReturnType().getNonLValueExprType(getASTContext());
}
/// function. This replaces the type parameters with the types they would
/// get if the receiver was parameterless (e.g. it may replace the type
/// parameter with 'id').
QualType getSendResultType() const;
/// Determine the type of an expression that sends a message to this
/// function with the given receiver type.
QualType getSendResultType(QualType receiverType) const;
TypeSourceInfo *getReturnTypeSourceInfo() const { return ReturnTInfo; }
void setReturnTypeSourceInfo(TypeSourceInfo *TInfo) { ReturnTInfo = TInfo; }
@ -399,6 +403,11 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
/// have already been created.
void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
/// \return the type for \c self and set \arg selfIsPseudoStrong and
/// \arg selfIsConsumed accordingly.
QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID,
bool &selfIsPseudoStrong, bool &selfIsConsumed);
ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
@ -501,6 +510,183 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
friend class ASTDeclWriter;
};
/// Describes the variance of a given generic parameter.
enum class ObjCTypeParamVariance : uint8_t {
/// The parameter is invariant: must match exactly.
Invariant,
/// The parameter is covariant, e.g., X<T> is a subtype of X<U> when
/// the type parameter is covariant and T is a subtype of U.
Covariant,
/// The parameter is contravariant, e.g., X<T> is a subtype of X<U>
/// when the type parameter is covariant and U is a subtype of T.
Contravariant,
};
/// Represents the declaration of an Objective-C type parameter.
///
/// \code
/// @interface NSDictionary<Key : id<NSCopying>, Value>
/// @end
/// \endcode
///
/// In the example above, both \c Key and \c Value are represented by
/// \c ObjCTypeParamDecl. \c Key has an explicit bound of \c id<NSCopying>,
/// while \c Value gets an implicit bound of \c id.
///
/// Objective-C type parameters are typedef-names in the grammar,
class ObjCTypeParamDecl : public TypedefNameDecl {
void anchor() override;
/// Index of this type parameter in the type parameter list.
unsigned Index : 14;
/// The variance of the type parameter.
unsigned Variance : 2;
/// The location of the variance, if any.
SourceLocation VarianceLoc;
/// The location of the ':', which will be valid when the bound was
/// explicitly specified.
SourceLocation ColonLoc;
ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc,
ObjCTypeParamVariance variance, SourceLocation varianceLoc,
unsigned index,
SourceLocation nameLoc, IdentifierInfo *name,
SourceLocation colonLoc, TypeSourceInfo *boundInfo)
: TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name,
boundInfo),
Index(index), Variance(static_cast<unsigned>(variance)),
VarianceLoc(varianceLoc), ColonLoc(colonLoc) { }
public:
static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc,
ObjCTypeParamVariance variance,
SourceLocation varianceLoc,
unsigned index,
SourceLocation nameLoc,
IdentifierInfo *name,
SourceLocation colonLoc,
TypeSourceInfo *boundInfo);
static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID);
SourceRange getSourceRange() const override LLVM_READONLY;
/// Determine the variance of this type parameter.
ObjCTypeParamVariance getVariance() const {
return static_cast<ObjCTypeParamVariance>(Variance);
}
/// Set the variance of this type parameter.
void setVariance(ObjCTypeParamVariance variance) {
Variance = static_cast<unsigned>(variance);
}
/// Retrieve the location of the variance keyword.
SourceLocation getVarianceLoc() const { return VarianceLoc; }
/// Retrieve the index into its type parameter list.
unsigned getIndex() const { return Index; }
/// Whether this type parameter has an explicitly-written type bound, e.g.,
/// "T : NSView".
bool hasExplicitBound() const { return ColonLoc.isValid(); }
/// Retrieve the location of the ':' separating the type parameter name
/// from the explicitly-specified bound.
SourceLocation getColonLoc() const { return ColonLoc; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCTypeParam; }
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// Stores a list of Objective-C type parameters for a parameterized class
/// or a category/extension thereof.
///
/// \code
/// @interface NSArray<T> // stores the <T>
/// @end
/// \endcode
class ObjCTypeParamList {
/// Stores the components of a SourceRange as a POD.
struct PODSourceRange {
unsigned Begin;
unsigned End;
};
union {
/// Location of the left and right angle brackets.
PODSourceRange Brackets;
// Used only for alignment.
ObjCTypeParamDecl *AlignmentHack;
};
/// The number of parameters in the list, which are tail-allocated.
unsigned NumParams;
ObjCTypeParamList(SourceLocation lAngleLoc,
ArrayRef<ObjCTypeParamDecl *> typeParams,
SourceLocation rAngleLoc);
public:
/// Create a new Objective-C type parameter list.
static ObjCTypeParamList *create(ASTContext &ctx,
SourceLocation lAngleLoc,
ArrayRef<ObjCTypeParamDecl *> typeParams,
SourceLocation rAngleLoc);
/// Iterate through the type parameters in the list.
typedef ObjCTypeParamDecl **iterator;
iterator begin() { return reinterpret_cast<ObjCTypeParamDecl **>(this + 1); }
iterator end() { return begin() + size(); }
/// Determine the number of type parameters in this list.
unsigned size() const { return NumParams; }
// Iterate through the type parameters in the list.
typedef ObjCTypeParamDecl * const *const_iterator;
const_iterator begin() const {
return reinterpret_cast<ObjCTypeParamDecl * const *>(this + 1);
}
const_iterator end() const {
return begin() + size();
}
ObjCTypeParamDecl *front() const {
assert(size() > 0 && "empty Objective-C type parameter list");
return *begin();
}
ObjCTypeParamDecl *back() const {
assert(size() > 0 && "empty Objective-C type parameter list");
return *(end() - 1);
}
SourceLocation getLAngleLoc() const {
return SourceLocation::getFromRawEncoding(Brackets.Begin);
}
SourceLocation getRAngleLoc() const {
return SourceLocation::getFromRawEncoding(Brackets.End);
}
SourceRange getSourceRange() const {
return SourceRange(getLAngleLoc(), getRAngleLoc());
}
/// Gather the default set of type arguments to be substituted for
/// these type parameters when dealing with an unspecialized type.
void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
};
/// ObjCContainerDecl - Represents a container for method declarations.
/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
/// ObjCProtocolDecl, and ObjCImplDecl.
@ -676,9 +862,9 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// declaration.
ObjCInterfaceDecl *Definition;
/// Class's super class.
ObjCInterfaceDecl *SuperClass;
/// When non-null, this is always an ObjCObjectType.
TypeSourceInfo *SuperClassTInfo;
/// Protocols referenced in the \@interface declaration
ObjCProtocolList ReferencedProtocols;
@ -719,16 +905,13 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
};
/// One of the \c InheritedDesignatedInitializersState enumeratos.
mutable unsigned InheritedDesignatedInitializers : 2;
/// \brief The location of the superclass, if any.
SourceLocation SuperClassLoc;
/// \brief The location of the last location in this declaration, before
/// the properties/methods. For example, this will be the '>', '}', or
/// identifier,
SourceLocation EndLoc;
DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(),
DefinitionData() : Definition(), SuperClassTInfo(), CategoryList(), IvarList(),
ExternallyCompleted(),
IvarListMissingImplementation(true),
HasDesignatedInitializers(),
@ -736,11 +919,15 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
};
ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
IdentifierInfo *Id, SourceLocation CLoc,
ObjCInterfaceDecl *PrevDecl, bool IsInternal);
IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
bool IsInternal);
void LoadExternalDefinition() const;
/// The type parameters associated with this class, if any.
ObjCTypeParamList *TypeParamList;
/// \brief Contains a pointer to the data associated with this class,
/// which will be NULL if this class has not yet been defined.
///
@ -771,12 +958,33 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
ObjCTypeParamList *typeParamList,
ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc = SourceLocation(),
bool isInternal = false);
static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
/// Retrieve the type parameters of this class.
///
/// This function looks for a type parameter list for the given
/// class; if the class has been declared (with \c \@class) but not
/// defined (with \c \@interface), it will search for a declaration that
/// has type parameters, skipping any declarations that do not.
ObjCTypeParamList *getTypeParamList() const;
/// Set the type parameters of this class.
///
/// This function is used by the AST importer, which must import the type
/// parameters after creating their DeclContext to avoid loops.
void setTypeParamList(ObjCTypeParamList *TPL);
/// Retrieve the type parameters written on this particular declaration of
/// the class.
ObjCTypeParamList *getTypeParamListAsWritten() const {
return TypeParamList;
}
SourceRange getSourceRange() const override LLVM_READONLY {
if (isThisDeclarationADefinition())
return ObjCContainerDecl::getSourceRange();
@ -1023,7 +1231,16 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// a forward declaration (\@class) to a definition (\@interface).
void startDefinition();
ObjCInterfaceDecl *getSuperClass() const {
/// Retrieve the superclass type.
const ObjCObjectType *getSuperClassType() const {
if (TypeSourceInfo *TInfo = getSuperClassTInfo())
return TInfo->getType()->castAs<ObjCObjectType>();
return nullptr;
}
// Retrieve the type source information for the superclass.
TypeSourceInfo *getSuperClassTInfo() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return nullptr;
@ -1031,13 +1248,15 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
if (data().ExternallyCompleted)
LoadExternalDefinition();
return data().SuperClass;
return data().SuperClassTInfo;
}
void setSuperClass(ObjCInterfaceDecl * superCls) {
data().SuperClass =
(superCls && superCls->hasDefinition()) ? superCls->getDefinition()
: superCls;
// Retrieve the declaration for the superclass of this class, which
// does not include any type arguments that apply to the superclass.
ObjCInterfaceDecl *getSuperClass() const;
void setSuperClass(TypeSourceInfo *superClass) {
data().SuperClassTInfo = superClass;
}
/// \brief Iterator that walks over the list of categories, filtering out
@ -1329,8 +1548,8 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }
void setSuperClassLoc(SourceLocation Loc) { data().SuperClassLoc = Loc; }
SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; }
/// Retrieve the starting location of the superclass.
SourceLocation getSuperClassLoc() const;
/// isImplicitInterfaceDecl - check that this is an implicitly declared
/// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
@ -1438,6 +1657,10 @@ class ObjCIvarDecl : public FieldDecl {
void setSynthesize(bool synth) { Synthesized = synth; }
bool getSynthesize() const { return Synthesized; }
/// Retrieve the type of this instance variable when viewed as a member of a
/// specific object type.
QualType getUsageType(QualType objectType) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCIvar; }
@ -1719,6 +1942,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// Interface belonging to this category
ObjCInterfaceDecl *ClassInterface;
/// The type parameters associated with this category, if any.
ObjCTypeParamList *TypeParamList;
/// referenced protocols in this category.
ObjCProtocolList ReferencedProtocols;
@ -1736,13 +1962,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation())
: ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
ClassInterface(IDecl), NextClassCategory(nullptr),
CategoryNameLoc(CategoryNameLoc),
IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
}
SourceLocation IvarRBraceLoc=SourceLocation());
public:
@ -1752,6 +1974,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
SourceLocation CategoryNameLoc,
IdentifierInfo *Id,
ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation());
static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@ -1759,6 +1982,17 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
/// Retrieve the type parameter list associated with this category or
/// extension.
ObjCTypeParamList *getTypeParamList() const { return TypeParamList; }
/// Set the type parameters of this category.
///
/// This function is used by the AST importer, which must import the type
/// parameters after creating their DeclContext to avoid loops.
void setTypeParamList(ObjCTypeParamList *TPL);
ObjCCategoryImplDecl *getImplementation() const;
void setImplementation(ObjCCategoryImplDecl *ImplD);
@ -2275,6 +2509,10 @@ class ObjCPropertyDecl : public NamedDecl {
DeclTypeSourceInfo = TSI;
}
/// Retrieve the type when this property is used with a specific base object
/// type.
QualType getUsageType(QualType objectType) const;
PropertyAttributeKind getPropertyAttributes() const {
return PropertyAttributeKind(PropertyAttributes);
}

View File

@ -687,40 +687,7 @@ class ObjCPropertyRefExpr : public Expr {
QualType getSuperReceiverType() const {
return QualType(Receiver.get<const Type*>(), 0);
}
QualType getGetterResultType() const {
QualType ResultType;
if (isExplicitProperty()) {
const ObjCPropertyDecl *PDecl = getExplicitProperty();
if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl())
ResultType = Getter->getReturnType();
else
ResultType = PDecl->getType();
} else {
const ObjCMethodDecl *Getter = getImplicitPropertyGetter();
if (Getter)
ResultType = Getter->getReturnType(); // with reference!
}
return ResultType;
}
QualType getSetterArgType() const {
QualType ArgType;
if (isImplicitProperty()) {
const ObjCMethodDecl *Setter = getImplicitPropertySetter();
ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
ArgType = (*P)->getType();
} else {
if (ObjCPropertyDecl *PDecl = getExplicitProperty())
if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) {
ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
ArgType = (*P)->getType();
}
if (ArgType.isNull())
ArgType = getType();
}
return ArgType;
}
ObjCInterfaceDecl *getClassReceiver() const {
return Receiver.get<ObjCInterfaceDecl*>();
}
@ -728,6 +695,9 @@ class ObjCPropertyRefExpr : public Expr {
bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
/// Determine the type of the base, regardless of the kind of receiver.
QualType getReceiverType(const ASTContext &ctx) const;
SourceLocation getLocStart() const LLVM_READONLY {
return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation();
}

View File

@ -1008,6 +1008,9 @@ DEF_TRAVERSE_TYPE(ObjCObjectType, {
// type is itself.
if (T->getBaseType().getTypePtr() != T)
TRY_TO(TraverseType(T->getBaseType()));
for (auto typeArg : T->getTypeArgsAsWritten()) {
TRY_TO(TraverseType(typeArg));
}
})
DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
@ -1234,6 +1237,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
// type is itself.
if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
})
DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
@ -1382,7 +1387,12 @@ DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
})
if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
for (auto typeParam : *typeParamList) {
TRY_TO(TraverseObjCTypeParamDecl(typeParam));
}
}
})
DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
})
@ -1391,7 +1401,16 @@ DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
})
if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
for (auto typeParam : *typeParamList) {
TRY_TO(TraverseObjCTypeParamDecl(typeParam));
}
}
if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
}
})
DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
})
@ -1410,6 +1429,15 @@ DEF_TRAVERSE_DECL(ObjCMethodDecl, {
return true;
})
DEF_TRAVERSE_DECL(ObjCTypeParamDecl, {
if (D->hasExplicitBound()) {
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the type alias, not something that was written in the
// source.
}
})
DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
if (D->getTypeSourceInfo())
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));

View File

@ -533,6 +533,24 @@ struct SplitQualType {
}
};
/// The kind of type we are substituting Objective-C type arguments into.
///
/// The kind of substitution affects the replacement of type parameters when
/// no concrete type information is provided, e.g., when dealing with an
/// unspecialized type.
enum class ObjCSubstitutionContext {
/// An ordinary type.
Ordinary,
/// The result type of a method or function.
Result,
/// The parameter type of a method or function.
Parameter,
/// The type of a property.
Property,
/// The superclass of a type.
Superclass,
};
/// QualType - For efficiency, we don't store CV-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
/// greatly reduces the number of nodes we need to allocate for types (for
@ -994,6 +1012,51 @@ class QualType {
/// type other than void.
bool isCForbiddenLValueType() const;
/// Substitute type arguments for the Objective-C type parameters used in the
/// subject type.
///
/// \param ctx ASTContext in which the type exists.
///
/// \param typeArgs The type arguments that will be substituted for the
/// Objective-C type parameters in the subject type, which are generally
/// computed via \c Type::getObjCSubstitutions. If empty, the type
/// parameters will be replaced with their bounds or id/Class, as appropriate
/// for the context.
///
/// \param context The context in which the subject type was written.
///
/// \returns the resulting type.
QualType substObjCTypeArgs(ASTContext &ctx,
ArrayRef<QualType> typeArgs,
ObjCSubstitutionContext context) const;
/// Substitute type arguments from an object type for the Objective-C type
/// parameters used in the subject type.
///
/// This operation combines the computation of type arguments for
/// substitution (\c Type::getObjCSubstitutions) with the actual process of
/// substitution (\c QualType::substObjCTypeArgs) for the convenience of
/// callers that need to perform a single substitution in isolation.
///
/// \param objectType The type of the object whose member type we're
/// substituting into. For example, this might be the receiver of a message
/// or the base of a property access.
///
/// \param dc The declaration context from which the subject type was
/// retrieved, which indicates (for example) which type parameters should
/// be substituted.
///
/// \param context The context in which the subject type was written.
///
/// \returns the subject type after replacing all of the Objective-C type
/// parameters with their corresponding arguments.
QualType substObjCMemberType(QualType objectType,
const DeclContext *dc,
ObjCSubstitutionContext context) const;
/// Strip Objective-C "__kindof" types from the given type.
QualType stripObjCKindOfType(const ASTContext &ctx) const;
private:
// These methods are implemented in a separate translation unit;
// "static"-ize them to avoid creating temporary QualTypes in the
@ -1288,10 +1351,17 @@ class Type : public ExtQualsTypeCommonBase {
unsigned : NumTypeBits;
/// The number of type arguments stored directly on this object type.
unsigned NumTypeArgs : 7;
/// NumProtocols - The number of protocols stored directly on this
/// object type.
unsigned NumProtocols : 32 - NumTypeBits;
unsigned NumProtocols : 6;
/// Whether this is a "kindof" type.
unsigned IsKindOf : 1;
};
static_assert(NumTypeBits + 7 + 6 + 1 <= 32, "Does not fit in an unsigned");
class ReferenceTypeBitfields {
friend class ReferenceType;
@ -1585,7 +1655,28 @@ class Type : public ExtQualsTypeCommonBase {
bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id
/// Whether the type is Objective-C 'id' or a __kindof type of an
/// object type, e.g., __kindof NSView * or __kindof id
/// <NSCopying>.
///
/// \param bound Will be set to the bound on non-id subtype types,
/// which will be (possibly specialized) Objective-C class type, or
/// null for 'id.
bool isObjCIdOrObjectKindOfType(const ASTContext &ctx,
const ObjCObjectType *&bound) const;
bool isObjCClassType() const; // Class
/// Whether the type is Objective-C 'Class' or a __kindof type of an
/// Class type, e.g., __kindof Class <NSCopying>.
///
/// Unlike \c isObjCIdOrObjectKindOfType, there is no relevant bound
/// here because Objective-C's type system cannot express "a class
/// object for a subclass of NSFoo".
bool isObjCClassOrClassKindOfType() const;
bool isBlockCompatibleObjCPointerType(ASTContext &ctx) const;
bool isObjCSelType() const; // Class
bool isObjCBuiltinType() const; // 'id' or 'Class'
bool isObjCARCBridgableType() const;
@ -1697,6 +1788,7 @@ class Type : public ExtQualsTypeCommonBase {
/// NOTE: getAs*ArrayType are methods on ASTContext.
const RecordType *getAsUnionType() const;
const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
const ObjCObjectType *getAsObjCInterfaceType() const;
// The following is a convenience method that returns an ObjCObjectPointerType
// for object declared using an interface.
const ObjCObjectPointerType *getAsObjCInterfacePointerType() const;
@ -1832,6 +1924,28 @@ class Type : public ExtQualsTypeCommonBase {
/// pointer type.
bool canHaveNullability() const;
/// Retrieve the set of substitutions required when accessing a member
/// of the Objective-C receiver type that is declared in the given context.
///
/// \c *this is the type of the object we're operating on, e.g., the
/// receiver for a message send or the base of a property access, and is
/// expected to be of some object or object pointer type.
///
/// \param dc The declaration context for which we are building up a
/// substitution mapping, which should be an Objective-C class, extension,
/// category, or method within.
///
/// \returns an array of type arguments that can be substituted for
/// the type parameters of the given declaration context in any type described
/// within that context, or an empty optional to indicate that no
/// substitution is required.
Optional<ArrayRef<QualType>>
getObjCSubstitutions(const DeclContext *dc) const;
/// Determines if this is an ObjC interface type that may accept type
/// parameters.
bool acceptsObjCTypeParams() const;
const char *getTypeClassName() const;
QualType getCanonicalTypeInternal() const {
@ -3497,6 +3611,7 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
attr_nonnull,
attr_nullable,
attr_null_unspecified,
attr_objc_kindof,
};
private:
@ -4369,19 +4484,25 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
};
/// ObjCObjectType - Represents a class type in Objective C.
/// Every Objective C type is a combination of a base type and a
/// list of protocols.
///
/// Every Objective C type is a combination of a base type, a set of
/// type arguments (optional, for parameterized classes) and a list of
/// protocols.
///
/// Given the following declarations:
/// \code
/// \@class C;
/// \@class C<T>;
/// \@protocol P;
/// \endcode
///
/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType
/// with base C and no protocols.
///
/// 'C<P>' is an ObjCObjectType with base C and protocol list [P].
/// 'C<P>' is an unspecialized ObjCObjectType with base C and protocol list [P].
/// 'C<C*>' is a specialized ObjCObjectType with type arguments 'C*' and no
/// protocol list.
/// 'C<C*><P>' is a specialized ObjCObjectType with base C, type arguments 'C*',
/// and protocol list [P].
///
/// 'id' is a TypedefType which is sugar for an ObjCObjectPointerType whose
/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType
@ -4391,8 +4512,10 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually
/// this should get its own sugar class to better represent the source.
class ObjCObjectType : public Type {
// ObjCObjectType.NumProtocols - the number of protocols stored
// ObjCObjectType.NumTypeArgs - the number of type arguments stored
// after the ObjCObjectPointerType node.
// ObjCObjectType.NumProtocols - the number of protocols stored
// after the type arguments of ObjCObjectPointerType node.
//
// These protocols are those written directly on the type. If
// protocol qualifiers ever become additive, the iterators will need
@ -4404,23 +4527,38 @@ class ObjCObjectType : public Type {
/// Either a BuiltinType or an InterfaceType or sugar for either.
QualType BaseType;
/// Cached superclass type.
mutable llvm::PointerIntPair<const ObjCObjectType *, 1, bool>
CachedSuperClassType;
ObjCProtocolDecl * const *getProtocolStorage() const {
return const_cast<ObjCObjectType*>(this)->getProtocolStorage();
}
QualType *getTypeArgStorage();
const QualType *getTypeArgStorage() const {
return const_cast<ObjCObjectType *>(this)->getTypeArgStorage();
}
ObjCProtocolDecl **getProtocolStorage();
protected:
ObjCObjectType(QualType Canonical, QualType Base,
ObjCProtocolDecl * const *Protocols, unsigned NumProtocols);
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf);
enum Nonce_ObjCInterface { Nonce_ObjCInterface };
ObjCObjectType(enum Nonce_ObjCInterface)
: Type(ObjCInterface, QualType(), false, false, false, false),
BaseType(QualType(this_(), 0)) {
ObjCObjectTypeBits.NumProtocols = 0;
ObjCObjectTypeBits.NumTypeArgs = 0;
ObjCObjectTypeBits.IsKindOf = 0;
}
void computeSuperClassTypeSlow() const;
public:
/// getBaseType - Gets the base type of this object type. This is
/// always (possibly sugar for) one of:
@ -4452,6 +4590,33 @@ class ObjCObjectType : public Type {
/// really is an interface.
ObjCInterfaceDecl *getInterface() const;
/// Determine whether this object type is "specialized", meaning
/// that it has type arguments.
bool isSpecialized() const;
/// Determine whether this object type was written with type arguments.
bool isSpecializedAsWritten() const {
return ObjCObjectTypeBits.NumTypeArgs > 0;
}
/// Determine whether this object type is "unspecialized", meaning
/// that it has no type arguments.
bool isUnspecialized() const { return !isSpecialized(); }
/// Determine whether this object type is "unspecialized" as
/// written, meaning that it has no type arguments.
bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
/// Retrieve the type arguments of this object type (semantically).
ArrayRef<QualType> getTypeArgs() const;
/// Retrieve the type arguments of this object type as they were
/// written.
ArrayRef<QualType> getTypeArgsAsWritten() const {
return ArrayRef<QualType>(getTypeArgStorage(),
ObjCObjectTypeBits.NumTypeArgs);
}
typedef ObjCProtocolDecl * const *qual_iterator;
typedef llvm::iterator_range<qual_iterator> qual_range;
@ -4471,6 +4636,35 @@ class ObjCObjectType : public Type {
return qual_begin()[I];
}
/// Retrieve all of the protocol qualifiers.
ArrayRef<ObjCProtocolDecl *> getProtocols() const {
return ArrayRef<ObjCProtocolDecl *>(qual_begin(), getNumProtocols());
}
/// Whether this is a "__kindof" type as written.
bool isKindOfTypeAsWritten() const { return ObjCObjectTypeBits.IsKindOf; }
/// Whether this ia a "__kindof" type (semantically).
bool isKindOfType() const;
/// Retrieve the type of the superclass of this object type.
///
/// This operation substitutes any type arguments into the
/// superclass of the current class type, potentially producing a
/// specialization of the superclass type. Produces a null type if
/// there is no superclass.
QualType getSuperClassType() const {
if (!CachedSuperClassType.getInt())
computeSuperClassTypeSlow();
assert(CachedSuperClassType.getInt() && "Superclass not set?");
return QualType(CachedSuperClassType.getPointer(), 0);
}
/// Strip off the Objective-C "kindof" type and (with it) any
/// protocol qualifiers.
QualType stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@ -4491,21 +4685,27 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode {
// will need to be modified.
ObjCObjectTypeImpl(QualType Canonical, QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols)
: ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {}
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf)
: ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {}
public:
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
QualType Base,
ObjCProtocolDecl *const *protocols,
unsigned NumProtocols);
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf);
};
inline QualType *ObjCObjectType::getTypeArgStorage() {
return reinterpret_cast<QualType *>(static_cast<ObjCObjectTypeImpl*>(this)+1);
}
inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
return reinterpret_cast<ObjCProtocolDecl**>(
static_cast<ObjCObjectTypeImpl*>(this) + 1);
return reinterpret_cast<ObjCProtocolDecl**>(
getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs);
}
/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
@ -4556,9 +4756,14 @@ class ObjCInterfaceType : public ObjCObjectType {
};
inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
if (const ObjCInterfaceType *T =
getBaseType()->getAs<ObjCInterfaceType>())
return T->getDecl();
QualType baseType = getBaseType();
while (const ObjCObjectType *ObjT = baseType->getAs<ObjCObjectType>()) {
if (const ObjCInterfaceType *T = dyn_cast<ObjCInterfaceType>(ObjT))
return T->getDecl();
baseType = ObjT->getBaseType();
}
return nullptr;
}
@ -4575,7 +4780,11 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
ObjCObjectPointerType(QualType Canonical, QualType Pointee)
: Type(ObjCObjectPointer, Canonical, false, false, false, false),
: Type(ObjCObjectPointer, Canonical,
Pointee->isDependentType(),
Pointee->isInstantiationDependentType(),
Pointee->isVariablyModifiedType(),
Pointee->containsUnexpandedParameterPack()),
PointeeType(Pointee) {}
friend class ASTContext; // ASTContext creates these.
@ -4617,9 +4826,7 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
/// qualifiers on the interface are ignored.
///
/// \return null if the base type for this pointer is 'id' or 'Class'
const ObjCInterfaceType *getInterfaceType() const {
return getObjectType()->getBaseType()->getAs<ObjCInterfaceType>();
}
const ObjCInterfaceType *getInterfaceType() const;
/// getInterfaceDecl - If this pointer points to an Objective \@interface
/// type, gets the declaration for that interface.
@ -4641,6 +4848,12 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
return getObjectType()->isObjCUnqualifiedClass();
}
/// isObjCIdOrClassType - True if this is equivalent to the 'id' or
/// 'Class' type,
bool isObjCIdOrClassType() const {
return getObjectType()->isObjCUnqualifiedIdOrClass();
}
/// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some
/// non-empty set of protocols.
bool isObjCQualifiedIdType() const {
@ -4653,6 +4866,34 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
return getObjectType()->isObjCQualifiedClass();
}
/// Whether this is a "__kindof" type.
bool isKindOfType() const { return getObjectType()->isKindOfType(); }
/// Whether this type is specialized, meaning that it has type arguments.
bool isSpecialized() const { return getObjectType()->isSpecialized(); }
/// Whether this type is specialized, meaning that it has type arguments.
bool isSpecializedAsWritten() const {
return getObjectType()->isSpecializedAsWritten();
}
/// Whether this type is unspecialized, meaning that is has no type arguments.
bool isUnspecialized() const { return getObjectType()->isUnspecialized(); }
/// Determine whether this object type is "unspecialized" as
/// written, meaning that it has no type arguments.
bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
/// Retrieve the type arguments for this type.
ArrayRef<QualType> getTypeArgs() const {
return getObjectType()->getTypeArgs();
}
/// Retrieve the type arguments for this type.
ArrayRef<QualType> getTypeArgsAsWritten() const {
return getObjectType()->getTypeArgsAsWritten();
}
/// An iterator over the qualifiers on the object type. Provided
/// for convenience. This will always iterate over the full set of
/// protocols on a type, not just those provided directly.
@ -4683,6 +4924,19 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
/// Retrieve the type of the superclass of this object pointer type.
///
/// This operation substitutes any type arguments into the
/// superclass of the current class type, potentially producing a
/// pointer to a specialization of the superclass type. Produces a
/// null type if there is no superclass.
QualType getSuperClassType() const;
/// Strip off the Objective-C "kindof" type and (with it) any
/// protocol qualifiers.
const ObjCObjectPointerType *stripObjCKindOfTypeAndQuals(
const ASTContext &ctx) const;
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType());
}

View File

@ -177,6 +177,9 @@ class TypeLoc {
memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
}
/// Copies the other type loc into this one.
void copy(TypeLoc other);
friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data;
}
@ -185,6 +188,10 @@ class TypeLoc {
return !(LHS == RHS);
}
/// Find the location of the nullability specifier (__nonnull,
/// __nullable, or __null_unspecifier), if there is one.
SourceLocation findNullabilityLoc() const;
private:
static bool isKind(const TypeLoc&) {
return true;
@ -249,6 +256,10 @@ class QualifiedTypeLoc : public TypeLoc {
// do nothing
}
void copyLocal(TypeLoc other) {
// do nothing
}
TypeLoc getNextTypeLoc() const {
return getUnqualifiedLoc();
}
@ -339,6 +350,20 @@ class ConcreteTypeLoc : public Base {
return size;
}
void copyLocal(Derived other) {
// Some subclasses have no data to copy.
if (asDerived()->getLocalDataSize() == 0) return;
// Copy the fixed-sized local data.
memcpy(getLocalData(), other.getLocalData(), sizeof(LocalData));
// Copy the variable-sized local data. We need to do this
// separately because the padding in the source and the padding in
// the destination might be different.
memcpy(getExtraLocalData(), other.getExtraLocalData(),
asDerived()->getExtraLocalDataSize());
}
TypeLoc getNextTypeLoc() const {
return getNextTypeLoc(asDerived()->getInnerType());
}
@ -799,9 +824,11 @@ class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
};
struct ObjCProtocolListLocInfo {
SourceLocation LAngleLoc;
SourceLocation RAngleLoc;
struct ObjCObjectTypeLocInfo {
SourceLocation TypeArgsLAngleLoc;
SourceLocation TypeArgsRAngleLoc;
SourceLocation ProtocolLAngleLoc;
SourceLocation ProtocolRAngleLoc;
bool HasBaseTypeAsWritten;
};
@ -813,25 +840,59 @@ struct ObjCProtocolListLocInfo {
class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
ObjCObjectTypeLoc,
ObjCObjectType,
ObjCProtocolListLocInfo> {
// SourceLocations are stored after Info, one for each Protocol.
ObjCObjectTypeLocInfo> {
// TypeSourceInfo*'s are stored after Info, one for each type argument.
TypeSourceInfo **getTypeArgLocArray() const {
return (TypeSourceInfo**)this->getExtraLocalData();
}
// SourceLocations are stored after the type argument information, one for
// each Protocol.
SourceLocation *getProtocolLocArray() const {
return (SourceLocation*) this->getExtraLocalData();
return (SourceLocation*)(getTypeArgLocArray() + getNumTypeArgs());
}
public:
SourceLocation getLAngleLoc() const {
return this->getLocalData()->LAngleLoc;
SourceLocation getTypeArgsLAngleLoc() const {
return this->getLocalData()->TypeArgsLAngleLoc;
}
void setLAngleLoc(SourceLocation Loc) {
this->getLocalData()->LAngleLoc = Loc;
void setTypeArgsLAngleLoc(SourceLocation Loc) {
this->getLocalData()->TypeArgsLAngleLoc = Loc;
}
SourceLocation getRAngleLoc() const {
return this->getLocalData()->RAngleLoc;
SourceLocation getTypeArgsRAngleLoc() const {
return this->getLocalData()->TypeArgsRAngleLoc;
}
void setRAngleLoc(SourceLocation Loc) {
this->getLocalData()->RAngleLoc = Loc;
void setTypeArgsRAngleLoc(SourceLocation Loc) {
this->getLocalData()->TypeArgsRAngleLoc = Loc;
}
unsigned getNumTypeArgs() const {
return this->getTypePtr()->getTypeArgsAsWritten().size();
}
TypeSourceInfo *getTypeArgTInfo(unsigned i) const {
assert(i < getNumTypeArgs() && "Index is out of bounds!");
return getTypeArgLocArray()[i];
}
void setTypeArgTInfo(unsigned i, TypeSourceInfo *TInfo) {
assert(i < getNumTypeArgs() && "Index is out of bounds!");
getTypeArgLocArray()[i] = TInfo;
}
SourceLocation getProtocolLAngleLoc() const {
return this->getLocalData()->ProtocolLAngleLoc;
}
void setProtocolLAngleLoc(SourceLocation Loc) {
this->getLocalData()->ProtocolLAngleLoc = Loc;
}
SourceLocation getProtocolRAngleLoc() const {
return this->getLocalData()->ProtocolRAngleLoc;
}
void setProtocolRAngleLoc(SourceLocation Loc) {
this->getLocalData()->ProtocolRAngleLoc = Loc;
}
unsigned getNumProtocols() const {
@ -852,6 +913,11 @@ class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
return *(this->getTypePtr()->qual_begin() + i);
}
ArrayRef<SourceLocation> getProtocolLocs() const {
return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols());
}
bool hasBaseTypeAsWritten() const {
return getLocalData()->HasBaseTypeAsWritten;
}
@ -865,23 +931,27 @@ class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
}
SourceRange getLocalSourceRange() const {
return SourceRange(getLAngleLoc(), getRAngleLoc());
SourceLocation start = getTypeArgsLAngleLoc();
if (start.isInvalid())
start = getProtocolLAngleLoc();
SourceLocation end = getProtocolRAngleLoc();
if (end.isInvalid())
end = getTypeArgsRAngleLoc();
return SourceRange(start, end);
}
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setHasBaseTypeAsWritten(true);
setLAngleLoc(Loc);
setRAngleLoc(Loc);
for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
setProtocolLoc(i, Loc);
}
void initializeLocal(ASTContext &Context, SourceLocation Loc);
unsigned getExtraLocalDataSize() const {
return this->getNumProtocols() * sizeof(SourceLocation);
return this->getNumTypeArgs() * sizeof(TypeSourceInfo *)
+ this->getNumProtocols() * sizeof(SourceLocation);
}
unsigned getExtraLocalDataAlignment() const {
return llvm::alignOf<SourceLocation>();
assert(llvm::alignOf<ObjCObjectTypeLoc>()
>= llvm::alignOf<TypeSourceInfo *>() &&
"not enough alignment for tail-allocated data");
return llvm::alignOf<TypeSourceInfo *>();
}
QualType getInnerType() const {

View File

@ -112,7 +112,7 @@ class BoundNodes {
///
/// FIXME: Do we want to support this now that we have bind()?
template <typename T>
internal::Matcher<T> id(const std::string &ID,
internal::Matcher<T> id(StringRef ID,
const internal::BindableMatcher<T> &InnerMatcher) {
return InnerMatcher.bind(ID);
}

View File

@ -140,8 +140,7 @@ class BoundNodesTreeBuilder {
};
/// \brief Add a binding from an id to a node.
void setBinding(const std::string &Id,
const ast_type_traits::DynTypedNode &DynNode) {
void setBinding(StringRef Id, const ast_type_traits::DynTypedNode &DynNode) {
if (Bindings.empty())
Bindings.emplace_back();
for (BoundNodesMap &Binding : Bindings)

View File

@ -242,7 +242,7 @@ struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
///
/// Supported types:
/// - \c unsigned
/// - \c std::string
/// - \c llvm::StringRef
/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
class VariantValue {
public:
@ -254,7 +254,7 @@ class VariantValue {
/// \brief Specific constructors for each supported type.
VariantValue(unsigned Unsigned);
VariantValue(const std::string &String);
VariantValue(StringRef String);
VariantValue(const VariantMatcher &Matchers);
/// \brief Returns true iff this is not an empty value.
@ -269,7 +269,7 @@ class VariantValue {
/// \brief String value functions.
bool isString() const;
const std::string &getString() const;
void setString(const std::string &String);
void setString(StringRef String);
/// \brief Matcher value functions.
bool isMatcher() const;

View File

@ -976,6 +976,11 @@ def TypeNullUnspecified : TypeAttr {
let Documentation = [TypeNullUnspecifiedDocs];
}
def ObjCKindOf : TypeAttr {
let Spellings = [Keyword<"__kindof">];
let Documentation = [Undocumented];
}
def AssumeAligned : InheritableAttr {
let Spellings = [GCC<"assume_aligned">];
let Subjects = SubjectList<[ObjCMethod, Function]>;
@ -1276,9 +1281,8 @@ def Pascal : InheritableAttr {
def Target : InheritableAttr {
let Spellings = [GCC<"target">];
let Args = [StringArgument<"features">];
let Subjects =
SubjectList<[Function], ErrorDiag, "ExpectedFunctionMethodOrClass">;
let Documentation = [Undocumented];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [TargetDocs];
}
def TransparentUnion : InheritableAttr {

View File

@ -678,6 +678,25 @@ The semantics are as follows:
}];
}
def TargetDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Clang supports the GNU style ``__attribute__((target("OPTIONS")))`` attribute.
This attribute may be attached to a function definition and instructs
the backend to use different code generation options than were passed on the
command line.
The current set of options correspond to the existing "subtarget features" for
the target with or without a "-mno-" in front corresponding to the absence
of the feature, as well as ``arch="CPU"`` which will change the default "CPU"
for the function.
Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2",
"avx", "xop" and largely correspond to the machine specific options handled by
the front end.
}];
}
def DocCatAMDGPURegisterAttributes :
DocumentationCategory<"AMD GPU Register Attributes"> {
let Content = [{

View File

@ -248,6 +248,11 @@ BUILTIN(__builtin_altivec_crypto_vpmsumh, "V8UsV8UsV8Us", "")
BUILTIN(__builtin_altivec_crypto_vpmsumw, "V4UiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_crypto_vpmsumd, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vclzb, "V16UcV16Uc", "")
BUILTIN(__builtin_altivec_vclzh, "V8UsV8Us", "")
BUILTIN(__builtin_altivec_vclzw, "V4UiV4Ui", "")
BUILTIN(__builtin_altivec_vclzd, "V2ULLiV2ULLi", "")
// VSX built-ins.
BUILTIN(__builtin_vsx_lxvd2x, "V2divC*", "")
@ -279,6 +284,47 @@ BUILTIN(__builtin_vsx_xvcmpgesp, "V4UiV4fV4f", "")
BUILTIN(__builtin_vsx_xvcmpgtdp, "V2ULLiV2dV2d", "")
BUILTIN(__builtin_vsx_xvcmpgtsp, "V4UiV4fV4f", "")
BUILTIN(__builtin_vsx_xvrdpim, "V2dV2d", "")
BUILTIN(__builtin_vsx_xvrspim, "V4fV4f", "")
BUILTIN(__builtin_vsx_xvrdpi, "V2dV2d", "")
BUILTIN(__builtin_vsx_xvrspi, "V4fV4f", "")
BUILTIN(__builtin_vsx_xvrdpic, "V2dV2d", "")
BUILTIN(__builtin_vsx_xvrspic, "V4fV4f", "")
BUILTIN(__builtin_vsx_xvrdpiz, "V2dV2d", "")
BUILTIN(__builtin_vsx_xvrspiz, "V4fV4f", "")
BUILTIN(__builtin_vsx_xvmaddadp, "V2dV2dV2dV2d", "")
BUILTIN(__builtin_vsx_xvmaddasp, "V4fV4fV4fV4f", "")
BUILTIN(__builtin_vsx_xvmsubadp, "V2dV2dV2dV2d", "")
BUILTIN(__builtin_vsx_xvmsubasp, "V4fV4fV4fV4f", "")
BUILTIN(__builtin_vsx_xvmuldp, "V2dV2dV2d", "")
BUILTIN(__builtin_vsx_xvmulsp, "V4fV4fV4f", "")
BUILTIN(__builtin_vsx_xvnmaddadp, "V2dV2dV2dV2d", "")
BUILTIN(__builtin_vsx_xvnmaddasp, "V4fV4fV4fV4f", "")
BUILTIN(__builtin_vsx_xvnmsubadp, "V2dV2dV2dV2d", "")
BUILTIN(__builtin_vsx_xvnmsubasp, "V4fV4fV4fV4f", "")
BUILTIN(__builtin_vsx_xvredp, "V2dV2d", "")
BUILTIN(__builtin_vsx_xvresp, "V4fV4f", "")
BUILTIN(__builtin_vsx_xvrsqrtedp, "V2dV2d", "")
BUILTIN(__builtin_vsx_xvrsqrtesp, "V4fV4f", "")
BUILTIN(__builtin_vsx_xvsqrtdp, "V2dV2d", "")
BUILTIN(__builtin_vsx_xvsqrtsp, "V4fV4f", "")
BUILTIN(__builtin_vsx_xxleqv, "V4UiV4UiV4Ui", "")
BUILTIN(__builtin_vsx_xvcpsgndp, "V2dV2dV2d", "")
BUILTIN(__builtin_vsx_xvcpsgnsp, "V4fV4fV4f", "")
// HTM builtins
BUILTIN(__builtin_tbegin, "UiUIi", "")
BUILTIN(__builtin_tend, "UiUIi", "")

View File

@ -1157,5 +1157,65 @@ BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "")
BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "")
BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "")
BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "")
BUILTIN(__builtin_ia32_blendmb_128_mask, "V16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_blendmb_256_mask, "V32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_blendmw_128_mask, "V8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_blendmw_256_mask, "V16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_pabsb128_mask, "V16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_pabsb256_mask, "V32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_pabsw128_mask, "V8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_pabsw256_mask, "V16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_packssdw128_mask, "V8sV4iV4iV8sUc", "")
BUILTIN(__builtin_ia32_packssdw256_mask, "V16sV8iV8iV16sUs", "")
BUILTIN(__builtin_ia32_packsswb128_mask, "V16cV8sV8sV16cUs", "")
BUILTIN(__builtin_ia32_packsswb256_mask, "V32cV16sV16sV32cUi", "")
BUILTIN(__builtin_ia32_packusdw128_mask, "V8sV4iV4iV8sUc", "")
BUILTIN(__builtin_ia32_packusdw256_mask, "V16sV8iV8iV16sUs", "")
BUILTIN(__builtin_ia32_packuswb128_mask, "V16cV8sV8sV16cUs", "")
BUILTIN(__builtin_ia32_packuswb256_mask, "V32cV16sV16sV32cUi", "")
BUILTIN(__builtin_ia32_paddsb128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_paddsb256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_paddsw128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_paddsw256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_paddusb128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_paddusb256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_paddusw128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_paddusw256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_pavgb128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_pavgb256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_pavgw128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_pavgw256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_pmaxsb128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_pmaxsb256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_pmaxsw128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_pmaxsw256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_pmaxub128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_pmaxub256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_pmaxuw128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_pmaxuw256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_pminsb128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_pminsb256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_pminsw128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_pminsw256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_pminub128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_pminub256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_pminuw128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_pminuw256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_pshufb128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_pshufb256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_psubsb128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_psubsb256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_psubsw128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_psubsw256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_psubusb128_mask, "V16cV16cV16cV16cUs", "")
BUILTIN(__builtin_ia32_psubusb256_mask, "V32cV32cV32cV32cUi", "")
BUILTIN(__builtin_ia32_psubusw128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_psubusw256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_vpermi2varhi128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_vpermt2varhi128_mask, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_vpermt2varhi128_maskz, "V8sV8sV8sV8sUc", "")
BUILTIN(__builtin_ia32_vpermt2varhi256_mask, "V16sV16sV16sV16sUs", "")
BUILTIN(__builtin_ia32_vpermt2varhi256_maskz, "V16sV16sV16sV16sUs", "")
#undef BUILTIN

View File

@ -21,6 +21,7 @@ def Named : Decl<1>;
def TypedefName : DDecl<Type, 1>;
def Typedef : DDecl<TypedefName>;
def TypeAlias : DDecl<TypedefName>;
def ObjCTypeParam : DDecl<TypedefName>;
def UnresolvedUsingTypename : DDecl<Type>;
def Tag : DDecl<Type, 1>, DeclContext;
def Enum : DDecl<Tag>;

View File

@ -179,6 +179,8 @@ def err_target_unsupported_fpmath : Error<
"the '%0' unit is not supported with this instruction set">;
def err_target_unsupported_unaligned : Error<
"the %0 sub-architecture does not support unaligned accesses">;
def err_opt_not_valid_with_opt : Error<
"option '%0' cannot be specified with '%1'">;
// Source manager
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;

View File

@ -69,8 +69,6 @@ def err_drv_no_module_support : Error<
"'%0': unable to use module files with this tool">;
def err_drv_clang_unsupported : Error<
"the clang compiler does not support '%0'">;
def err_drv_clang_unsupported_per_platform : Error<
"the clang compiler does not support '%0' on this platform">;
def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error<
"the clang compiler does not support '%0' for C++ on Darwin/i386">;
def err_drv_command_failed : Error<

View File

@ -280,6 +280,7 @@ def FunctionDefInObjCContainer : DiagGroup<"function-def-in-objc-container">;
def BadFunctionCast : DiagGroup<"bad-function-cast">;
def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">;
def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">;
def ObjCProtocolQualifiers : DiagGroup<"objc-protocol-qualifiers">;
def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
def ObjCDesignatedInit : DiagGroup<"objc-designated-initializers">;
def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">;

View File

@ -1004,10 +1004,6 @@ def err_pragma_invalid_keyword : Error<
def warn_pragma_unroll_cuda_value_in_parens : Warning<
"argument to '#pragma unroll' should not be in parentheses in CUDA C/C++">,
InGroup<CudaCompat>;
def err_empty_attribute_block : Error<
"Microsoft attribute block cannot be empty">;
} // end of Parse Issue category.
let CategoryName = "Modules Issue" in {
@ -1017,4 +1013,16 @@ def err_module_expected_semi : Error<
"expected ';' after module name">;
}
let CategoryName = "Generics Issue" in {
def err_objc_expected_type_parameter : Error<
"expected type parameter name">;
def err_objc_parameterized_implementation : Error<
"@implementation cannot have type parameters">;
def err_objc_type_args_after_protocols : Error<
"protocol qualifiers must precede type arguments">;
}
} // end of Parser diagnostics

View File

@ -188,6 +188,8 @@ def ext_flexible_array_init : Extension<
"flexible array initialization is a GNU extension">, InGroup<GNUFlexibleArrayInitializer>;
// Declarations.
def err_redeclaration_different_type : Error<
"redeclaration of %0 with a different type%diff{: $ vs $|}1,2">;
def err_bad_variable_name : Error<
"%0 cannot be the name of a variable or data member">;
def err_bad_parameter_name : Error<
@ -978,6 +980,12 @@ def warning_multiple_selectors: Warning<
"several methods with selector %0 of mismatched types are found "
"for the @selector expression">,
InGroup<SelectorTypeMismatch>, DefaultIgnore;
def err_objc_kindof_nonobject : Error<
"'__kindof' specifier cannot be applied to non-object type %0">;
def err_objc_kindof_wrong_position : Error<
"'__kindof' type specifier must precede the declarator">;
// C++ declarations
def err_static_assert_expression_is_not_constant : Error<
"static_assert expression is not an integral constant expression">;
@ -2131,6 +2139,11 @@ def warn_concatenated_nsarray_literal : Warning<
InGroup<ObjCStringConcatenation>;
def note_objc_literal_comparison_isequal : Note<
"use 'isEqual:' instead">;
def warn_objc_collection_literal_element : Warning<
"object of type %0 is not compatible with "
"%select{array element type|dictionary key type|dictionary value type}1 %2">,
InGroup<ObjCLiteralConversion>;
def err_attribute_argument_is_zero : Error<
"%0 attribute must be greater than 0">;
def warn_attribute_argument_n_negative : Warning<
@ -2148,6 +2161,10 @@ def warn_objc_redundant_literal_use : Warning<
def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", "
"\"local-dynamic\", \"initial-exec\" or \"local-exec\"">;
def err_tls_var_aligned_over_maximum : Error<
"alignment (%0) of thread-local variable %1 is greater than the maximum supported "
"alignment (%2) for a thread-local variable on this target">;
def err_only_annotate_after_access_spec : Error<
"access specifier can only have annotation attributes">;
@ -4740,6 +4757,8 @@ def warn_division_by_zero : Warning<"division by zero is undefined">,
InGroup<DivZero>;
def warn_remainder_by_zero : Warning<"remainder by zero is undefined">,
InGroup<DivZero>;
def warn_shift_lhs_negative : Warning<"shifting a negative signed value is undefined">,
InGroup<DiagGroup<"shift-negative-value">>;
def warn_shift_negative : Warning<"shift count is negative">,
InGroup<DiagGroup<"shift-count-negative">>;
def warn_shift_gt_typewidth : Warning<"shift count >= width of type">,
@ -5576,6 +5595,8 @@ def err_seh_try_outside_functions : Error<
"cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls">;
def err_mixing_cxx_try_seh_try : Error<
"cannot use C++ 'try' in the same function as SEH '__try'">;
def err_seh_try_unsupported : Error<
"SEH '__try' is not supported on this target">;
def note_conflicting_try_here : Note<
"conflicting %0 here">;
def warn_jump_out_of_seh_finally : Warning<
@ -7740,6 +7761,84 @@ def warn_nullability_missing : Warning<
"type specifier (_Nonnull, _Nullable, or _Null_unspecified)">,
InGroup<NullabilityCompleteness>;
def err_type_arg_explicit_nullability : Error<
"type argument %0 cannot explicitly specify nullability">;
def err_type_param_bound_explicit_nullability : Error<
"type parameter %0 bound %1 cannot explicitly specify nullability">;
}
let CategoryName = "Generics Issue" in {
def err_objc_type_param_bound_nonobject : Error<
"type bound %0 for type parameter %1 is not an Objective-C pointer type">;
def err_objc_type_param_bound_missing_pointer : Error<
"missing '*' in type bound %0 for type parameter %1">;
def err_objc_type_param_redecl : Error<
"redeclaration of type parameter %0">;
def err_objc_type_param_arity_mismatch : Error<
"%select{forward class declaration|class definition|category|extension}0 has "
"too %select{few|many}1 type parameters (expected %2, have %3)">;
def err_objc_type_param_bound_conflict : Error<
"type bound %0 for type parameter %1 conflicts with "
"%select{implicit|previous}2 bound %3%select{for type parameter %5|}4">;
def err_objc_type_param_variance_conflict : Error<
"%select{in|co|contra}0variant type parameter %1 conflicts with previous "
"%select{in|co|contra}2variant type parameter %3">;
def note_objc_type_param_here : Note<"type parameter %0 declared here">;
def err_objc_type_param_bound_missing : Error<
"missing type bound %0 for type parameter %1 in %select{@interface|@class}2">;
def err_objc_parameterized_category_nonclass : Error<
"%select{extension|category}0 of non-parameterized class %1 cannot have type "
"parameters">;
def err_objc_parameterized_forward_class : Error<
"forward declaration of non-parameterized class %0 cannot have type "
"parameters">;
def err_objc_parameterized_forward_class_first : Error<
"class %0 previously declared with type parameters">;
def err_objc_type_arg_missing_star : Error<
"type argument %0 must be a pointer (requires a '*')">;
def err_objc_type_arg_missing : Error<
"no type or protocol named %0">;
def err_objc_type_args_and_protocols : Error<
"angle brackets contain both a %select{type|protocol}0 (%1) and a "
"%select{protocol|type}0 (%2)">;
def err_objc_type_args_non_class : Error<
"type arguments cannot be applied to non-class type %0">;
def err_objc_type_args_non_parameterized_class : Error<
"type arguments cannot be applied to non-parameterized class %0">;
def err_objc_type_args_specialized_class : Error<
"type arguments cannot be applied to already-specialized class type %0">;
def err_objc_type_args_wrong_arity : Error<
"too %select{many|few}0 type arguments for class %1 (have %2, expected %3)">;
}
def err_objc_type_arg_not_id_compatible : Error<
"type argument %0 is neither an Objective-C object nor a block type">;
def err_objc_type_arg_does_not_match_bound : Error<
"type argument %0 does not satisfy the bound (%1) of type parameter %2">;
def warn_objc_redundant_qualified_class_type : Warning<
"parameterized class %0 already conforms to the protocols listed; did you "
"forget a '*'?">, InGroup<ObjCProtocolQualifiers>;
} // end of sema component.

View File

@ -49,7 +49,7 @@ class IdentifierInfo {
// Objective-C keyword ('protocol' in '@protocol') or builtin (__builtin_inf).
// First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values
// are for builtins.
unsigned ObjCOrBuiltinID :11;
unsigned ObjCOrBuiltinID :13;
bool HasMacro : 1; // True if there is a #define for this.
bool HadMacro : 1; // True if there was a #define for this.
bool IsExtension : 1; // True if identifier is a lang extension.
@ -69,7 +69,7 @@ class IdentifierInfo {
// stored externally.
bool IsModulesImport : 1; // True if this is the 'import' contextual
// keyword.
// 32-bit word is filled.
// 30 bit left in 64-bit word.
void *FETokenInfo; // Managed by the language front-end.
llvm::StringMapEntry<IdentifierInfo*> *Entry;

View File

@ -161,6 +161,7 @@ LANGOPT(NativeHalfType , 1, 0, "Native half type support")
LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns")
LANGOPT(CUDA , 1, 0, "CUDA")
LANGOPT(OpenMP , 1, 0, "OpenMP support")
LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
LANGOPT(CUDAIsDevice , 1, 0, "Compiling for CUDA device")
LANGOPT(CUDAAllowHostCallsFromHostDevice, 1, 0, "Allow host device functions to call host functions")
LANGOPT(CUDADisableTargetCallChecks, 1, 0, "Disable checks for call targets (host, device, etc.)")

View File

@ -17,8 +17,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include <stdint.h>
#include "llvm/Support/MathExtras.h"
namespace clang {
@ -47,22 +46,28 @@ enum SanitizerOrdinal : uint64_t {
}
struct SanitizerSet {
SanitizerSet();
SanitizerSet() : Mask(0) {}
/// \brief Check if a certain (single) sanitizer is enabled.
bool has(SanitizerMask K) const;
bool has(SanitizerMask K) const {
assert(llvm::isPowerOf2_64(K));
return Mask & K;
}
/// \brief Check if one or more sanitizers are enabled.
bool hasOneOf(SanitizerMask K) const;
bool hasOneOf(SanitizerMask K) const { return Mask & K; }
/// \brief Enable or disable a certain (single) sanitizer.
void set(SanitizerMask K, bool Value);
void set(SanitizerMask K, bool Value) {
assert(llvm::isPowerOf2_64(K));
Mask = Value ? (Mask | K) : (Mask & ~K);
}
/// \brief Disable all sanitizers.
void clear();
void clear() { Mask = 0; }
/// \brief Returns true if at least one sanitizer is enabled.
bool empty() const;
bool empty() const { return Mask == 0; }
/// \brief Bitmask of enabled sanitizers.
SanitizerMask Mask;

View File

@ -70,6 +70,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
unsigned char MinGlobalAlign;
unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
unsigned short MaxVectorAlign;
unsigned short MaxTLSAlign;
unsigned short SimdDefaultAlign;
const char *DescriptionString;
const char *UserLabelPrefix;
@ -809,6 +810,21 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
return TLSSupported;
}
/// \brief Return the maximum alignment (in bits) of a TLS variable
///
/// Gets the maximum alignment (in bits) of a TLS variable on this target.
/// Returns zero if there is no such constraint.
unsigned short getMaxTLSAlign() const {
return MaxTLSAlign;
}
/// \brief Whether the target supports SEH __try.
bool isSEHTrySupported() const {
return getTriple().isOSWindows() &&
(getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64);
}
/// \brief Return true if {|} are normal characters in the asm string.
///
/// If this returns false (the default), then {abc|xyz} is syntax

View File

@ -526,6 +526,11 @@ KEYWORD(__bridge_transfer , KEYARC)
KEYWORD(__bridge_retained , KEYARC)
KEYWORD(__bridge_retain , KEYARC)
// Objective-C keywords.
KEYWORD(__covariant , KEYOBJC2)
KEYWORD(__contravariant , KEYOBJC2)
KEYWORD(__kindof , KEYOBJC2)
// Alternate spelling for various tokens. There are GCC extensions in all
// languages, but should not be disabled in strict conformance mode.
ALIAS("__alignof__" , __alignof , KEYALL)

View File

@ -0,0 +1,43 @@
//===-- CodeGen/ObjectFilePCHContainerOperations.h - ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_CODEGEN_OBJECT_FILE_PCH_CONTAINER_OPERATIONS_H
#define LLVM_CLANG_CODEGEN_OBJECT_FILE_PCH_CONTAINER_OPERATIONS_H
#include "clang/Frontend/PCHContainerOperations.h"
namespace clang {
/// \brief A PCHContainerOperations implementation that uses LLVM to
/// wraps Clang modules inside a COFF, ELF, or Mach-O container.
class ObjectFilePCHContainerOperations
: public PCHContainerOperations {
/// \brief Return an ASTConsumer that can be chained with a
/// PCHGenerator that produces a wrapper file format
/// that also contains full debug info for the module.
std::unique_ptr<ASTConsumer>
CreatePCHContainerGenerator(
DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO,
const PreprocessorOptions &PPO, const TargetOptions &TO,
const LangOptions &LO, const std::string &MainFileName,
const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
std::shared_ptr<PCHBuffer> Buffer) const override;
/// \brief Initialize an llvm::BitstreamReader with the serialized
/// AST inside the PCH container Buffer.
void ExtractPCH(llvm::MemoryBufferRef Buffer,
llvm::BitstreamReader &StreamFile) const override;
};
}
#endif

View File

@ -41,6 +41,8 @@ class Action {
enum ActionClass {
InputClass = 0,
BindArchClass,
CudaDeviceClass,
CudaHostClass,
PreprocessJobClass,
PrecompileJobClass,
AnalyzeJobClass,
@ -71,16 +73,16 @@ class Action {
unsigned OwnsInputs : 1;
protected:
Action(ActionClass _Kind, types::ID _Type)
: Kind(_Kind), Type(_Type), OwnsInputs(true) {}
Action(ActionClass _Kind, std::unique_ptr<Action> Input, types::ID _Type)
: Kind(_Kind), Type(_Type), Inputs(1, Input.release()), OwnsInputs(true) {
Action(ActionClass Kind, types::ID Type)
: Kind(Kind), Type(Type), OwnsInputs(true) {}
Action(ActionClass Kind, std::unique_ptr<Action> Input, types::ID Type)
: Kind(Kind), Type(Type), Inputs(1, Input.release()), OwnsInputs(true) {
}
Action(ActionClass _Kind, std::unique_ptr<Action> Input)
: Kind(_Kind), Type(Input->getType()), Inputs(1, Input.release()),
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)
: Kind(_Kind), Type(_Type), Inputs(_Inputs), OwnsInputs(true) {}
Action(ActionClass Kind, const ActionList &Inputs, types::ID Type)
: Kind(Kind), Type(Type), Inputs(Inputs), OwnsInputs(true) {}
public:
virtual ~Action();
@ -108,7 +110,7 @@ class InputAction : public Action {
const llvm::opt::Arg &Input;
public:
InputAction(const llvm::opt::Arg &_Input, types::ID _Type);
InputAction(const llvm::opt::Arg &Input, types::ID Type);
const llvm::opt::Arg &getInputArg() const { return Input; }
@ -124,7 +126,7 @@ class BindArchAction : public Action {
const char *ArchName;
public:
BindArchAction(std::unique_ptr<Action> Input, const char *_ArchName);
BindArchAction(std::unique_ptr<Action> Input, const char *ArchName);
const char *getArchName() const { return ArchName; }
@ -133,6 +135,41 @@ class BindArchAction : public Action {
}
};
class CudaDeviceAction : public Action {
virtual void anchor();
/// GPU architecture to bind -- e.g 'sm_35'.
const char *GpuArchName;
/// True when action results are not consumed by the host action (e.g when
/// -fsyntax-only or --cuda-device-only options are used).
bool AtTopLevel;
public:
CudaDeviceAction(std::unique_ptr<Action> Input, const char *ArchName,
bool AtTopLevel);
const char *getGpuArchName() const { return GpuArchName; }
bool isAtTopLevel() const { return AtTopLevel; }
static bool classof(const Action *A) {
return A->getKind() == CudaDeviceClass;
}
};
class CudaHostAction : public Action {
virtual void anchor();
ActionList DeviceActions;
public:
CudaHostAction(std::unique_ptr<Action> Input,
const ActionList &DeviceActions);
~CudaHostAction() override;
ActionList &getDeviceActions() { return DeviceActions; }
const ActionList &getDeviceActions() const { return DeviceActions; }
static bool classof(const Action *A) { return A->getKind() == CudaHostClass; }
};
class JobAction : public Action {
virtual void anchor();
protected:

View File

@ -188,7 +188,7 @@ def _SLASH_EP : CLFlag<"EP">,
def _SLASH_FA : CLFlag<"FA">,
HelpText<"Output assembly code file during compilation">;
def _SLASH_Fa : CLJoined<"Fa">,
HelpText<"Output assembly code to this file during compilation">,
HelpText<"Output assembly code to this file during compilation (with /FA)">,
MetaVarName<"<file or directory>">;
def _SLASH_fallback : CLCompileFlag<"fallback">,
HelpText<"Fall back to cl.exe if clang-cl fails to compile">;
@ -198,10 +198,10 @@ def _SLASH_Fe : CLJoined<"Fe">,
HelpText<"Set output executable file or directory (ends in / or \\)">,
MetaVarName<"<file or directory>">;
def _SLASH_Fi : CLCompileJoined<"Fi">,
HelpText<"Set preprocess output file name">,
HelpText<"Set preprocess output file name (with /P)">,
MetaVarName<"<file>">;
def _SLASH_Fo : CLCompileJoined<"Fo">,
HelpText<"Set output object file, or directory (ends in / or \\)">,
HelpText<"Set output object file, or directory (ends in / or \\) (with /c)">,
MetaVarName<"<file or directory>">;
def _SLASH_LD : CLFlag<"LD">, HelpText<"Create DLL">;
def _SLASH_LDd : CLFlag<"LDd">, HelpText<"Create debug DLL">;

View File

@ -405,12 +405,12 @@ class Driver {
bool IsUsingLTO(const llvm::opt::ArgList &Args) const;
private:
/// \brief Retrieves a ToolChain for a particular target triple.
/// \brief Retrieves a ToolChain for a particular \p Target triple.
///
/// Will cache ToolChains for the life of the driver object, and create them
/// on-demand.
const ToolChain &getToolChain(const llvm::opt::ArgList &Args,
StringRef DarwinArchName = "") const;
const llvm::Triple &Target) const;
/// @}

View File

@ -106,6 +106,9 @@ class Command {
const char *getExecutable() const { return Executable; }
const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
/// Print a command argument, and optionally quote it.
static void printArg(llvm::raw_ostream &OS, const char *Arg, bool Quote);
};
/// Like Command, but with a fallback which is executed in case

View File

@ -351,6 +351,12 @@ def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group<clang_i_Group>,
MetaVarName<"<directory>">;
def c : Flag<["-"], "c">, Flags<[DriverOption]>,
HelpText<"Only run preprocess, compile, and assemble steps">;
def cuda_device_only : Flag<["--"], "cuda-device-only">,
HelpText<"Do device-side CUDA compilation only">;
def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">,
Flags<[DriverOption, HelpHidden]>, HelpText<"CUDA GPU architecture">;
def cuda_host_only : Flag<["--"], "cuda-host-only">,
HelpText<"Do host-side CUDA compilation only">;
def dA : Flag<["-"], "dA">, Group<d_Group>;
def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
@ -422,13 +428,24 @@ def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">,
def fprofile_instr_generate_EQ : Joined<["-"], "fprofile-instr-generate=">,
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<file>">,
HelpText<"Generate instrumented code to collect execution counts into <file> (overridden by LLVM_PROFILE_FILE env var)">;
def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>;
def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>,
Flags<[DriverOption]>;
def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use instrumentation data for profile-guided optimization">;
def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Generate coverage mapping to enable code coverage analysis">;
def fprofile_generate : Flag<["-"], "fprofile-generate">,
Alias<fprofile_instr_generate>;
def fprofile_generate_EQ : Joined<["-"], "fprofile-generate=">,
Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<directory>">,
HelpText<"Generate instrumented code to collect execution counts into <directory>/default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
def fprofile_use : Flag<["-"], "fprofile-use">, Group<f_Group>,
Alias<fprofile_instr_use>;
def fprofile_use_EQ : Joined<["-"], "fprofile-use=">,
Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<pathname>">,
HelpText<"Use instrumentation data for profile-guided optimization. If pathname is a directory, it reads from <pathname>/default.profdata. Otherwise, it reads from file <pathname>.">;
def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable the 'blocks' language feature">;
@ -522,7 +539,8 @@ def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
Flags<[CC1Option, CoreOption]>, MetaVarName<"<check>">,
HelpText<"Turn on runtime checks for various forms of undefined "
"or suspicious behavior. See user manual for available checks ">;
def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>;
def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>,
Flags<[CoreOption]>;
def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
Group<f_clang_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Path to blacklist file for sanitizers">;
@ -547,24 +565,29 @@ def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins
def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Disable origins tracking in MemorySanitizer">;
def fsanitize_memory_use_after_dtor : Flag<["-"], "fsanitize-memory-use-after-dtor">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Enable use-after-destroy detection in MemorySanitizer">;
def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-padding=">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Level of field padding for AddressSanitizer">;
def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>;
def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>,
Flags<[CoreOption]>;
def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">,
Group<f_clang_Group>;
Group<f_clang_Group>, Flags<[CoreOption]>;
def fsanitize_recover_EQ : CommaJoined<["-"], "fsanitize-recover=">,
Group<f_clang_Group>,
Flags<[CC1Option]>,
Flags<[CC1Option, CoreOption]>,
HelpText<"Enable recovery for specified sanitizers">;
def fno_sanitize_recover_EQ
: CommaJoined<["-"], "fno-sanitize-recover=">,
Group<f_clang_Group>,
Group<f_clang_Group>, Flags<[CoreOption]>,
HelpText<"Disable recovery for specified sanitizers">;
def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Group>,
Flags<[CC1Option, CoreOption]>,
HelpText<"Enable trapping for specified sanitizers">;
def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>,
Flags<[CoreOption]>,
HelpText<"Disable trapping for specified sanitizers">;
def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">,
Group<f_clang_Group>;
@ -641,7 +664,7 @@ def flat__namespace : Flag<["-"], "flat_namespace">;
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def flto_EQ : Joined<["-"], "flto=">, Group<clang_ignored_gcc_optimization_f_Group>;
def flto : Flag<["-"], "flto">, Group<f_Group>;
def flto : Flag<["-"], "flto">, Flags<[CC1Option]>, Group<f_Group>;
def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>;
def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
Group<f_Group>, Flags<[DriverOption, CoreOption]>;
@ -879,6 +902,8 @@ def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>;
def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>;
def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>, Flags<[NoArgumentUnused]>;
def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
@ -904,7 +929,6 @@ def fpie : Flag<["-"], "fpie">, Group<f_Group>;
def fno_pie : Flag<["-"], "fno-pie">, Group<f_Group>;
def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group<f_Group>;
def fno_profile_arcs : Flag<["-"], "fno-profile-arcs">, Group<f_Group>;
def fprofile_generate : Flag<["-"], "fprofile-generate">, Group<f_Group>;
def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>;
def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group<clang_ignored_f_Group>;
def freg_struct_return : Flag<["-"], "freg-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
@ -1518,7 +1542,8 @@ def print_libgcc_file_name : Flag<["-", "--"], "print-libgcc-file-name">,
HelpText<"Print the library path for \"libgcc.a\"">;
def print_multi_directory : Flag<["-", "--"], "print-multi-directory">;
def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">;
def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
Flags<[Unsupported]>;
def print_prog_name_EQ : Joined<["-", "--"], "print-prog-name=">,
HelpText<"Print the full program path of <name>">, MetaVarName<"<name>">;
def print_search_dirs : Flag<["-", "--"], "print-search-dirs">,
@ -1527,6 +1552,7 @@ def private__bundle : Flag<["-"], "private_bundle">;
def pthreads : Flag<["-"], "pthreads">;
def pthread : Flag<["-"], "pthread">, Flags<[CC1Option]>,
HelpText<"Support POSIX threads in generated code">;
def no_pthread : Flag<["-"], "no-pthread">, Flags<[CC1Option]>;
def p : Flag<["-"], "p">;
def pie : Flag<["-"], "pie">;
def read__only__relocs : Separate<["-"], "read_only_relocs">;
@ -1793,8 +1819,6 @@ defm : BooleanFFlag<"keep-inline-functions">, Group<clang_ignored_gcc_optimizati
def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_gcc_optimization_f_Group>;
defm profile_use : BooleanFFlag<"profile-use">, Group<clang_ignored_gcc_optimization_f_Group>;
def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Group<clang_ignored_gcc_optimization_f_Group>;
def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>;
defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_gcc_optimization_f_Group>;

View File

@ -29,6 +29,7 @@ class SanitizerArgs {
std::vector<std::string> BlacklistFiles;
int CoverageFeatures;
int MsanTrackOrigins;
bool MsanUseAfterDtor;
int AsanFieldPadding;
bool AsanZeroBaseShadow;
bool AsanSharedRuntime;

View File

@ -44,6 +44,7 @@ TYPE("c", C, PP_C, "c", "u")
TYPE("cl", CL, PP_C, "cl", "u")
TYPE("cuda-cpp-output", PP_CUDA, INVALID, "cui", "u")
TYPE("cuda", CUDA, PP_CUDA, "cu", "u")
TYPE("cuda", CUDA_DEVICE, PP_CUDA, "cu", "")
TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", "u")
TYPE("objective-c", ObjC, PP_ObjC, "m", "u")

View File

@ -63,6 +63,9 @@ namespace types {
/// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
bool isCXX(ID Id);
/// isCuda - Is this a CUDA input.
bool isCuda(ID Id);
/// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
bool isObjC(ID Id);

View File

@ -166,6 +166,9 @@ struct FormatStyle {
/// Like \c Attach, but break before braces on function, namespace and
/// class definitions.
BS_Linux,
/// Like ``Attach``, but break before braces on enum, function, and record
/// definitions.
BS_Mozilla,
/// Like \c Attach, but break before function definitions, and 'else'.
BS_Stroustrup,
/// Always break before braces.
@ -290,6 +293,12 @@ struct FormatStyle {
/// \brief Language, this format style is targeted at.
LanguageKind Language;
/// \brief A regular expression matching macros that start a block.
std::string MacroBlockBegin;
/// \brief A regular expression matching macros that end a block.
std::string MacroBlockEnd;
/// \brief The maximum number of consecutive empty lines to keep.
unsigned MaxEmptyLinesToKeep;
@ -479,6 +488,8 @@ struct FormatStyle {
IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
KeepEmptyLinesAtTheStartOfBlocks ==
R.KeepEmptyLinesAtTheStartOfBlocks &&
MacroBlockBegin == R.MacroBlockBegin &&
MacroBlockEnd == R.MacroBlockEnd &&
MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
NamespaceIndentation == R.NamespaceIndentation &&
ObjCBlockIndentWidth == R.ObjCBlockIndentWidth &&

View File

@ -67,6 +67,8 @@ CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is
CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to
///< be generated.
CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the
///< compile step.
CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants.
CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled.
CODEGENOPT(MSVolatile , 1, 0) ///< Set when /volatile:ms is enabled.
@ -110,6 +112,8 @@ CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero
///< offset in AddressSanitizer.
CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
///< MemorySanitizer
CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection
///< in MemorySanitizer
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
///< instrumentation.
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage

View File

@ -155,6 +155,7 @@ class CodeGenOptions : public CodeGenOptionsBase {
std::vector<std::string> DependentLibraries;
/// Name of the profile file to use as output for -fprofile-instr-generate
/// and -fprofile-generate.
std::string InstrProfileOutput;
/// Name of the profile file to use with -fprofile-sample-use.

View File

@ -30,6 +30,7 @@
namespace llvm {
class raw_fd_ostream;
class Timer;
class TimerGroup;
}
namespace clang {
@ -101,7 +102,10 @@ class CompilerInstance : public ModuleLoader {
/// \brief The semantic analysis object.
std::unique_ptr<Sema> TheSema;
/// \brief The frontend timer
/// \brief The frontend timer group.
std::unique_ptr<llvm::TimerGroup> FrontendTimerGroup;
/// \brief The frontend timer.
std::unique_ptr<llvm::Timer> FrontendTimer;
/// \brief The ASTReader, if one exists.
@ -157,9 +161,10 @@ class CompilerInstance : public ModuleLoader {
std::string TempFilename;
std::unique_ptr<raw_ostream> OS;
OutputFile(const std::string &filename, const std::string &tempFilename,
OutputFile(std::string filename, std::string tempFilename,
std::unique_ptr<raw_ostream> OS)
: Filename(filename), TempFilename(tempFilename), OS(std::move(OS)) {}
: Filename(std::move(filename)), TempFilename(std::move(tempFilename)),
OS(std::move(OS)) {}
OutputFile(OutputFile &&O)
: Filename(std::move(O.Filename)),
TempFilename(std::move(O.TempFilename)), OS(std::move(O.OS)) {}
@ -614,7 +619,7 @@ class CompilerInstance : public ModuleLoader {
///
/// \return - The new object on success, or null on failure.
static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource(
StringRef Path, const std::string &Sysroot, bool DisablePCHValidation,
StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
const PCHContainerOperations &PCHContainerOps,
void *DeserializationListener, bool OwnDeserializationListener,
@ -627,11 +632,9 @@ class CompilerInstance : public ModuleLoader {
/// Create a code completion consumer to print code completion results, at
/// \p Filename, \p Line, and \p Column, to the given output stream \p OS.
static CodeCompleteConsumer *
createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename,
unsigned Line, unsigned Column,
const CodeCompleteOptions &Opts,
raw_ostream &OS);
static CodeCompleteConsumer *createCodeCompletionConsumer(
Preprocessor &PP, StringRef Filename, unsigned Line, unsigned Column,
const CodeCompleteOptions &Opts, raw_ostream &OS);
/// \brief Create the Sema object to be used for parsing.
void createSema(TranslationUnitKind TUKind,

View File

@ -452,9 +452,13 @@ class ModuleMap {
/// \param HomeDir The directory in which relative paths within this module
/// map file will be resolved.
///
/// \param ExternModuleLoc The location of the "extern module" declaration
/// that caused us to load this module map file, if any.
///
/// \returns true if an error occurred, false otherwise.
bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
const DirectoryEntry *HomeDir);
const DirectoryEntry *HomeDir,
SourceLocation ExternModuleLoc = SourceLocation());
/// \brief Dump the contents of the module map, for debugging purposes.
void dump();

View File

@ -786,6 +786,22 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
(!getLangOpts().Modules || (bool)getMacroDefinition(II));
}
/// \brief Determine whether II is defined as a macro within the module M,
/// if that is a module that we've already preprocessed. Does not check for
/// macros imported into M.
bool isMacroDefinedInLocalModule(const IdentifierInfo *II, Module *M) {
if (!II->hasMacroDefinition())
return false;
auto I = Submodules.find(M);
if (I == Submodules.end())
return false;
auto J = I->second.Macros.find(II);
if (J == I->second.Macros.end())
return false;
auto *MD = J->second.getLatest();
return MD && MD->isDefined();
}
MacroDefinition getMacroDefinition(const IdentifierInfo *II) {
if (!II->hasMacroDefinition())
return MacroDefinition();

View File

@ -46,6 +46,8 @@ namespace clang {
class PoisonSEHIdentifiersRAIIObject;
class VersionTuple;
class OMPClause;
class ObjCTypeParamList;
class ObjCTypeParameter;
/// Parser - This implements a parser for the C family of languages. After
/// parsing units of the grammar, productions are invoked to handle whatever has
@ -1246,6 +1248,13 @@ class Parser : public CodeCompletionHandler {
DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
ParsedAttributes &prefixAttrs);
ObjCTypeParamList *parseObjCTypeParamList();
ObjCTypeParamList *parseObjCTypeParamListOrProtocolRefs(
SourceLocation &lAngleLoc,
SmallVectorImpl<IdentifierLocPair> &protocolIdents,
SourceLocation &rAngleLoc,
bool mayBeProtocolList = true);
void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
BalancedDelimiterTracker &T,
SmallVectorImpl<Decl *> &AllIvarDecls,
@ -1258,8 +1267,48 @@ class Parser : public CodeCompletionHandler {
bool WarnOnDeclarations,
bool ForObjCContainer,
SourceLocation &LAngleLoc,
SourceLocation &EndProtoLoc);
bool ParseObjCProtocolQualifiers(DeclSpec &DS);
SourceLocation &EndProtoLoc,
bool consumeLastToken);
/// Parse the first angle-bracket-delimited clause for an
/// Objective-C object or object pointer type, which may be either
/// type arguments or protocol qualifiers.
void parseObjCTypeArgsOrProtocolQualifiers(
ParsedType baseType,
SourceLocation &typeArgsLAngleLoc,
SmallVectorImpl<ParsedType> &typeArgs,
SourceLocation &typeArgsRAngleLoc,
SourceLocation &protocolLAngleLoc,
SmallVectorImpl<Decl *> &protocols,
SmallVectorImpl<SourceLocation> &protocolLocs,
SourceLocation &protocolRAngleLoc,
bool consumeLastToken,
bool warnOnIncompleteProtocols);
/// Parse either Objective-C type arguments or protocol qualifiers; if the
/// former, also parse protocol qualifiers afterward.
void parseObjCTypeArgsAndProtocolQualifiers(
ParsedType baseType,
SourceLocation &typeArgsLAngleLoc,
SmallVectorImpl<ParsedType> &typeArgs,
SourceLocation &typeArgsRAngleLoc,
SourceLocation &protocolLAngleLoc,
SmallVectorImpl<Decl *> &protocols,
SmallVectorImpl<SourceLocation> &protocolLocs,
SourceLocation &protocolRAngleLoc,
bool consumeLastToken);
/// Parse a protocol qualifier type such as '<NSCopying>', which is
/// an anachronistic way of writing 'id<NSCopying>'.
TypeResult parseObjCProtocolQualifierType(SourceLocation &rAngleLoc);
/// Parse Objective-C type arguments and protocol qualifiers, extending the
/// current type with the parsed result.
TypeResult parseObjCTypeArgsAndProtocolQualifiers(SourceLocation loc,
ParsedType type,
bool consumeLastToken,
SourceLocation &endLoc);
void ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
Decl *CDecl);
DeclGroupPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
@ -2469,7 +2518,8 @@ class Parser : public CodeCompletionHandler {
typedef SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
bool ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
bool ConsumeLastToken);
bool ConsumeLastToken,
bool ObjCGenericList);
bool ParseTemplateIdAfterTemplateName(TemplateTy Template,
SourceLocation TemplateNameLoc,
const CXXScopeSpec &SS,

View File

@ -765,11 +765,13 @@ class CodeCompletionResult {
/// \param Allocator The allocator that will be used to allocate the
/// string itself.
CodeCompletionString *CreateCodeCompletionString(Sema &S,
const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments);
CodeCompletionString *CreateCodeCompletionString(ASTContext &Ctx,
Preprocessor &PP,
const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments);

View File

@ -373,14 +373,6 @@ class DeclSpec {
// Scope specifier for the type spec, if applicable.
CXXScopeSpec TypeScope;
// List of protocol qualifiers for objective-c classes. Used for
// protocol-qualified interfaces "NString<foo>" and protocol-qualified id
// "id<foo>".
Decl * const *ProtocolQualifiers;
unsigned NumProtocolQualifiers;
SourceLocation ProtocolLAngleLoc;
SourceLocation *ProtocolLocs;
// SourceLocation info. These are null if the item wasn't specified or if
// the setting was synthesized.
SourceRange Range;
@ -442,16 +434,10 @@ class DeclSpec {
Constexpr_specified(false),
Concept_specified(false),
Attrs(attrFactory),
ProtocolQualifiers(nullptr),
NumProtocolQualifiers(0),
ProtocolLocs(nullptr),
writtenBS(),
ObjCQualifiers(nullptr) {
}
~DeclSpec() {
delete [] ProtocolQualifiers;
delete [] ProtocolLocs;
}
// storage-class-specifier
SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
TSCS getThreadStorageClassSpec() const {
@ -490,6 +476,8 @@ class DeclSpec {
bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; }
bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
bool isTypeSpecOwned() const { return TypeSpecOwned; }
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
ParsedType getRepAsType() const {
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
return TypeRep;
@ -751,19 +739,6 @@ class DeclSpec {
Attrs.takeAllFrom(attrs);
}
typedef Decl * const *ProtocolQualifierListTy;
ProtocolQualifierListTy getProtocolQualifiers() const {
return ProtocolQualifiers;
}
SourceLocation *getProtocolLocs() const { return ProtocolLocs; }
unsigned getNumProtocolQualifiers() const {
return NumProtocolQualifiers;
}
SourceLocation getProtocolLAngleLoc() const { return ProtocolLAngleLoc; }
void setProtocolQualifiers(Decl * const *Protos, unsigned NP,
SourceLocation *ProtoLocs,
SourceLocation LAngleLoc);
/// Finish - This does final analysis of the declspec, issuing diagnostics for
/// things like "_Imaginary" (lacking an FP type). After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.

View File

@ -1387,7 +1387,8 @@ class Sema {
/// Determine if \p D has a visible definition. If not, suggest a declaration
/// that should be made visible to expose the definition.
bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested);
bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
bool OnlyNeedComplete = false);
bool hasVisibleDefinition(const NamedDecl *D) {
NamedDecl *Hidden;
return hasVisibleDefinition(const_cast<NamedDecl*>(D), &Hidden);
@ -1848,7 +1849,7 @@ class Sema {
bool isAcceptableTagRedeclaration(const TagDecl *Previous,
TagTypeKind NewTag, bool isDefinition,
SourceLocation NewTagLoc,
const IdentifierInfo &Name);
const IdentifierInfo *Name);
enum TagUseKind {
TUK_Reference, // Reference to a tag: 'struct foo *X;'
@ -2187,6 +2188,7 @@ class Sema {
void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
QualType FromType, QualType ToType);
void maybeExtendBlockObject(ExprResult &E);
CastKind PrepareCastToObjCObjectPointer(ExprResult &E);
bool CheckPointerConversion(Expr *From, QualType ToType,
CastKind &Kind,
@ -7088,16 +7090,44 @@ class Sema {
};
ObjCContainerKind getObjCContainerKind() const;
Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
DeclResult actOnObjCTypeParam(Scope *S,
ObjCTypeParamVariance variance,
SourceLocation varianceLoc,
unsigned index,
IdentifierInfo *paramName,
SourceLocation paramLoc,
SourceLocation colonLoc,
ParsedType typeBound);
ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
ArrayRef<Decl *> typeParams,
SourceLocation rAngleLoc);
void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
Decl *ActOnStartClassInterface(Scope *S,
SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName,
SourceLocation ClassLoc,
ObjCTypeParamList *typeParamList,
IdentifierInfo *SuperName,
SourceLocation SuperLoc,
ArrayRef<ParsedType> SuperTypeArgs,
SourceRange SuperTypeArgsRange,
Decl * const *ProtoRefs,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList);
void ActOnSuperClassOfClassInterface(Scope *S,
SourceLocation AtInterfaceLoc,
ObjCInterfaceDecl *IDecl,
IdentifierInfo *ClassName,
SourceLocation ClassLoc,
IdentifierInfo *SuperName,
SourceLocation SuperLoc,
ArrayRef<ParsedType> SuperTypeArgs,
SourceRange SuperTypeArgsRange);
void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
IdentifierInfo *SuperName,
@ -7124,6 +7154,7 @@ class Sema {
Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName,
SourceLocation ClassLoc,
ObjCTypeParamList *typeParamList,
IdentifierInfo *CategoryName,
SourceLocation CategoryLoc,
Decl * const *ProtoRefs,
@ -7147,9 +7178,10 @@ class Sema {
ArrayRef<Decl *> Decls);
DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
IdentifierInfo **IdentList,
SourceLocation *IdentLocs,
unsigned NumElts);
IdentifierInfo **IdentList,
SourceLocation *IdentLocs,
ArrayRef<ObjCTypeParamList *> TypeParamLists,
unsigned NumElts);
DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
const IdentifierLocPair *IdentList,
@ -7161,6 +7193,61 @@ class Sema {
unsigned NumProtocols,
SmallVectorImpl<Decl *> &Protocols);
/// Given a list of identifiers (and their locations), resolve the
/// names to either Objective-C protocol qualifiers or type
/// arguments, as appropriate.
void actOnObjCTypeArgsOrProtocolQualifiers(
Scope *S,
ParsedType baseType,
SourceLocation lAngleLoc,
ArrayRef<IdentifierInfo *> identifiers,
ArrayRef<SourceLocation> identifierLocs,
SourceLocation rAngleLoc,
SourceLocation &typeArgsLAngleLoc,
SmallVectorImpl<ParsedType> &typeArgs,
SourceLocation &typeArgsRAngleLoc,
SourceLocation &protocolLAngleLoc,
SmallVectorImpl<Decl *> &protocols,
SourceLocation &protocolRAngleLoc,
bool warnOnIncompleteProtocols);
/// Build a an Objective-C protocol-qualified 'id' type where no
/// base type was specified.
TypeResult actOnObjCProtocolQualifierType(
SourceLocation lAngleLoc,
ArrayRef<Decl *> protocols,
ArrayRef<SourceLocation> protocolLocs,
SourceLocation rAngleLoc);
/// Build a specialized and/or protocol-qualified Objective-C type.
TypeResult actOnObjCTypeArgsAndProtocolQualifiers(
Scope *S,
SourceLocation Loc,
ParsedType BaseType,
SourceLocation TypeArgsLAngleLoc,
ArrayRef<ParsedType> TypeArgs,
SourceLocation TypeArgsRAngleLoc,
SourceLocation ProtocolLAngleLoc,
ArrayRef<Decl *> Protocols,
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc);
/// Build an Objective-C object pointer type.
QualType BuildObjCObjectType(QualType BaseType,
SourceLocation Loc,
SourceLocation TypeArgsLAngleLoc,
ArrayRef<TypeSourceInfo *> TypeArgs,
SourceLocation TypeArgsRAngleLoc,
SourceLocation ProtocolLAngleLoc,
ArrayRef<ObjCProtocolDecl *> Protocols,
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc,
bool FailOnError = false);
/// Check the application of the Objective-C '__kindof' qualifier to
/// the given type.
bool checkObjCKindOfType(QualType &type, SourceLocation loc);
/// Ensure attributes are consistent with type.
/// \param [in, out] Attributes The attributes to check; they will
/// be modified to be consistent with \p PropertyTy.
@ -7610,13 +7697,13 @@ class Sema {
void DestroyDataSharingAttributesStack();
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op,
OpenMPClauseKind CKind);
/// \brief Checks if the specified variable is used in one of the private
public:
/// \brief Check if the specified variable is used in a private clause in
/// Checks if the specified variable is used in one of the private
/// clauses in OpenMP constructs.
bool IsOpenMPCapturedVar(VarDecl *VD);
public:
/// \brief Check if the specified variable is used in one of the private
/// clauses in OpenMP constructs.
/// OpenMP constructs.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
bool isOpenMPPrivateVar(VarDecl *VD, unsigned Level);

View File

@ -413,6 +413,7 @@ namespace clang {
#define LINKAGESPEC(DERIVED, BASE)
#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
#define OBJCMETHOD(DERIVED, BASE)
#define OBJCTYPEPARAM(DERIVED, BASE)
#define OBJCIVAR(DERIVED, BASE)
#define OBJCPROPERTY(DERIVED, BASE)
#define OBJCPROPERTYIMPL(DERIVED, BASE)

View File

@ -1105,7 +1105,9 @@ namespace clang {
/// \brief An OMPThreadPrivateDecl record.
DECL_OMP_THREADPRIVATE,
/// \brief An EmptyDecl record.
DECL_EMPTY
DECL_EMPTY,
/// \brief An ObjCTypeParamDecl record.
DECL_OBJC_TYPE_PARAM,
};
/// \brief Record codes for each kind of statement or expression.

View File

@ -42,6 +42,7 @@
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Timer.h"
#include <deque>
#include <map>
#include <memory>
@ -380,6 +381,9 @@ class ASTReader
/// \brief The module manager which manages modules and their dependencies
ModuleManager ModuleMgr;
/// \brief A timer used to track the time spent deserializing.
std::unique_ptr<llvm::Timer> ReadTimer;
/// \brief The location where the module file will be considered as
/// imported from. For non-module AST types it should be invalid.
SourceLocation CurrentImportLoc;
@ -976,12 +980,14 @@ class ASTReader
MergedLookups;
typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> >
MergedDeclsMap;
KeyDeclsMap;
/// \brief A mapping from canonical declarations to the set of additional
/// (global, previously-canonical) declaration IDs that have been merged with
/// that canonical declaration.
MergedDeclsMap MergedDecls;
/// \brief A mapping from canonical declarations to the set of global
/// declaration IDs for key declaration that have been merged with that
/// canonical declaration. A key declaration is a formerly-canonical
/// declaration whose module did not import any other key declaration for that
/// entity. These are the IDs that we use as keys when finding redecl chains.
KeyDeclsMap KeyDecls;
/// \brief A mapping from DeclContexts to the semantic DeclContext that we
/// are treating as the definition of the entity. This is used, for instance,
@ -1054,6 +1060,36 @@ class ASTReader
void ResolveImportedPath(ModuleFile &M, std::string &Filename);
static void ResolveImportedPath(std::string &Filename, StringRef Prefix);
/// \brief Returns the first key declaration for the given declaration. This
/// is one that is formerly-canonical (or still canonical) and whose module
/// did not import any other key declaration of the entity.
Decl *getKeyDeclaration(Decl *D) {
D = D->getCanonicalDecl();
if (D->isFromASTFile())
return D;
auto I = KeyDecls.find(D);
if (I == KeyDecls.end() || I->second.empty())
return D;
return GetExistingDecl(I->second[0]);
}
const Decl *getKeyDeclaration(const Decl *D) {
return getKeyDeclaration(const_cast<Decl*>(D));
}
/// \brief Run a callback on each imported key declaration of \p D.
template <typename Fn>
void forEachImportedKeyDecl(const Decl *D, Fn Visit) {
D = D->getCanonicalDecl();
if (D->isFromASTFile())
Visit(D);
auto It = KeyDecls.find(const_cast<Decl*>(D));
if (It != KeyDecls.end())
for (auto ID : It->second)
Visit(GetExistingDecl(ID));
}
private:
struct ImportedModule {
ModuleFile *Mod;
@ -1124,18 +1160,6 @@ class ASTReader
/// merged into its redecl chain.
Decl *getMostRecentExistingDecl(Decl *D);
template <typename Fn>
void forEachFormerlyCanonicalImportedDecl(const Decl *D, Fn Visit) {
D = D->getCanonicalDecl();
if (D->isFromASTFile())
Visit(D);
auto It = MergedDecls.find(const_cast<Decl*>(D));
if (It != MergedDecls.end())
for (auto ID : It->second)
Visit(GetExistingDecl(ID));
}
RecordLocation DeclCursorForID(serialization::DeclID ID,
unsigned &RawLocation);
void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
@ -1261,12 +1285,16 @@ class ASTReader
///
/// \param UseGlobalIndex If true, the AST reader will try to load and use
/// the global module index.
///
/// \param ReadTimer If non-null, a timer used to track the time spent
/// deserializing.
ASTReader(Preprocessor &PP, ASTContext &Context,
const PCHContainerOperations &PCHContainerOps,
StringRef isysroot = "", bool DisableValidation = false,
bool AllowASTWithCompilerErrors = false,
bool AllowConfigurationMismatch = false,
bool ValidateSystemInputs = false, bool UseGlobalIndex = true);
bool ValidateSystemInputs = false, bool UseGlobalIndex = true,
std::unique_ptr<llvm::Timer> ReadTimer = {});
~ASTReader() override;
@ -1690,7 +1718,7 @@ class ASTReader
/// \brief Notify ASTReader that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
void StartedDeserializing() override { ++NumCurrentElementsDeserializing; }
void StartedDeserializing() override;
/// \brief Notify ASTReader that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.

View File

@ -398,7 +398,7 @@ class ASTWriter : public ASTDeserializationListener,
/// \brief The set of declarations that may have redeclaration chains that
/// need to be serialized.
llvm::SmallSetVector<Decl *, 4> Redeclarations;
llvm::SmallVector<const Decl *, 16> Redeclarations;
/// \brief Statements that we've encountered while serializing a
/// declaration or type.

View File

@ -64,6 +64,9 @@
#endif
namespace clang {
class DiagnosticsEngine;
class AnalyzerOptions;
namespace ento {
class CheckerOptInfo;
@ -118,6 +121,10 @@ class CheckerRegistry {
void initializeManager(CheckerManager &mgr,
SmallVectorImpl<CheckerOptInfo> &opts) const;
/// Check if every option corresponds to a specific checker or package.
void validateCheckerOptions(const AnalyzerOptions &opts,
DiagnosticsEngine &diags) const;
/// Prints the name and description of all checkers in this registry.
/// This output is not intended to be machine-parseable.
void printHelp(raw_ostream &out, size_t maxNameChars = 30) const ;

View File

@ -1917,11 +1917,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
// We can use protocol_iterator here instead of
// all_referenced_protocol_iterator since we are walking all categories.
for (auto *Proto : OI->all_referenced_protocols()) {
Protocols.insert(Proto->getCanonicalDecl());
for (auto *P : Proto->protocols()) {
Protocols.insert(P->getCanonicalDecl());
CollectInheritedProtocols(P, Protocols);
}
CollectInheritedProtocols(Proto, Protocols);
}
// Categories of this Interface.
@ -1935,16 +1931,16 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
}
} else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
for (auto *Proto : OC->protocols()) {
Protocols.insert(Proto->getCanonicalDecl());
for (const auto *P : Proto->protocols())
CollectInheritedProtocols(P, Protocols);
CollectInheritedProtocols(Proto, Protocols);
}
} else if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) {
for (auto *Proto : OP->protocols()) {
Protocols.insert(Proto->getCanonicalDecl());
for (const auto *P : Proto->protocols())
CollectInheritedProtocols(P, Protocols);
}
// Insert the protocol.
if (!Protocols.insert(
const_cast<ObjCProtocolDecl *>(OP->getCanonicalDecl())).second)
return;
for (auto *Proto : OP->protocols())
CollectInheritedProtocols(Proto, Protocols);
}
}
@ -3618,45 +3614,89 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
QualType ASTContext::getObjCObjectType(QualType BaseType,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) const {
// If the base type is an interface and there aren't any protocols
// to add, then the interface type will do just fine.
if (!NumProtocols && isa<ObjCInterfaceType>(BaseType))
return BaseType;
return getObjCObjectType(BaseType, { },
llvm::makeArrayRef(Protocols, NumProtocols),
/*isKindOf=*/false);
}
QualType ASTContext::getObjCObjectType(
QualType baseType,
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf) const {
// If the base type is an interface and there aren't any protocols or
// type arguments to add, then the interface type will do just fine.
if (typeArgs.empty() && protocols.empty() && !isKindOf &&
isa<ObjCInterfaceType>(baseType))
return baseType;
// Look in the folding set for an existing type.
llvm::FoldingSetNodeID ID;
ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols);
ObjCObjectTypeImpl::Profile(ID, baseType, typeArgs, protocols, isKindOf);
void *InsertPos = nullptr;
if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
// Build the canonical type, which has the canonical base type and
// a sorted-and-uniqued list of protocols.
QualType Canonical;
bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols);
if (!ProtocolsSorted || !BaseType.isCanonical()) {
if (!ProtocolsSorted) {
SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
Protocols + NumProtocols);
unsigned UniqueCount = NumProtocols;
// Determine the type arguments to be used for canonicalization,
// which may be explicitly specified here or written on the base
// type.
ArrayRef<QualType> effectiveTypeArgs = typeArgs;
if (effectiveTypeArgs.empty()) {
if (auto baseObject = baseType->getAs<ObjCObjectType>())
effectiveTypeArgs = baseObject->getTypeArgs();
}
SortAndUniqueProtocols(&Sorted[0], UniqueCount);
Canonical = getObjCObjectType(getCanonicalType(BaseType),
&Sorted[0], UniqueCount);
// Build the canonical type, which has the canonical base type and a
// sorted-and-uniqued list of protocols and the type arguments
// canonicalized.
QualType canonical;
bool typeArgsAreCanonical = std::all_of(effectiveTypeArgs.begin(),
effectiveTypeArgs.end(),
[&](QualType type) {
return type.isCanonical();
});
bool protocolsSorted = areSortedAndUniqued(protocols.data(),
protocols.size());
if (!typeArgsAreCanonical || !protocolsSorted || !baseType.isCanonical()) {
// Determine the canonical type arguments.
ArrayRef<QualType> canonTypeArgs;
SmallVector<QualType, 4> canonTypeArgsVec;
if (!typeArgsAreCanonical) {
canonTypeArgsVec.reserve(effectiveTypeArgs.size());
for (auto typeArg : effectiveTypeArgs)
canonTypeArgsVec.push_back(getCanonicalType(typeArg));
canonTypeArgs = canonTypeArgsVec;
} else {
Canonical = getObjCObjectType(getCanonicalType(BaseType),
Protocols, NumProtocols);
canonTypeArgs = effectiveTypeArgs;
}
ArrayRef<ObjCProtocolDecl *> canonProtocols;
SmallVector<ObjCProtocolDecl*, 8> canonProtocolsVec;
if (!protocolsSorted) {
canonProtocolsVec.insert(canonProtocolsVec.begin(),
protocols.begin(),
protocols.end());
unsigned uniqueCount = protocols.size();
SortAndUniqueProtocols(&canonProtocolsVec[0], uniqueCount);
canonProtocols = llvm::makeArrayRef(&canonProtocolsVec[0], uniqueCount);
} else {
canonProtocols = protocols;
}
canonical = getObjCObjectType(getCanonicalType(baseType), canonTypeArgs,
canonProtocols, isKindOf);
// Regenerate InsertPos.
ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos);
}
unsigned Size = sizeof(ObjCObjectTypeImpl);
Size += NumProtocols * sizeof(ObjCProtocolDecl *);
void *Mem = Allocate(Size, TypeAlignment);
unsigned size = sizeof(ObjCObjectTypeImpl);
size += typeArgs.size() * sizeof(QualType);
size += protocols.size() * sizeof(ObjCProtocolDecl *);
void *mem = Allocate(size, TypeAlignment);
ObjCObjectTypeImpl *T =
new (Mem) ObjCObjectTypeImpl(Canonical, BaseType, Protocols, NumProtocols);
new (mem) ObjCObjectTypeImpl(canonical, baseType, typeArgs, protocols,
isKindOf);
Types.push_back(T);
ObjCObjectTypes.InsertNode(T, InsertPos);
@ -5623,13 +5663,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
case Type::ObjCInterface: {
// Ignore protocol qualifiers when mangling at this level.
T = T->castAs<ObjCObjectType>()->getBaseType();
// The assumption seems to be that this assert will succeed
// because nested levels will have filtered out 'id' and 'Class'.
const ObjCInterfaceType *OIT = T->castAs<ObjCInterfaceType>();
// @encode(class_name)
ObjCInterfaceDecl *OI = OIT->getDecl();
ObjCInterfaceDecl *OI = T->castAs<ObjCObjectType>()->getInterface();
S += '{';
S += OI->getObjCRuntimeNameAsString();
S += '=';
@ -5921,7 +5956,7 @@ void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
TypedefDecl *ASTContext::getObjCIdDecl() const {
if (!ObjCIdDecl) {
QualType T = getObjCObjectType(ObjCBuiltinIdTy, nullptr, 0);
QualType T = getObjCObjectType(ObjCBuiltinIdTy, { }, { });
T = getObjCObjectPointerType(T);
ObjCIdDecl = buildImplicitTypedef(T, "id");
}
@ -5938,7 +5973,7 @@ TypedefDecl *ASTContext::getObjCSelDecl() const {
TypedefDecl *ASTContext::getObjCClassDecl() const {
if (!ObjCClassDecl) {
QualType T = getObjCObjectType(ObjCBuiltinClassTy, nullptr, 0);
QualType T = getObjCObjectType(ObjCBuiltinClassTy, { }, { });
T = getObjCObjectPointerType(T);
ObjCClassDecl = buildImplicitTypedef(T, "Class");
}
@ -5951,6 +5986,7 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const {
= ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(),
&Idents.get("Protocol"),
/*typeParamList=*/nullptr,
/*PrevDecl=*/nullptr,
SourceLocation(), true);
}
@ -6743,18 +6779,36 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
RHS->isObjCUnqualifiedIdOrClass())
return true;
if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId())
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false);
// Function object that propagates a successful result or handles
// __kindof types.
auto finish = [&](bool succeeded) -> bool {
if (succeeded)
return true;
if (!RHS->isKindOfType())
return false;
// Strip off __kindof and protocol qualifiers, then check whether
// we can assign the other way.
return canAssignObjCInterfaces(RHSOPT->stripObjCKindOfTypeAndQuals(*this),
LHSOPT->stripObjCKindOfTypeAndQuals(*this));
};
if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId()) {
return finish(ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false));
}
if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass())
return ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0));
if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass()) {
return finish(ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0)));
}
// If we have 2 user-defined types, fall into that path.
if (LHS->getInterface() && RHS->getInterface())
return canAssignObjCInterfaces(LHS, RHS);
if (LHS->getInterface() && RHS->getInterface()) {
return finish(canAssignObjCInterfaces(LHS, RHS));
}
return false;
}
@ -6768,26 +6822,46 @@ bool ASTContext::canAssignObjCInterfacesInBlockPointer(
const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT,
bool BlockReturnType) {
// Function object that propagates a successful result or handles
// __kindof types.
auto finish = [&](bool succeeded) -> bool {
if (succeeded)
return true;
const ObjCObjectPointerType *Expected = BlockReturnType ? RHSOPT : LHSOPT;
if (!Expected->isKindOfType())
return false;
// Strip off __kindof and protocol qualifiers, then check whether
// we can assign the other way.
return canAssignObjCInterfacesInBlockPointer(
RHSOPT->stripObjCKindOfTypeAndQuals(*this),
LHSOPT->stripObjCKindOfTypeAndQuals(*this),
BlockReturnType);
};
if (RHSOPT->isObjCBuiltinType() || LHSOPT->isObjCIdType())
return true;
if (LHSOPT->isObjCBuiltinType()) {
return RHSOPT->isObjCBuiltinType() || RHSOPT->isObjCQualifiedIdType();
return finish(RHSOPT->isObjCBuiltinType() ||
RHSOPT->isObjCQualifiedIdType());
}
if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false);
return finish(ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false));
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
if (LHS && RHS) { // We have 2 user-defined types.
if (LHS != RHS) {
if (LHS->getDecl()->isSuperClassOf(RHS->getDecl()))
return BlockReturnType;
return finish(BlockReturnType);
if (RHS->getDecl()->isSuperClassOf(LHS->getDecl()))
return !BlockReturnType;
return finish(!BlockReturnType);
}
else
return true;
@ -6795,78 +6869,253 @@ bool ASTContext::canAssignObjCInterfacesInBlockPointer(
return false;
}
/// Comparison routine for Objective-C protocols to be used with
/// llvm::array_pod_sort.
static int compareObjCProtocolsByName(ObjCProtocolDecl * const *lhs,
ObjCProtocolDecl * const *rhs) {
return (*lhs)->getName().compare((*rhs)->getName());
}
/// getIntersectionOfProtocols - This routine finds the intersection of set
/// of protocols inherited from two distinct objective-c pointer objects.
/// of protocols inherited from two distinct objective-c pointer objects with
/// the given common base.
/// It is used to build composite qualifier list of the composite type of
/// the conditional expression involving two objective-c pointer objects.
static
void getIntersectionOfProtocols(ASTContext &Context,
const ObjCInterfaceDecl *CommonBase,
const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT,
SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
SmallVectorImpl<ObjCProtocolDecl *> &IntersectionSet) {
const ObjCObjectType* LHS = LHSOPT->getObjectType();
const ObjCObjectType* RHS = RHSOPT->getObjectType();
assert(LHS->getInterface() && "LHS must have an interface base");
assert(RHS->getInterface() && "RHS must have an interface base");
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet;
unsigned LHSNumProtocols = LHS->getNumProtocols();
if (LHSNumProtocols > 0)
InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
else {
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
Context.CollectInheritedProtocols(LHS->getInterface(),
LHSInheritedProtocols);
InheritedProtocolSet.insert(LHSInheritedProtocols.begin(),
LHSInheritedProtocols.end());
// Add all of the protocols for the LHS.
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSProtocolSet;
// Start with the protocol qualifiers.
for (auto proto : LHS->quals()) {
Context.CollectInheritedProtocols(proto, LHSProtocolSet);
}
unsigned RHSNumProtocols = RHS->getNumProtocols();
if (RHSNumProtocols > 0) {
ObjCProtocolDecl **RHSProtocols =
const_cast<ObjCProtocolDecl **>(RHS->qual_begin());
for (unsigned i = 0; i < RHSNumProtocols; ++i)
if (InheritedProtocolSet.count(RHSProtocols[i]))
IntersectionOfProtocols.push_back(RHSProtocols[i]);
} else {
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
Context.CollectInheritedProtocols(RHS->getInterface(),
RHSInheritedProtocols);
for (ObjCProtocolDecl *ProtDecl : RHSInheritedProtocols)
if (InheritedProtocolSet.count(ProtDecl))
IntersectionOfProtocols.push_back(ProtDecl);
// Also add the protocols associated with the LHS interface.
Context.CollectInheritedProtocols(LHS->getInterface(), LHSProtocolSet);
// Add all of the protocls for the RHS.
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSProtocolSet;
// Start with the protocol qualifiers.
for (auto proto : RHS->quals()) {
Context.CollectInheritedProtocols(proto, RHSProtocolSet);
}
// Also add the protocols associated with the RHS interface.
Context.CollectInheritedProtocols(RHS->getInterface(), RHSProtocolSet);
// Compute the intersection of the collected protocol sets.
for (auto proto : LHSProtocolSet) {
if (RHSProtocolSet.count(proto))
IntersectionSet.push_back(proto);
}
// Compute the set of protocols that is implied by either the common type or
// the protocols within the intersection.
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ImpliedProtocols;
Context.CollectInheritedProtocols(CommonBase, ImpliedProtocols);
// Remove any implied protocols from the list of inherited protocols.
if (!ImpliedProtocols.empty()) {
IntersectionSet.erase(
std::remove_if(IntersectionSet.begin(),
IntersectionSet.end(),
[&](ObjCProtocolDecl *proto) -> bool {
return ImpliedProtocols.count(proto) > 0;
}),
IntersectionSet.end());
}
// Sort the remaining protocols by name.
llvm::array_pod_sort(IntersectionSet.begin(), IntersectionSet.end(),
compareObjCProtocolsByName);
}
/// Determine whether the first type is a subtype of the second.
static bool canAssignObjCObjectTypes(ASTContext &ctx, QualType lhs,
QualType rhs) {
// Common case: two object pointers.
const ObjCObjectPointerType *lhsOPT = lhs->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
if (lhsOPT && rhsOPT)
return ctx.canAssignObjCInterfaces(lhsOPT, rhsOPT);
// Two block pointers.
const BlockPointerType *lhsBlock = lhs->getAs<BlockPointerType>();
const BlockPointerType *rhsBlock = rhs->getAs<BlockPointerType>();
if (lhsBlock && rhsBlock)
return ctx.typesAreBlockPointerCompatible(lhs, rhs);
// If either is an unqualified 'id' and the other is a block, it's
// acceptable.
if ((lhsOPT && lhsOPT->isObjCIdType() && rhsBlock) ||
(rhsOPT && rhsOPT->isObjCIdType() && lhsBlock))
return true;
return false;
}
// Check that the given Objective-C type argument lists are equivalent.
static bool sameObjCTypeArgs(ASTContext &ctx,
const ObjCInterfaceDecl *iface,
ArrayRef<QualType> lhsArgs,
ArrayRef<QualType> rhsArgs,
bool stripKindOf) {
if (lhsArgs.size() != rhsArgs.size())
return false;
ObjCTypeParamList *typeParams = iface->getTypeParamList();
for (unsigned i = 0, n = lhsArgs.size(); i != n; ++i) {
if (ctx.hasSameType(lhsArgs[i], rhsArgs[i]))
continue;
switch (typeParams->begin()[i]->getVariance()) {
case ObjCTypeParamVariance::Invariant:
if (!stripKindOf ||
!ctx.hasSameType(lhsArgs[i].stripObjCKindOfType(ctx),
rhsArgs[i].stripObjCKindOfType(ctx))) {
return false;
}
break;
case ObjCTypeParamVariance::Covariant:
if (!canAssignObjCObjectTypes(ctx, lhsArgs[i], rhsArgs[i]))
return false;
break;
case ObjCTypeParamVariance::Contravariant:
if (!canAssignObjCObjectTypes(ctx, rhsArgs[i], lhsArgs[i]))
return false;
break;
}
}
return true;
}
/// areCommonBaseCompatible - Returns common base class of the two classes if
/// one found. Note that this is O'2 algorithm. But it will be called as the
/// last type comparison in a ?-exp of ObjC pointer types before a
/// warning is issued. So, its invokation is extremely rare.
QualType ASTContext::areCommonBaseCompatible(
const ObjCObjectPointerType *Lptr,
const ObjCObjectPointerType *Rptr) {
const ObjCObjectPointerType *Lptr,
const ObjCObjectPointerType *Rptr) {
const ObjCObjectType *LHS = Lptr->getObjectType();
const ObjCObjectType *RHS = Rptr->getObjectType();
const ObjCInterfaceDecl* LDecl = LHS->getInterface();
const ObjCInterfaceDecl* RDecl = RHS->getInterface();
if (!LDecl || !RDecl || (declaresSameEntity(LDecl, RDecl)))
return QualType();
do {
LHS = cast<ObjCInterfaceType>(getObjCInterfaceType(LDecl));
if (canAssignObjCInterfaces(LHS, RHS)) {
SmallVector<ObjCProtocolDecl *, 8> Protocols;
getIntersectionOfProtocols(*this, Lptr, Rptr, Protocols);
QualType Result = QualType(LHS, 0);
if (!LDecl || !RDecl)
return QualType();
// Follow the left-hand side up the class hierarchy until we either hit a
// root or find the RHS. Record the ancestors in case we don't find it.
llvm::SmallDenseMap<const ObjCInterfaceDecl *, const ObjCObjectType *, 4>
LHSAncestors;
while (true) {
// Record this ancestor. We'll need this if the common type isn't in the
// path from the LHS to the root.
LHSAncestors[LHS->getInterface()->getCanonicalDecl()] = LHS;
if (declaresSameEntity(LHS->getInterface(), RDecl)) {
// Get the type arguments.
ArrayRef<QualType> LHSTypeArgs = LHS->getTypeArgsAsWritten();
bool anyChanges = false;
if (LHS->isSpecialized() && RHS->isSpecialized()) {
// Both have type arguments, compare them.
if (!sameObjCTypeArgs(*this, LHS->getInterface(),
LHS->getTypeArgs(), RHS->getTypeArgs(),
/*stripKindOf=*/true))
return QualType();
} else if (LHS->isSpecialized() != RHS->isSpecialized()) {
// If only one has type arguments, the result will not have type
// arguments.
LHSTypeArgs = { };
anyChanges = true;
}
// Compute the intersection of protocols.
SmallVector<ObjCProtocolDecl *, 8> Protocols;
getIntersectionOfProtocols(*this, LHS->getInterface(), Lptr, Rptr,
Protocols);
if (!Protocols.empty())
Result = getObjCObjectType(Result, Protocols.data(), Protocols.size());
Result = getObjCObjectPointerType(Result);
return Result;
anyChanges = true;
// If anything in the LHS will have changed, build a new result type.
if (anyChanges) {
QualType Result = getObjCInterfaceType(LHS->getInterface());
Result = getObjCObjectType(Result, LHSTypeArgs, Protocols,
LHS->isKindOfType());
return getObjCObjectPointerType(Result);
}
return getObjCObjectPointerType(QualType(LHS, 0));
}
} while ((LDecl = LDecl->getSuperClass()));
// Find the superclass.
QualType LHSSuperType = LHS->getSuperClassType();
if (LHSSuperType.isNull())
break;
LHS = LHSSuperType->castAs<ObjCObjectType>();
}
// We didn't find anything by following the LHS to its root; now check
// the RHS against the cached set of ancestors.
while (true) {
auto KnownLHS = LHSAncestors.find(RHS->getInterface()->getCanonicalDecl());
if (KnownLHS != LHSAncestors.end()) {
LHS = KnownLHS->second;
// Get the type arguments.
ArrayRef<QualType> RHSTypeArgs = RHS->getTypeArgsAsWritten();
bool anyChanges = false;
if (LHS->isSpecialized() && RHS->isSpecialized()) {
// Both have type arguments, compare them.
if (!sameObjCTypeArgs(*this, LHS->getInterface(),
LHS->getTypeArgs(), RHS->getTypeArgs(),
/*stripKindOf=*/true))
return QualType();
} else if (LHS->isSpecialized() != RHS->isSpecialized()) {
// If only one has type arguments, the result will not have type
// arguments.
RHSTypeArgs = { };
anyChanges = true;
}
// Compute the intersection of protocols.
SmallVector<ObjCProtocolDecl *, 8> Protocols;
getIntersectionOfProtocols(*this, RHS->getInterface(), Lptr, Rptr,
Protocols);
if (!Protocols.empty())
anyChanges = true;
if (anyChanges) {
QualType Result = getObjCInterfaceType(RHS->getInterface());
Result = getObjCObjectType(Result, RHSTypeArgs, Protocols,
RHS->isKindOfType());
return getObjCObjectPointerType(Result);
}
return getObjCObjectPointerType(QualType(RHS, 0));
}
// Find the superclass of the RHS.
QualType RHSSuperType = RHS->getSuperClassType();
if (RHSSuperType.isNull())
break;
RHS = RHSSuperType->castAs<ObjCObjectType>();
}
return QualType();
}
@ -6877,21 +7126,15 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
// Verify that the base decls are compatible: the RHS must be a subclass of
// the LHS.
if (!LHS->getInterface()->isSuperClassOf(RHS->getInterface()))
ObjCInterfaceDecl *LHSInterface = LHS->getInterface();
bool IsSuperClass = LHSInterface->isSuperClassOf(RHS->getInterface());
if (!IsSuperClass)
return false;
// RHS must have a superset of the protocols in the LHS. If the LHS is not
// protocol qualified at all, then we are good.
if (LHS->getNumProtocols() == 0)
return true;
// Okay, we know the LHS has protocol qualifiers. But RHS may or may not.
// More detailed analysis is required.
// OK, if LHS is same or a superclass of RHS *and*
// this LHS, or as RHS's super class is assignment compatible with LHS.
bool IsSuperClass =
LHS->getInterface()->isSuperClassOf(RHS->getInterface());
if (IsSuperClass) {
// If the LHS has protocol qualifiers, determine whether all of them are
// satisfied by the RHS (i.e., the RHS has a superset of the protocols in the
// LHS).
if (LHS->getNumProtocols() > 0) {
// OK if conversion of LHS to SuperClass results in narrowing of types
// ; i.e., SuperClass may implement at least one of the protocols
// in LHS's protocol list. Example, SuperObj<P1> = lhs<P1,P2> is ok.
@ -6901,7 +7144,7 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
// Also, if RHS has explicit quelifiers, include them for comparing with LHS's
// qualifiers.
for (auto *RHSPI : RHS->quals())
SuperClassInheritedProtocols.insert(RHSPI->getCanonicalDecl());
CollectInheritedProtocols(RHSPI, SuperClassInheritedProtocols);
// If there is no protocols associated with RHS, it is not a match.
if (SuperClassInheritedProtocols.empty())
return false;
@ -6916,9 +7159,26 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
if (!SuperImplementsProtocol)
return false;
}
return true;
}
return false;
// If the LHS is specialized, we may need to check type arguments.
if (LHS->isSpecialized()) {
// Follow the superclass chain until we've matched the LHS class in the
// hierarchy. This substitutes type arguments through.
const ObjCObjectType *RHSSuper = RHS;
while (!declaresSameEntity(RHSSuper->getInterface(), LHSInterface))
RHSSuper = RHSSuper->getSuperClassType()->castAs<ObjCObjectType>();
// If the RHS is specializd, compare type arguments.
if (RHSSuper->isSpecialized() &&
!sameObjCTypeArgs(*this, LHS->getInterface(),
LHS->getTypeArgs(), RHSSuper->getTypeArgs(),
/*stripKindOf=*/true)) {
return false;
}
}
return true;
}
bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {

View File

@ -125,12 +125,23 @@ break; \
if (const PointerType *Ty = QT->getAs<PointerType>()) {
QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(),
ShouldAKA));
} else if (const auto *Ty = QT->getAs<ObjCObjectPointerType>()) {
QT = Context.getObjCObjectPointerType(Desugar(Context, Ty->getPointeeType(),
ShouldAKA));
} else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {
QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(),
ShouldAKA));
} else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {
QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(),
ShouldAKA));
} else if (const auto *Ty = QT->getAs<ObjCObjectType>()) {
if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {
QualType BaseType = Desugar(Context, Ty->getBaseType(), ShouldAKA);
QT = Context.getObjCObjectType(BaseType, Ty->getTypeArgsAsWritten(),
llvm::makeArrayRef(Ty->qual_begin(),
Ty->getNumProtocols()),
Ty->isKindOfTypeAsWritten());
}
}
return QC.apply(Context, QT);
@ -181,8 +192,8 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
if (CompareCanTy == CanTy)
continue; // Same canonical types
std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());
bool aka;
QualType CompareDesugar = Desugar(Context, CompareTy, aka);
bool ShouldAKA = false;
QualType CompareDesugar = Desugar(Context, CompareTy, ShouldAKA);
std::string CompareDesugarStr =
CompareDesugar.getAsString(Context.getPrintingPolicy());
if (CompareS != S && CompareDesugarStr != S)

View File

@ -240,6 +240,9 @@ namespace {
void dumpTemplateArgument(const TemplateArgument &A,
SourceRange R = SourceRange());
// Objective-C utilities.
void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams);
// Types
void VisitComplexType(const ComplexType *T) {
dumpTypeAsChild(T->getElementType());
@ -463,6 +466,7 @@ namespace {
// ObjC Decls
void VisitObjCIvarDecl(const ObjCIvarDecl *D);
void VisitObjCMethodDecl(const ObjCMethodDecl *D);
void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D);
void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
@ -954,6 +958,18 @@ void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) {
});
}
//===----------------------------------------------------------------------===//
// Objective-C Utilities
//===----------------------------------------------------------------------===//
void ASTDumper::dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) {
if (!typeParams)
return;
for (auto typeParam : *typeParams) {
dumpDecl(typeParam);
}
}
//===----------------------------------------------------------------------===//
// Decl dumping methods.
//===----------------------------------------------------------------------===//
@ -1457,9 +1473,30 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
dumpStmt(D->getBody());
}
void ASTDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
dumpName(D);
switch (D->getVariance()) {
case ObjCTypeParamVariance::Invariant:
break;
case ObjCTypeParamVariance::Covariant:
OS << " covariant";
break;
case ObjCTypeParamVariance::Contravariant:
OS << " contravariant";
break;
}
if (D->hasExplicitBound())
OS << " bounded";
dumpType(D->getUnderlyingType());
}
void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
dumpName(D);
dumpDeclRef(D->getClassInterface());
dumpObjCTypeParamList(D->getTypeParamList());
dumpDeclRef(D->getImplementation());
for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(),
E = D->protocol_end();
@ -1482,6 +1519,7 @@ void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
dumpName(D);
dumpObjCTypeParamList(D->getTypeParamListAsWritten());
dumpDeclRef(D->getSuperClass(), "super");
dumpDeclRef(D->getImplementation());

View File

@ -150,9 +150,12 @@ namespace clang {
Decl *VisitImplicitParamDecl(ImplicitParamDecl *D);
Decl *VisitParmVarDecl(ParmVarDecl *D);
Decl *VisitObjCMethodDecl(ObjCMethodDecl *D);
Decl *VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D);
Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D);
Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D);
ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list);
Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
@ -1841,6 +1844,15 @@ QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
if (ToBaseType.isNull())
return QualType();
SmallVector<QualType, 4> TypeArgs;
for (auto TypeArg : T->getTypeArgsAsWritten()) {
QualType ImportedTypeArg = Importer.Import(TypeArg);
if (ImportedTypeArg.isNull())
return QualType();
TypeArgs.push_back(ImportedTypeArg);
}
SmallVector<ObjCProtocolDecl *, 4> Protocols;
for (auto *P : T->quals()) {
ObjCProtocolDecl *Protocol
@ -1850,9 +1862,9 @@ QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
Protocols.push_back(Protocol);
}
return Importer.getToContext().getObjCObjectType(ToBaseType,
Protocols.data(),
Protocols.size());
return Importer.getToContext().getObjCObjectType(ToBaseType, TypeArgs,
Protocols,
T->isKindOfTypeAsWritten());
}
QualType
@ -3423,6 +3435,35 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
return ToMethod;
}
Decl *ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
// Import the major distinguishing characteristics of a category.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
if (ToD)
return ToD;
TypeSourceInfo *BoundInfo = Importer.Import(D->getTypeSourceInfo());
if (!BoundInfo)
return nullptr;
ObjCTypeParamDecl *Result = ObjCTypeParamDecl::Create(
Importer.getToContext(), DC,
D->getVariance(),
Importer.Import(D->getVarianceLoc()),
D->getIndex(),
Importer.Import(D->getLocation()),
Name.getAsIdentifierInfo(),
Importer.Import(D->getColonLoc()),
BoundInfo);
Importer.Imported(D, Result);
Result->setLexicalDeclContext(LexicalDC);
return Result;
}
Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
// Import the major distinguishing characteristics of a category.
DeclContext *DC, *LexicalDC;
@ -3450,11 +3491,16 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
Importer.Import(D->getCategoryNameLoc()),
Name.getAsIdentifierInfo(),
ToInterface,
/*TypeParamList=*/nullptr,
Importer.Import(D->getIvarLBraceLoc()),
Importer.Import(D->getIvarRBraceLoc()));
ToCategory->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToCategory);
Importer.Imported(D, ToCategory);
// Import the type parameter list after calling Imported, to avoid
// loops when bringing in their DeclContext.
ToCategory->setTypeParamList(ImportObjCTypeParamList(
D->getTypeParamList()));
// Import protocols
SmallVector<ObjCProtocolDecl *, 4> Protocols;
@ -3663,13 +3709,11 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
// If this class has a superclass, import it.
if (From->getSuperClass()) {
ObjCInterfaceDecl *Super = cast_or_null<ObjCInterfaceDecl>(
Importer.Import(From->getSuperClass()));
if (!Super)
TypeSourceInfo *SuperTInfo = Importer.Import(From->getSuperClassTInfo());
if (!SuperTInfo)
return true;
To->setSuperClass(Super);
To->setSuperClassLoc(Importer.Import(From->getSuperClassLoc()));
To->setSuperClass(SuperTInfo);
}
// Import protocols
@ -3716,6 +3760,27 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
return false;
}
ObjCTypeParamList *
ASTNodeImporter::ImportObjCTypeParamList(ObjCTypeParamList *list) {
if (!list)
return nullptr;
SmallVector<ObjCTypeParamDecl *, 4> toTypeParams;
for (auto fromTypeParam : *list) {
auto toTypeParam = cast_or_null<ObjCTypeParamDecl>(
Importer.Import(fromTypeParam));
if (!toTypeParam)
return nullptr;
toTypeParams.push_back(toTypeParam);
}
return ObjCTypeParamList::create(Importer.getToContext(),
Importer.Import(list->getLAngleLoc()),
toTypeParams,
Importer.Import(list->getRAngleLoc()));
}
Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
// If this class has a definition in the translation unit we're coming from,
// but this particular declaration is not that definition, import the
@ -3756,13 +3821,18 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
if (!ToIface) {
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getAtStartLoc()),
Name.getAsIdentifierInfo(),
Name.getAsIdentifierInfo(),
/*TypeParamList=*/nullptr,
/*PrevDecl=*/nullptr, Loc,
D->isImplicitInterfaceDecl());
ToIface->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToIface);
}
Importer.Imported(D, ToIface);
// Import the type parameter list after calling Imported, to avoid
// loops when bringing in their DeclContext.
ToIface->setTypeParamList(ImportObjCTypeParamList(
D->getTypeParamListAsWritten()));
if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface))
return nullptr;
@ -5313,7 +5383,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
return nullptr;
return ToContext.getTrivialTypeSourceInfo(T,
FromTSI->getTypeLoc().getLocStart());
Import(FromTSI->getTypeLoc().getLocStart()));
}
Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {

View File

@ -1803,15 +1803,19 @@ void VarDecl::setStorageClass(StorageClass SC) {
VarDecl::TLSKind VarDecl::getTLSKind() const {
switch (VarDeclBits.TSCSpec) {
case TSCS_unspecified:
if (!hasAttr<ThreadAttr>())
if (!hasAttr<ThreadAttr>() &&
!(getASTContext().getLangOpts().OpenMPUseTLS &&
getASTContext().getTargetInfo().isTLSSupported() &&
hasAttr<OMPThreadPrivateDeclAttr>()))
return TLS_None;
return getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2015)
return ((getASTContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2015)) ||
hasAttr<OMPThreadPrivateDeclAttr>())
? TLS_Dynamic
: TLS_Static;
case TSCS___thread: // Fall through.
case TSCS__Thread_local:
return TLS_Static;
return TLS_Static;
case TSCS_thread_local:
return TLS_Dynamic;
}
@ -2712,7 +2716,7 @@ bool FunctionDecl::isMSExternInline() const {
for (const FunctionDecl *FD = getMostRecentDecl(); FD;
FD = FD->getPreviousDecl())
if (FD->getStorageClass() == SC_Extern)
if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
return true;
return false;
@ -2724,7 +2728,7 @@ static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) {
for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD;
FD = FD->getPreviousDecl())
if (FD->getStorageClass() == SC_Extern)
if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
return false;
return true;

View File

@ -561,6 +561,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case TypeAliasTemplate:
case UnresolvedUsingTypename:
case TemplateTypeParm:
case ObjCTypeParam:
return IDNS_Ordinary | IDNS_Type;
case UsingShadow:

View File

@ -1272,7 +1272,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
break;
CTD = NewCTD;
}
return CTD->getTemplatedDecl();
return CTD->getTemplatedDecl()->getDefinition();
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
@ -1281,7 +1281,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
break;
CTPSD = NewCTPSD;
}
return CTPSD;
return CTPSD->getDefinition();
}
}
@ -1290,7 +1290,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
const CXXRecordDecl *RD = this;
while (auto *NewRD = RD->getInstantiatedFromMemberClass())
RD = NewRD;
return RD;
return RD->getDefinition();
}
}

View File

@ -239,6 +239,62 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
void ObjCInterfaceDecl::anchor() { }
ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const {
// If this particular declaration has a type parameter list, return it.
if (ObjCTypeParamList *written = getTypeParamListAsWritten())
return written;
// If there is a definition, return its type parameter list.
if (const ObjCInterfaceDecl *def = getDefinition())
return def->getTypeParamListAsWritten();
// Otherwise, look at previous declarations to determine whether any
// of them has a type parameter list, skipping over those
// declarations that do not.
for (auto decl = getMostRecentDecl(); decl; decl = decl->getPreviousDecl()) {
if (ObjCTypeParamList *written = decl->getTypeParamListAsWritten())
return written;
}
return nullptr;
}
void ObjCInterfaceDecl::setTypeParamList(ObjCTypeParamList *TPL) {
TypeParamList = TPL;
if (!TPL)
return;
// Set the declaration context of each of the type parameters.
for (auto typeParam : *TypeParamList)
typeParam->setDeclContext(this);
}
ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return nullptr;
if (data().ExternallyCompleted)
LoadExternalDefinition();
if (const ObjCObjectType *superType = getSuperClassType()) {
if (ObjCInterfaceDecl *superDecl = superType->getInterface()) {
if (ObjCInterfaceDecl *superDef = superDecl->getDefinition())
return superDef;
return superDecl;
}
}
return nullptr;
}
SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
if (TypeSourceInfo *superTInfo = getSuperClassTInfo())
return superTInfo->getTypeLoc().getLocStart();
return SourceLocation();
}
/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
/// with name 'PropertyId' in the primary class; including those in protocols
/// (direct or indirect) used by the primary class.
@ -889,9 +945,13 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
return family;
}
void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
const ObjCInterfaceDecl *OID) {
QualType ObjCMethodDecl::getSelfType(ASTContext &Context,
const ObjCInterfaceDecl *OID,
bool &selfIsPseudoStrong,
bool &selfIsConsumed) {
QualType selfTy;
selfIsPseudoStrong = false;
selfIsConsumed = false;
if (isInstanceMethod()) {
// There may be no interface context due to error in declaration
// of the interface (which has been reported). Recover gracefully.
@ -904,9 +964,6 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
} else // we have a factory method.
selfTy = Context.getObjCClassType();
bool selfIsPseudoStrong = false;
bool selfIsConsumed = false;
if (Context.getLangOpts().ObjCAutoRefCount) {
if (isInstanceMethod()) {
selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
@ -930,7 +987,14 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
selfIsPseudoStrong = true;
}
}
return selfTy;
}
void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
const ObjCInterfaceDecl *OID) {
bool selfIsPseudoStrong, selfIsConsumed;
QualType selfTy =
getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed);
ImplicitParamDecl *self
= ImplicitParamDecl::Create(Context, this, SourceLocation(),
&Context.Idents.get("self"), selfTy);
@ -966,6 +1030,20 @@ SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const {
return SourceRange();
}
QualType ObjCMethodDecl::getSendResultType() const {
ASTContext &Ctx = getASTContext();
return getReturnType().getNonLValueExprType(Ctx)
.substObjCTypeArgs(Ctx, {}, ObjCSubstitutionContext::Result);
}
QualType ObjCMethodDecl::getSendResultType(QualType receiverType) const {
// FIXME: Handle related result types here.
return getReturnType().getNonLValueExprType(getASTContext())
.substObjCMemberType(receiverType, getDeclContext(),
ObjCSubstitutionContext::Result);
}
static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
const ObjCMethodDecl *Method,
SmallVectorImpl<const ObjCMethodDecl *> &Methods,
@ -1136,6 +1214,81 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
return nullptr;
}
//===----------------------------------------------------------------------===//
// ObjCTypeParamDecl
//===----------------------------------------------------------------------===//
void ObjCTypeParamDecl::anchor() { }
ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
ObjCTypeParamVariance variance,
SourceLocation varianceLoc,
unsigned index,
SourceLocation nameLoc,
IdentifierInfo *name,
SourceLocation colonLoc,
TypeSourceInfo *boundInfo) {
return new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
nameLoc, name, colonLoc, boundInfo);
}
ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
unsigned ID) {
return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr,
ObjCTypeParamVariance::Invariant,
SourceLocation(), 0, SourceLocation(),
nullptr, SourceLocation(), nullptr);
}
SourceRange ObjCTypeParamDecl::getSourceRange() const {
SourceLocation startLoc = VarianceLoc;
if (startLoc.isInvalid())
startLoc = getLocation();
if (hasExplicitBound()) {
return SourceRange(startLoc,
getTypeSourceInfo()->getTypeLoc().getEndLoc());
}
return SourceRange(startLoc);
}
//===----------------------------------------------------------------------===//
// ObjCTypeParamList
//===----------------------------------------------------------------------===//
ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc,
ArrayRef<ObjCTypeParamDecl *> typeParams,
SourceLocation rAngleLoc)
: NumParams(typeParams.size())
{
Brackets.Begin = lAngleLoc.getRawEncoding();
Brackets.End = rAngleLoc.getRawEncoding();
std::copy(typeParams.begin(), typeParams.end(), begin());
}
ObjCTypeParamList *ObjCTypeParamList::create(
ASTContext &ctx,
SourceLocation lAngleLoc,
ArrayRef<ObjCTypeParamDecl *> typeParams,
SourceLocation rAngleLoc) {
unsigned size = sizeof(ObjCTypeParamList)
+ sizeof(ObjCTypeParamDecl *) * typeParams.size();
static_assert(llvm::AlignOf<ObjCTypeParamList>::Alignment >=
llvm::AlignOf<ObjCTypeParamDecl *>::Alignment,
"type parameter list needs greater alignment");
unsigned align = llvm::alignOf<ObjCTypeParamList>();
void *mem = ctx.Allocate(size, align);
return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc);
}
void ObjCTypeParamList::gatherDefaultTypeArgs(
SmallVectorImpl<QualType> &typeArgs) const {
typeArgs.reserve(size());
for (auto typeParam : *this)
typeArgs.push_back(typeParam->getUnderlyingType());
}
//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
@ -1144,11 +1297,13 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
ObjCTypeParamList *typeParamList,
ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc,
bool isInternal){
ObjCInterfaceDecl *Result = new (C, DC)
ObjCInterfaceDecl(C, DC, atLoc, Id, ClassLoc, PrevDecl, isInternal);
ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl,
isInternal);
Result->Data.setInt(!C.getLangOpts().Modules);
C.getObjCInterfaceType(Result, PrevDecl);
return Result;
@ -1159,6 +1314,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
ObjCInterfaceDecl *Result = new (C, ID) ObjCInterfaceDecl(C, nullptr,
SourceLocation(),
nullptr,
nullptr,
SourceLocation(),
nullptr, false);
Result->Data.setInt(!C.getLangOpts().Modules);
@ -1167,11 +1323,13 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
SourceLocation AtLoc, IdentifierInfo *Id,
ObjCTypeParamList *typeParamList,
SourceLocation CLoc,
ObjCInterfaceDecl *PrevDecl,
bool IsInternal)
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc),
redeclarable_base(C), TypeForDecl(nullptr), Data() {
redeclarable_base(C), TypeForDecl(nullptr), TypeParamList(nullptr),
Data() {
setPreviousDecl(PrevDecl);
// Copy the 'data' pointer over.
@ -1179,6 +1337,8 @@ ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
Data = PrevDecl->Data;
setImplicit(IsInternal);
setTypeParamList(typeParamList);
}
void ObjCInterfaceDecl::LoadExternalDefinition() const {
@ -1492,6 +1652,11 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
}
}
QualType ObjCIvarDecl::getUsageType(QualType objectType) const {
return getType().substObjCMemberType(objectType, getDeclContext(),
ObjCSubstitutionContext::Property);
}
//===----------------------------------------------------------------------===//
// ObjCAtDefsFieldDecl
//===----------------------------------------------------------------------===//
@ -1648,17 +1813,34 @@ ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
void ObjCCategoryDecl::anchor() { }
ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc,
SourceLocation IvarRBraceLoc)
: ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
ClassInterface(IDecl), TypeParamList(nullptr),
NextClassCategory(nullptr), CategoryNameLoc(CategoryNameLoc),
IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc)
{
setTypeParamList(typeParamList);
}
ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id,
ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc,
SourceLocation IvarRBraceLoc) {
ObjCCategoryDecl *CatDecl =
new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id,
IDecl, IvarLBraceLoc, IvarRBraceLoc);
IDecl, typeParamList, IvarLBraceLoc,
IvarRBraceLoc);
if (IDecl) {
// Link this category into its class's category list.
CatDecl->NextClassCategory = IDecl->getCategoryListRaw();
@ -1676,7 +1858,7 @@ ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(),
SourceLocation(), SourceLocation(),
nullptr, nullptr);
nullptr, nullptr, nullptr);
}
ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
@ -1688,6 +1870,15 @@ void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
getASTContext().setObjCImplementation(this, ImplD);
}
void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) {
TypeParamList = TPL;
if (!TPL)
return;
// Set the declaration context of each of the type parameters.
for (auto typeParam : *TypeParamList)
typeParam->setDeclContext(this);
}
//===----------------------------------------------------------------------===//
// ObjCCategoryImplDecl
@ -1876,6 +2067,11 @@ ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
QualType(), nullptr, None);
}
QualType ObjCPropertyDecl::getUsageType(QualType objectType) const {
return DeclType.substObjCMemberType(objectType, getDeclContext(),
ObjCSubstitutionContext::Property);
}
//===----------------------------------------------------------------------===//
// ObjCPropertyImplDecl
//===----------------------------------------------------------------------===//

View File

@ -44,6 +44,8 @@ namespace {
void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
QualType T);
void PrintObjCTypeParams(ObjCTypeParamList *Params);
public:
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0, bool PrintInstantiation = false)
@ -962,6 +964,38 @@ void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
Out << ')';
}
void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) {
Out << "<";
unsigned First = true;
for (auto *Param : *Params) {
if (First) {
First = false;
} else {
Out << ", ";
}
switch (Param->getVariance()) {
case ObjCTypeParamVariance::Invariant:
break;
case ObjCTypeParamVariance::Covariant:
Out << "__covariant ";
break;
case ObjCTypeParamVariance::Contravariant:
Out << "__contravariant ";
break;
}
Out << Param->getDeclName().getAsString();
if (Param->hasExplicitBound()) {
Out << " : " << Param->getUnderlyingType().getAsString(Policy);
}
}
Out << ">";
}
void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isInstanceMethod())
Out << "- ";
@ -1037,14 +1071,24 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (!OID->isThisDeclarationADefinition()) {
Out << "@class " << I << ";";
Out << "@class " << I;
if (auto TypeParams = OID->getTypeParamListAsWritten()) {
PrintObjCTypeParams(TypeParams);
}
Out << ";";
return;
}
bool eolnOut = false;
Out << "@interface " << I;
if (auto TypeParams = OID->getTypeParamListAsWritten()) {
PrintObjCTypeParams(TypeParams);
}
if (SID)
Out << "@interface " << I << " : " << *SID;
else
Out << "@interface " << I;
Out << " : " << OID->getSuperClass()->getName();
// Protocols?
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
@ -1107,7 +1151,11 @@ void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
}
void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
Out << "@interface " << *PID->getClassInterface() << '(' << *PID << ")\n";
Out << "@interface " << *PID->getClassInterface();
if (auto TypeParams = PID->getTypeParamList()) {
PrintObjCTypeParams(TypeParams);
}
Out << "(" << *PID << ")\n";
if (PID->ivar_size() > 0) {
Out << "{\n";
Indentation += Policy.Indentation;

View File

@ -3748,6 +3748,16 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
return nullptr;
}
QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const {
if (isClassReceiver())
return ctx.getObjCInterfaceType(getClassReceiver());
if (isSuperReceiver())
return getSuperReceiverType();
return getBase()->getType();
}
StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
switch (getBridgeKind()) {
case OBC_Bridge:

View File

@ -2379,6 +2379,10 @@ void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
}
void CXXNameMangler::mangleType(const ObjCObjectType *T) {
// Treat __kindof as a vendor extended type qualifier.
if (T->isKindOfType())
Out << "U8__kindof";
if (!T->qual_empty()) {
// Mangle protocol qualifiers.
SmallString<64> QualStr;
@ -2391,7 +2395,16 @@ void CXXNameMangler::mangleType(const ObjCObjectType *T) {
QualOS.flush();
Out << 'U' << QualStr.size() << QualStr;
}
mangleType(T->getBaseType());
if (T->isSpecialized()) {
// Mangle type arguments as I <type>+ E
Out << 'I';
for (auto typeArg : T->getTypeArgs())
mangleType(typeArg);
Out << 'E';
}
}
void CXXNameMangler::mangleType(const BlockPointerType *T) {

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,8 @@
#include "llvm/Support/raw_ostream.h"
using namespace clang;
static const unsigned TypeLocMaxDataAlign = llvm::alignOf<void *>();
//===----------------------------------------------------------------------===//
// TypeLoc Implementation
//===----------------------------------------------------------------------===//
@ -125,6 +127,46 @@ void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
}
}
namespace {
class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> {
TypeLoc Source;
public:
TypeLocCopier(TypeLoc source) : Source(source) { }
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) { \
dest.copyLocal(Source.castAs<CLASS##TypeLoc>()); \
}
#include "clang/AST/TypeLocNodes.def"
};
}
void TypeLoc::copy(TypeLoc other) {
assert(getFullDataSize() == other.getFullDataSize());
// If both data pointers are aligned to the maximum alignment, we
// can memcpy because getFullDataSize() accurately reflects the
// layout of the data.
if (reinterpret_cast<uintptr_t>(Data)
== llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(Data),
TypeLocMaxDataAlign) &&
reinterpret_cast<uintptr_t>(other.Data)
== llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(other.Data),
TypeLocMaxDataAlign)) {
memcpy(Data, other.Data, getFullDataSize());
return;
}
// Copy each of the pieces.
TypeLoc TL(getType(), Data);
do {
TypeLocCopier(other).Visit(TL);
other = other.getNextTypeLoc();
} while ((TL = TL.getNextTypeLoc()));
}
SourceLocation TypeLoc::getBeginLoc() const {
TypeLoc Cur = *this;
TypeLoc LeftMost = Cur;
@ -312,6 +354,33 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
return TL;
}
SourceLocation TypeLoc::findNullabilityLoc() const {
if (auto attributedLoc = getAs<AttributedTypeLoc>()) {
if (attributedLoc.getAttrKind() == AttributedType::attr_nullable ||
attributedLoc.getAttrKind() == AttributedType::attr_nonnull ||
attributedLoc.getAttrKind() == AttributedType::attr_null_unspecified)
return attributedLoc.getAttrNameLoc();
}
return SourceLocation();
}
void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setHasBaseTypeAsWritten(true);
setTypeArgsLAngleLoc(Loc);
setTypeArgsRAngleLoc(Loc);
for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) {
setTypeArgTInfo(i,
Context.getTrivialTypeSourceInfo(
getTypePtr()->getTypeArgsAsWritten()[i], Loc));
}
setProtocolLAngleLoc(Loc);
setProtocolRAngleLoc(Loc);
for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
setProtocolLoc(i, Loc);
}
void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>

View File

@ -1129,6 +1129,9 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
T->getAttrKind() == AttributedType::attr_objc_ownership)
return printBefore(T->getEquivalentType(), OS);
if (T->getAttrKind() == AttributedType::attr_objc_kindof)
OS << "__kindof ";
printBefore(T->getModifiedType(), OS);
if (T->isMSTypeSpec()) {
@ -1165,6 +1168,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
T->getAttrKind() == AttributedType::attr_objc_ownership)
return printAfter(T->getEquivalentType(), OS);
if (T->getAttrKind() == AttributedType::attr_objc_kindof)
return;
// TODO: not all attributes are GCC-style attributes.
if (T->isMSTypeSpec())
return;
@ -1310,59 +1316,61 @@ void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
raw_ostream &OS) {
if (T->qual_empty())
if (T->qual_empty() && T->isUnspecializedAsWritten() &&
!T->isKindOfTypeAsWritten())
return printBefore(T->getBaseType(), OS);
if (T->isKindOfTypeAsWritten())
OS << "__kindof ";
print(T->getBaseType(), OS, StringRef());
OS << '<';
bool isFirst = true;
for (const auto *I : T->quals()) {
if (isFirst)
isFirst = false;
else
OS << ',';
OS << I->getName();
if (T->isSpecializedAsWritten()) {
bool isFirst = true;
OS << '<';
for (auto typeArg : T->getTypeArgsAsWritten()) {
if (isFirst)
isFirst = false;
else
OS << ",";
print(typeArg, OS, StringRef());
}
OS << '>';
}
OS << '>';
if (!T->qual_empty()) {
bool isFirst = true;
OS << '<';
for (const auto *I : T->quals()) {
if (isFirst)
isFirst = false;
else
OS << ',';
OS << I->getName();
}
OS << '>';
}
spaceBeforePlaceHolder(OS);
}
void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
raw_ostream &OS) {
if (T->qual_empty())
if (T->qual_empty() && T->isUnspecializedAsWritten() &&
!T->isKindOfTypeAsWritten())
return printAfter(T->getBaseType(), OS);
}
void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
raw_ostream &OS) {
T->getPointeeType().getLocalQualifiers().print(OS, Policy,
/*appendSpaceIfNonEmpty=*/true);
printBefore(T->getPointeeType(), OS);
assert(!T->isObjCSelType());
if (T->isObjCIdType() || T->isObjCQualifiedIdType())
OS << "id";
else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
OS << "Class";
else
OS << T->getInterfaceDecl()->getName();
if (!T->qual_empty()) {
OS << '<';
for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
E = T->qual_end();
I != E; ++I) {
OS << (*I)->getName();
if (I+1 != E)
OS << ',';
}
OS << '>';
}
// If we need to print the pointer, print it now.
if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&
!T->isObjCClassType() && !T->isObjCQualifiedClassType()) {
OS << " *"; // Don't forget the implicit pointer.
} else {
spaceBeforePlaceHolder(OS);
if (HasEmptyPlaceHolder)
OS << ' ';
OS << '*';
}
}
void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,

View File

@ -20,21 +20,21 @@ namespace clang {
namespace ast_matchers {
namespace internal {
bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
@ -51,7 +51,7 @@ void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
namespace {
typedef bool (*VariadicOperatorFunction)(
const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
template <VariadicOperatorFunction Func>
@ -228,7 +228,7 @@ void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
}
bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers) {
if (InnerMatchers.size() != 1)
@ -248,7 +248,7 @@ bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
}
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers) {
@ -262,7 +262,7 @@ bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
return true;
}
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers) {
@ -279,7 +279,7 @@ bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
return Matched;
}
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers) {

View File

@ -216,7 +216,7 @@ class Parser::CodeTokenizer {
if (Code[Length] == Marker) {
Result->Kind = TokenInfo::TK_Literal;
Result->Text = Code.substr(0, Length + 1);
Result->Value = Code.substr(1, Length - 1).str();
Result->Value = Code.substr(1, Length - 1);
Code = Code.drop_front(Length + 1);
return;
}

View File

@ -249,7 +249,7 @@ VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
setUnsigned(Unsigned);
}
VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
setString(String);
}
@ -319,7 +319,7 @@ const std::string &VariantValue::getString() const {
return *Value.String;
}
void VariantValue::setString(const std::string &NewValue) {
void VariantValue::setString(StringRef NewValue) {
reset();
Type = VT_String;
Value.String = new std::string(NewValue);

View File

@ -19,6 +19,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
@ -585,3 +586,5 @@ void FileManager::PrintStats() const {
//llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups;
}
PCHContainerOperations::~PCHContainerOperations() {}

View File

@ -109,7 +109,8 @@ namespace {
WCHARSUPPORT = 0x04000,
HALFSUPPORT = 0x08000,
KEYCONCEPTS = 0x10000,
KEYALL = (0x1ffff & ~KEYNOMS18 &
KEYOBJC2 = 0x20000,
KEYALL = (0x3ffff & ~KEYNOMS18 &
~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
};
@ -144,6 +145,7 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
// in non-arc mode.
if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
if (LangOpts.ObjC2 && (Flags & KEYOBJC2)) return KS_Enabled;
if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future;
return KS_Disabled;
}

View File

@ -82,10 +82,6 @@ bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
return true;
for (const Module *Current = this; Current; Current = Current->Parent) {
if (!Current->MissingHeaders.empty()) {
MissingHeader = Current->MissingHeaders.front();
return false;
}
for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
if (hasFeature(Current->Requirements[I].first, LangOpts, Target) !=
Current->Requirements[I].second) {
@ -93,6 +89,10 @@ bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
return false;
}
}
if (!Current->MissingHeaders.empty()) {
MissingHeader = Current->MissingHeaders.front();
return false;
}
}
llvm_unreachable("could not find a reason why module is unavailable");
@ -184,7 +184,11 @@ void Module::addRequirement(StringRef Feature, bool RequiredState,
}
void Module::markUnavailable(bool MissingRequirement) {
if (!IsAvailable)
auto needUpdate = [MissingRequirement](Module *M) {
return M->IsAvailable || (!M->IsMissingRequirement && MissingRequirement);
};
if (!needUpdate(this))
return;
SmallVector<Module *, 2> Stack;
@ -193,7 +197,7 @@ void Module::markUnavailable(bool MissingRequirement) {
Module *Current = Stack.back();
Stack.pop_back();
if (!Current->IsAvailable)
if (!needUpdate(Current))
continue;
Current->IsAvailable = false;
@ -201,7 +205,7 @@ void Module::markUnavailable(bool MissingRequirement) {
for (submodule_iterator Sub = Current->submodule_begin(),
SubEnd = Current->submodule_end();
Sub != SubEnd; ++Sub) {
if ((*Sub)->IsAvailable)
if (needUpdate(*Sub))
Stack.push_back(*Sub);
}
}

View File

@ -14,34 +14,9 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/MathExtras.h"
using namespace clang;
SanitizerSet::SanitizerSet() : Mask(0) {}
bool SanitizerSet::has(SanitizerMask K) const {
assert(llvm::countPopulation(K) == 1);
return Mask & K;
}
bool SanitizerSet::hasOneOf(SanitizerMask K) const {
return Mask & K;
}
void SanitizerSet::set(SanitizerMask K, bool Value) {
assert(llvm::countPopulation(K) == 1);
Mask = Value ? (Mask | K) : (Mask & ~K);
}
void SanitizerSet::clear() {
Mask = 0;
}
bool SanitizerSet::empty() const {
return Mask == 0;
}
SanitizerMask clang::parseSanitizerValue(StringRef Value, bool AllowGroups) {
SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)

View File

@ -50,6 +50,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
LargeArrayAlign = 0;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
MaxVectorAlign = 0;
MaxTLSAlign = 0;
SimdDefaultAlign = 0;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;

View File

@ -580,6 +580,8 @@ class PS4OSTargetInfo : public OSTargetInfo<Target> {
PS4OSTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {
this->WCharType = this->UnsignedShort;
// On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits).
this->MaxTLSAlign = 256;
this->UserLabelPrefix = "";
switch (Triple.getArch()) {
@ -863,6 +865,8 @@ class PPCTargetInfo : public TargetInfo {
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;
bool hasFeature(StringRef Feature) const override;
void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
bool Enabled) const override;
void getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const override;
@ -1036,7 +1040,6 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
if (Feature == "power8-vector") {
HasP8Vector = true;
HasVSX = true;
continue;
}
@ -1047,7 +1050,6 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
if (Feature == "direct-move") {
HasDirectMove = true;
HasVSX = true;
continue;
}
@ -1064,6 +1066,15 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
// TODO: Finish this list and add an assert that we've handled them
// all.
}
if (!HasVSX && (HasP8Vector || HasDirectMove)) {
if (HasP8Vector)
Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector" <<
"-mno-vsx";
else if (HasDirectMove)
Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move" <<
"-mno-vsx";
return false;
}
return true;
}
@ -1285,6 +1296,11 @@ void PPCTargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
.Case("ppc64le", true)
.Case("pwr8", true)
.Default(false);
Features["vsx"] = llvm::StringSwitch<bool>(CPU)
.Case("ppc64le", true)
.Case("pwr8", true)
.Case("pwr7", true)
.Default(false);
}
bool PPCTargetInfo::hasFeature(StringRef Feature) const {
@ -1301,6 +1317,39 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
.Default(false);
}
/* There is no clear way for the target to know which of the features in the
final feature vector came from defaults and which are actually specified by
the user. To that end, we use the fact that this function is not called on
default features - only user specified ones. By the first time this
function is called, the default features are populated.
We then keep track of the features that the user specified so that we
can ensure we do not override a user's request (only defaults).
For example:
-mcpu=pwr8 -mno-vsx (should disable vsx and everything that depends on it)
-mcpu=pwr8 -mdirect-move -mno-vsx (should actually be diagnosed)
NOTE: Do not call this from PPCTargetInfo::getDefaultFeatures
*/
void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name, bool Enabled) const {
static llvm::StringMap<bool> ExplicitFeatures;
ExplicitFeatures[Name] = Enabled;
// At this point, -mno-vsx turns off the dependent features but we respect
// the user's requests.
if (!Enabled && Name == "vsx") {
Features["direct-move"] = ExplicitFeatures["direct-move"];
Features["power8-vector"] = ExplicitFeatures["power8-vector"];
}
if ((Enabled && Name == "power8-vector") ||
(Enabled && Name == "direct-move")) {
if (ExplicitFeatures.find("vsx") == ExplicitFeatures.end()) {
Features["vsx"] = true;
}
}
Features[Name] = Enabled;
}
const char * const PPCTargetInfo::GCCRegNames[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
@ -1472,7 +1521,7 @@ class PPC64TargetInfo : public PPCTargetInfo {
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::CharPtrBuiltinVaList;
}
// PPC64 Linux-specifc ABI options.
// PPC64 Linux-specific ABI options.
bool setABI(const std::string &Name) override {
if (Name == "elfv1" || Name == "elfv1-qpx" || Name == "elfv2") {
ABI = Name;
@ -3996,14 +4045,8 @@ class ARMTargetInfo : public TargetInfo {
FP_Neon
} FPMath;
unsigned ArchISA;
unsigned ArchKind;
unsigned ArchProfile;
unsigned ArchVersion;
unsigned FPU : 5;
unsigned ShouldUseInlineAtomic : 1;
unsigned IsAAPCS : 1;
unsigned IsThumb : 1;
unsigned HWDiv : 2;
@ -4025,6 +4068,37 @@ class ARMTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
static bool shouldUseInlineAtomic(const llvm::Triple &T) {
StringRef ArchName = T.getArchName();
if (T.getArch() == llvm::Triple::arm ||
T.getArch() == llvm::Triple::armeb) {
StringRef VersionStr;
if (ArchName.startswith("armv"))
VersionStr = ArchName.substr(4, 1);
else if (ArchName.startswith("armebv"))
VersionStr = ArchName.substr(6, 1);
else
return false;
unsigned Version;
if (VersionStr.getAsInteger(10, Version))
return false;
return Version >= 6;
}
assert(T.getArch() == llvm::Triple::thumb ||
T.getArch() == llvm::Triple::thumbeb);
StringRef VersionStr;
if (ArchName.startswith("thumbv"))
VersionStr = ArchName.substr(6, 1);
else if (ArchName.startswith("thumbebv"))
VersionStr = ArchName.substr(8, 1);
else
return false;
unsigned Version;
if (VersionStr.getAsInteger(10, Version))
return false;
return Version >= 7;
}
void setABIAAPCS() {
IsAAPCS = true;
@ -4123,27 +4197,6 @@ class ARMTargetInfo : public TargetInfo {
// FIXME: Override "preferred align" for double and long long.
}
void setArchInfo(StringRef ArchName) {
ArchISA = llvm::ARMTargetParser::parseArchISA(ArchName);
ArchKind = llvm::ARMTargetParser::parseArch(ArchName);
ArchProfile = llvm::ARMTargetParser::parseArchProfile(ArchName);
ArchVersion = llvm::ARMTargetParser::parseArchVersion(ArchName);
}
void setAtomic() {
// Cortex M does not support 8 byte atomics, while general Thumb2 does.
if (ArchProfile == llvm::ARM::PK_M) {
MaxAtomicPromoteWidth = 32;
if (ShouldUseInlineAtomic)
MaxAtomicInlineWidth = 32;
}
else {
MaxAtomicPromoteWidth = 64;
if (ShouldUseInlineAtomic)
MaxAtomicInlineWidth = 64;
}
}
public:
ARMTargetInfo(const llvm::Triple &Triple, bool IsBigEndian)
: TargetInfo(Triple), CPU("arm1136j-s"), FPMath(FP_Default),
@ -4159,27 +4212,12 @@ class ARMTargetInfo : public TargetInfo {
break;
}
// if subArch is not specified Arc Info is based on the default CPU
if (Triple.getSubArch() == llvm::Triple::SubArchType::NoSubArch) {
unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU);
setArchInfo(llvm::ARMTargetParser::getArchName(ArchKind));
ShouldUseInlineAtomic = false;
}
else {
setArchInfo(Triple.getArchName());
// FIXME: Should't this be updated also when calling setCPU() ?
// Doing so currently causes regressions
ShouldUseInlineAtomic = (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) ||
(ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7);
}
// {} in inline assembly are neon specifiers, not assembly variant
// specifiers.
NoAsmVariants = true;
// FIXME: Should't this be updated also when calling setCPU() ?
// Doing so currently causes regressions
IsThumb = (ArchISA == llvm::ARM::IK_THUMB);
// FIXME: Should we just treat this as a feature?
IsThumb = getTriple().getArchName().startswith("thumb");
// FIXME: This duplicates code from the driver that sets the -target-abi
// option - this code is used if -target-abi isn't passed and should
@ -4224,7 +4262,10 @@ class ARMTargetInfo : public TargetInfo {
// ARM targets default to using the ARM C++ ABI.
TheCXXABI.set(TargetCXXABI::GenericARM);
setAtomic();
// ARM has atomics up to 8 bytes
MaxAtomicPromoteWidth = 64;
if (shouldUseInlineAtomic(getTriple()))
MaxAtomicInlineWidth = 64;
// Do force alignment of members that follow zero length bitfields. If
// the alignment of the zero-length bitfield is greater than the member
@ -4255,6 +4296,11 @@ class ARMTargetInfo : public TargetInfo {
// FIXME: This should be based on Arch attributes, not CPU names.
void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
StringRef ArchName = getTriple().getArchName();
unsigned ArchKind = llvm::ARMTargetParser::parseArch(ArchName);
bool IsV8 = (ArchKind == llvm::ARM::AK_ARMV8A ||
ArchKind == llvm::ARM::AK_ARMV8_1A);
if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore")
Features["vfp2"] = true;
else if (CPU == "cortex-a8" || CPU == "cortex-a9") {
@ -4279,7 +4325,7 @@ class ARMTargetInfo : public TargetInfo {
Features["hwdiv-arm"] = true;
Features["crc"] = true;
Features["crypto"] = true;
} else if (CPU == "cortex-r5" || CPU == "cortex-r7" || ArchVersion == 8) {
} else if (CPU == "cortex-r5" || CPU == "cortex-r7" || IsV8) {
Features["hwdiv"] = true;
Features["hwdiv-arm"] = true;
} else if (CPU == "cortex-m3" || CPU == "cortex-m4" || CPU == "cortex-m7" ||
@ -4362,14 +4408,26 @@ class ARMTargetInfo : public TargetInfo {
.Case("hwdiv-arm", HWDiv & HWDivARM)
.Default(false);
}
const char *getCPUAttr() const {
const char *CPUAttr;
const char *getCPUDefineSuffix(StringRef Name) const {
if(Name == "generic") {
auto subarch = getTriple().getSubArch();
switch (subarch) {
case llvm::Triple::SubArchType::ARMSubArch_v8_1a:
return "8_1A";
default:
break;
}
}
unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(Name);
if (ArchKind == llvm::ARM::AK_INVALID)
return "";
// For most sub-arches, the build attribute CPU name is enough.
// For Cortex variants, it's slightly different.
switch(ArchKind) {
default:
CPUAttr = llvm::ARMTargetParser::getCPUAttr(ArchKind);
return CPUAttr ? CPUAttr : "" ;
return llvm::ARMTargetParser::getCPUAttr(ArchKind);
case llvm::ARM::AK_ARMV6M:
case llvm::ARM::AK_ARMV6SM:
return "6M";
@ -4389,8 +4447,23 @@ class ARMTargetInfo : public TargetInfo {
return "8_1A";
}
}
const char *getCPUProfile() const {
switch(ArchProfile) {
const char *getCPUProfile(StringRef Name) const {
if(Name == "generic") {
auto subarch = getTriple().getSubArch();
switch (subarch) {
case llvm::Triple::SubArchType::ARMSubArch_v8_1a:
return "A";
default:
break;
}
}
unsigned CPUArch = llvm::ARMTargetParser::parseCPUArch(Name);
if (CPUArch == llvm::ARM::AK_INVALID)
return "";
StringRef ArchName = llvm::ARMTargetParser::getArchName(CPUArch);
switch(llvm::ARMTargetParser::parseArchProfile(ArchName)) {
case llvm::ARM::PK_A:
return "A";
case llvm::ARM::PK_R:
@ -4402,26 +4475,35 @@ class ARMTargetInfo : public TargetInfo {
}
}
bool setCPU(const std::string &Name) override {
unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(Name);
if (ArchKind == llvm::ARM::AK_INVALID)
if (!getCPUDefineSuffix(Name))
return false;
setArchInfo(llvm::ARMTargetParser::getArchName(ArchKind));
setAtomic();
// Cortex M does not support 8 byte atomics, while general Thumb2 does.
StringRef Profile = getCPUProfile(Name);
if (Profile == "M" && MaxAtomicInlineWidth) {
MaxAtomicPromoteWidth = 32;
MaxAtomicInlineWidth = 32;
}
CPU = Name;
return true;
}
bool setFPMath(StringRef Name) override;
bool supportsThumb(StringRef CPUAttr) const {
return CPUAttr.count('T') || ArchVersion >= 6;
bool supportsThumb(StringRef ArchName, StringRef CPUArch,
unsigned CPUArchVer) const {
return CPUArchVer >= 7 || (CPUArch.find('T') != StringRef::npos) ||
(CPUArch.find('M') != StringRef::npos);
}
bool supportsThumb2(StringRef CPUAttr) const {
return CPUAttr.equals("6T2") || ArchVersion >= 7;
bool supportsThumb2(StringRef ArchName, StringRef CPUArch,
unsigned CPUArchVer) const {
// We check both CPUArchVer and ArchName because when only triple is
// specified, the default CPU is arm1136j-s.
return ArchName.endswith("v6t2") || ArchName.endswith("v7") ||
ArchName.endswith("v8.1a") ||
ArchName.endswith("v8") || CPUArch == "6T2" || CPUArchVer >= 7;
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
StringRef CPUAttr = getCPUAttr();
StringRef CPUProfile = getCPUProfile();
// Target identification.
Builder.defineMacro("__arm");
Builder.defineMacro("__arm__");
@ -4429,12 +4511,19 @@ class ARMTargetInfo : public TargetInfo {
// Target properties.
Builder.defineMacro("__REGISTER_PREFIX__", "");
Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
StringRef CPUArch = getCPUDefineSuffix(CPU);
unsigned int CPUArchVer;
if (CPUArch.substr(0, 1).getAsInteger<unsigned int>(10, CPUArchVer))
llvm_unreachable("Invalid char for architecture version number");
Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__");
// ACLE 6.4.1 ARM/Thumb instruction set architecture
StringRef CPUProfile = getCPUProfile(CPU);
StringRef ArchName = getTriple().getArchName();
// __ARM_ARCH is defined as an integer value indicating the current ARM ISA
Builder.defineMacro("__ARM_ARCH", std::to_string(ArchVersion));
if (ArchVersion >= 8) {
Builder.defineMacro("__ARM_ARCH", CPUArch.substr(0, 1));
if (CPUArch[0] >= '8') {
Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN");
Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING");
}
@ -4448,9 +4537,9 @@ class ARMTargetInfo : public TargetInfo {
// __ARM_ARCH_ISA_THUMB is defined to 1 if the core supporst the original
// Thumb ISA (including v6-M). It is set to 2 if the core supports the
// Thumb-2 ISA as found in the v6T2 architecture and all v7 architecture.
if (supportsThumb2(CPUAttr))
if (supportsThumb2(ArchName, CPUArch, CPUArchVer))
Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
else if (supportsThumb(CPUAttr))
else if (supportsThumb(ArchName, CPUArch, CPUArchVer))
Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
// __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
@ -4475,7 +4564,7 @@ class ARMTargetInfo : public TargetInfo {
// FIXME: It's more complicated than this and we don't really support
// interworking.
// Windows on ARM does not "support" interworking
if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
if (5 <= CPUArchVer && CPUArchVer <= 8 && !getTriple().isOSWindows())
Builder.defineMacro("__THUMB_INTERWORK__");
if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
@ -4498,7 +4587,7 @@ class ARMTargetInfo : public TargetInfo {
if (IsThumb) {
Builder.defineMacro("__THUMBEL__");
Builder.defineMacro("__thumb__");
if (supportsThumb2(CPUAttr))
if (supportsThumb2(ArchName, CPUArch, CPUArchVer))
Builder.defineMacro("__thumb2__");
}
if (((HWDiv & HWDivThumb) && IsThumb) || ((HWDiv & HWDivARM) && !IsThumb))
@ -4521,7 +4610,7 @@ class ARMTargetInfo : public TargetInfo {
// the VFP define, hence the soft float and arch check. This is subtly
// different from gcc, we follow the intent which was that it should be set
// when Neon instructions are actually available.
if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
if ((FPU & NeonFPU) && !SoftFloat && CPUArchVer >= 7) {
Builder.defineMacro("__ARM_NEON");
Builder.defineMacro("__ARM_NEON__");
}
@ -4538,18 +4627,18 @@ class ARMTargetInfo : public TargetInfo {
if (Crypto)
Builder.defineMacro("__ARM_FEATURE_CRYPTO");
if (ArchVersion >= 6 && CPUAttr != "6M") {
if (CPUArchVer >= 6 && CPUArch != "6M") {
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
bool is5EOrAbove = (ArchVersion >= 6 ||
(ArchVersion == 5 && CPUAttr.count('E')));
// FIXME: We are not getting all 32-bit ARM architectures
bool is32Bit = (!IsThumb || supportsThumb2(CPUAttr));
if (is5EOrAbove && is32Bit && (CPUProfile != "M" || CPUAttr == "7EM"))
bool is5EOrAbove = (CPUArchVer >= 6 ||
(CPUArchVer == 5 &&
CPUArch.find('E') != StringRef::npos));
bool is32Bit = (!IsThumb || supportsThumb2(ArchName, CPUArch, CPUArchVer));
if (is5EOrAbove && is32Bit && (CPUProfile != "M" || CPUArch == "7EM"))
Builder.defineMacro("__ARM_FEATURE_DSP");
}
void getTargetBuiltins(const Builtin::Info *&Records,
@ -6632,6 +6721,19 @@ void PNaClTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
NumAliases = 0;
}
// We attempt to use PNaCl (le32) frontend and Mips32EL backend.
class NaClMips32ELTargetInfo : public Mips32ELTargetInfo {
public:
NaClMips32ELTargetInfo(const llvm::Triple &Triple) :
Mips32ELTargetInfo(Triple) {
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
}
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::PNaClABIBuiltinVaList;
}
};
class Le64TargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
@ -7002,7 +7104,7 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<Mips32ELTargetInfo>(Triple);
case llvm::Triple::NaCl:
return new NaClTargetInfo<Mips32ELTargetInfo>(Triple);
return new NaClTargetInfo<NaClMips32ELTargetInfo>(Triple);
default:
return new Mips32ELTargetInfo(Triple);
}

View File

@ -292,6 +292,7 @@ void EmitAssemblyHelper::CreatePasses() {
PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime;
PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops;
PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions;
PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO;
PMBuilder.RerollLoops = CodeGenOpts.RerollLoops;
PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
@ -454,8 +455,6 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
BackendArgs.push_back("-limit-float-precision");
BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
}
if (llvm::TimePassesIsEnabled)
BackendArgs.push_back("-time-passes");
for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i)
BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str());
BackendArgs.push_back(nullptr);

View File

@ -93,6 +93,7 @@ namespace {
BFI = OrigBFI;
BFI.Offset = Offset;
BFI.StorageSize = AtomicSizeInBits;
BFI.StorageOffset += OffsetInChars;
LVal = LValue::MakeBitfield(Addr, BFI, lvalue.getType(),
lvalue.getAlignment());
LVal.setTBAAInfo(lvalue.getTBAAInfo());

View File

@ -535,7 +535,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BI__builtin_readcyclecounter: {
Value *F = CGM.getIntrinsic(Intrinsic::readcyclecounter);
return RValue::get(Builder.CreateCall(F, {}));
return RValue::get(Builder.CreateCall(F));
}
case Builtin::BI__builtin___clear_cache: {
Value *Begin = EmitScalarExpr(E->getArg(0));
@ -923,7 +923,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BI__builtin_unwind_init: {
Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init);
return RValue::get(Builder.CreateCall(F, {}));
return RValue::get(Builder.CreateCall(F));
}
case Builtin::BI__builtin_extend_pointer: {
// Extends a pointer to the size of an _Unwind_Word, which is
@ -962,7 +962,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Store the stack pointer to the setjmp buffer.
Value *StackAddr =
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave), {});
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave));
Value *StackSaveSlot =
Builder.CreateGEP(Buf, ConstantInt::get(Int32Ty, 2));
Builder.CreateStore(StackAddr, StackSaveSlot);
@ -3399,7 +3399,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
: InlineAsm::get(FTy, ".inst 0x" + utohexstr(ZExtValue), "",
/*SideEffects=*/true);
return Builder.CreateCall(Emit, {});
return Builder.CreateCall(Emit);
}
if (BuiltinID == ARM::BI__builtin_arm_dbg) {
@ -3543,7 +3543,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
if (BuiltinID == ARM::BI__builtin_arm_clrex) {
Function *F = CGM.getIntrinsic(Intrinsic::arm_clrex);
return Builder.CreateCall(F, {});
return Builder.CreateCall(F);
}
// CRC32
@ -4339,7 +4339,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
if (BuiltinID == AArch64::BI__builtin_arm_clrex) {
Function *F = CGM.getIntrinsic(Intrinsic::aarch64_clrex);
return Builder.CreateCall(F, {});
return Builder.CreateCall(F);
}
// CRC32
@ -6375,7 +6375,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
break;
}
Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID), {});
Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID));
Builder.CreateStore(Builder.CreateExtractValue(Call, 0), Ops[0]);
return Builder.CreateExtractValue(Call, 1);
}
@ -6633,14 +6633,104 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
llvm::Function *F = CGM.getIntrinsic(ID);
return Builder.CreateCall(F, Ops, "");
}
case PPC::BI__builtin_vsx_xvrspip:
case PPC::BI__builtin_vsx_xvrdpip:
// Square root
case PPC::BI__builtin_vsx_xvsqrtsp:
case PPC::BI__builtin_vsx_xvsqrtdp: {
llvm::Type *ResultType = ConvertType(E->getType());
Value *X = EmitScalarExpr(E->getArg(0));
ID = Intrinsic::ceil;
ID = Intrinsic::sqrt;
llvm::Function *F = CGM.getIntrinsic(ID, ResultType);
return Builder.CreateCall(F, X);
}
// Count leading zeros
case PPC::BI__builtin_altivec_vclzb:
case PPC::BI__builtin_altivec_vclzh:
case PPC::BI__builtin_altivec_vclzw:
case PPC::BI__builtin_altivec_vclzd: {
llvm::Type *ResultType = ConvertType(E->getType());
Value *X = EmitScalarExpr(E->getArg(0));
Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);
Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType);
return Builder.CreateCall(F, {X, Undef});
}
// Copy sign
case PPC::BI__builtin_vsx_xvcpsgnsp:
case PPC::BI__builtin_vsx_xvcpsgndp: {
llvm::Type *ResultType = ConvertType(E->getType());
Value *X = EmitScalarExpr(E->getArg(0));
Value *Y = EmitScalarExpr(E->getArg(1));
ID = Intrinsic::copysign;
llvm::Function *F = CGM.getIntrinsic(ID, ResultType);
return Builder.CreateCall(F, {X, Y});
}
// Rounding/truncation
case PPC::BI__builtin_vsx_xvrspip:
case PPC::BI__builtin_vsx_xvrdpip:
case PPC::BI__builtin_vsx_xvrdpim:
case PPC::BI__builtin_vsx_xvrspim:
case PPC::BI__builtin_vsx_xvrdpi:
case PPC::BI__builtin_vsx_xvrspi:
case PPC::BI__builtin_vsx_xvrdpic:
case PPC::BI__builtin_vsx_xvrspic:
case PPC::BI__builtin_vsx_xvrdpiz:
case PPC::BI__builtin_vsx_xvrspiz: {
llvm::Type *ResultType = ConvertType(E->getType());
Value *X = EmitScalarExpr(E->getArg(0));
if (BuiltinID == PPC::BI__builtin_vsx_xvrdpim ||
BuiltinID == PPC::BI__builtin_vsx_xvrspim)
ID = Intrinsic::floor;
else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpi ||
BuiltinID == PPC::BI__builtin_vsx_xvrspi)
ID = Intrinsic::round;
else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpic ||
BuiltinID == PPC::BI__builtin_vsx_xvrspic)
ID = Intrinsic::nearbyint;
else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpip ||
BuiltinID == PPC::BI__builtin_vsx_xvrspip)
ID = Intrinsic::ceil;
else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpiz ||
BuiltinID == PPC::BI__builtin_vsx_xvrspiz)
ID = Intrinsic::trunc;
llvm::Function *F = CGM.getIntrinsic(ID, ResultType);
return Builder.CreateCall(F, X);
}
// FMA variations
case PPC::BI__builtin_vsx_xvmaddadp:
case PPC::BI__builtin_vsx_xvmaddasp:
case PPC::BI__builtin_vsx_xvnmaddadp:
case PPC::BI__builtin_vsx_xvnmaddasp:
case PPC::BI__builtin_vsx_xvmsubadp:
case PPC::BI__builtin_vsx_xvmsubasp:
case PPC::BI__builtin_vsx_xvnmsubadp:
case PPC::BI__builtin_vsx_xvnmsubasp: {
llvm::Type *ResultType = ConvertType(E->getType());
Value *X = EmitScalarExpr(E->getArg(0));
Value *Y = EmitScalarExpr(E->getArg(1));
Value *Z = EmitScalarExpr(E->getArg(2));
Value *Zero = llvm::ConstantFP::getZeroValueForNegation(ResultType);
llvm::Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);
switch (BuiltinID) {
case PPC::BI__builtin_vsx_xvmaddadp:
case PPC::BI__builtin_vsx_xvmaddasp:
return Builder.CreateCall(F, {X, Y, Z});
case PPC::BI__builtin_vsx_xvnmaddadp:
case PPC::BI__builtin_vsx_xvnmaddasp:
return Builder.CreateFSub(Zero,
Builder.CreateCall(F, {X, Y, Z}), "sub");
case PPC::BI__builtin_vsx_xvmsubadp:
case PPC::BI__builtin_vsx_xvmsubasp:
return Builder.CreateCall(F,
{X, Y, Builder.CreateFSub(Zero, Z, "sub")});
case PPC::BI__builtin_vsx_xvnmsubadp:
case PPC::BI__builtin_vsx_xvnmsubasp:
Value *FsubRes =
Builder.CreateCall(F, {X, Y, Builder.CreateFSub(Zero, Z, "sub")});
return Builder.CreateFSub(Zero, FsubRes, "sub");
}
llvm_unreachable("Unknown FMA operation");
return nullptr; // Suppress no-return warning
}
}
}
// Emit an intrinsic that has 1 float or double.

View File

@ -912,20 +912,21 @@ static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val,
/// CreateCoercedLoad - Create a load from \arg SrcPtr interpreted as
/// a pointer to an object of type \arg Ty.
/// a pointer to an object of type \arg Ty, known to be aligned to
/// \arg SrcAlign bytes.
///
/// This safely handles the case when the src type is smaller than the
/// destination type; in this situation the values of bits which not
/// present in the src are undefined.
static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
llvm::Type *Ty,
llvm::Type *Ty, CharUnits SrcAlign,
CodeGenFunction &CGF) {
llvm::Type *SrcTy =
cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
// If SrcTy and Ty are the same, just do a load.
if (SrcTy == Ty)
return CGF.Builder.CreateLoad(SrcPtr);
return CGF.Builder.CreateAlignedLoad(SrcPtr, SrcAlign.getQuantity());
uint64_t DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
@ -940,7 +941,8 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
// extension or truncation to the desired type.
if ((isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) &&
(isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy))) {
llvm::LoadInst *Load = CGF.Builder.CreateLoad(SrcPtr);
llvm::LoadInst *Load =
CGF.Builder.CreateAlignedLoad(SrcPtr, SrcAlign.getQuantity());
return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF);
}
@ -954,23 +956,20 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
// to that information.
llvm::Value *Casted =
CGF.Builder.CreateBitCast(SrcPtr, llvm::PointerType::getUnqual(Ty));
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Casted);
// FIXME: Use better alignment / avoid requiring aligned load.
Load->setAlignment(1);
return Load;
return CGF.Builder.CreateAlignedLoad(Casted, SrcAlign.getQuantity());
}
// Otherwise do coercion through memory. This is stupid, but
// simple.
llvm::Value *Tmp = CGF.CreateTempAlloca(Ty);
llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(Ty);
Tmp->setAlignment(SrcAlign.getQuantity());
llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy();
llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy);
llvm::Value *SrcCasted = CGF.Builder.CreateBitCast(SrcPtr, I8PtrTy);
// FIXME: Use better alignment.
CGF.Builder.CreateMemCpy(Casted, SrcCasted,
llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize),
1, false);
return CGF.Builder.CreateLoad(Tmp);
SrcAlign.getQuantity(), false);
return CGF.Builder.CreateAlignedLoad(Tmp, SrcAlign.getQuantity());
}
// Function to store a first-class aggregate into memory. We prefer to
@ -979,39 +978,45 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
// FIXME: Do we need to recurse here?
static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val,
llvm::Value *DestPtr, bool DestIsVolatile,
bool LowAlignment) {
CharUnits DestAlign) {
// Prefer scalar stores to first-class aggregate stores.
if (llvm::StructType *STy =
dyn_cast<llvm::StructType>(Val->getType())) {
const llvm::StructLayout *Layout =
CGF.CGM.getDataLayout().getStructLayout(STy);
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
llvm::Value *EltPtr = CGF.Builder.CreateConstGEP2_32(STy, DestPtr, 0, i);
llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i);
llvm::StoreInst *SI = CGF.Builder.CreateStore(Elt, EltPtr,
DestIsVolatile);
if (LowAlignment)
SI->setAlignment(1);
uint64_t EltOffset = Layout->getElementOffset(i);
CharUnits EltAlign =
DestAlign.alignmentAtOffset(CharUnits::fromQuantity(EltOffset));
CGF.Builder.CreateAlignedStore(Elt, EltPtr, EltAlign.getQuantity(),
DestIsVolatile);
}
} else {
llvm::StoreInst *SI = CGF.Builder.CreateStore(Val, DestPtr, DestIsVolatile);
if (LowAlignment)
SI->setAlignment(1);
CGF.Builder.CreateAlignedStore(Val, DestPtr, DestAlign.getQuantity(),
DestIsVolatile);
}
}
/// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src,
/// where the source and destination may have different types.
/// where the source and destination may have different types. The
/// destination is known to be aligned to \arg DstAlign bytes.
///
/// This safely handles the case when the src type is larger than the
/// destination type; the upper bits of the src will be lost.
static void CreateCoercedStore(llvm::Value *Src,
llvm::Value *DstPtr,
bool DstIsVolatile,
CharUnits DstAlign,
CodeGenFunction &CGF) {
llvm::Type *SrcTy = Src->getType();
llvm::Type *DstTy =
cast<llvm::PointerType>(DstPtr->getType())->getElementType();
if (SrcTy == DstTy) {
CGF.Builder.CreateStore(Src, DstPtr, DstIsVolatile);
CGF.Builder.CreateAlignedStore(Src, DstPtr, DstAlign.getQuantity(),
DstIsVolatile);
return;
}
@ -1027,7 +1032,8 @@ static void CreateCoercedStore(llvm::Value *Src,
if ((isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy)) &&
(isa<llvm::IntegerType>(DstTy) || isa<llvm::PointerType>(DstTy))) {
Src = CoerceIntOrPtrToIntOrPtr(Src, DstTy, CGF);
CGF.Builder.CreateStore(Src, DstPtr, DstIsVolatile);
CGF.Builder.CreateAlignedStore(Src, DstPtr, DstAlign.getQuantity(),
DstIsVolatile);
return;
}
@ -1037,8 +1043,7 @@ static void CreateCoercedStore(llvm::Value *Src,
if (SrcSize <= DstSize) {
llvm::Value *Casted =
CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
// FIXME: Use better alignment / avoid requiring aligned store.
BuildAggStore(CGF, Src, Casted, DstIsVolatile, true);
BuildAggStore(CGF, Src, Casted, DstIsVolatile, DstAlign);
} else {
// Otherwise do coercion through memory. This is stupid, but
// simple.
@ -1049,15 +1054,15 @@ static void CreateCoercedStore(llvm::Value *Src,
//
// FIXME: Assert that we aren't truncating non-padding bits when have access
// to that information.
llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy);
CGF.Builder.CreateStore(Src, Tmp);
llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(SrcTy);
Tmp->setAlignment(DstAlign.getQuantity());
CGF.Builder.CreateAlignedStore(Src, Tmp, DstAlign.getQuantity());
llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy();
llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy);
llvm::Value *DstCasted = CGF.Builder.CreateBitCast(DstPtr, I8PtrTy);
// FIXME: Use better alignment.
CGF.Builder.CreateMemCpy(DstCasted, Casted,
llvm::ConstantInt::get(CGF.IntPtrTy, DstSize),
1, false);
DstAlign.getQuantity(), false);
}
}
@ -1506,7 +1511,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl);
if (FD) {
if (const TargetAttr *TD = FD->getAttr<TargetAttr>()) {
if (const auto *TD = FD->getAttr<TargetAttr>()) {
StringRef FeaturesStr = TD->getFeatures();
SmallVector<StringRef, 1> AttrFeatures;
FeaturesStr.split(AttrFeatures, ",");
@ -1514,9 +1519,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// Grab the various features and prepend a "+" to turn on the feature to
// the backend and add them to our existing set of features.
for (auto &Feature : AttrFeatures) {
// Go ahead and trim whitespace rather than either erroring or
// accepting it weirdly.
Feature = Feature.trim();
// While we're here iterating check for a different target cpu.
if (Feature.startswith("arch="))
TargetCPU = Feature.split("=").second;
TargetCPU = Feature.split("=").second.trim();
else if (Feature.startswith("tune="))
// We don't support cpu tuning this way currently.
;
@ -1992,6 +2001,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
Alloca->setAlignment(AlignmentToUse);
llvm::Value *V = Alloca;
llvm::Value *Ptr = V; // Pointer to store into.
CharUnits PtrAlign = CharUnits::fromQuantity(AlignmentToUse);
// If the value is offset in memory, apply the offset now.
if (unsigned Offs = ArgI.getDirectOffset()) {
@ -1999,6 +2009,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
Ptr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), Ptr, Offs);
Ptr = Builder.CreateBitCast(Ptr,
llvm::PointerType::getUnqual(ArgI.getCoerceToType()));
PtrAlign = PtrAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs));
}
// Fast-isel and the optimizer generally like scalar values better than
@ -2043,7 +2054,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
assert(NumIRArgs == 1);
auto AI = FnArgs[FirstIRArg];
AI->setName(Arg->getName() + ".coerce");
CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, *this);
CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, PtrAlign, *this);
}
@ -2411,15 +2422,17 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
}
} else {
llvm::Value *V = ReturnValue;
CharUnits Align = getContext().getTypeAlignInChars(RetTy);
// If the value is offset in memory, apply the offset now.
if (unsigned Offs = RetAI.getDirectOffset()) {
V = Builder.CreateBitCast(V, Builder.getInt8PtrTy());
V = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), V, Offs);
V = Builder.CreateBitCast(V,
llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
Align = Align.alignmentAtOffset(CharUnits::fromQuantity(Offs));
}
RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this);
RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), Align, *this);
}
// In ARC, end functions that return a retainable type with a call
@ -3282,12 +3295,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// FIXME: Avoid the conversion through memory if possible.
llvm::Value *SrcPtr;
CharUnits SrcAlign;
if (RV.isScalar() || RV.isComplex()) {
SrcPtr = CreateMemTemp(I->Ty, "coerce");
SrcAlign = TypeAlign;
LValue SrcLV = MakeAddrLValue(SrcPtr, I->Ty, TypeAlign);
EmitInitStoreOfNonAggregate(*this, RV, SrcLV);
} else
} else {
SrcPtr = RV.getAggregateAddr();
// This alignment is guaranteed by EmitCallArg.
SrcAlign = TypeAlign;
}
// If the value is offset in memory, apply the offset now.
if (unsigned Offs = ArgInfo.getDirectOffset()) {
@ -3295,7 +3313,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
SrcPtr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), SrcPtr, Offs);
SrcPtr = Builder.CreateBitCast(SrcPtr,
llvm::PointerType::getUnqual(ArgInfo.getCoerceToType()));
SrcAlign = SrcAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs));
}
// Fast-isel and the optimizer generally like scalar values better than
@ -3334,7 +3352,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// In the simple case, just pass the coerced loaded value.
assert(NumIRArgs == 1);
IRCallArgs[FirstIRArg] =
CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(), *this);
CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(),
SrcAlign, *this);
}
break;
@ -3531,12 +3550,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case TEK_Aggregate: {
llvm::Value *DestPtr = ReturnValue.getValue();
bool DestIsVolatile = ReturnValue.isVolatile();
CharUnits DestAlign = getContext().getTypeAlignInChars(RetTy);
if (!DestPtr) {
DestPtr = CreateMemTemp(RetTy, "agg.tmp");
DestIsVolatile = false;
}
BuildAggStore(*this, CI, DestPtr, DestIsVolatile, false);
BuildAggStore(*this, CI, DestPtr, DestIsVolatile, DestAlign);
return RValue::getAggregate(DestPtr);
}
case TEK_Scalar: {
@ -3553,6 +3573,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::Value *DestPtr = ReturnValue.getValue();
bool DestIsVolatile = ReturnValue.isVolatile();
CharUnits DestAlign = getContext().getTypeAlignInChars(RetTy);
if (!DestPtr) {
DestPtr = CreateMemTemp(RetTy, "coerce");
@ -3561,14 +3582,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the value is offset in memory, apply the offset now.
llvm::Value *StorePtr = DestPtr;
CharUnits StoreAlign = DestAlign;
if (unsigned Offs = RetAI.getDirectOffset()) {
StorePtr = Builder.CreateBitCast(StorePtr, Builder.getInt8PtrTy());
StorePtr =
Builder.CreateConstGEP1_32(Builder.getInt8Ty(), StorePtr, Offs);
StorePtr = Builder.CreateBitCast(StorePtr,
llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
StoreAlign =
StoreAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs));
}
CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this);
CreateCoercedStore(CI, StorePtr, DestIsVolatile, StoreAlign, *this);
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
}

View File

@ -554,6 +554,20 @@ static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) {
return false;
}
static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF,
CXXCtorInitializer *MemberInit,
LValue &LHS) {
FieldDecl *Field = MemberInit->getAnyMember();
if (MemberInit->isIndirectMemberInitializer()) {
// If we are initializing an anonymous union field, drill down to the field.
IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember();
for (const auto *I : IndirectField->chain())
LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I));
} else {
LHS = CGF.EmitLValueForFieldInitialization(LHS, Field);
}
}
static void EmitMemberInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXCtorInitializer *MemberInit,
@ -572,16 +586,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
if (MemberInit->isIndirectMemberInitializer()) {
// If we are initializing an anonymous union field, drill down to
// the field.
IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember();
for (const auto *I : IndirectField->chain())
LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I));
FieldType = MemberInit->getIndirectMember()->getAnonField()->getType();
} else {
LHS = CGF.EmitLValueForFieldInitialization(LHS, Field);
}
EmitLValueForAnyFieldInitialization(CGF, MemberInit, LHS);
// Special case: if we are in a copy or move constructor, and we are copying
// an array of PODs or classes with trivial copy constructors, ignore the
@ -606,6 +611,11 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
// Copy the aggregate.
CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType,
LHS.isVolatileQualified());
// Ensure that we destroy the objects if an exception is thrown later in
// the constructor.
QualType::DestructionKind dtorKind = FieldType.isDestructedType();
if (CGF.needsEHCleanup(dtorKind))
CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
return;
}
}
@ -906,32 +916,18 @@ namespace {
return;
}
CharUnits Alignment;
uint64_t FirstByteOffset;
if (FirstField->isBitField()) {
const CGRecordLayout &RL =
CGF.getTypes().getCGRecordLayout(FirstField->getParent());
const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField);
Alignment = CharUnits::fromQuantity(BFInfo.StorageAlignment);
// FirstFieldOffset is not appropriate for bitfields,
// it won't tell us what the storage offset should be and thus might not
// be properly aligned.
//
// Instead calculate the storage offset using the offset of the field in
// the struct type.
const llvm::DataLayout &DL = CGF.CGM.getDataLayout();
FirstByteOffset =
DL.getStructLayout(RL.getLLVMType())
->getElementOffsetInBits(RL.getLLVMFieldNo(FirstField));
// we need to use the storage offset instead.
FirstByteOffset = CGF.getContext().toBits(BFInfo.StorageOffset);
} else {
Alignment = CGF.getContext().getDeclAlign(FirstField);
FirstByteOffset = FirstFieldOffset;
}
assert((CGF.getContext().toCharUnitsFromBits(FirstByteOffset) %
Alignment) == 0 && "Bad field alignment.");
CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
llvm::Value *ThisPtr = CGF.LoadCXXThis();
@ -941,6 +937,9 @@ namespace {
LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField);
CharUnits Offset = CGF.getContext().toCharUnitsFromBits(FirstByteOffset);
CharUnits Alignment = DestLV.getAlignment().alignmentAtOffset(Offset);
emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddr() : Dest.getAddress(),
Src.isBitField() ? Src.getBitFieldAddr() : Src.getAddress(),
MemcpySize, Alignment);
@ -1078,6 +1077,7 @@ namespace {
CopyingValueRepresentation CVR(CGF);
EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
AggregatedInits[0], ConstructorDecl, Args);
AggregatedInits.clear();
}
reset();
return;
@ -1094,10 +1094,14 @@ namespace {
LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
QualType FieldType = AggregatedInits[i]->getMember()->getType();
CXXCtorInitializer *MemberInit = AggregatedInits[i];
QualType FieldType = MemberInit->getAnyMember()->getType();
QualType::DestructionKind dtorKind = FieldType.isDestructedType();
if (CGF.needsEHCleanup(dtorKind))
CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
if (!CGF.needsEHCleanup(dtorKind))
continue;
LValue FieldLHS = LHS;
EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS);
CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);
}
}
@ -1363,6 +1367,25 @@ static bool CanSkipVTablePointerInitialization(ASTContext &Context,
return true;
}
// Generates function call for handling object poisoning, passing in
// references to 'this' and its size as arguments.
static void EmitDtorSanitizerCallback(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor) {
const ASTRecordLayout &Layout =
CGF.getContext().getASTRecordLayout(Dtor->getParent());
llvm::Value *Args[] = {
CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.VoidPtrTy),
llvm::ConstantInt::get(CGF.SizeTy, Layout.getSize().getQuantity())};
llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy};
llvm::FunctionType *FnType =
llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
llvm::Value *Fn =
CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback");
CGF.EmitNounwindRuntimeCall(Fn, Args);
}
/// EmitDestructorBody - Emits the body of the current destructor.
void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
@ -1450,6 +1473,10 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// Exit the try if applicable.
if (isTryBody)
ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
// Insert memory-poisoning instrumentation.
if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor)
EmitDtorSanitizerCallback(*this, Dtor);
}
void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) {
@ -2202,8 +2229,7 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
llvm::Value *VTable,
CFITypeCheckKind TCK,
SourceLocation Loc) {
// FIXME: Add blacklisting scheme.
if (RD->isInStdNamespace())
if (CGM.IsCFIBlacklistedRecord(RD))
return;
SanitizerScope SanScope(this);

View File

@ -106,8 +106,6 @@ ApplyDebugLocation::~ApplyDebugLocation() {
CGF.Builder.SetCurrentDebugLocation(std::move(OriginalLocation));
}
/// ArtificialLocation - An RAII object that temporarily switches to
/// an artificial debug location that has a valid scope, but no line
void CGDebugInfo::setLocation(SourceLocation Loc) {
// If the new location isn't valid return.
if (Loc.isInvalid())
@ -140,7 +138,6 @@ void CGDebugInfo::setLocation(SourceLocation Loc) {
}
}
/// getContextDescriptor - Get context info for the decl.
llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context) {
if (!Context)
return TheCU;
@ -162,9 +159,6 @@ llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context) {
return TheCU;
}
/// getFunctionName - Get function name for the given FunctionDecl. If the
/// name is constructed on demand (e.g. C++ destructor) then the name
/// is stored on the side.
StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
assert(FD && "Invalid FunctionDecl!");
IdentifierInfo *FII = FD->getIdentifier();
@ -220,13 +214,10 @@ StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
return internString(OS.str());
}
/// getSelectorName - Return selector name. This is used for debugging
/// info.
StringRef CGDebugInfo::getSelectorName(Selector S) {
return internString(S.getAsString());
}
/// getClassName - Get class name including template argument list.
StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
// quick optimization to avoid having to intern strings that are already
// stored reliably elsewhere
@ -244,7 +235,6 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
return internString(Name);
}
/// getOrCreateFile - Get the file debug info descriptor for the input location.
llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
@ -274,13 +264,10 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
return F;
}
/// getOrCreateMainFile - Get the file info for main compile unit.
llvm::DIFile *CGDebugInfo::getOrCreateMainFile() {
return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
}
/// getLineNumber - Get line number for the location. If location is invalid
/// then use current location.
unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
if (Loc.isInvalid() && CurLoc.isInvalid())
return 0;
@ -289,7 +276,6 @@ unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
return PLoc.isValid() ? PLoc.getLine() : 0;
}
/// getColumnNumber - Get column number for the location.
unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) {
// We may not want column information at all.
if (!Force && !CGM.getCodeGenOpts().DebugColumnInfo)
@ -314,7 +300,6 @@ StringRef CGDebugInfo::getCurrentDirname() {
return CWDName = internString(CWD);
}
/// CreateCompileUnit - Create new compile unit.
void CGDebugInfo::CreateCompileUnit() {
// Should we be asking the SourceManager for the main file name, instead of
@ -385,8 +370,6 @@ void CGDebugInfo::CreateCompileUnit() {
DebugKind != CodeGenOptions::LocTrackingOnly);
}
/// CreateType - Get the Basic type from the cache or create a new
/// one if necessary.
llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
llvm::dwarf::TypeKind Encoding;
StringRef BTName;
@ -537,8 +520,6 @@ llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
return DBuilder.createBasicType("complex", Size, Align, Encoding);
}
/// CreateCVRType - Get the qualified type from the cache or create
/// a new one if necessary.
llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
llvm::DIFile *Unit) {
QualifierCollector Qc;
@ -627,6 +608,7 @@ static SmallString<256> getUniqueTagTypeName(const TagType *Ty,
return FullName;
}
/// \return the approproate DWARF tag for a composite type.
static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) {
llvm::dwarf::Tag Tag;
if (RD->isStruct() || RD->isInterface())
@ -642,7 +624,6 @@ static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) {
return Tag;
}
// Creates a forward declaration for a RecordDecl in the given context.
llvm::DICompositeType *
CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
llvm::DIScope *Ctx) {
@ -705,9 +686,6 @@ llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
llvm::DIFile *Unit) {
if (BlockLiteralGeneric)
return BlockLiteralGeneric;
SmallVector<llvm::Metadata *, 8> EltTys;
QualType FType;
uint64_t FieldSize, FieldOffset;
@ -723,10 +701,10 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
EltTys.clear();
unsigned Flags = llvm::DINode::FlagAppleBlock;
unsigned LineNo = getLineNumber(CurLoc);
unsigned LineNo = 0;
auto *EltTy =
DBuilder.createStructType(Unit, "__block_descriptor", Unit, LineNo,
DBuilder.createStructType(Unit, "__block_descriptor", nullptr, LineNo,
FieldOffset, 0, Flags, nullptr, Elements);
// Bit size, align and offset of the type.
@ -746,19 +724,22 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
FieldSize = CGM.getContext().getTypeSize(Ty);
FieldAlign = CGM.getContext().getTypeAlign(Ty);
EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", Unit, LineNo,
EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", nullptr, LineNo,
FieldSize, FieldAlign, FieldOffset,
0, DescTy));
FieldOffset += FieldSize;
Elements = DBuilder.getOrCreateArray(EltTys);
// The __block_literal_generic structs are marked with a special
// DW_AT_APPLE_BLOCK attribute and are an implementation detail only
// the debugger needs to know about. To allow type uniquing, emit
// them without a name or a location.
EltTy =
DBuilder.createStructType(Unit, "__block_literal_generic", Unit, LineNo,
DBuilder.createStructType(Unit, "", nullptr, LineNo,
FieldOffset, 0, Flags, nullptr, Elements);
BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
return BlockLiteralGeneric;
return DBuilder.createPointerType(EltTy, Size);
}
llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
@ -871,7 +852,6 @@ llvm::DIType *CGDebugInfo::createFieldType(
AlignInBits, offsetInBits, flags, debugType);
}
/// CollectRecordLambdaFields - Helper for CollectRecordFields.
void CGDebugInfo::CollectRecordLambdaFields(
const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements,
llvm::DIType *RecordTy) {
@ -916,7 +896,6 @@ void CGDebugInfo::CollectRecordLambdaFields(
}
}
/// Helper for CollectRecordFields.
llvm::DIDerivedType *
CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
const RecordDecl *RD) {
@ -946,7 +925,6 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
return GV;
}
/// CollectRecordNormalField - Helper for CollectRecordFields.
void CGDebugInfo::CollectRecordNormalField(
const FieldDecl *field, uint64_t OffsetInBits, llvm::DIFile *tunit,
SmallVectorImpl<llvm::Metadata *> &elements, llvm::DIType *RecordTy,
@ -971,8 +949,6 @@ void CGDebugInfo::CollectRecordNormalField(
elements.push_back(fieldType);
}
/// CollectRecordFields - A helper function to collect debug info for
/// record fields. This is used while creating debug info entry for a Record.
void CGDebugInfo::CollectRecordFields(
const RecordDecl *record, llvm::DIFile *tunit,
SmallVectorImpl<llvm::Metadata *> &elements,
@ -1011,9 +987,6 @@ void CGDebugInfo::CollectRecordFields(
}
}
/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
/// function type is not updated to include implicit "this" pointer. Use this
/// routine to get a method type which includes "this" pointer.
llvm::DISubroutineType *
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile *Unit) {
@ -1088,8 +1061,6 @@ static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
return false;
}
/// CreateCXXMemberFunction - A helper function to create a subprogram for
/// a single member function GlobalDecl.
llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
const CXXMethodDecl *Method, llvm::DIFile *Unit, llvm::DIType *RecordTy) {
bool IsCtorOrDtor =
@ -1165,9 +1136,6 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
return SP;
}
/// CollectCXXMemberFunctions - A helper function to collect debug info for
/// C++ member functions. This is used while creating debug info entry for
/// a Record.
void CGDebugInfo::CollectCXXMemberFunctions(
const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy) {
@ -1206,9 +1174,6 @@ void CGDebugInfo::CollectCXXMemberFunctions(
}
}
/// CollectCXXBases - A helper function to collect debug info for
/// C++ base classes. This is used while creating debug info entry for
/// a Record.
void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys,
llvm::DIType *RecordTy) {
@ -1246,7 +1211,6 @@ void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
}
}
/// CollectTemplateParams - A helper function to collect template parameters.
llvm::DINodeArray
CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
ArrayRef<TemplateArgument> TAList,
@ -1351,8 +1315,6 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
return DBuilder.getOrCreateArray(TemplateParams);
}
/// CollectFunctionTemplateParams - A helper function to collect debug
/// info for function template parameters.
llvm::DINodeArray
CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
llvm::DIFile *Unit) {
@ -1367,8 +1329,6 @@ CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
return llvm::DINodeArray();
}
/// CollectCXXTemplateParams - A helper function to collect debug info for
/// template parameters.
llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(
const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile *Unit) {
// Always get the full list of parameters, not just the ones from
@ -1379,7 +1339,6 @@ llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(
return CollectTemplateParams(TPList, TAList.asArray(), Unit);
}
/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) {
if (VTablePtrType)
return VTablePtrType;
@ -1397,14 +1356,11 @@ llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) {
return VTablePtrType;
}
/// getVTableName - Get vtable name for the given Class.
StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
// Copy the gdb compatible name on the side and use its reference.
return internString("_vptr$", RD->getNameAsString());
}
/// CollectVTableInfo - If the C++ class has vtable info then insert appropriate
/// debug info entry in EltTys vector.
void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys) {
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
@ -1424,7 +1380,6 @@ void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
EltTys.push_back(VPTR);
}
/// getOrCreateRecordType - Emit record type's standalone debug info.
llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy,
SourceLocation Loc) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@ -1432,8 +1387,6 @@ llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy,
return T;
}
/// getOrCreateInterfaceType - Emit an objective c interface type standalone
/// debug info.
llvm::DIType *CGDebugInfo::getOrCreateInterfaceType(QualType D,
SourceLocation Loc) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@ -1531,7 +1484,6 @@ static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind,
return false;
}
/// CreateType - get structure or union type.
llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0)));
@ -1605,7 +1557,6 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
return FwdDecl;
}
/// CreateType - get objective-c object type.
llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty,
llvm::DIFile *Unit) {
// Ignore protocols.
@ -1636,7 +1587,6 @@ static bool hasDefaultSetterName(const ObjCPropertyDecl *PD,
Setter->getDeclName().getObjCSelector().getNameForSlot(0);
}
/// CreateType - get objective-c interface type.
llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::DIFile *Unit) {
ObjCInterfaceDecl *ID = Ty->getDecl();
@ -1956,7 +1906,6 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
return getOrCreateType(Ty->getValueType(), U);
}
/// CreateEnumType - get enumeration type.
llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
@ -2076,8 +2025,6 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
} while (true);
}
/// getType - Get the type from the cache or return null type if it doesn't
/// exist.
llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) {
// Unwrap the type as needed for debug information.
@ -2104,8 +2051,6 @@ void CGDebugInfo::completeTemplateDefinition(
RetainedTypes.push_back(CGM.getContext().getRecordType(&SD).getAsOpaquePtr());
}
/// getOrCreateType - Get the type from the cache or create a new
/// one if necessary.
llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
if (Ty.isNull())
return nullptr;
@ -2126,8 +2071,6 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
return Res;
}
/// Currently the checksum of an interface includes the number of
/// ivars and property accessors.
unsigned CGDebugInfo::Checksum(const ObjCInterfaceDecl *ID) {
// The assumption is that the number of ivars can only increase
// monotonically, so it is safe to just use their current number as
@ -2152,7 +2095,6 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) {
}
}
/// CreateTypeNode - Create a new debug type node.
llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
// Handle qualifiers, which recursively handles what they refer to.
if (Ty.hasLocalQualifiers())
@ -2233,8 +2175,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
llvm_unreachable("type should have been unwrapped!");
}
/// getOrCreateLimitedType - Get the type from the cache or create a new
/// limited type if necessary.
llvm::DIType *CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty,
llvm::DIFile *Unit) {
QualType QTy(Ty, 0);
@ -2328,7 +2268,6 @@ void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD,
DBuilder.replaceVTableHolder(RealDecl, ContainingType);
}
/// CreateMemberType - Create new member and increase Offset by FType's size.
llvm::DIType *CGDebugInfo::CreateMemberType(llvm::DIFile *Unit, QualType FType,
StringRef Name, uint64_t *Offset) {
llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
@ -2493,8 +2432,6 @@ llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
return nullptr;
}
/// getFunctionDeclaration - Return debug info descriptor to describe method
/// declaration for the given method definition.
llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) {
if (!D || DebugKind <= CodeGenOptions::DebugLineTablesOnly)
return nullptr;
@ -2591,7 +2528,6 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
}
/// EmitFunctionStart - Constructs the debug code for entering a function.
void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
SourceLocation ScopeLoc, QualType FnType,
llvm::Function *Fn, CGBuilderTy &Builder) {
@ -2667,9 +2603,6 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
RegionMap[D].reset(SP);
}
/// EmitLocation - Emit metadata to indicate a change in line/column
/// information in the source file. If the location is invalid, the
/// previous location will be reused.
void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
// Update our current location
setLocation(Loc);
@ -2682,8 +2615,6 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
getLineNumber(CurLoc), getColumnNumber(CurLoc), Scope));
}
/// CreateLexicalBlock - Creates a new lexical block node and pushes it on
/// the stack.
void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
llvm::MDNode *Back = nullptr;
if (!LexicalBlockStack.empty())
@ -2693,8 +2624,6 @@ void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
getColumnNumber(CurLoc)));
}
/// EmitLexicalBlockStart - Constructs the debug code for entering a declarative
/// region - beginning of a DW_TAG_lexical_block.
void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder,
SourceLocation Loc) {
// Set our current location.
@ -2711,8 +2640,6 @@ void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder,
CreateLexicalBlock(Loc);
}
/// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative
/// region - end of a DW_TAG_lexical_block.
void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder,
SourceLocation Loc) {
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
@ -2726,7 +2653,6 @@ void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder,
LexicalBlockStack.pop_back();
}
/// EmitFunctionEnd - Constructs the debug code for exiting a function.
void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
unsigned RCount = FnBeginRegionCount.back();
@ -2741,8 +2667,6 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
FnBeginRegionCount.pop_back();
}
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *XOffset) {
@ -2816,7 +2740,6 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
nullptr, Elements);
}
/// EmitDeclare - Emit local variable declaration debug info.
void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::Tag Tag,
llvm::Value *Storage, unsigned ArgNo,
CGBuilderTy &Builder) {
@ -2944,12 +2867,6 @@ void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
}
/// Look up the completed type for a self pointer in the TypeCache and
/// create a copy of it with the ObjectPointer and Artificial flags
/// set. If the type is not cached, a new one is created. This should
/// never happen though, since creating a type for the implicit self
/// argument implies that we already parsed the interface definition
/// and the ivar declarations in the implementation.
llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy,
llvm::DIType *Ty) {
llvm::DIType *CachedTy = getTypeOrNull(QualTy);
@ -3027,8 +2944,6 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
Builder.GetInsertBlock());
}
/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
/// variable declaration.
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
unsigned ArgNo,
CGBuilderTy &Builder) {
@ -3192,8 +3107,6 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
Builder.GetInsertBlock());
}
/// If D is an out-of-class definition of a static data member of a class, find
/// its corresponding in-class declaration.
llvm::DIDerivedType *
CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
if (!D->isStaticDataMember())
@ -3213,9 +3126,6 @@ CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC));
}
/// Recursively collect all of the member fields of a global anonymous decl and
/// create static variables for them. The first time this is called it needs
/// to be on a union and then from there we can have additional unnamed fields.
llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls(
const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo,
StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext) {
@ -3241,7 +3151,6 @@ llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls(
return GV;
}
/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const VarDecl *D) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@ -3274,7 +3183,6 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
DeclCache[D->getCanonicalDecl()].reset(static_cast<llvm::Metadata *>(GV));
}
/// EmitGlobalVariable - Emit global variable's debug info.
void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
llvm::Constant *Init) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@ -3380,8 +3288,6 @@ CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) {
return R;
}
/// getOrCreateNamesSpace - Return namespace descriptor for the given
/// namespace decl.
llvm::DINamespace *
CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
NSDecl = NSDecl->getCanonicalDecl();

View File

@ -26,26 +26,26 @@
#include "llvm/Support/Allocator.h"
namespace llvm {
class MDNode;
class MDNode;
}
namespace clang {
class CXXMethodDecl;
class VarDecl;
class ObjCInterfaceDecl;
class ObjCIvarDecl;
class ClassTemplateSpecializationDecl;
class GlobalDecl;
class UsingDecl;
class CXXMethodDecl;
class VarDecl;
class ObjCInterfaceDecl;
class ObjCIvarDecl;
class ClassTemplateSpecializationDecl;
class GlobalDecl;
class UsingDecl;
namespace CodeGen {
class CodeGenModule;
class CodeGenFunction;
class CGBlockInfo;
class CodeGenModule;
class CodeGenFunction;
class CGBlockInfo;
/// \brief This class gathers all debug information during compilation
/// and is responsible for emitting to llvm globals or pass directly to
/// the backend.
/// This class gathers all debug information during compilation and is
/// responsible for emitting to llvm globals or pass directly to the
/// backend.
class CGDebugInfo {
friend class ApplyDebugLocation;
friend class SaveAndRestoreLocation;
@ -65,9 +65,8 @@ class CGDebugInfo {
llvm::DIType *OCLImage2dArrayDITy = nullptr;
llvm::DIType *OCLImage3dDITy = nullptr;
llvm::DIType *OCLEventDITy = nullptr;
llvm::DIType *BlockLiteralGeneric = nullptr;
/// \brief Cache of previously constructed Types.
/// Cache of previously constructed Types.
llvm::DenseMap<const void *, llvm::TrackingMDRef> TypeCache;
struct ObjCInterfaceCacheEntry {
@ -79,41 +78,40 @@ class CGDebugInfo {
: Type(Type), Decl(Decl), Unit(Unit) {}
};
/// \brief Cache of previously constructed interfaces
/// which may change.
/// Cache of previously constructed interfaces which may change.
llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache;
/// \brief Cache of references to AST files such as PCHs or modules.
/// Cache of references to AST files such as PCHs or modules.
llvm::DenseMap<uint64_t, llvm::DIModule *> ModuleRefCache;
/// \brief list of interfaces we want to keep even if orphaned.
/// List of interfaces we want to keep even if orphaned.
std::vector<void *> RetainedTypes;
/// \brief Cache of forward declared types to RAUW at the end of
/// Cache of forward declared types to RAUW at the end of
/// compilation.
std::vector<std::pair<const TagType *, llvm::TrackingMDRef>> ReplaceMap;
/// \brief Cache of replaceable forward declarartions (functions and
/// Cache of replaceable forward declarartions (functions and
/// variables) to RAUW at the end of compilation.
std::vector<std::pair<const DeclaratorDecl *, llvm::TrackingMDRef>>
FwdDeclReplaceMap;
// LexicalBlockStack - Keep track of our current nested lexical block.
/// Keep track of our current nested lexical block.
std::vector<llvm::TypedTrackingMDRef<llvm::DIScope>> LexicalBlockStack;
llvm::DenseMap<const Decl *, llvm::TrackingMDRef> RegionMap;
// FnBeginRegionCount - Keep track of LexicalBlockStack counter at the
// beginning of a function. This is used to pop unbalanced regions at
// the end of a function.
/// Keep track of LexicalBlockStack counter at the beginning of a
/// function. This is used to pop unbalanced regions at the end of a
/// function.
std::vector<unsigned> FnBeginRegionCount;
/// \brief This is a storage for names that are
/// constructed on demand. For example, C++ destructors, C++ operators etc..
/// This is a storage for names that are constructed on demand. For
/// example, C++ destructors, C++ operators etc..
llvm::BumpPtrAllocator DebugInfoNames;
StringRef CWDName;
llvm::DenseMap<const char *, llvm::TrackingMDRef> DIFileCache;
llvm::DenseMap<const FunctionDecl *, llvm::TrackingMDRef> SPCache;
/// \brief Cache declarations relevant to DW_TAG_imported_declarations (C++
/// Cache declarations relevant to DW_TAG_imported_declarations (C++
/// using declarations) that aren't covered by other more specific caches.
llvm::DenseMap<const Decl *, llvm::TrackingMDRef> DeclCache;
llvm::DenseMap<const NamespaceDecl *, llvm::TrackingMDRef> NameSpaceCache;
@ -122,6 +120,9 @@ class CGDebugInfo {
llvm::DenseMap<const Decl *, llvm::TrackingMDRef> StaticDataMemberCache;
/// Helper functions for getOrCreateType.
/// @{
/// Currently the checksum of an interface includes the number of
/// ivars and property accessors.
unsigned Checksum(const ObjCInterfaceDecl *InterfaceDecl);
llvm::DIType *CreateType(const BuiltinType *Ty);
llvm::DIType *CreateType(const ComplexType *Ty);
@ -133,14 +134,17 @@ class CGDebugInfo {
llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const BlockPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F);
/// Get structure or union type.
llvm::DIType *CreateType(const RecordType *Tyg);
llvm::DIType *CreateTypeDefinition(const RecordType *Ty);
llvm::DICompositeType *CreateLimitedType(const RecordType *Ty);
void CollectContainingType(const CXXRecordDecl *RD,
llvm::DICompositeType *CT);
/// Get Objective-C interface type.
llvm::DIType *CreateType(const ObjCInterfaceType *Ty, llvm::DIFile *F);
llvm::DIType *CreateTypeDefinition(const ObjCInterfaceType *Ty,
llvm::DIFile *F);
/// Get Objective-C object type.
llvm::DIType *CreateType(const ObjCObjectType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const VectorType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const ArrayType *Ty, llvm::DIFile *F);
@ -148,10 +152,25 @@ class CGDebugInfo {
llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit);
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
/// Get enumeration type.
llvm::DIType *CreateEnumType(const EnumType *Ty);
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
/// Look up the completed type for a self pointer in the TypeCache and
/// create a copy of it with the ObjectPointer and Artificial flags
/// set. If the type is not cached, a new one is created. This should
/// never happen though, since creating a type for the implicit self
/// argument implies that we already parsed the interface definition
/// and the ivar declarations in the implementation.
llvm::DIType *CreateSelfType(const QualType &QualTy, llvm::DIType *Ty);
/// @}
/// Get the type from the cache or return null type if it doesn't
/// exist.
llvm::DIType *getTypeOrNull(const QualType);
/// Return the debug type for a C++ method.
/// \arg CXXMethodDecl is of FunctionType. This function type is
/// not updated to include implicit \c this pointer. Use this routine
/// to get a method type which includes \c this pointer.
llvm::DISubroutineType *getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile *F);
llvm::DISubroutineType *
@ -159,7 +178,9 @@ class CGDebugInfo {
llvm::DIFile *Unit);
llvm::DISubroutineType *
getOrCreateFunctionType(const Decl *D, QualType FnType, llvm::DIFile *F);
/// \return debug info descriptor for vtable.
llvm::DIType *getOrCreateVTablePtrType(llvm::DIFile *F);
/// \return namespace descriptor for the given namespace decl.
llvm::DINamespace *getOrCreateNameSpace(const NamespaceDecl *N);
llvm::DIType *getOrCreateTypeDeclaration(QualType PointeeTy, llvm::DIFile *F);
llvm::DIType *CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty,
@ -168,23 +189,37 @@ class CGDebugInfo {
llvm::Value *getCachedInterfaceTypeOrNull(const QualType Ty);
llvm::DIType *getOrCreateStructPtrType(StringRef Name, llvm::DIType *&Cache);
/// A helper function to create a subprogram for a single member
/// function GlobalDecl.
llvm::DISubprogram *CreateCXXMemberFunction(const CXXMethodDecl *Method,
llvm::DIFile *F,
llvm::DIType *RecordTy);
/// A helper function to collect debug info for C++ member
/// functions. This is used while creating debug info entry for a
/// Record.
void CollectCXXMemberFunctions(const CXXRecordDecl *Decl, llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DIType *T);
/// A helper function to collect debug info for C++ base
/// classes. This is used while creating debug info entry for a
/// Record.
void CollectCXXBases(const CXXRecordDecl *Decl, llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &EltTys,
llvm::DIType *RecordTy);
/// A helper function to collect template parameters.
llvm::DINodeArray CollectTemplateParams(const TemplateParameterList *TPList,
ArrayRef<TemplateArgument> TAList,
llvm::DIFile *Unit);
/// A helper function to collect debug info for function template
/// parameters.
llvm::DINodeArray CollectFunctionTemplateParams(const FunctionDecl *FD,
llvm::DIFile *Unit);
/// A helper function to collect debug info for template
/// parameters.
llvm::DINodeArray
CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TS,
llvm::DIFile *F);
@ -195,7 +230,8 @@ class CGDebugInfo {
llvm::DIFile *tunit, llvm::DIScope *scope,
const RecordDecl *RD = nullptr);
// Helpers for collecting fields of a record.
/// Helpers for collecting fields of a record.
/// @{
void CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl,
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DIType *RecordTy);
@ -210,11 +246,13 @@ class CGDebugInfo {
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DICompositeType *RecordTy);
/// If the C++ class has vtable info then insert appropriate debug
/// info entry in EltTys vector.
void CollectVTableInfo(const CXXRecordDecl *Decl, llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &EltTys);
/// @}
// CreateLexicalBlock - Create a new lexical block node and push it on
// the stack.
/// Create a new lexical block node and push it on the stack.
void CreateLexicalBlock(SourceLocation Loc);
public:
@ -223,86 +261,84 @@ class CGDebugInfo {
void finalize();
/// \brief Update the current source location. If \arg loc is
/// invalid it is ignored.
/// Update the current source location. If \arg loc is invalid it is
/// ignored.
void setLocation(SourceLocation Loc);
/// \brief Emit metadata to indicate a change in line/column
/// information in the source file.
/// Emit metadata to indicate a change in line/column information in
/// the source file. If the location is invalid, the previous
/// location will be reused.
void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc);
/// \brief Emit a call to llvm.dbg.function.start to indicate
/// Emit a call to llvm.dbg.function.start to indicate
/// start of a new function.
/// \param Loc The location of the function header.
/// \param ScopeLoc The location of the function body.
void EmitFunctionStart(GlobalDecl GD,
SourceLocation Loc, SourceLocation ScopeLoc,
QualType FnType, llvm::Function *Fn,
CGBuilderTy &Builder);
void EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
SourceLocation ScopeLoc, QualType FnType,
llvm::Function *Fn, CGBuilderTy &Builder);
/// \brief Constructs the debug code for exiting a function.
/// Constructs the debug code for exiting a function.
void EmitFunctionEnd(CGBuilderTy &Builder);
/// \brief Emit metadata to indicate the beginning of a
/// new lexical block and push the block onto the stack.
/// Emit metadata to indicate the beginning of a new lexical block
/// and push the block onto the stack.
void EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc);
/// \brief Emit metadata to indicate the end of a new lexical
/// block and pop the current block.
/// Emit metadata to indicate the end of a new lexical block and pop
/// the current block.
void EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc);
/// \brief Emit call to llvm.dbg.declare for an automatic
/// variable declaration.
/// Emit call to \c llvm.dbg.declare for an automatic variable
/// declaration.
void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
CGBuilderTy &Builder);
/// \brief Emit call to llvm.dbg.declare for an
/// imported variable declaration in a block.
/// Emit call to \c llvm.dbg.declare for an imported variable
/// declaration in a block.
void EmitDeclareOfBlockDeclRefVariable(const VarDecl *variable,
llvm::Value *storage,
CGBuilderTy &Builder,
const CGBlockInfo &blockInfo,
llvm::Instruction *InsertPoint = 0);
/// \brief Emit call to llvm.dbg.declare for an argument
/// variable declaration.
/// Emit call to \c llvm.dbg.declare for an argument variable
/// declaration.
void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
unsigned ArgNo, CGBuilderTy &Builder);
/// \brief Emit call to
/// llvm.dbg.declare for the block-literal argument to a block
/// invocation function.
/// Emit call to \c llvm.dbg.declare for the block-literal argument
/// to a block invocation function.
void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::Value *Arg, unsigned ArgNo,
llvm::Value *LocalAddr,
CGBuilderTy &Builder);
/// \brief Emit information about a global variable.
/// Emit information about a global variable.
void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
/// \brief Emit global variable's debug info.
/// Emit global variable's debug info.
void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init);
/// \brief Emit C++ using directive.
/// Emit C++ using directive.
void EmitUsingDirective(const UsingDirectiveDecl &UD);
/// \brief Emit the type explicitly casted to.
/// Emit the type explicitly casted to.
void EmitExplicitCastType(QualType Ty);
/// \brief Emit C++ using declaration.
/// Emit C++ using declaration.
void EmitUsingDecl(const UsingDecl &UD);
/// \brief Emit an @import declaration.
/// Emit an @import declaration.
void EmitImportDecl(const ImportDecl &ID);
/// \brief Emit C++ namespace alias.
/// Emit C++ namespace alias.
llvm::DIImportedEntity *EmitNamespaceAlias(const NamespaceAliasDecl &NA);
/// \brief Emit record type's standalone debug info.
/// Emit record type's standalone debug info.
llvm::DIType *getOrCreateRecordType(QualType Ty, SourceLocation L);
/// \brief Emit an objective c interface type standalone
/// debug info.
/// Emit an Objective-C interface type standalone debug info.
llvm::DIType *getOrCreateInterfaceType(QualType Ty, SourceLocation Loc);
void completeType(const EnumDecl *ED);
@ -313,120 +349,124 @@ class CGDebugInfo {
void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD);
private:
/// \brief Emit call to llvm.dbg.declare for a variable declaration.
/// Emit call to llvm.dbg.declare for a variable declaration.
/// Tag accepts custom types DW_TAG_arg_variable and DW_TAG_auto_variable,
/// otherwise would be of type llvm::dwarf::Tag.
void EmitDeclare(const VarDecl *decl, llvm::dwarf::Tag Tag, llvm::Value *AI,
unsigned ArgNo, CGBuilderTy &Builder);
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
/// Build up structure info for the byref. See \a BuildByRefType.
llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *OffSet);
/// \brief Get context info for the decl.
/// Get context info for the decl.
llvm::DIScope *getContextDescriptor(const Decl *Decl);
llvm::DIScope *getCurrentContextDescriptor(const Decl *Decl);
/// \brief Create a forward decl for a RecordType in a given context.
/// Create a forward decl for a RecordType in a given context.
llvm::DICompositeType *getOrCreateRecordFwdDecl(const RecordType *,
llvm::DIScope *);
/// \brief Return current directory name.
/// Return current directory name.
StringRef getCurrentDirname();
/// \brief Create new compile unit.
/// Create new compile unit.
void CreateCompileUnit();
/// \brief Get the file debug info descriptor for the input
/// location.
/// Get the file debug info descriptor for the input location.
llvm::DIFile *getOrCreateFile(SourceLocation Loc);
/// \brief Get the file info for main compile unit.
/// Get the file info for main compile unit.
llvm::DIFile *getOrCreateMainFile();
/// \brief Get the type from the cache or create a new type if
/// necessary.
/// Get the type from the cache or create a new type if necessary.
llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg);
/// \brief Get a reference to a clang module.
/// Get a reference to a clang module.
llvm::DIModule *
getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod);
/// \brief Get the type from the cache or create a new
/// partial type if necessary.
/// Get the type from the cache or create a new partial type if
/// necessary.
llvm::DIType *getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile *F);
/// \brief Create type metadata for a source language type.
/// Create type metadata for a source language type.
llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg);
/// \brief return the underlying ObjCInterfaceDecl
/// if Ty is an ObjCInterface or a pointer to one.
ObjCInterfaceDecl* getObjCInterfaceDecl(QualType Ty);
/// Return the underlying ObjCInterfaceDecl if \arg Ty is an
/// ObjCInterface or a pointer to one.
ObjCInterfaceDecl *getObjCInterfaceDecl(QualType Ty);
/// \brief Create new member and increase Offset by FType's size.
/// Create new member and increase Offset by FType's size.
llvm::DIType *CreateMemberType(llvm::DIFile *Unit, QualType FType,
StringRef Name, uint64_t *Offset);
/// \brief Retrieve the DIDescriptor, if any, for the canonical form of this
/// Retrieve the DIDescriptor, if any, for the canonical form of this
/// declaration.
llvm::DINode *getDeclarationOrDefinition(const Decl *D);
/// \brief Return debug info descriptor to describe method
/// \return debug info descriptor to describe method
/// declaration for the given method definition.
llvm::DISubprogram *getFunctionDeclaration(const Decl *D);
/// Return debug info descriptor to describe in-class static data member
/// declaration for the given out-of-class definition.
/// \return debug info descriptor to describe in-class static data
/// member declaration for the given out-of-class definition. If D
/// is an out-of-class definition of a static data member of a
/// class, find its corresponding in-class declaration.
llvm::DIDerivedType *
getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D);
/// \brief Create a subprogram describing the forward
/// decalration represented in the given FunctionDecl.
/// Create a subprogram describing the forward declaration
/// represented in the given FunctionDecl.
llvm::DISubprogram *getFunctionForwardDeclaration(const FunctionDecl *FD);
/// \brief Create a global variable describing the forward decalration
/// Create a global variable describing the forward decalration
/// represented in the given VarDecl.
llvm::DIGlobalVariable *
getGlobalVariableForwardDeclaration(const VarDecl *VD);
/// Return a global variable that represents one of the collection of
/// global variables created for an anonmyous union.
/// \brief Return a global variable that represents one of the
/// collection of global variables created for an anonmyous union.
///
/// Recursively collect all of the member fields of a global
/// anonymous decl and create static variables for them. The first
/// time this is called it needs to be on a union and then from
/// there we can have additional unnamed fields.
llvm::DIGlobalVariable *
CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile *Unit,
unsigned LineNo, StringRef LinkageName,
llvm::GlobalVariable *Var, llvm::DIScope *DContext);
/// \brief Get function name for the given FunctionDecl. If the
/// name is constructed on demand (e.g. C++ destructor) then the name
/// is stored on the side.
/// Get function name for the given FunctionDecl. If the name is
/// constructed on demand (e.g., C++ destructor) then the name is
/// stored on the side.
StringRef getFunctionName(const FunctionDecl *FD);
/// \brief Returns the unmangled name of an Objective-C method.
/// Returns the unmangled name of an Objective-C method.
/// This is the display name for the debugging info.
StringRef getObjCMethodName(const ObjCMethodDecl *FD);
/// \brief Return selector name. This is used for debugging
/// Return selector name. This is used for debugging
/// info.
StringRef getSelectorName(Selector S);
/// \brief Get class name including template argument list.
/// Get class name including template argument list.
StringRef getClassName(const RecordDecl *RD);
/// \brief Get vtable name for the given Class.
/// Get the vtable name for the given class.
StringRef getVTableName(const CXXRecordDecl *Decl);
/// \brief Get line number for the location. If location is invalid
/// Get line number for the location. If location is invalid
/// then use current location.
unsigned getLineNumber(SourceLocation Loc);
/// \brief Get column number for the location. If location is
/// Get column number for the location. If location is
/// invalid then use current location.
/// \param Force Assume DebugColumnInfo option is true.
unsigned getColumnNumber(SourceLocation Loc, bool Force=false);
unsigned getColumnNumber(SourceLocation Loc, bool Force = false);
/// \brief Collect various properties of a FunctionDecl.
/// Collect various properties of a FunctionDecl.
/// \param GD A GlobalDecl whose getDecl() must return a FunctionDecl.
void collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
StringRef &Name, StringRef &LinkageName,
@ -434,12 +474,12 @@ class CGDebugInfo {
llvm::DINodeArray &TParamsArray,
unsigned &Flags);
/// \brief Collect various properties of a VarDecl.
/// Collect various properties of a VarDecl.
void collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
unsigned &LineNo, QualType &T, StringRef &Name,
StringRef &LinkageName, llvm::DIScope *&VDContext);
/// \brief Allocate a copy of \p A using the DebugInfoNames allocator
/// Allocate a copy of \p A using the DebugInfoNames allocator
/// and return a reference to it. If multiple arguments are given the strings
/// are concatenated.
StringRef internString(StringRef A, StringRef B = StringRef()) {
@ -450,7 +490,7 @@ class CGDebugInfo {
}
};
/// \brief A scoped helper to set the current debug location to the specified
/// A scoped helper to set the current debug location to the specified
/// location or preferred location of the specified Expr.
class ApplyDebugLocation {
private:
@ -460,55 +500,56 @@ class ApplyDebugLocation {
llvm::DebugLoc OriginalLocation;
CodeGenFunction &CGF;
public:
/// \brief Set the location to the (valid) TemporaryLocation.
public:
/// Set the location to the (valid) TemporaryLocation.
ApplyDebugLocation(CodeGenFunction &CGF, SourceLocation TemporaryLocation);
ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E);
ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc);
~ApplyDebugLocation();
/// \brief Apply TemporaryLocation if it is valid. Otherwise switch to an
/// artificial debug location that has a valid scope, but no line information.
/// \brief Apply TemporaryLocation if it is valid. Otherwise switch
/// to an artificial debug location that has a valid scope, but no
/// line information.
///
/// Artificial locations are useful when emitting compiler-generated helper
/// functions that have no source location associated with them. The DWARF
/// specification allows the compiler to use the special line number 0 to
/// indicate code that can not be attributed to any source location. Note that
/// passing an empty SourceLocation to CGDebugInfo::setLocation() will result
/// in the last valid location being reused.
/// Artificial locations are useful when emitting compiler-generated
/// helper functions that have no source location associated with
/// them. The DWARF specification allows the compiler to use the
/// special line number 0 to indicate code that can not be
/// attributed to any source location. Note that passing an empty
/// SourceLocation to CGDebugInfo::setLocation() will result in the
/// last valid location being reused.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF) {
return ApplyDebugLocation(CGF, false, SourceLocation());
}
/// \brief Apply TemporaryLocation if it is valid. Otherwise switch to an
/// artificial debug location that has a valid scope, but no line information.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF,
SourceLocation TemporaryLocation) {
/// \brief Apply TemporaryLocation if it is valid. Otherwise switch
/// to an artificial debug location that has a valid scope, but no
/// line information.
static ApplyDebugLocation
CreateDefaultArtificial(CodeGenFunction &CGF,
SourceLocation TemporaryLocation) {
return ApplyDebugLocation(CGF, false, TemporaryLocation);
}
/// \brief Set the IRBuilder to not attach debug locations. Note that passing
/// an empty SourceLocation to CGDebugInfo::setLocation() will result in the
/// last valid location being reused. Note that all instructions that do not
/// have a location at the beginning of a function are counted towards to
/// funciton prologue.
/// Set the IRBuilder to not attach debug locations. Note that
/// passing an empty SourceLocation to \a CGDebugInfo::setLocation()
/// will result in the last valid location being reused. Note that
/// all instructions that do not have a location at the beginning of
/// a function are counted towards to funciton prologue.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF) {
return ApplyDebugLocation(CGF, true, SourceLocation());
}
/// \brief Apply TemporaryLocation if it is valid. Otherwise set the IRBuilder
/// to not attach debug locations.
static ApplyDebugLocation CreateDefaultEmpty(CodeGenFunction &CGF,
SourceLocation TemporaryLocation) {
static ApplyDebugLocation
CreateDefaultEmpty(CodeGenFunction &CGF, SourceLocation TemporaryLocation) {
return ApplyDebugLocation(CGF, true, TemporaryLocation);
}
};
} // namespace CodeGen
} // namespace clang
#endif

View File

@ -79,6 +79,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::Captured:
case Decl::ClassScopeFunctionSpecialization:
case Decl::UsingShadow:
case Decl::ObjCTypeParam:
llvm_unreachable("Declaration should not be in declstmts!");
case Decl::Function: // void X();
case Decl::Record: // struct/union/class X;
@ -987,7 +988,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
llvm::Value *Stack = CreateTempAlloca(Int8PtrTy, "saved_stack");
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave);
llvm::Value *V = Builder.CreateCall(F, {});
llvm::Value *V = Builder.CreateCall(F);
Builder.CreateStore(V, Stack);

View File

@ -20,6 +20,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicInst.h"
@ -1279,14 +1280,6 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {
}
void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
// FIXME: Implement SEH on other architectures.
const llvm::Triple &T = CGM.getTarget().getTriple();
if (T.getArch() != llvm::Triple::x86_64 ||
!T.isKnownWindowsMSVCEnvironment()) {
ErrorUnsupported(&S, "__try statement");
return;
}
EnterSEHTryStmt(S);
{
JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
@ -1311,24 +1304,27 @@ struct PerformSEHFinally : EHScopeStack::Cleanup {
void Emit(CodeGenFunction &CGF, Flags F) override {
ASTContext &Context = CGF.getContext();
QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy};
FunctionProtoType::ExtProtoInfo EPI;
const auto *FTP = cast<FunctionType>(
Context.getFunctionType(Context.VoidTy, ArgTys, EPI));
CodeGenModule &CGM = CGF.CGM;
CallArgList Args;
// Compute the two argument values.
QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy};
llvm::Value *LocalAddrFn = CGM.getIntrinsic(llvm::Intrinsic::localaddress);
llvm::Value *FP = CGF.Builder.CreateCall(LocalAddrFn);
llvm::Value *IsForEH =
llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
Args.add(RValue::get(IsForEH), ArgTys[0]);
CodeGenModule &CGM = CGF.CGM;
llvm::Value *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0);
llvm::Value *FrameAddr = CGM.getIntrinsic(llvm::Intrinsic::frameaddress);
llvm::Value *FP = CGF.Builder.CreateCall(FrameAddr, Zero);
Args.add(RValue::get(FP), ArgTys[1]);
// Arrange a two-arg function info and type.
FunctionProtoType::ExtProtoInfo EPI;
const auto *FPT = cast<FunctionProtoType>(
Context.getFunctionType(Context.VoidTy, ArgTys, EPI));
const CGFunctionInfo &FnInfo =
CGM.getTypes().arrangeFreeFunctionCall(Args, FTP, /*chainCall=*/false);
CGM.getTypes().arrangeFreeFunctionCall(Args, FPT,
/*chainCall=*/false);
CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
}
};
@ -1340,9 +1336,15 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
CodeGenFunction &ParentCGF;
const VarDecl *ParentThis;
SmallVector<const VarDecl *, 4> Captures;
llvm::Value *SEHCodeSlot = nullptr;
CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis)
: ParentCGF(ParentCGF), ParentThis(ParentThis) {}
// Return true if we need to do any capturing work.
bool foundCaptures() {
return !Captures.empty() || SEHCodeSlot;
}
void Visit(const Stmt *S) {
// See if this is a capture, then recurse.
ConstStmtVisitor<CaptureFinder>::Visit(S);
@ -1366,27 +1368,106 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
void VisitCXXThisExpr(const CXXThisExpr *E) {
Captures.push_back(ParentThis);
}
void VisitCallExpr(const CallExpr *E) {
// We only need to add parent frame allocations for these builtins in x86.
if (ParentCGF.getTarget().getTriple().getArch() != llvm::Triple::x86)
return;
unsigned ID = E->getBuiltinCallee();
switch (ID) {
case Builtin::BI__exception_code:
case Builtin::BI_exception_code:
// This is the simple case where we are the outermost finally. All we
// have to do here is make sure we escape this and recover it in the
// outlined handler.
if (!SEHCodeSlot)
SEHCodeSlot = ParentCGF.SEHCodeSlotStack.back();
break;
}
}
};
}
llvm::Value *CodeGenFunction::recoverAddrOfEscapedLocal(
CodeGenFunction &ParentCGF, llvm::Value *ParentVar, llvm::Value *ParentFP) {
llvm::CallInst *RecoverCall = nullptr;
CGBuilderTy Builder(AllocaInsertPt);
if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
// Mark the variable escaped if nobody else referenced it and compute the
// localescape index.
auto InsertPair = ParentCGF.EscapedLocals.insert(
std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size()));
int FrameEscapeIdx = InsertPair.first->second;
// call i8* @llvm.localrecover(i8* bitcast(@parentFn), i8* %fp, i32 N)
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
&CGM.getModule(), llvm::Intrinsic::localrecover);
llvm::Constant *ParentI8Fn =
llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
RecoverCall = Builder.CreateCall(
FrameRecoverFn, {ParentI8Fn, ParentFP,
llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
} else {
// If the parent didn't have an alloca, we're doing some nested outlining.
// Just clone the existing localrecover call, but tweak the FP argument to
// use our FP value. All other arguments are constants.
auto *ParentRecover =
cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts());
assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover &&
"expected alloca or localrecover in parent LocalDeclMap");
RecoverCall = cast<llvm::CallInst>(ParentRecover->clone());
RecoverCall->setArgOperand(1, ParentFP);
RecoverCall->insertBefore(AllocaInsertPt);
}
// Bitcast the variable, rename it, and insert it in the local decl map.
llvm::Value *ChildVar =
Builder.CreateBitCast(RecoverCall, ParentVar->getType());
ChildVar->setName(ParentVar->getName());
return ChildVar;
}
void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
const Stmt *OutlinedStmt,
llvm::Value *ParentFP) {
bool IsFilter) {
// Find all captures in the Stmt.
CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl);
Finder.Visit(OutlinedStmt);
// Typically there are no captures and we can exit early.
if (Finder.Captures.empty())
// We can exit early on x86_64 when there are no captures. We just have to
// save the exception code in filters so that __exception_code() works.
if (!Finder.foundCaptures() &&
CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
if (IsFilter)
EmitSEHExceptionCodeSave(ParentCGF, nullptr, nullptr);
return;
}
// Prepare the first two arguments to llvm.framerecover.
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
&CGM.getModule(), llvm::Intrinsic::framerecover);
llvm::Constant *ParentI8Fn =
llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
llvm::Value *EntryEBP = nullptr;
llvm::Value *ParentFP;
if (IsFilter && CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) {
// 32-bit SEH filters need to be careful about FP recovery. The end of the
// EH registration is passed in as the EBP physical register. We can
// recover that with llvm.frameaddress(1), and adjust that to recover the
// parent's true frame pointer.
CGBuilderTy Builder(AllocaInsertPt);
EntryEBP = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::frameaddress), {Builder.getInt32(1)});
llvm::Function *RecoverFPIntrin =
CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp);
llvm::Constant *ParentI8Fn =
llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryEBP});
} else {
// Otherwise, for x64 and 32-bit finally functions, the parent FP is the
// second parameter.
auto AI = CurFn->arg_begin();
++AI;
ParentFP = AI;
}
// Create llvm.framerecover calls for all captures.
// Create llvm.localrecover calls for all captures.
for (const VarDecl *VD : Finder.Captures) {
if (isa<ImplicitParamDecl>(VD)) {
CGM.ErrorUnsupported(VD, "'this' captured by SEH");
@ -1407,49 +1488,63 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
continue;
llvm::Value *ParentVar = I->second;
llvm::CallInst *RecoverCall = nullptr;
CGBuilderTy Builder(AllocaInsertPt);
if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
// Mark the variable escaped if nobody else referenced it and compute the
// frameescape index.
auto InsertPair =
ParentCGF.EscapedLocals.insert(std::make_pair(ParentAlloca, -1));
if (InsertPair.second)
InsertPair.first->second = ParentCGF.EscapedLocals.size() - 1;
int FrameEscapeIdx = InsertPair.first->second;
// call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 N)
RecoverCall = Builder.CreateCall(
FrameRecoverFn, {ParentI8Fn, ParentFP,
llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
} else {
// If the parent didn't have an alloca, we're doing some nested outlining.
// Just clone the existing framerecover call, but tweak the FP argument to
// use our FP value. All other arguments are constants.
auto *ParentRecover =
cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts());
assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::framerecover &&
"expected alloca or framerecover in parent LocalDeclMap");
RecoverCall = cast<llvm::CallInst>(ParentRecover->clone());
RecoverCall->setArgOperand(1, ParentFP);
RecoverCall->insertBefore(AllocaInsertPt);
}
// Bitcast the variable, rename it, and insert it in the local decl map.
llvm::Value *ChildVar =
Builder.CreateBitCast(RecoverCall, ParentVar->getType());
ChildVar->setName(ParentVar->getName());
LocalDeclMap[VD] = ChildVar;
LocalDeclMap[VD] =
recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP);
}
if (Finder.SEHCodeSlot) {
SEHCodeSlotStack.push_back(
recoverAddrOfEscapedLocal(ParentCGF, Finder.SEHCodeSlot, ParentFP));
}
if (IsFilter)
EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryEBP);
}
/// Arrange a function prototype that can be called by Windows exception
/// handling personalities. On Win64, the prototype looks like:
/// RetTy func(void *EHPtrs, void *ParentFP);
void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
StringRef Name, QualType RetTy,
FunctionArgList &Args,
bool IsFilter,
const Stmt *OutlinedStmt) {
SourceLocation StartLoc = OutlinedStmt->getLocStart();
// Get the mangled function name.
SmallString<128> Name;
{
llvm::raw_svector_ostream OS(Name);
const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
MangleContext &Mangler = CGM.getCXXABI().getMangleContext();
if (IsFilter)
Mangler.mangleSEHFilterExpression(Parent, OS);
else
Mangler.mangleSEHFinallyBlock(Parent, OS);
}
FunctionArgList Args;
if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 || !IsFilter) {
// All SEH finally functions take two parameters. Win64 filters take two
// parameters. Win32 filters take no parameters.
if (IsFilter) {
Args.push_back(ImplicitParamDecl::Create(
getContext(), nullptr, StartLoc,
&getContext().Idents.get("exception_pointers"),
getContext().VoidPtrTy));
} else {
Args.push_back(ImplicitParamDecl::Create(
getContext(), nullptr, StartLoc,
&getContext().Idents.get("abnormal_termination"),
getContext().UnsignedCharTy));
}
Args.push_back(ImplicitParamDecl::Create(
getContext(), nullptr, StartLoc,
&getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
}
QualType RetTy = IsFilter ? getContext().LongTy : getContext().VoidTy;
llvm::Function *ParentFn = ParentCGF.CurFn;
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false);
@ -1474,10 +1569,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart());
CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn);
auto AI = Fn->arg_begin();
++AI;
EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI);
EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter);
}
/// Create a stub filter function that will ultimately hold the code of the
@ -1487,37 +1579,7 @@ llvm::Function *
CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
const SEHExceptStmt &Except) {
const Expr *FilterExpr = Except.getFilterExpr();
SourceLocation StartLoc = FilterExpr->getLocStart();
SEHPointersDecl = ImplicitParamDecl::Create(
getContext(), nullptr, StartLoc,
&getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy);
FunctionArgList Args;
Args.push_back(SEHPointersDecl);
Args.push_back(ImplicitParamDecl::Create(
getContext(), nullptr, StartLoc,
&getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
// Get the mangled function name.
SmallString<128> Name;
{
llvm::raw_svector_ostream OS(Name);
const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
CGM.getCXXABI().getMangleContext().mangleSEHFilterExpression(Parent, OS);
}
startOutlinedSEHHelper(ParentCGF, Name, getContext().LongTy, Args,
FilterExpr);
// Mark finally block calls as nounwind and noinline to make LLVM's job a
// little easier.
// FIXME: Remove these restrictions in the future.
CurFn->addFnAttr(llvm::Attribute::NoUnwind);
CurFn->addFnAttr(llvm::Attribute::NoInline);
EmitSEHExceptionCodeSave();
startOutlinedSEHHelper(ParentCGF, true, FilterExpr);
// Emit the original filter expression, convert to i32, and return.
llvm::Value *R = EmitScalarExpr(FilterExpr);
@ -1534,29 +1596,13 @@ llvm::Function *
CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
const SEHFinallyStmt &Finally) {
const Stmt *FinallyBlock = Finally.getBlock();
SourceLocation StartLoc = FinallyBlock->getLocStart();
startOutlinedSEHHelper(ParentCGF, false, FinallyBlock);
FunctionArgList Args;
Args.push_back(ImplicitParamDecl::Create(
getContext(), nullptr, StartLoc,
&getContext().Idents.get("abnormal_termination"),
getContext().UnsignedCharTy));
Args.push_back(ImplicitParamDecl::Create(
getContext(), nullptr, StartLoc,
&getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
// Get the mangled function name.
SmallString<128> Name;
{
llvm::raw_svector_ostream OS(Name);
const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
CGM.getCXXABI().getMangleContext().mangleSEHFinallyBlock(Parent, OS);
}
startOutlinedSEHHelper(ParentCGF, Name, getContext().VoidTy, Args,
FinallyBlock);
// Mark finally block calls as nounwind and noinline to make LLVM's job a
// little easier.
// FIXME: Remove these restrictions in the future.
CurFn->addFnAttr(llvm::Attribute::NoUnwind);
CurFn->addFnAttr(llvm::Attribute::NoInline);
// Emit the original filter expression, convert to i32, and return.
EmitStmt(FinallyBlock);
@ -1566,44 +1612,58 @@ CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
return CurFn;
}
void CodeGenFunction::EmitSEHExceptionCodeSave() {
void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
llvm::Value *ParentFP,
llvm::Value *EntryEBP) {
// Get the pointer to the EXCEPTION_POINTERS struct. This is returned by the
// __exception_info intrinsic.
if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
// On Win64, the info is passed as the first parameter to the filter.
auto AI = CurFn->arg_begin();
SEHInfo = AI;
SEHCodeSlotStack.push_back(
CreateMemTemp(getContext().IntTy, "__exception_code"));
} else {
// On Win32, the EBP on entry to the filter points to the end of an
// exception registration object. It contains 6 32-bit fields, and the info
// pointer is stored in the second field. So, GEP 20 bytes backwards and
// load the pointer.
SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryEBP, -20);
SEHInfo = Builder.CreateBitCast(SEHInfo, Int8PtrTy->getPointerTo());
SEHInfo = Builder.CreateLoad(Int8PtrTy, SEHInfo);
SEHCodeSlotStack.push_back(recoverAddrOfEscapedLocal(
ParentCGF, ParentCGF.SEHCodeSlotStack.back(), ParentFP));
}
// Save the exception code in the exception slot to unify exception access in
// the filter function and the landing pad.
// struct EXCEPTION_POINTERS {
// EXCEPTION_RECORD *ExceptionRecord;
// CONTEXT *ContextRecord;
// };
// void *exn.slot =
// (void *)(uintptr_t)exception_pointers->ExceptionRecord->ExceptionCode;
llvm::Value *Ptrs = Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl));
// int exceptioncode = exception_pointers->ExceptionRecord->ExceptionCode;
llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo();
llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr);
Ptrs = Builder.CreateBitCast(Ptrs, PtrsTy->getPointerTo());
llvm::Value *Ptrs = Builder.CreateBitCast(SEHInfo, PtrsTy->getPointerTo());
llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0);
Rec = Builder.CreateLoad(Rec);
llvm::Value *Code = Builder.CreateLoad(Rec);
Code = Builder.CreateZExt(Code, CGM.IntPtrTy);
// FIXME: Change landing pads to produce {i32, i32} and make the exception
// slot an i32.
Code = Builder.CreateIntToPtr(Code, CGM.VoidPtrTy);
Builder.CreateStore(Code, getExceptionSlot());
assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
Builder.CreateStore(Code, SEHCodeSlotStack.back());
}
llvm::Value *CodeGenFunction::EmitSEHExceptionInfo() {
// Sema should diagnose calling this builtin outside of a filter context, but
// don't crash if we screw up.
if (!SEHPointersDecl)
if (!SEHInfo)
return llvm::UndefValue::get(Int8PtrTy);
return Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl));
assert(SEHInfo->getType() == Int8PtrTy);
return SEHInfo;
}
llvm::Value *CodeGenFunction::EmitSEHExceptionCode() {
// If we're in a landing pad or filter function, the exception slot contains
// the code.
assert(ExceptionSlot);
llvm::Value *Code =
Builder.CreatePtrToInt(getExceptionFromSlot(), CGM.IntPtrTy);
return Builder.CreateTrunc(Code, CGM.Int32Ty);
assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
return Builder.CreateLoad(Int32Ty, SEHCodeSlotStack.back());
}
llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
@ -1616,9 +1676,11 @@ llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
// Push a cleanup for __finally blocks.
// Outline the finally block.
llvm::Function *FinallyFunc =
HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
// Push a cleanup for __finally blocks.
EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc);
return;
}
@ -1627,12 +1689,16 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
const SEHExceptStmt *Except = S.getExceptHandler();
assert(Except);
EHCatchScope *CatchScope = EHStack.pushCatch(1);
SEHCodeSlotStack.push_back(
CreateMemTemp(getContext().IntTy, "__exception_code"));
// If the filter is known to evaluate to 1, then we can use the clause "catch
// i8* null".
// If the filter is known to evaluate to 1, then we can use the clause
// "catch i8* null". We can't do this on x86 because the filter has to save
// the exception code.
llvm::Constant *C =
CGM.EmitConstantExpr(Except->getFilterExpr(), getContext().IntTy, this);
if (C && C->isOneValue()) {
if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 && C &&
C->isOneValue()) {
CatchScope->setCatchAllHandler(0, createBasicBlock("__except"));
return;
}
@ -1664,6 +1730,7 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
if (!CatchScope.hasEHBranches()) {
CatchScope.clearHandlerBlocks();
EHStack.popCatch();
SEHCodeSlotStack.pop_back();
return;
}
@ -1683,9 +1750,20 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
EmitBlockAfterUses(ExceptBB);
// On Win64, the exception pointer is the exception code. Copy it to the slot.
if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
llvm::Value *Code =
Builder.CreatePtrToInt(getExceptionFromSlot(), IntPtrTy);
Code = Builder.CreateTrunc(Code, Int32Ty);
Builder.CreateStore(Code, SEHCodeSlotStack.back());
}
// Emit the __except body.
EmitStmt(Except->getBlock());
// End the lifetime of the exception code.
SEHCodeSlotStack.pop_back();
if (HaveInsertPoint())
Builder.CreateBr(ContBB);

View File

@ -1356,14 +1356,15 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) {
const CGBitFieldInfo &Info = LV.getBitFieldInfo();
CharUnits Align = LV.getAlignment().alignmentAtOffset(Info.StorageOffset);
// Get the output type.
llvm::Type *ResLTy = ConvertType(LV.getType());
llvm::Value *Ptr = LV.getBitFieldAddr();
llvm::Value *Val = Builder.CreateLoad(Ptr, LV.isVolatileQualified(),
"bf.load");
cast<llvm::LoadInst>(Val)->setAlignment(Info.StorageAlignment);
llvm::Value *Val = Builder.CreateAlignedLoad(Ptr, Align.getQuantity(),
LV.isVolatileQualified(),
"bf.load");
if (Info.IsSigned) {
assert(static_cast<unsigned>(Info.Offset + Info.Size) <= Info.StorageSize);
@ -1559,6 +1560,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
llvm::Value **Result) {
const CGBitFieldInfo &Info = Dst.getBitFieldInfo();
CharUnits Align = Dst.getAlignment().alignmentAtOffset(Info.StorageOffset);
llvm::Type *ResLTy = ConvertTypeForMem(Dst.getType());
llvm::Value *Ptr = Dst.getBitFieldAddr();
@ -1575,9 +1577,9 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
// and mask together with source before storing.
if (Info.StorageSize != Info.Size) {
assert(Info.StorageSize > Info.Size && "Invalid bitfield size.");
llvm::Value *Val = Builder.CreateLoad(Ptr, Dst.isVolatileQualified(),
"bf.load");
cast<llvm::LoadInst>(Val)->setAlignment(Info.StorageAlignment);
llvm::Value *Val = Builder.CreateAlignedLoad(Ptr, Align.getQuantity(),
Dst.isVolatileQualified(),
"bf.load");
// Mask the source value as needed.
if (!hasBooleanRepresentation(Dst.getType()))
@ -1603,9 +1605,8 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
}
// Write the new value back out.
llvm::StoreInst *Store = Builder.CreateStore(SrcVal, Ptr,
Dst.isVolatileQualified());
Store->setAlignment(Info.StorageAlignment);
Builder.CreateAlignedStore(SrcVal, Ptr, Align.getQuantity(),
Dst.isVolatileQualified());
// Return the new value of the bit-field, if requested.
if (Result) {
@ -2415,8 +2416,7 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
}
llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
llvm::CallInst *TrapCall =
Builder.CreateCall(CGM.getIntrinsic(IntrID), {});
llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(IntrID));
if (!CGM.getCodeGenOpts().TrapFuncName.empty())
TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex,

View File

@ -31,10 +31,9 @@ using namespace CodeGen;
typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult;
static TryEmitResult
tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e);
static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
QualType ET,
const ObjCMethodDecl *Method,
RValue Result);
static RValue AdjustObjCObjectType(CodeGenFunction &CGF,
QualType ET,
RValue Result);
/// Given the address of a variable of pointer type, find the correct
/// null to store into it.
@ -248,23 +247,22 @@ llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) {
return CGM.getObjCRuntime().GenerateProtocolRef(*this, E->getProtocol());
}
/// \brief Adjust the type of the result of an Objective-C message send
/// expression when the method has a related result type.
static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
QualType ExpT,
const ObjCMethodDecl *Method,
RValue Result) {
if (!Method)
/// \brief Adjust the type of an Objective-C object that doesn't match up due
/// to type erasure at various points, e.g., related result types or the use
/// of parameterized classes.
static RValue AdjustObjCObjectType(CodeGenFunction &CGF, QualType ExpT,
RValue Result) {
if (!ExpT->isObjCRetainableType())
return Result;
if (!Method->hasRelatedResultType() ||
CGF.getContext().hasSameType(ExpT, Method->getReturnType()) ||
!Result.isScalar())
// If the converted types are the same, we're done.
llvm::Type *ExpLLVMTy = CGF.ConvertType(ExpT);
if (ExpLLVMTy == Result.getScalarVal()->getType())
return Result;
// We have applied a related result type. Cast the rvalue appropriately.
// We have applied a substitution. Cast the rvalue appropriately.
return RValue::get(CGF.Builder.CreateBitCast(Result.getScalarVal(),
CGF.ConvertType(ExpT)));
ExpLLVMTy));
}
/// Decide whether to extend the lifetime of the receiver of a
@ -449,7 +447,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
Builder.CreateStore(newSelf, selfAddr);
}
return AdjustRelatedResultType(*this, E->getType(), method, result);
return AdjustObjCObjectType(*this, E->getType(), result);
}
namespace {
@ -2011,7 +2009,7 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
// Call the marker asm if we made one, which we do only at -O0.
if (marker)
Builder.CreateCall(marker, {});
Builder.CreateCall(marker);
return emitARCValueOperation(*this, value,
CGM.getARCEntrypoints().objc_retainAutoreleasedReturnValue,

View File

@ -134,7 +134,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo(
CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize,
CGF.CGM.getContext().toBits(StorageSize),
Alignment.getQuantity()));
CharUnits::fromQuantity(0)));
V = CGF.Builder.CreateBitCast(V,
llvm::Type::getIntNPtrTy(CGF.getLLVMContext(),
@ -160,7 +160,7 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) override {
if (!MightThrow) {
CGF.Builder.CreateCall(Fn, {})->setDoesNotThrow();
CGF.Builder.CreateCall(Fn)->setDoesNotThrow();
return;
}

View File

@ -537,7 +537,7 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
break;
}
case OMPRTL__kmpc_barrier: {
// Build void __kmpc_cancel_barrier(ident_t *loc, kmp_int32 global_tid);
// Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
@ -829,6 +829,15 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
break;
}
case OMPRTL__kmpc_cancel: {
// Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
// kmp_int32 cncl_kind)
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
break;
}
}
return RTLFn;
}
@ -923,6 +932,8 @@ llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
llvm::Constant *
CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
assert(!CGM.getLangOpts().OpenMPUseTLS ||
!CGM.getContext().getTargetInfo().isTLSSupported());
// Lookup the entry, lazily creating it if necessary.
return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Twine(CGM.getMangledName(VD)) + ".cache.");
@ -932,6 +943,10 @@ llvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
const VarDecl *VD,
llvm::Value *VDAddr,
SourceLocation Loc) {
if (CGM.getLangOpts().OpenMPUseTLS &&
CGM.getContext().getTargetInfo().isTLSSupported())
return VDAddr;
auto VarTy = VDAddr->getType()->getPointerElementType();
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy),
@ -961,6 +976,10 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit(
llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc,
bool PerformInit, CodeGenFunction *CGF) {
if (CGM.getLangOpts().OpenMPUseTLS &&
CGM.getContext().getTargetInfo().isTLSSupported())
return nullptr;
VD = VD->getDefinition(CGM.getContext());
if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
ThreadPrivateWithDefinition.insert(VD);
@ -2723,18 +2742,18 @@ void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
}
void CGOpenMPRuntime::emitCancellationPointCall(
CodeGenFunction &CGF, SourceLocation Loc,
OpenMPDirectiveKind CancelRegion) {
// Build call kmp_int32 OMPRTL__kmpc_cancellationpoint(ident_t *loc, kmp_int32
// global_tid, kmp_int32 cncl_kind);
enum {
CancelNoreq = 0,
CancelParallel = 1,
CancelLoop = 2,
CancelSections = 3,
CancelTaskgroup = 4
} CancelKind = CancelNoreq;
namespace {
enum RTCancelKind {
CancelNoreq = 0,
CancelParallel = 1,
CancelLoop = 2,
CancelSections = 3,
CancelTaskgroup = 4
};
}
static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
RTCancelKind CancelKind = CancelNoreq;
if (CancelRegion == OMPD_parallel)
CancelKind = CancelParallel;
else if (CancelRegion == OMPD_for)
@ -2745,14 +2764,22 @@ void CGOpenMPRuntime::emitCancellationPointCall(
assert(CancelRegion == OMPD_taskgroup);
CancelKind = CancelTaskgroup;
}
return CancelKind;
}
void CGOpenMPRuntime::emitCancellationPointCall(
CodeGenFunction &CGF, SourceLocation Loc,
OpenMPDirectiveKind CancelRegion) {
// Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
// global_tid, kmp_int32 cncl_kind);
if (auto *OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
auto CancelDest =
CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
if (CancelDest.isValid()) {
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc),
getThreadID(CGF, Loc),
CGF.Builder.getInt32(CancelKind)};
llvm::Value *Args[] = {
emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
// Ignore return result until untied tasks are supported.
auto *Result = CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
@ -2774,3 +2801,36 @@ void CGOpenMPRuntime::emitCancellationPointCall(
}
}
void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
OpenMPDirectiveKind CancelRegion) {
// Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
// kmp_int32 cncl_kind);
if (auto *OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
auto CancelDest =
CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
if (CancelDest.isValid()) {
llvm::Value *Args[] = {
emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
// Ignore return result until untied tasks are supported.
auto *Result =
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
// if (__kmpc_cancel()) {
// __kmpc_cancel_barrier();
// exit from construct;
// }
auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
auto *ContBB = CGF.createBasicBlock(".cancel.continue");
auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
CGF.EmitBlock(ExitBB);
// __kmpc_cancel_barrier();
emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false);
// exit from construct;
CGF.EmitBranchThroughCleanup(CancelDest);
CGF.EmitBlock(ContBB, /*IsFinished=*/true);
}
}
}

View File

@ -151,6 +151,9 @@ class CGOpenMPRuntime {
// Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
// global_tid, kmp_int32 cncl_kind);
OMPRTL__kmpc_cancellationpoint,
// Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
// kmp_int32 cncl_kind);
OMPRTL__kmpc_cancel,
};
/// \brief Values for bit flags used in the ident_t to describe the fields.
@ -698,6 +701,12 @@ class CGOpenMPRuntime {
virtual void emitCancellationPointCall(CodeGenFunction &CGF,
SourceLocation Loc,
OpenMPDirectiveKind CancelRegion);
/// \brief Emit code for 'cancel' construct.
/// \param CancelRegion Region kind for which the cancel must be emitted.
///
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
OpenMPDirectiveKind CancelRegion);
};
} // namespace CodeGen

View File

@ -78,16 +78,16 @@ struct CGBitFieldInfo {
/// bitfield.
unsigned StorageSize;
/// The alignment which should be used when accessing the bitfield.
unsigned StorageAlignment;
/// The offset of the bitfield storage from the start of the struct.
CharUnits StorageOffset;
CGBitFieldInfo()
: Offset(), Size(), IsSigned(), StorageSize(), StorageAlignment() {}
: Offset(), Size(), IsSigned(), StorageSize(), StorageOffset() {}
CGBitFieldInfo(unsigned Offset, unsigned Size, bool IsSigned,
unsigned StorageSize, unsigned StorageAlignment)
unsigned StorageSize, CharUnits StorageOffset)
: Offset(Offset), Size(Size), IsSigned(IsSigned),
StorageSize(StorageSize), StorageAlignment(StorageAlignment) {}
StorageSize(StorageSize), StorageOffset(StorageOffset) {}
void print(raw_ostream &OS) const;
void dump() const;
@ -99,7 +99,7 @@ struct CGBitFieldInfo {
const FieldDecl *FD,
uint64_t Offset, uint64_t Size,
uint64_t StorageSize,
uint64_t StorageAlignment);
CharUnits StorageOffset);
};
/// CGRecordLayout - This class handles struct and union layout info while

View File

@ -228,11 +228,7 @@ void CGRecordLowering::setBitFieldInfo(
Info.Offset = (unsigned)(getFieldBitOffset(FD) - Context.toBits(StartOffset));
Info.Size = FD->getBitWidthValue(Context);
Info.StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType);
// Here we calculate the actual storage alignment of the bits. E.g if we've
// got an alignment >= 2 and the bitfield starts at offset 6 we've got an
// alignment of 2.
Info.StorageAlignment =
Layout.getAlignment().alignmentAtOffset(StartOffset).getQuantity();
Info.StorageOffset = StartOffset;
if (Info.Size > Info.StorageSize)
Info.Size = Info.StorageSize;
// Reverse the bit offsets for big endian machines. Because we represent
@ -651,7 +647,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
const FieldDecl *FD,
uint64_t Offset, uint64_t Size,
uint64_t StorageSize,
uint64_t StorageAlignment) {
CharUnits StorageOffset) {
// This function is vestigial from CGRecordLayoutBuilder days but is still
// used in GCObjCRuntime.cpp. That usage has a "fixme" attached to it that
// when addressed will allow for the removal of this function.
@ -683,7 +679,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
Offset = StorageSize - (Offset + Size);
}
return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageAlignment);
return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageOffset);
}
CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D,
@ -856,7 +852,7 @@ void CGBitFieldInfo::print(raw_ostream &OS) const {
<< " Size:" << Size
<< " IsSigned:" << IsSigned
<< " StorageSize:" << StorageSize
<< " StorageAlignment:" << StorageAlignment << ">";
<< " StorageOffset:" << StorageOffset.getQuantity() << ">";
}
void CGBitFieldInfo::dump() const {

View File

@ -1852,6 +1852,14 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
std::vector<llvm::Value*> InOutArgs;
std::vector<llvm::Type*> InOutArgTypes;
// An inline asm can be marked readonly if it meets the following conditions:
// - it doesn't have any sideeffects
// - it doesn't clobber memory
// - it doesn't return a value by-reference
// It can be marked readnone if it doesn't have any input memory constraints
// in addition to meeting the conditions listed above.
bool ReadOnly = true, ReadNone = true;
for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
@ -1915,6 +1923,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Args.push_back(Dest.getAddress());
Constraints += "=*";
Constraints += OutputConstraint;
ReadOnly = ReadNone = false;
}
if (Info.isReadWrite()) {
@ -1959,6 +1968,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
if (Info.allowsMemory())
ReadNone = false;
if (!Constraints.empty())
Constraints += ',';
@ -2023,7 +2035,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
StringRef Clobber = S.getClobber(i);
if (Clobber != "memory" && Clobber != "cc")
if (Clobber == "memory")
ReadOnly = ReadNone = false;
else if (Clobber != "cc")
Clobber = getTarget().getNormalizedGCCRegisterName(Clobber);
if (!Constraints.empty())
@ -2063,6 +2077,16 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoUnwind);
// Attach readnone and readonly attributes.
if (!HasSideEffect) {
if (ReadNone)
Result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::ReadNone);
else if (ReadOnly)
Result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::ReadOnly);
}
// Slap the source location of the inline asm into a !srcloc metadata on the
// call.
if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S)) {

View File

@ -2108,7 +2108,8 @@ void CodeGenFunction::EmitOMPCancellationPointDirective(
}
void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
llvm_unreachable("CodeGen for 'omp cancel' is not supported yet.");
CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(),
S.getCancelRegion());
}
CodeGenFunction::JumpDest

View File

@ -364,7 +364,7 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
FinishFunction();
}
void CodeGenFunction::GenerateThunk(llvm::Function *Fn,
void CodeGenFunction::generateThunk(llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk) {
StartThunk(Fn, GD, FnInfo);
@ -376,13 +376,6 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn,
// Make the call and return the result.
EmitCallAndReturnForThunk(Callee, &Thunk);
// Set the right linkage.
CGM.setFunctionLinkage(GD, Fn);
// Set the right visibility.
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
setThunkVisibility(CGM, MD, Thunk, Fn);
}
void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
@ -455,11 +448,17 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk);
} else {
// Normal thunk body generation.
CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk);
CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, Thunk);
}
CGM.setFunctionLinkage(GD, ThunkFn);
CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD,
!Thunk.Return.isEmpty());
// Set the right visibility.
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
setThunkVisibility(CGM, MD, Thunk, ThunkFn);
if (CGM.supportsCOMDAT() && ThunkFn->isWeakForLinker())
ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));
}
@ -841,6 +840,11 @@ void CodeGenModule::EmitDeferredVTables() {
DeferredVTables.clear();
}
bool CodeGenModule::IsCFIBlacklistedRecord(const CXXRecordDecl *RD) {
// FIXME: Make this user configurable.
return RD->isInStdNamespace();
}
void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
const VTableLayout &VTLayout) {
if (!LangOpts.Sanitize.has(SanitizerKind::CFIVCall) &&
@ -855,8 +859,7 @@ void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
std::vector<llvm::MDTuple *> BitsetEntries;
// Create a bit set entry for each address point.
for (auto &&AP : VTLayout.getAddressPoints()) {
// FIXME: Add blacklisting scheme.
if (AP.first.getBase()->isInStdNamespace())
if (IsCFIBlacklistedRecord(AP.first.getBase()))
continue;
BitsetEntries.push_back(CreateVTableBitSetEntry(

View File

@ -10,6 +10,7 @@ set(LLVM_LINK_COMPONENTS
Linker
MC
ObjCARCOpts
Object
ProfileData
ScalarOpts
Support
@ -71,6 +72,7 @@ add_clang_library(clangCodeGen
ItaniumCXXABI.cpp
MicrosoftCXXABI.cpp
ModuleBuilder.cpp
ObjectFilePCHContainerOperations.cpp
SanitizerMetadata.cpp
TargetInfo.cpp

View File

@ -45,12 +45,12 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr),
NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr),
ExceptionSlot(nullptr), EHSelectorSlot(nullptr),
AbnormalTerminationSlot(nullptr), SEHPointersDecl(nullptr),
DebugInfo(CGM.getModuleDebugInfo()), DisableDebugInfo(false),
DidCallStackSave(false), IndirectBranch(nullptr), PGO(cgm),
SwitchInsn(nullptr), SwitchWeights(nullptr), CaseRangeBlock(nullptr),
UnreachableBlock(nullptr), NumReturnExprs(0), NumSimpleReturnExprs(0),
CXXABIThisDecl(nullptr), CXXABIThisValue(nullptr), CXXThisValue(nullptr),
DebugInfo(CGM.getModuleDebugInfo()),
DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr),
PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr),
CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0),
NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr),
CXXABIThisValue(nullptr), CXXThisValue(nullptr),
CXXDefaultInitExprThis(nullptr), CXXStructorImplicitParamDecl(nullptr),
CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr),
CurLexicalScope(nullptr), TerminateLandingPad(nullptr),
@ -284,7 +284,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
Builder.ClearInsertionPoint();
}
// If some of our locals escaped, insert a call to llvm.frameescape in the
// If some of our locals escaped, insert a call to llvm.localescape in the
// entry block.
if (!EscapedLocals.empty()) {
// Invert the map from local to index into a simple vector. There should be
@ -294,7 +294,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
for (auto &Pair : EscapedLocals)
EscapeArgs[Pair.second] = Pair.first;
llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration(
&CGM.getModule(), llvm::Intrinsic::frameescape);
&CGM.getModule(), llvm::Intrinsic::localescape);
CGBuilderTy(AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
}

View File

@ -324,11 +324,13 @@ class CodeGenFunction : public CodeGenTypeCache {
/// write the current selector value into this alloca.
llvm::AllocaInst *EHSelectorSlot;
llvm::AllocaInst *AbnormalTerminationSlot;
/// A stack of exception code slots. Entering an __except block pushes a slot
/// on the stack and leaving pops one. The __exception_code() intrinsic loads
/// a value from the top of the stack.
SmallVector<llvm::Value *, 1> SEHCodeSlotStack;
/// The implicit parameter to SEH filter functions of type
/// 'EXCEPTION_POINTERS*'.
ImplicitParamDecl *SEHPointersDecl;
/// Value returned by __exception_info intrinsic.
llvm::Value *SEHInfo = nullptr;
/// Emits a landing pad for the current EH stack.
llvm::BasicBlock *EmitLandingPad();
@ -886,7 +888,7 @@ class CodeGenFunction : public CodeGenTypeCache {
DeclMapTy LocalDeclMap;
/// Track escaped local variables with auto storage. Used during SEH
/// outlining to produce a call to llvm.frameescape.
/// outlining to produce a call to llvm.localescape.
llvm::DenseMap<llvm::AllocaInst *, int> EscapedLocals;
/// LabelMap - This keeps track of the LLVM basic block for each C label.
@ -1292,8 +1294,8 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitMustTailThunk(const CXXMethodDecl *MD, llvm::Value *AdjustedThisPtr,
llvm::Value *Callee);
/// GenerateThunk - Generate a thunk for the given method.
void GenerateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
/// Generate a thunk for the given method.
void generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk);
llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn,
@ -2048,8 +2050,7 @@ class CodeGenFunction : public CodeGenTypeCache {
void EnterSEHTryStmt(const SEHTryStmt &S);
void ExitSEHTryStmt(const SEHTryStmt &S);
void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StringRef Name,
QualType RetTy, FunctionArgList &Args,
void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter,
const Stmt *OutlinedStmt);
llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
@ -2058,16 +2059,27 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
const SEHFinallyStmt &Finally);
void EmitSEHExceptionCodeSave();
void EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
llvm::Value *ParentFP,
llvm::Value *EntryEBP);
llvm::Value *EmitSEHExceptionCode();
llvm::Value *EmitSEHExceptionInfo();
llvm::Value *EmitSEHAbnormalTermination();
/// Scan the outlined statement for captures from the parent function. For
/// each capture, mark the capture as escaped and emit a call to
/// llvm.framerecover. Insert the framerecover result into the LocalDeclMap.
/// llvm.localrecover. Insert the localrecover result into the LocalDeclMap.
void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt,
llvm::Value *ParentFP);
bool IsFilter);
/// Recovers the address of a local in a parent function. ParentVar is the
/// address of the variable used in the immediate parent function. It can
/// either be an alloca or a call to llvm.localrecover if there are nested
/// outlined functions. ParentFP is the frame pointer of the outermost parent
/// frame.
llvm::Value *recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
llvm::Value *ParentVar,
llvm::Value *ParentFP);
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> Attrs = None);
@ -2931,6 +2943,26 @@ class CodeGenFunction : public CodeGenTypeCache {
SourceLocation Loc);
public:
#ifndef NDEBUG
// Determine whether the given argument is an Objective-C method
// that may have type parameters in its signature.
static bool isObjCMethodWithTypeParams(const ObjCMethodDecl *method) {
const DeclContext *dc = method->getDeclContext();
if (const ObjCInterfaceDecl *classDecl= dyn_cast<ObjCInterfaceDecl>(dc)) {
return classDecl->getTypeParamListAsWritten();
}
if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) {
return catDecl->getTypeParamList();
}
return false;
}
template<typename T>
static bool isObjCMethodWithTypeParams(const T *) { return false; }
#endif
/// EmitCallArgs - Emit call arguments for a function.
template <typename T>
void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo,
@ -2944,18 +2976,25 @@ class CodeGenFunction : public CodeGenTypeCache {
assert((ParamsToSkip == 0 || CallArgTypeInfo) &&
"Can't skip parameters if type info is not provided");
if (CallArgTypeInfo) {
#ifndef NDEBUG
bool isGenericMethod = isObjCMethodWithTypeParams(CallArgTypeInfo);
#endif
// First, use the argument types that the type info knows about
for (auto I = CallArgTypeInfo->param_type_begin() + ParamsToSkip,
E = CallArgTypeInfo->param_type_end();
I != E; ++I, ++Arg) {
assert(Arg != ArgEnd && "Running over edge of argument list!");
assert(
((*I)->isVariablyModifiedType() ||
getContext()
.getCanonicalType((*I).getNonReferenceType())
.getTypePtr() ==
getContext().getCanonicalType(Arg->getType()).getTypePtr()) &&
"type mismatch in call argument!");
assert((isGenericMethod ||
((*I)->isVariablyModifiedType() ||
(*I).getNonReferenceType()->isObjCRetainableType() ||
getContext()
.getCanonicalType((*I).getNonReferenceType())
.getTypePtr() ==
getContext()
.getCanonicalType(Arg->getType())
.getTypePtr())) &&
"type mismatch in call argument!");
ArgTypes.push_back(*I);
}
}

Some files were not shown because too many files have changed in this diff Show More