Vendor import of clang trunk r303571:
https://llvm.org/svn/llvm-project/cfe/trunk@303571
This commit is contained in:
parent
6a6f323115
commit
a398cb507e
@ -935,7 +935,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief Get the additional modules in which the definition \p Def has
|
||||
/// been merged.
|
||||
ArrayRef<Module*> getModulesWithMergedDefinition(NamedDecl *Def) {
|
||||
ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def) {
|
||||
auto MergedIt = MergedDefModules.find(Def);
|
||||
if (MergedIt == MergedDefModules.end())
|
||||
return None;
|
||||
@ -2324,8 +2324,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
uint64_t getTargetNullPointerValue(QualType QT) const;
|
||||
|
||||
bool addressSpaceMapManglingFor(unsigned AS) const {
|
||||
return AddrSpaceMapMangling ||
|
||||
AS >= LangAS::Count;
|
||||
return AddrSpaceMapMangling || AS >= LangAS::FirstTargetAddressSpace;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -127,7 +127,11 @@ class CXXBasePaths {
|
||||
/// class subobjects for that class type. The key of the map is
|
||||
/// the cv-unqualified canonical type of the base class subobject.
|
||||
llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects;
|
||||
|
||||
|
||||
/// VisitedDependentRecords - Records the dependent records that have been
|
||||
/// already visited.
|
||||
llvm::SmallDenseSet<const CXXRecordDecl *, 4> VisitedDependentRecords;
|
||||
|
||||
/// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
|
||||
/// ambiguous paths while it is looking for a path from a derived
|
||||
/// type to a base type.
|
||||
|
@ -34,6 +34,7 @@ class DeclarationName;
|
||||
class DependentDiagnostic;
|
||||
class EnumDecl;
|
||||
class ExportDecl;
|
||||
class ExternalSourceSymbolAttr;
|
||||
class FunctionDecl;
|
||||
class FunctionType;
|
||||
enum Linkage : unsigned char;
|
||||
@ -332,15 +333,15 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
|
||||
bool AccessDeclContextSanity() const;
|
||||
|
||||
protected:
|
||||
|
||||
Decl(Kind DK, DeclContext *DC, SourceLocation L)
|
||||
: NextInContextAndBits(), DeclCtx(DC),
|
||||
Loc(L), DeclKind(DK), InvalidDecl(0),
|
||||
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
|
||||
Access(AS_none), FromASTFile(0), Hidden(DC && cast<Decl>(DC)->Hidden),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
|
||||
CacheValidAndLinkage(0)
|
||||
{
|
||||
: NextInContextAndBits(), DeclCtx(DC), Loc(L), DeclKind(DK),
|
||||
InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false),
|
||||
Referenced(false), Access(AS_none), FromASTFile(0),
|
||||
Hidden(DC && cast<Decl>(DC)->Hidden &&
|
||||
(!cast<Decl>(DC)->isFromASTFile() ||
|
||||
hasLocalOwningModuleStorage())),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
|
||||
CacheValidAndLinkage(0) {
|
||||
if (StatisticsEnabled) add(DK);
|
||||
}
|
||||
|
||||
@ -562,6 +563,10 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
|
||||
NextInContextAndBits.setInt(Bits);
|
||||
}
|
||||
|
||||
/// \brief Looks on this and related declarations for an applicable
|
||||
/// external source symbol attribute.
|
||||
ExternalSourceSymbolAttr *getExternalSourceSymbolAttr() const;
|
||||
|
||||
/// \brief Whether this declaration was marked as being private to the
|
||||
/// module in which it was defined.
|
||||
bool isModulePrivate() const {
|
||||
@ -698,6 +703,9 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
|
||||
Module *getLocalOwningModule() const {
|
||||
if (isFromASTFile() || !Hidden)
|
||||
return nullptr;
|
||||
|
||||
assert(hasLocalOwningModuleStorage() &&
|
||||
"hidden local decl but no local module storage");
|
||||
return reinterpret_cast<Module *const *>(this)[-1];
|
||||
}
|
||||
void setLocalOwningModule(Module *M) {
|
||||
|
@ -333,15 +333,18 @@ class Qualifiers {
|
||||
|
||||
bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
|
||||
unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
|
||||
bool hasTargetSpecificAddressSpace() const {
|
||||
return getAddressSpace() >= LangAS::FirstTargetAddressSpace;
|
||||
}
|
||||
/// Get the address space attribute value to be printed by diagnostics.
|
||||
unsigned getAddressSpaceAttributePrintValue() const {
|
||||
auto Addr = getAddressSpace();
|
||||
// This function is not supposed to be used with language specific
|
||||
// address spaces. If that happens, the diagnostic message should consider
|
||||
// printing the QualType instead of the address space value.
|
||||
assert(Addr == 0 || Addr >= LangAS::Count);
|
||||
assert(Addr == 0 || hasTargetSpecificAddressSpace());
|
||||
if (Addr)
|
||||
return Addr - LangAS::Count;
|
||||
return Addr - LangAS::FirstTargetAddressSpace;
|
||||
// TODO: The diagnostic messages where Addr may be 0 should be fixed
|
||||
// since it cannot differentiate the situation where 0 denotes the default
|
||||
// address space or user specified __attribute__((address_space(0))).
|
||||
@ -2008,10 +2011,11 @@ class Type : public ExtQualsTypeCommonBase {
|
||||
Optional<NullabilityKind> getNullability(const ASTContext &context) const;
|
||||
|
||||
/// Determine whether the given type can have a nullability
|
||||
/// specifier applied to it, i.e., if it is any kind of pointer type
|
||||
/// or a dependent type that could instantiate to any kind of
|
||||
/// pointer type.
|
||||
bool canHaveNullability() const;
|
||||
/// specifier applied to it, i.e., if it is any kind of pointer type.
|
||||
///
|
||||
/// \param ResultIfUnknown The value to return if we don't yet know whether
|
||||
/// this type can have nullability because it is dependent.
|
||||
bool canHaveNullability(bool ResultIfUnknown = true) const;
|
||||
|
||||
/// Retrieve the set of substitutions required when accessing a member
|
||||
/// of the Objective-C receiver type that is declared in the given context.
|
||||
|
@ -45,13 +45,12 @@ enum ID {
|
||||
// This denotes the count of language-specific address spaces and also
|
||||
// the offset added to the target-specific address spaces, which are usually
|
||||
// specified by address space attributes __attribute__(address_space(n))).
|
||||
Count
|
||||
FirstTargetAddressSpace
|
||||
};
|
||||
|
||||
/// The type of a lookup table which maps from language-specific address spaces
|
||||
/// to target-specific ones.
|
||||
typedef unsigned Map[Count];
|
||||
|
||||
typedef unsigned Map[FirstTargetAddressSpace];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1179,6 +1179,12 @@ def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> {
|
||||
let Documentation = [MipsInterruptDocs];
|
||||
}
|
||||
|
||||
def MicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> {
|
||||
let Spellings = [GCC<"micromips">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
let Documentation = [MicroMipsDocs];
|
||||
}
|
||||
|
||||
def Mode : Attr {
|
||||
let Spellings = [GCC<"mode">];
|
||||
let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag,
|
||||
@ -1261,6 +1267,12 @@ def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> {
|
||||
let Spellings = [GCC<"nomicromips">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
let Documentation = [MicroMipsDocs];
|
||||
}
|
||||
|
||||
// This is not a TargetSpecificAttr so that is silently accepted and
|
||||
// ignored on other targets as encouraged by the OpenCL spec.
|
||||
//
|
||||
|
@ -1269,6 +1269,19 @@ The semantics are as follows:
|
||||
}];
|
||||
}
|
||||
|
||||
def MicroMipsDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the GNU style ``__attribute__((micromips))`` and
|
||||
``__attribute__((nomicromips))`` attributes on MIPS targets. These attributes
|
||||
may be attached to a function definition and instructs the backend to generate
|
||||
or not to generate microMIPS code for that function.
|
||||
|
||||
These attributes override the `-mmicromips` and `-mno-micromips` options
|
||||
on the command line.
|
||||
}];
|
||||
}
|
||||
|
||||
def AVRInterruptDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
|
@ -2490,7 +2490,7 @@ def err_attribute_address_multiple_qualifiers : Error<
|
||||
def err_attribute_address_function_type : Error<
|
||||
"function type may not be qualified with an address space">;
|
||||
def err_as_qualified_auto_decl : Error<
|
||||
"automatic variable qualified with an address space">;
|
||||
"automatic variable qualified with an%select{| invalid}0 address space">;
|
||||
def err_arg_with_address_space : Error<
|
||||
"parameter may not be qualified with an address space">;
|
||||
def err_field_with_address_space : Error<
|
||||
|
@ -168,7 +168,7 @@ class LangOptions : public LangOptionsBase {
|
||||
|
||||
/// Do we need to track the owning module for a local declaration?
|
||||
bool trackLocalOwningModule() const {
|
||||
return ModulesLocalVisibility;
|
||||
return isCompilingModule() || ModulesLocalVisibility || ModulesTS;
|
||||
}
|
||||
|
||||
bool isSignedOverflowDefined() const {
|
||||
|
@ -1133,6 +1133,9 @@ struct FormatStyle {
|
||||
/// ``Foo <Protocol>`` instead of ``Foo<Protocol>``.
|
||||
bool ObjCSpaceBeforeProtocolList;
|
||||
|
||||
/// \brief The penalty for breaking around an assignment operator.
|
||||
unsigned PenaltyBreakAssignment;
|
||||
|
||||
/// \brief The penalty for breaking a function call after ``call(``.
|
||||
unsigned PenaltyBreakBeforeFirstCallParameter;
|
||||
|
||||
@ -1420,6 +1423,8 @@ struct FormatStyle {
|
||||
ObjCBlockIndentWidth == R.ObjCBlockIndentWidth &&
|
||||
ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty &&
|
||||
ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&
|
||||
PenaltyBreakAssignment ==
|
||||
R.PenaltyBreakAssignment &&
|
||||
PenaltyBreakBeforeFirstCallParameter ==
|
||||
R.PenaltyBreakBeforeFirstCallParameter &&
|
||||
PenaltyBreakComment == R.PenaltyBreakComment &&
|
||||
|
@ -507,16 +507,6 @@ class ModuleMap {
|
||||
/// false otherwise.
|
||||
bool resolveConflicts(Module *Mod, bool Complain);
|
||||
|
||||
/// \brief Infers the (sub)module based on the given source location and
|
||||
/// source manager.
|
||||
///
|
||||
/// \param Loc The location within the source that we are querying, along
|
||||
/// with its source manager.
|
||||
///
|
||||
/// \returns The module that owns this source location, or null if no
|
||||
/// module owns this source location.
|
||||
Module *inferModuleFromLocation(FullSourceLoc Loc);
|
||||
|
||||
/// \brief Sets the umbrella header of the given module to the given
|
||||
/// header.
|
||||
void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
|
||||
|
@ -1917,14 +1917,11 @@ class Preprocessor {
|
||||
/// into a module, or is outside any module, returns nullptr.
|
||||
Module *getModuleForLocation(SourceLocation Loc);
|
||||
|
||||
/// \brief Find the module that contains the specified location, either
|
||||
/// directly or indirectly.
|
||||
Module *getModuleContainingLocation(SourceLocation Loc);
|
||||
|
||||
/// \brief We want to produce a diagnostic at location IncLoc concerning a
|
||||
/// missing module import.
|
||||
///
|
||||
/// \param IncLoc The location at which the missing import was detected.
|
||||
/// \param M The desired module.
|
||||
/// \param MLoc A location within the desired module at which some desired
|
||||
/// effect occurred (eg, where a desired entity was declared).
|
||||
///
|
||||
@ -1932,6 +1929,7 @@ class Preprocessor {
|
||||
/// Null if no such file could be determined or if a #include is not
|
||||
/// appropriate.
|
||||
const FileEntry *getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
|
||||
Module *M,
|
||||
SourceLocation MLoc);
|
||||
|
||||
private:
|
||||
|
@ -304,8 +304,9 @@ class Parser : public CodeCompletionHandler {
|
||||
}
|
||||
|
||||
/// ConsumeToken - Consume the current 'peek token' and lex the next one.
|
||||
/// This does not work with special tokens: string literals, code completion
|
||||
/// and balanced tokens must be handled using the specific consume methods.
|
||||
/// This does not work with special tokens: string literals, code completion,
|
||||
/// annotation tokens and balanced tokens must be handled using the specific
|
||||
/// consume methods.
|
||||
/// Returns the location of the consumed token.
|
||||
SourceLocation ConsumeToken() {
|
||||
assert(!isTokenSpecial() &&
|
||||
@ -366,7 +367,7 @@ class Parser : public CodeCompletionHandler {
|
||||
/// isTokenSpecial - True if this token requires special consumption methods.
|
||||
bool isTokenSpecial() const {
|
||||
return isTokenStringLiteral() || isTokenParen() || isTokenBracket() ||
|
||||
isTokenBrace() || Tok.is(tok::code_completion);
|
||||
isTokenBrace() || Tok.is(tok::code_completion) || Tok.isAnnotation();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the current token is '=' or is a type of '='.
|
||||
@ -397,9 +398,19 @@ class Parser : public CodeCompletionHandler {
|
||||
if (Tok.is(tok::code_completion))
|
||||
return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken()
|
||||
: handleUnexpectedCodeCompletionToken();
|
||||
if (Tok.isAnnotation())
|
||||
return ConsumeAnnotationToken();
|
||||
return ConsumeToken();
|
||||
}
|
||||
|
||||
SourceLocation ConsumeAnnotationToken() {
|
||||
assert(Tok.isAnnotation() && "wrong consume method");
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
PrevTokLocation = Tok.getAnnotationEndLoc();
|
||||
PP.Lex(Tok);
|
||||
return Loc;
|
||||
}
|
||||
|
||||
/// ConsumeParen - This consume method keeps the paren count up-to-date.
|
||||
///
|
||||
SourceLocation ConsumeParen() {
|
||||
@ -1449,6 +1460,7 @@ class Parser : public CodeCompletionHandler {
|
||||
};
|
||||
|
||||
ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast);
|
||||
ExprResult ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast);
|
||||
ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast);
|
||||
ExprResult ParseConstraintExpression();
|
||||
// Expr that doesn't include commas.
|
||||
|
@ -1999,41 +1999,6 @@ class Declarator {
|
||||
llvm_unreachable("unknown context kind!");
|
||||
}
|
||||
|
||||
/// diagnoseIdentifier - Return true if the identifier is prohibited and
|
||||
/// should be diagnosed (because it cannot be anything else).
|
||||
bool diagnoseIdentifier() const {
|
||||
switch (Context) {
|
||||
case FileContext:
|
||||
case KNRTypeListContext:
|
||||
case MemberContext:
|
||||
case BlockContext:
|
||||
case ForContext:
|
||||
case InitStmtContext:
|
||||
case ConditionContext:
|
||||
case PrototypeContext:
|
||||
case LambdaExprParameterContext:
|
||||
case TemplateParamContext:
|
||||
case CXXCatchContext:
|
||||
case ObjCCatchContext:
|
||||
case TypeNameContext:
|
||||
case FunctionalCastContext:
|
||||
case ConversionIdContext:
|
||||
case ObjCParameterContext:
|
||||
case ObjCResultContext:
|
||||
case BlockLiteralContext:
|
||||
case CXXNewContext:
|
||||
case LambdaExprContext:
|
||||
return false;
|
||||
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case TemplateTypeArgContext:
|
||||
case TrailingReturnContext:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
}
|
||||
|
||||
/// Return true if the context permits a C++17 decomposition declarator.
|
||||
bool mayHaveDecompositionDeclarator() const {
|
||||
switch (Context) {
|
||||
|
@ -1507,6 +1507,12 @@ class Sema {
|
||||
hasVisibleDefaultArgument(const NamedDecl *D,
|
||||
llvm::SmallVectorImpl<Module *> *Modules = nullptr);
|
||||
|
||||
/// Determine if there is a visible declaration of \p D that is an explicit
|
||||
/// specialization declaration for a specialization of a template. (For a
|
||||
/// member specialization, use hasVisibleMemberSpecialization.)
|
||||
bool hasVisibleExplicitSpecialization(
|
||||
const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
|
||||
|
||||
/// Determine if there is a visible declaration of \p D that is a member
|
||||
/// specialization declaration (as opposed to an instantiated declaration).
|
||||
bool hasVisibleMemberSpecialization(
|
||||
@ -2360,7 +2366,7 @@ class Sema {
|
||||
void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);
|
||||
void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
|
||||
bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn);
|
||||
void notePreviousDefinition(SourceLocation Old, SourceLocation New);
|
||||
void notePreviousDefinition(const NamedDecl *Old, SourceLocation New);
|
||||
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
|
||||
|
||||
// AssignmentAction - This is used by all the assignment diagnostic functions
|
||||
@ -7377,9 +7383,9 @@ class Sema {
|
||||
/// but have not yet been performed.
|
||||
std::deque<PendingImplicitInstantiation> PendingInstantiations;
|
||||
|
||||
class SavePendingInstantiationsAndVTableUsesRAII {
|
||||
class GlobalEagerInstantiationScope {
|
||||
public:
|
||||
SavePendingInstantiationsAndVTableUsesRAII(Sema &S, bool Enabled)
|
||||
GlobalEagerInstantiationScope(Sema &S, bool Enabled)
|
||||
: S(S), Enabled(Enabled) {
|
||||
if (!Enabled) return;
|
||||
|
||||
@ -7387,7 +7393,14 @@ class Sema {
|
||||
SavedVTableUses.swap(S.VTableUses);
|
||||
}
|
||||
|
||||
~SavePendingInstantiationsAndVTableUsesRAII() {
|
||||
void perform() {
|
||||
if (Enabled) {
|
||||
S.DefineUsedVTables();
|
||||
S.PerformPendingInstantiations();
|
||||
}
|
||||
}
|
||||
|
||||
~GlobalEagerInstantiationScope() {
|
||||
if (!Enabled) return;
|
||||
|
||||
// Restore the set of pending vtables.
|
||||
@ -7417,14 +7430,16 @@ class Sema {
|
||||
/// types, static variables, enumerators, etc.
|
||||
std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
|
||||
|
||||
class SavePendingLocalImplicitInstantiationsRAII {
|
||||
class LocalEagerInstantiationScope {
|
||||
public:
|
||||
SavePendingLocalImplicitInstantiationsRAII(Sema &S): S(S) {
|
||||
LocalEagerInstantiationScope(Sema &S) : S(S) {
|
||||
SavedPendingLocalImplicitInstantiations.swap(
|
||||
S.PendingLocalImplicitInstantiations);
|
||||
}
|
||||
|
||||
~SavePendingLocalImplicitInstantiationsRAII() {
|
||||
void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); }
|
||||
|
||||
~LocalEagerInstantiationScope() {
|
||||
assert(S.PendingLocalImplicitInstantiations.empty() &&
|
||||
"there shouldn't be any pending local implicit instantiations");
|
||||
SavedPendingLocalImplicitInstantiations.swap(
|
||||
@ -7434,7 +7449,7 @@ class Sema {
|
||||
private:
|
||||
Sema &S;
|
||||
std::deque<PendingImplicitInstantiation>
|
||||
SavedPendingLocalImplicitInstantiations;
|
||||
SavedPendingLocalImplicitInstantiations;
|
||||
};
|
||||
|
||||
/// A helper class for building up ExtParameterInfos.
|
||||
|
@ -478,10 +478,18 @@ class ASTReader
|
||||
/// in the chain.
|
||||
DeclUpdateOffsetsMap DeclUpdateOffsets;
|
||||
|
||||
struct PendingUpdateRecord {
|
||||
Decl *D;
|
||||
serialization::GlobalDeclID ID;
|
||||
// Whether the declaration was just deserialized.
|
||||
bool JustLoaded;
|
||||
PendingUpdateRecord(serialization::GlobalDeclID ID, Decl *D,
|
||||
bool JustLoaded)
|
||||
: D(D), ID(ID), JustLoaded(JustLoaded) {}
|
||||
};
|
||||
/// \brief Declaration updates for already-loaded declarations that we need
|
||||
/// to apply once we finish processing an import.
|
||||
llvm::SmallVector<std::pair<serialization::GlobalDeclID, Decl*>, 16>
|
||||
PendingUpdateRecords;
|
||||
llvm::SmallVector<PendingUpdateRecord, 16> PendingUpdateRecords;
|
||||
|
||||
enum class PendingFakeDefinitionKind { NotFake, Fake, FakeLoaded };
|
||||
|
||||
@ -1279,7 +1287,7 @@ class ASTReader
|
||||
|
||||
RecordLocation DeclCursorForID(serialization::DeclID ID,
|
||||
SourceLocation &Location);
|
||||
void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
|
||||
void loadDeclUpdateRecords(PendingUpdateRecord &Record);
|
||||
void loadPendingDeclChain(Decl *D, uint64_t LocalOffset);
|
||||
void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D,
|
||||
unsigned PreviousGeneration = 0);
|
||||
|
@ -627,10 +627,6 @@ class ASTWriter : public ASTDeserializationListener,
|
||||
/// \brief Add a version tuple to the given record
|
||||
void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record);
|
||||
|
||||
/// \brief Infer the submodule ID that contains an entity at the given
|
||||
/// source location.
|
||||
serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc);
|
||||
|
||||
/// \brief Retrieve or create a submodule ID for this module, or return 0 if
|
||||
/// the submodule is neither local (a submodle of the currently-written module)
|
||||
/// nor from an imported module.
|
||||
|
@ -8730,8 +8730,8 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
|
||||
char *End;
|
||||
unsigned AddrSpace = strtoul(Str, &End, 10);
|
||||
if (End != Str && AddrSpace != 0) {
|
||||
Type = Context.getAddrSpaceQualType(Type, AddrSpace +
|
||||
LangAS::Count);
|
||||
Type = Context.getAddrSpaceQualType(
|
||||
Type, AddrSpace + LangAS::FirstTargetAddressSpace);
|
||||
Str = End;
|
||||
}
|
||||
if (c == '*')
|
||||
@ -9546,13 +9546,8 @@ uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const {
|
||||
}
|
||||
|
||||
unsigned ASTContext::getTargetAddressSpace(unsigned AS) const {
|
||||
// For OpenCL, only function local variables are not explicitly marked with
|
||||
// an address space in the AST, and these need to be the address space of
|
||||
// alloca.
|
||||
if (!AS && LangOpts.OpenCL)
|
||||
return getTargetInfo().getDataLayout().getAllocaAddrSpace();
|
||||
if (AS >= LangAS::Count)
|
||||
return AS - LangAS::Count;
|
||||
if (AS >= LangAS::FirstTargetAddressSpace)
|
||||
return AS - LangAS::FirstTargetAddressSpace;
|
||||
else
|
||||
return (*AddrSpaceMap)[AS];
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ bool CXXBasePaths::isAmbiguous(CanQualType BaseType) {
|
||||
void CXXBasePaths::clear() {
|
||||
Paths.clear();
|
||||
ClassSubobjects.clear();
|
||||
VisitedDependentRecords.clear();
|
||||
ScratchPath.clear();
|
||||
DetectedVirtual = nullptr;
|
||||
}
|
||||
@ -67,6 +68,7 @@ void CXXBasePaths::swap(CXXBasePaths &Other) {
|
||||
std::swap(Origin, Other.Origin);
|
||||
Paths.swap(Other.Paths);
|
||||
ClassSubobjects.swap(Other.ClassSubobjects);
|
||||
VisitedDependentRecords.swap(Other.VisitedDependentRecords);
|
||||
std::swap(FindAmbiguities, Other.FindAmbiguities);
|
||||
std::swap(RecordPaths, Other.RecordPaths);
|
||||
std::swap(DetectVirtual, Other.DetectVirtual);
|
||||
@ -278,8 +280,14 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
|
||||
dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()))
|
||||
BaseRecord = TD->getTemplatedDecl();
|
||||
}
|
||||
if (BaseRecord && !BaseRecord->hasDefinition())
|
||||
BaseRecord = nullptr;
|
||||
if (BaseRecord) {
|
||||
if (!BaseRecord->hasDefinition() ||
|
||||
VisitedDependentRecords.count(BaseRecord)) {
|
||||
BaseRecord = nullptr;
|
||||
} else {
|
||||
VisitedDependentRecords.insert(BaseRecord);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BaseRecord = cast<CXXRecordDecl>(
|
||||
BaseSpec.getType()->castAs<RecordType>()->getDecl());
|
||||
|
@ -407,6 +407,27 @@ bool Decl::isExported() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
ExternalSourceSymbolAttr *Decl::getExternalSourceSymbolAttr() const {
|
||||
const Decl *Definition = nullptr;
|
||||
if (auto ID = dyn_cast<ObjCInterfaceDecl>(this)) {
|
||||
Definition = ID->getDefinition();
|
||||
} else if (auto PD = dyn_cast<ObjCProtocolDecl>(this)) {
|
||||
Definition = PD->getDefinition();
|
||||
} else if (auto TD = dyn_cast<TagDecl>(this)) {
|
||||
Definition = TD->getDefinition();
|
||||
}
|
||||
if (!Definition)
|
||||
Definition = this;
|
||||
|
||||
if (auto *attr = Definition->getAttr<ExternalSourceSymbolAttr>())
|
||||
return attr;
|
||||
if (auto *dcd = dyn_cast<Decl>(getDeclContext())) {
|
||||
return dcd->getAttr<ExternalSourceSymbolAttr>();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Decl::hasDefiningAttr() const {
|
||||
return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>();
|
||||
}
|
||||
|
@ -4579,7 +4579,7 @@ class ExprEvaluatorBase
|
||||
}
|
||||
|
||||
bool handleCallExpr(const CallExpr *E, APValue &Result,
|
||||
const LValue *ResultSlot) {
|
||||
const LValue *ResultSlot) {
|
||||
const Expr *Callee = E->getCallee()->IgnoreParens();
|
||||
QualType CalleeType = Callee->getType();
|
||||
|
||||
@ -4588,6 +4588,23 @@ class ExprEvaluatorBase
|
||||
auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
|
||||
bool HasQualifier = false;
|
||||
|
||||
struct EvaluateIgnoredRAII {
|
||||
public:
|
||||
EvaluateIgnoredRAII(EvalInfo &Info, llvm::ArrayRef<const Expr*> ToEval)
|
||||
: Info(Info), ToEval(ToEval) {}
|
||||
~EvaluateIgnoredRAII() {
|
||||
if (Info.noteFailure()) {
|
||||
for (auto E : ToEval)
|
||||
EvaluateIgnoredValue(Info, E);
|
||||
}
|
||||
}
|
||||
void cancel() { ToEval = {}; }
|
||||
void drop_front() { ToEval = ToEval.drop_front(); }
|
||||
private:
|
||||
EvalInfo &Info;
|
||||
llvm::ArrayRef<const Expr*> ToEval;
|
||||
} EvalArguments(Info, Args);
|
||||
|
||||
// Extract function decl and 'this' pointer from the callee.
|
||||
if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
|
||||
const ValueDecl *Member = nullptr;
|
||||
@ -4637,10 +4654,12 @@ class ExprEvaluatorBase
|
||||
if (Args.empty())
|
||||
return Error(E);
|
||||
|
||||
if (!EvaluateObjectArgument(Info, Args[0], ThisVal))
|
||||
const Expr *FirstArg = Args[0];
|
||||
Args = Args.drop_front();
|
||||
EvalArguments.drop_front();
|
||||
if (!EvaluateObjectArgument(Info, FirstArg, ThisVal))
|
||||
return false;
|
||||
This = &ThisVal;
|
||||
Args = Args.slice(1);
|
||||
} else if (MD && MD->isLambdaStaticInvoker()) {
|
||||
// Map the static invoker for the lambda back to the call operator.
|
||||
// Conveniently, we don't have to slice out the 'this' argument (as is
|
||||
@ -4692,8 +4711,12 @@ class ExprEvaluatorBase
|
||||
const FunctionDecl *Definition = nullptr;
|
||||
Stmt *Body = FD->getBody(Definition);
|
||||
|
||||
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
|
||||
!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
|
||||
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
|
||||
return false;
|
||||
|
||||
EvalArguments.cancel();
|
||||
|
||||
if (!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
|
||||
Result, ResultSlot))
|
||||
return false;
|
||||
|
||||
|
@ -3531,7 +3531,7 @@ Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const
|
||||
} while (true);
|
||||
}
|
||||
|
||||
bool Type::canHaveNullability() const {
|
||||
bool Type::canHaveNullability(bool ResultIfUnknown) const {
|
||||
QualType type = getCanonicalTypeInternal();
|
||||
|
||||
switch (type->getTypeClass()) {
|
||||
@ -3559,7 +3559,8 @@ bool Type::canHaveNullability() const {
|
||||
case Type::SubstTemplateTypeParmPack:
|
||||
case Type::DependentName:
|
||||
case Type::DependentTemplateSpecialization:
|
||||
return true;
|
||||
case Type::Auto:
|
||||
return ResultIfUnknown;
|
||||
|
||||
// Dependent template specializations can instantiate to pointer
|
||||
// types unless they're known to be specializations of a class
|
||||
@ -3571,12 +3572,7 @@ bool Type::canHaveNullability() const {
|
||||
if (isa<ClassTemplateDecl>(templateDecl))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
// auto is considered dependent when it isn't deduced.
|
||||
case Type::Auto:
|
||||
case Type::DeducedTemplateSpecialization:
|
||||
return !cast<DeducedType>(type.getTypePtr())->isDeduced();
|
||||
return ResultIfUnknown;
|
||||
|
||||
case Type::Builtin:
|
||||
switch (cast<BuiltinType>(type.getTypePtr())->getKind()) {
|
||||
@ -3595,7 +3591,7 @@ bool Type::canHaveNullability() const {
|
||||
case BuiltinType::PseudoObject:
|
||||
case BuiltinType::UnknownAny:
|
||||
case BuiltinType::ARCUnbridgedCast:
|
||||
return true;
|
||||
return ResultIfUnknown;
|
||||
|
||||
case BuiltinType::Void:
|
||||
case BuiltinType::ObjCId:
|
||||
@ -3614,6 +3610,7 @@ bool Type::canHaveNullability() const {
|
||||
case BuiltinType::OMPArraySection:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("unknown builtin type");
|
||||
|
||||
// Non-pointer types.
|
||||
case Type::Complex:
|
||||
@ -3629,6 +3626,7 @@ bool Type::canHaveNullability() const {
|
||||
case Type::FunctionProto:
|
||||
case Type::FunctionNoProto:
|
||||
case Type::Record:
|
||||
case Type::DeducedTemplateSpecialization:
|
||||
case Type::Enum:
|
||||
case Type::InjectedClassName:
|
||||
case Type::PackExpansion:
|
||||
|
@ -1668,9 +1668,9 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
|
||||
OS << "__shared";
|
||||
break;
|
||||
default:
|
||||
assert(addrspace >= LangAS::Count);
|
||||
assert(addrspace >= LangAS::FirstTargetAddressSpace);
|
||||
OS << "__attribute__((address_space(";
|
||||
OS << addrspace - LangAS::Count;
|
||||
OS << addrspace - LangAS::FirstTargetAddressSpace;
|
||||
OS << ")))";
|
||||
}
|
||||
}
|
||||
|
@ -2034,25 +2034,45 @@ ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
|
||||
return llvm::makeArrayRef(GCCRegNames);
|
||||
}
|
||||
|
||||
static const LangAS::Map AMDGPUPrivateIsZeroMap = {
|
||||
4, // Default
|
||||
1, // opencl_global
|
||||
3, // opencl_local
|
||||
2, // opencl_constant
|
||||
4, // opencl_generic
|
||||
1, // cuda_device
|
||||
2, // cuda_constant
|
||||
3 // cuda_shared
|
||||
static const LangAS::Map AMDGPUNonOpenCLPrivateIsZeroMap = {
|
||||
4, // Default
|
||||
1, // opencl_global
|
||||
3, // opencl_local
|
||||
2, // opencl_constant
|
||||
4, // opencl_generic
|
||||
1, // cuda_device
|
||||
2, // cuda_constant
|
||||
3 // cuda_shared
|
||||
};
|
||||
static const LangAS::Map AMDGPUGenericIsZeroMap = {
|
||||
0, // Default
|
||||
1, // opencl_global
|
||||
3, // opencl_local
|
||||
2, // opencl_constant
|
||||
0, // opencl_generic
|
||||
1, // cuda_device
|
||||
2, // cuda_constant
|
||||
3 // cuda_shared
|
||||
static const LangAS::Map AMDGPUNonOpenCLGenericIsZeroMap = {
|
||||
0, // Default
|
||||
1, // opencl_global
|
||||
3, // opencl_local
|
||||
2, // opencl_constant
|
||||
0, // opencl_generic
|
||||
1, // cuda_device
|
||||
2, // cuda_constant
|
||||
3 // cuda_shared
|
||||
};
|
||||
static const LangAS::Map AMDGPUOpenCLPrivateIsZeroMap = {
|
||||
0, // Default
|
||||
1, // opencl_global
|
||||
3, // opencl_local
|
||||
2, // opencl_constant
|
||||
4, // opencl_generic
|
||||
1, // cuda_device
|
||||
2, // cuda_constant
|
||||
3 // cuda_shared
|
||||
};
|
||||
static const LangAS::Map AMDGPUOpenCLGenericIsZeroMap = {
|
||||
5, // Default
|
||||
1, // opencl_global
|
||||
3, // opencl_local
|
||||
2, // opencl_constant
|
||||
0, // opencl_generic
|
||||
1, // cuda_device
|
||||
2, // cuda_constant
|
||||
3 // cuda_shared
|
||||
};
|
||||
|
||||
// If you edit the description strings, make sure you update
|
||||
@ -2149,8 +2169,12 @@ class AMDGPUTargetInfo final : public TargetInfo {
|
||||
: DataLayoutStringR600);
|
||||
assert(DataLayout->getAllocaAddrSpace() == AS.Private);
|
||||
|
||||
AddrSpaceMap = IsGenericZero ? &AMDGPUGenericIsZeroMap :
|
||||
&AMDGPUPrivateIsZeroMap;
|
||||
AddrSpaceMap =
|
||||
llvm::StringSwitch<const LangAS::Map *>(Triple.getEnvironmentName())
|
||||
.Case("opencl", &AMDGPUOpenCLPrivateIsZeroMap)
|
||||
.Case("amdgiz", &AMDGPUNonOpenCLGenericIsZeroMap)
|
||||
.Case("amdgizcl", &AMDGPUOpenCLGenericIsZeroMap)
|
||||
.Default(&AMDGPUNonOpenCLPrivateIsZeroMap);
|
||||
UseAddrSpaceMapMangling = true;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ namespace {
|
||||
BFI.StorageOffset += OffsetInChars;
|
||||
LVal = LValue::MakeBitfield(Address(Addr, lvalue.getAlignment()),
|
||||
BFI, lvalue.getType(),
|
||||
lvalue.getAlignmentSource());
|
||||
lvalue.getBaseInfo());
|
||||
LVal.setTBAAInfo(lvalue.getTBAAInfo());
|
||||
AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned);
|
||||
if (AtomicTy.isNull()) {
|
||||
@ -203,7 +203,7 @@ namespace {
|
||||
addr = CGF.Builder.CreateStructGEP(addr, 0, CharUnits());
|
||||
|
||||
return LValue::MakeAddr(addr, getValueType(), CGF.getContext(),
|
||||
LVal.getAlignmentSource(), LVal.getTBAAInfo());
|
||||
LVal.getBaseInfo(), LVal.getTBAAInfo());
|
||||
}
|
||||
|
||||
/// \brief Emits atomic load.
|
||||
@ -1181,15 +1181,15 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
|
||||
if (LVal.isBitField())
|
||||
return CGF.EmitLoadOfBitfieldLValue(
|
||||
LValue::MakeBitfield(addr, LVal.getBitFieldInfo(), LVal.getType(),
|
||||
LVal.getAlignmentSource()), loc);
|
||||
LVal.getBaseInfo()), loc);
|
||||
if (LVal.isVectorElt())
|
||||
return CGF.EmitLoadOfLValue(
|
||||
LValue::MakeVectorElt(addr, LVal.getVectorIdx(), LVal.getType(),
|
||||
LVal.getAlignmentSource()), loc);
|
||||
LVal.getBaseInfo()), loc);
|
||||
assert(LVal.isExtVectorElt());
|
||||
return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt(
|
||||
addr, LVal.getExtVectorElts(), LVal.getType(),
|
||||
LVal.getAlignmentSource()));
|
||||
LVal.getBaseInfo()));
|
||||
}
|
||||
|
||||
RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
|
||||
@ -1506,26 +1506,26 @@ EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal,
|
||||
UpdateLVal =
|
||||
LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(),
|
||||
AtomicLVal.getType(),
|
||||
AtomicLVal.getAlignmentSource());
|
||||
AtomicLVal.getBaseInfo());
|
||||
DesiredLVal =
|
||||
LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
|
||||
AtomicLVal.getType(),
|
||||
AtomicLVal.getAlignmentSource());
|
||||
AtomicLVal.getBaseInfo());
|
||||
} else if (AtomicLVal.isVectorElt()) {
|
||||
UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(),
|
||||
AtomicLVal.getType(),
|
||||
AtomicLVal.getAlignmentSource());
|
||||
AtomicLVal.getBaseInfo());
|
||||
DesiredLVal = LValue::MakeVectorElt(
|
||||
DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(),
|
||||
AtomicLVal.getAlignmentSource());
|
||||
AtomicLVal.getBaseInfo());
|
||||
} else {
|
||||
assert(AtomicLVal.isExtVectorElt());
|
||||
UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(),
|
||||
AtomicLVal.getType(),
|
||||
AtomicLVal.getAlignmentSource());
|
||||
AtomicLVal.getBaseInfo());
|
||||
DesiredLVal = LValue::MakeExtVectorElt(
|
||||
DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
|
||||
AtomicLVal.getAlignmentSource());
|
||||
AtomicLVal.getBaseInfo());
|
||||
}
|
||||
UpdateLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
|
||||
DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
|
||||
@ -1612,17 +1612,17 @@ static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics,
|
||||
DesiredLVal =
|
||||
LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
|
||||
AtomicLVal.getType(),
|
||||
AtomicLVal.getAlignmentSource());
|
||||
AtomicLVal.getBaseInfo());
|
||||
} else if (AtomicLVal.isVectorElt()) {
|
||||
DesiredLVal =
|
||||
LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(),
|
||||
AtomicLVal.getType(),
|
||||
AtomicLVal.getAlignmentSource());
|
||||
AtomicLVal.getBaseInfo());
|
||||
} else {
|
||||
assert(AtomicLVal.isExtVectorElt());
|
||||
DesiredLVal = LValue::MakeExtVectorElt(
|
||||
DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
|
||||
AtomicLVal.getAlignmentSource());
|
||||
AtomicLVal.getBaseInfo());
|
||||
}
|
||||
DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
|
||||
// Store new value in the corresponding memory area
|
||||
|
@ -918,8 +918,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
||||
// FIXME: Pass a specific location for the expr init so that the store is
|
||||
// attributed to a reasonable location - otherwise it may be attributed to
|
||||
// locations of subexpressions in the initialization.
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
EmitExprAsInit(&l2r, &blockFieldPseudoVar,
|
||||
MakeAddrLValue(blockField, type, AlignmentSource::Decl),
|
||||
MakeAddrLValue(blockField, type, BaseInfo),
|
||||
/*captured by init*/ false);
|
||||
}
|
||||
|
||||
|
@ -8842,9 +8842,8 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
|
||||
const CallExpr *E) {
|
||||
auto MakeLdg = [&](unsigned IntrinsicID) {
|
||||
Value *Ptr = EmitScalarExpr(E->getArg(0));
|
||||
AlignmentSource AlignSource;
|
||||
clang::CharUnits Align =
|
||||
getNaturalPointeeTypeAlignment(E->getArg(0)->getType(), &AlignSource);
|
||||
getNaturalPointeeTypeAlignment(E->getArg(0)->getType());
|
||||
return Builder.CreateCall(
|
||||
CGM.getIntrinsic(IntrinsicID, {Ptr->getType()->getPointerElementType(),
|
||||
Ptr->getType()}),
|
||||
|
@ -129,14 +129,14 @@ Address
|
||||
CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base,
|
||||
llvm::Value *memberPtr,
|
||||
const MemberPointerType *memberPtrType,
|
||||
AlignmentSource *alignSource) {
|
||||
LValueBaseInfo *BaseInfo) {
|
||||
// Ask the ABI to compute the actual address.
|
||||
llvm::Value *ptr =
|
||||
CGM.getCXXABI().EmitMemberDataPointerAddress(*this, E, base,
|
||||
memberPtr, memberPtrType);
|
||||
|
||||
QualType memberType = memberPtrType->getPointeeType();
|
||||
CharUnits memberAlign = getNaturalTypeAlignment(memberType, alignSource);
|
||||
CharUnits memberAlign = getNaturalTypeAlignment(memberType, BaseInfo);
|
||||
memberAlign =
|
||||
CGM.getDynamicOffsetAlignment(base.getAlignment(),
|
||||
memberPtrType->getClass()->getAsCXXRecordDecl(),
|
||||
|
@ -2613,7 +2613,7 @@ llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
|
||||
// best to make this behavior a command line or debugger tuning
|
||||
// option.
|
||||
FullSourceLoc Loc(D->getLocation(), CGM.getContext().getSourceManager());
|
||||
if (Module *M = ClangModuleMap->inferModuleFromLocation(Loc)) {
|
||||
if (Module *M = D->getOwningModule()) {
|
||||
// This is a (sub-)module.
|
||||
auto Info = ExternalASTSource::ASTSourceDescriptor(*M);
|
||||
return getOrCreateModuleRef(Info, /*SkeletonCU=*/false);
|
||||
|
@ -11,14 +11,15 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CodeGenFunction.h"
|
||||
#include "CGBlocks.h"
|
||||
#include "CGCXXABI.h"
|
||||
#include "CGCleanup.h"
|
||||
#include "CGDebugInfo.h"
|
||||
#include "CGOpenCLRuntime.h"
|
||||
#include "CGOpenMPRuntime.h"
|
||||
#include "CodeGenFunction.h"
|
||||
#include "CodeGenModule.h"
|
||||
#include "TargetInfo.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
@ -1105,6 +1106,21 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
|
||||
address = Address(vla, alignment);
|
||||
}
|
||||
|
||||
// Alloca always returns a pointer in alloca address space, which may
|
||||
// be different from the type defined by the language. For example,
|
||||
// in C++ the auto variables are in the default address space. Therefore
|
||||
// cast alloca to the expected address space when necessary.
|
||||
auto T = D.getType();
|
||||
assert(T.getAddressSpace() == LangAS::Default);
|
||||
if (getASTAllocaAddressSpace() != LangAS::Default) {
|
||||
auto *Addr = getTargetHooks().performAddrSpaceCast(
|
||||
*this, address.getPointer(), getASTAllocaAddressSpace(),
|
||||
T.getAddressSpace(),
|
||||
address.getElementType()->getPointerTo(
|
||||
getContext().getTargetAddressSpace(T.getAddressSpace())),
|
||||
/*non-null*/ true);
|
||||
address = Address(Addr, address.getAlignment());
|
||||
}
|
||||
setAddrOfLocalVar(&D, address);
|
||||
emission.Addr = address;
|
||||
|
||||
|
@ -374,12 +374,14 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
|
||||
// dynamic initialization or a cleanup and we can just return the address
|
||||
// of the temporary.
|
||||
if (Var->hasInitializer())
|
||||
return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
|
||||
return MakeAddrLValue(Object, M->getType(),
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
|
||||
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
|
||||
}
|
||||
LValue RefTempDst = MakeAddrLValue(Object, M->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl,
|
||||
false));
|
||||
|
||||
switch (getEvaluationKind(E->getType())) {
|
||||
default: llvm_unreachable("expected scalar or aggregate expression");
|
||||
@ -465,7 +467,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
|
||||
|
||||
case SubobjectAdjustment::FieldAdjustment: {
|
||||
LValue LV = MakeAddrLValue(Object, E->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
LV = EmitLValueForField(LV, Adjustment.Field);
|
||||
assert(LV.isSimple() &&
|
||||
"materialized temporary field is not a simple lvalue");
|
||||
@ -482,7 +484,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
|
||||
}
|
||||
}
|
||||
|
||||
return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
|
||||
return MakeAddrLValue(Object, M->getType(),
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
RValue
|
||||
@ -847,7 +850,7 @@ void CodeGenModule::EmitExplicitCastExprType(const ExplicitCastExpr *E,
|
||||
/// EmitPointerWithAlignment - Given an expression of pointer type, try to
|
||||
/// derive a more accurate bound on the alignment of the pointer.
|
||||
Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
|
||||
AlignmentSource *Source) {
|
||||
LValueBaseInfo *BaseInfo) {
|
||||
// We allow this with ObjC object pointers because of fragile ABIs.
|
||||
assert(E->getType()->isPointerType() ||
|
||||
E->getType()->isObjCObjectPointerType());
|
||||
@ -866,16 +869,20 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
|
||||
if (PtrTy->getPointeeType()->isVoidType())
|
||||
break;
|
||||
|
||||
AlignmentSource InnerSource;
|
||||
Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), &InnerSource);
|
||||
if (Source) *Source = InnerSource;
|
||||
LValueBaseInfo InnerInfo;
|
||||
Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), &InnerInfo);
|
||||
if (BaseInfo) *BaseInfo = InnerInfo;
|
||||
|
||||
// If this is an explicit bitcast, and the source l-value is
|
||||
// opaque, honor the alignment of the casted-to type.
|
||||
if (isa<ExplicitCastExpr>(CE) &&
|
||||
InnerSource != AlignmentSource::Decl) {
|
||||
Addr = Address(Addr.getPointer(),
|
||||
getNaturalPointeeTypeAlignment(E->getType(), Source));
|
||||
InnerInfo.getAlignmentSource() != AlignmentSource::Decl) {
|
||||
LValueBaseInfo ExpInfo;
|
||||
CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(),
|
||||
&ExpInfo);
|
||||
if (BaseInfo)
|
||||
BaseInfo->mergeForCast(ExpInfo);
|
||||
Addr = Address(Addr.getPointer(), Align);
|
||||
}
|
||||
|
||||
if (SanOpts.has(SanitizerKind::CFIUnrelatedCast) &&
|
||||
@ -893,12 +900,12 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
|
||||
|
||||
// Array-to-pointer decay.
|
||||
case CK_ArrayToPointerDecay:
|
||||
return EmitArrayToPointerDecay(CE->getSubExpr(), Source);
|
||||
return EmitArrayToPointerDecay(CE->getSubExpr(), BaseInfo);
|
||||
|
||||
// Derived-to-base conversions.
|
||||
case CK_UncheckedDerivedToBase:
|
||||
case CK_DerivedToBase: {
|
||||
Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), Source);
|
||||
Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), BaseInfo);
|
||||
auto Derived = CE->getSubExpr()->getType()->getPointeeCXXRecordDecl();
|
||||
return GetAddressOfBaseClass(Addr, Derived,
|
||||
CE->path_begin(), CE->path_end(),
|
||||
@ -917,7 +924,7 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
|
||||
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
|
||||
if (UO->getOpcode() == UO_AddrOf) {
|
||||
LValue LV = EmitLValue(UO->getSubExpr());
|
||||
if (Source) *Source = LV.getAlignmentSource();
|
||||
if (BaseInfo) *BaseInfo = LV.getBaseInfo();
|
||||
return LV.getAddress();
|
||||
}
|
||||
}
|
||||
@ -925,7 +932,7 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
|
||||
// TODO: conditional operators, comma.
|
||||
|
||||
// Otherwise, use the alignment of the type.
|
||||
CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), Source);
|
||||
CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), BaseInfo);
|
||||
return Address(EmitScalarExpr(E), Align);
|
||||
}
|
||||
|
||||
@ -1094,7 +1101,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
|
||||
llvm::Value *V = LV.getPointer();
|
||||
Scope.ForceCleanup({&V});
|
||||
return LValue::MakeAddr(Address(V, LV.getAlignment()), LV.getType(),
|
||||
getContext(), LV.getAlignmentSource(),
|
||||
getContext(), LV.getBaseInfo(),
|
||||
LV.getTBAAInfo());
|
||||
}
|
||||
// FIXME: Is it possible to create an ExprWithCleanups that produces a
|
||||
@ -1269,7 +1276,7 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
|
||||
llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue,
|
||||
SourceLocation Loc) {
|
||||
return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
|
||||
lvalue.getType(), Loc, lvalue.getAlignmentSource(),
|
||||
lvalue.getType(), Loc, lvalue.getBaseInfo(),
|
||||
lvalue.getTBAAInfo(),
|
||||
lvalue.getTBAABaseType(), lvalue.getTBAAOffset(),
|
||||
lvalue.isNontemporal());
|
||||
@ -1381,7 +1388,7 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
|
||||
llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
|
||||
QualType Ty,
|
||||
SourceLocation Loc,
|
||||
AlignmentSource AlignSource,
|
||||
LValueBaseInfo BaseInfo,
|
||||
llvm::MDNode *TBAAInfo,
|
||||
QualType TBAABaseType,
|
||||
uint64_t TBAAOffset,
|
||||
@ -1413,7 +1420,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
|
||||
|
||||
// Atomic operations have to be done on integral types.
|
||||
LValue AtomicLValue =
|
||||
LValue::MakeAddr(Addr, Ty, getContext(), AlignSource, TBAAInfo);
|
||||
LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo);
|
||||
if (Ty->isAtomicType() || LValueIsSuitableForInlineAtomic(AtomicLValue)) {
|
||||
return EmitAtomicLoad(AtomicLValue, Loc).getScalarVal();
|
||||
}
|
||||
@ -1469,7 +1476,7 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
|
||||
|
||||
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
|
||||
bool Volatile, QualType Ty,
|
||||
AlignmentSource AlignSource,
|
||||
LValueBaseInfo BaseInfo,
|
||||
llvm::MDNode *TBAAInfo,
|
||||
bool isInit, QualType TBAABaseType,
|
||||
uint64_t TBAAOffset,
|
||||
@ -1500,7 +1507,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
|
||||
Value = EmitToMemory(Value, Ty);
|
||||
|
||||
LValue AtomicLValue =
|
||||
LValue::MakeAddr(Addr, Ty, getContext(), AlignSource, TBAAInfo);
|
||||
LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo);
|
||||
if (Ty->isAtomicType() ||
|
||||
(!isInit && LValueIsSuitableForInlineAtomic(AtomicLValue))) {
|
||||
EmitAtomicStore(RValue::get(Value), AtomicLValue, isInit);
|
||||
@ -1526,7 +1533,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
|
||||
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,
|
||||
bool isInit) {
|
||||
EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),
|
||||
lvalue.getType(), lvalue.getAlignmentSource(),
|
||||
lvalue.getType(), lvalue.getBaseInfo(),
|
||||
lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(),
|
||||
lvalue.getTBAAOffset(), lvalue.isNontemporal());
|
||||
}
|
||||
@ -2058,38 +2065,39 @@ static LValue EmitThreadPrivateVarDeclLValue(
|
||||
llvm::Type *RealVarTy, SourceLocation Loc) {
|
||||
Addr = CGF.CGM.getOpenMPRuntime().getAddrOfThreadPrivate(CGF, VD, Addr, Loc);
|
||||
Addr = CGF.Builder.CreateElementBitCast(Addr, RealVarTy);
|
||||
return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
return CGF.MakeAddrLValue(Addr, T, BaseInfo);
|
||||
}
|
||||
|
||||
Address CodeGenFunction::EmitLoadOfReference(Address Addr,
|
||||
const ReferenceType *RefTy,
|
||||
AlignmentSource *Source) {
|
||||
LValueBaseInfo *BaseInfo) {
|
||||
llvm::Value *Ptr = Builder.CreateLoad(Addr);
|
||||
return Address(Ptr, getNaturalTypeAlignment(RefTy->getPointeeType(),
|
||||
Source, /*forPointee*/ true));
|
||||
|
||||
BaseInfo, /*forPointee*/ true));
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitLoadOfReferenceLValue(Address RefAddr,
|
||||
const ReferenceType *RefTy) {
|
||||
AlignmentSource Source;
|
||||
Address Addr = EmitLoadOfReference(RefAddr, RefTy, &Source);
|
||||
return MakeAddrLValue(Addr, RefTy->getPointeeType(), Source);
|
||||
LValueBaseInfo BaseInfo;
|
||||
Address Addr = EmitLoadOfReference(RefAddr, RefTy, &BaseInfo);
|
||||
return MakeAddrLValue(Addr, RefTy->getPointeeType(), BaseInfo);
|
||||
}
|
||||
|
||||
Address CodeGenFunction::EmitLoadOfPointer(Address Ptr,
|
||||
const PointerType *PtrTy,
|
||||
AlignmentSource *Source) {
|
||||
LValueBaseInfo *BaseInfo) {
|
||||
llvm::Value *Addr = Builder.CreateLoad(Ptr);
|
||||
return Address(Addr, getNaturalTypeAlignment(PtrTy->getPointeeType(), Source,
|
||||
return Address(Addr, getNaturalTypeAlignment(PtrTy->getPointeeType(),
|
||||
BaseInfo,
|
||||
/*forPointeeType=*/true));
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr,
|
||||
const PointerType *PtrTy) {
|
||||
AlignmentSource Source;
|
||||
Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &Source);
|
||||
return MakeAddrLValue(Addr, PtrTy->getPointeeType(), Source);
|
||||
LValueBaseInfo BaseInfo;
|
||||
Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &BaseInfo);
|
||||
return MakeAddrLValue(Addr, PtrTy->getPointeeType(), BaseInfo);
|
||||
}
|
||||
|
||||
static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
|
||||
@ -2115,7 +2123,8 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
|
||||
if (auto RefTy = VD->getType()->getAs<ReferenceType>()) {
|
||||
LV = CGF.EmitLoadOfReferenceLValue(Addr, RefTy);
|
||||
} else {
|
||||
LV = CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
LV = CGF.MakeAddrLValue(Addr, T, BaseInfo);
|
||||
}
|
||||
setObjCGCLValueClass(CGF.getContext(), E, LV);
|
||||
return LV;
|
||||
@ -2149,7 +2158,8 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
|
||||
const Expr *E, const FunctionDecl *FD) {
|
||||
llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, FD);
|
||||
CharUnits Alignment = CGF.getContext().getDeclAlign(FD);
|
||||
return CGF.MakeAddrLValue(V, E->getType(), Alignment, AlignmentSource::Decl);
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
return CGF.MakeAddrLValue(V, E->getType(), Alignment, BaseInfo);
|
||||
}
|
||||
|
||||
static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD,
|
||||
@ -2214,8 +2224,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
// Should we be using the alignment of the constant pointer we emitted?
|
||||
CharUnits Alignment = getNaturalTypeAlignment(E->getType(), nullptr,
|
||||
/*pointee*/ true);
|
||||
|
||||
return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl);
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
return MakeAddrLValue(Address(Val, Alignment), T, BaseInfo);
|
||||
}
|
||||
|
||||
// Check for captured variables.
|
||||
@ -2232,14 +2242,16 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
LValue CapLVal =
|
||||
EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD),
|
||||
CapturedStmtInfo->getContextValue());
|
||||
bool MayAlias = CapLVal.getBaseInfo().getMayAlias();
|
||||
return MakeAddrLValue(
|
||||
Address(CapLVal.getPointer(), getContext().getDeclAlign(VD)),
|
||||
CapLVal.getType(), AlignmentSource::Decl);
|
||||
CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl, MayAlias));
|
||||
}
|
||||
|
||||
assert(isa<BlockDecl>(CurCodeDecl));
|
||||
Address addr = GetAddrOfBlockDecl(VD, VD->hasAttr<BlocksAttr>());
|
||||
return MakeAddrLValue(addr, T, AlignmentSource::Decl);
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
return MakeAddrLValue(addr, T, BaseInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2253,7 +2265,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
if (ND->hasAttr<WeakRefAttr>()) {
|
||||
const auto *VD = cast<ValueDecl>(ND);
|
||||
ConstantAddress Aliasee = CGM.GetWeakRefReference(VD);
|
||||
return MakeAddrLValue(Aliasee, T, AlignmentSource::Decl);
|
||||
return MakeAddrLValue(Aliasee, T,
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
if (const auto *VD = dyn_cast<VarDecl>(ND)) {
|
||||
@ -2299,7 +2312,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
if (auto RefTy = VD->getType()->getAs<ReferenceType>()) {
|
||||
LV = EmitLoadOfReferenceLValue(addr, RefTy);
|
||||
} else {
|
||||
LV = MakeAddrLValue(addr, T, AlignmentSource::Decl);
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
LV = MakeAddrLValue(addr, T, BaseInfo);
|
||||
}
|
||||
|
||||
bool isLocalStorage = VD->hasLocalStorage();
|
||||
@ -2344,9 +2358,9 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
|
||||
QualType T = E->getSubExpr()->getType()->getPointeeType();
|
||||
assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
|
||||
|
||||
AlignmentSource AlignSource;
|
||||
Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &AlignSource);
|
||||
LValue LV = MakeAddrLValue(Addr, T, AlignSource);
|
||||
LValueBaseInfo BaseInfo;
|
||||
Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &BaseInfo);
|
||||
LValue LV = MakeAddrLValue(Addr, T, BaseInfo);
|
||||
LV.getQuals().setAddressSpace(ExprTy.getAddressSpace());
|
||||
|
||||
// We should not generate __weak write barrier on indirect reference
|
||||
@ -2378,7 +2392,7 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
|
||||
(E->getOpcode() == UO_Real
|
||||
? emitAddrOfRealComponent(LV.getAddress(), LV.getType())
|
||||
: emitAddrOfImagComponent(LV.getAddress(), LV.getType()));
|
||||
LValue ElemLV = MakeAddrLValue(Component, T, LV.getAlignmentSource());
|
||||
LValue ElemLV = MakeAddrLValue(Component, T, LV.getBaseInfo());
|
||||
ElemLV.getQuals().addQualifiers(LV.getQuals());
|
||||
return ElemLV;
|
||||
}
|
||||
@ -2398,12 +2412,14 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
|
||||
|
||||
LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
|
||||
return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E),
|
||||
E->getType(), AlignmentSource::Decl);
|
||||
E->getType(),
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
|
||||
return MakeAddrLValue(CGM.GetAddrOfConstantStringFromObjCEncode(E),
|
||||
E->getType(), AlignmentSource::Decl);
|
||||
E->getType(),
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
|
||||
@ -2415,6 +2431,7 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
|
||||
StringRef NameItems[] = {
|
||||
PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName};
|
||||
std::string GVName = llvm::join(NameItems, NameItems + 2, ".");
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
if (auto *BD = dyn_cast<BlockDecl>(CurCodeDecl)) {
|
||||
std::string Name = SL->getString();
|
||||
if (!Name.empty()) {
|
||||
@ -2423,14 +2440,14 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
|
||||
if (Discriminator)
|
||||
Name += "_" + Twine(Discriminator + 1).str();
|
||||
auto C = CGM.GetAddrOfConstantCString(Name, GVName.c_str());
|
||||
return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
|
||||
return MakeAddrLValue(C, E->getType(), BaseInfo);
|
||||
} else {
|
||||
auto C = CGM.GetAddrOfConstantCString(FnName, GVName.c_str());
|
||||
return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
|
||||
return MakeAddrLValue(C, E->getType(), BaseInfo);
|
||||
}
|
||||
}
|
||||
auto C = CGM.GetAddrOfConstantStringFromLiteral(SL, GVName);
|
||||
return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
|
||||
return MakeAddrLValue(C, E->getType(), BaseInfo);
|
||||
}
|
||||
|
||||
/// Emit a type description suitable for use by a runtime sanitizer library. The
|
||||
@ -2937,14 +2954,14 @@ llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
|
||||
}
|
||||
|
||||
Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E,
|
||||
AlignmentSource *AlignSource) {
|
||||
LValueBaseInfo *BaseInfo) {
|
||||
assert(E->getType()->isArrayType() &&
|
||||
"Array to pointer decay must have array source type!");
|
||||
|
||||
// Expressions of array type can't be bitfields or vector elements.
|
||||
LValue LV = EmitLValue(E);
|
||||
Address Addr = LV.getAddress();
|
||||
if (AlignSource) *AlignSource = LV.getAlignmentSource();
|
||||
if (BaseInfo) *BaseInfo = LV.getBaseInfo();
|
||||
|
||||
// If the array type was an incomplete type, we need to make sure
|
||||
// the decay ends up being the right type.
|
||||
@ -3079,7 +3096,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
|
||||
assert(LHS.isSimple() && "Can only subscript lvalue vectors here!");
|
||||
return LValue::MakeVectorElt(LHS.getAddress(), Idx,
|
||||
E->getBase()->getType(),
|
||||
LHS.getAlignmentSource());
|
||||
LHS.getBaseInfo());
|
||||
}
|
||||
|
||||
// All the other cases basically behave like simple offsetting.
|
||||
@ -3092,17 +3109,17 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
|
||||
|
||||
QualType EltType = LV.getType()->castAs<VectorType>()->getElementType();
|
||||
Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true);
|
||||
return MakeAddrLValue(Addr, EltType, LV.getAlignmentSource());
|
||||
return MakeAddrLValue(Addr, EltType, LV.getBaseInfo());
|
||||
}
|
||||
|
||||
AlignmentSource AlignSource;
|
||||
LValueBaseInfo BaseInfo;
|
||||
Address Addr = Address::invalid();
|
||||
if (const VariableArrayType *vla =
|
||||
getContext().getAsVariableArrayType(E->getType())) {
|
||||
// The base must be a pointer, which is not an aggregate. Emit
|
||||
// it. It needs to be emitted first in case it's what captures
|
||||
// the VLA bounds.
|
||||
Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
|
||||
Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo);
|
||||
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
|
||||
|
||||
// The element count here is the total number of non-VLA elements.
|
||||
@ -3125,7 +3142,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
|
||||
// Indexing over an interface, as in "NSString *P; P[4];"
|
||||
|
||||
// Emit the base pointer.
|
||||
Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
|
||||
Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo);
|
||||
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
|
||||
|
||||
CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT);
|
||||
@ -3171,16 +3188,16 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
|
||||
{CGM.getSize(CharUnits::Zero()), Idx},
|
||||
E->getType(),
|
||||
!getLangOpts().isSignedOverflowDefined());
|
||||
AlignSource = ArrayLV.getAlignmentSource();
|
||||
BaseInfo = ArrayLV.getBaseInfo();
|
||||
} else {
|
||||
// The base must be a pointer; emit it with an estimate of its alignment.
|
||||
Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
|
||||
Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo);
|
||||
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
|
||||
Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(),
|
||||
!getLangOpts().isSignedOverflowDefined());
|
||||
}
|
||||
|
||||
LValue LV = MakeAddrLValue(Addr, E->getType(), AlignSource);
|
||||
LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo);
|
||||
|
||||
// TODO: Preserve/extend path TBAA metadata?
|
||||
|
||||
@ -3193,7 +3210,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
|
||||
}
|
||||
|
||||
static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base,
|
||||
AlignmentSource &AlignSource,
|
||||
LValueBaseInfo &BaseInfo,
|
||||
QualType BaseTy, QualType ElTy,
|
||||
bool IsLowerBound) {
|
||||
LValue BaseLVal;
|
||||
@ -3201,7 +3218,7 @@ static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base,
|
||||
BaseLVal = CGF.EmitOMPArraySectionExpr(ASE, IsLowerBound);
|
||||
if (BaseTy->isArrayType()) {
|
||||
Address Addr = BaseLVal.getAddress();
|
||||
AlignSource = BaseLVal.getAlignmentSource();
|
||||
BaseInfo = BaseLVal.getBaseInfo();
|
||||
|
||||
// If the array type was an incomplete type, we need to make sure
|
||||
// the decay ends up being the right type.
|
||||
@ -3220,10 +3237,12 @@ static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base,
|
||||
return CGF.Builder.CreateElementBitCast(Addr,
|
||||
CGF.ConvertTypeForMem(ElTy));
|
||||
}
|
||||
CharUnits Align = CGF.getNaturalTypeAlignment(ElTy, &AlignSource);
|
||||
LValueBaseInfo TypeInfo;
|
||||
CharUnits Align = CGF.getNaturalTypeAlignment(ElTy, &TypeInfo);
|
||||
BaseInfo.mergeForCast(TypeInfo);
|
||||
return Address(CGF.Builder.CreateLoad(BaseLVal.getAddress()), Align);
|
||||
}
|
||||
return CGF.EmitPointerWithAlignment(Base, &AlignSource);
|
||||
return CGF.EmitPointerWithAlignment(Base, &BaseInfo);
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
|
||||
@ -3327,13 +3346,13 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
|
||||
assert(Idx);
|
||||
|
||||
Address EltPtr = Address::invalid();
|
||||
AlignmentSource AlignSource;
|
||||
LValueBaseInfo BaseInfo;
|
||||
if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) {
|
||||
// The base must be a pointer, which is not an aggregate. Emit
|
||||
// it. It needs to be emitted first in case it's what captures
|
||||
// the VLA bounds.
|
||||
Address Base =
|
||||
emitOMPArraySectionBase(*this, E->getBase(), AlignSource, BaseTy,
|
||||
emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, BaseTy,
|
||||
VLA->getElementType(), IsLowerBound);
|
||||
// The element count here is the total number of non-VLA elements.
|
||||
llvm::Value *NumElements = getVLASize(VLA).first;
|
||||
@ -3367,15 +3386,15 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
|
||||
EltPtr = emitArraySubscriptGEP(
|
||||
*this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx},
|
||||
ResultExprTy, !getLangOpts().isSignedOverflowDefined());
|
||||
AlignSource = ArrayLV.getAlignmentSource();
|
||||
BaseInfo = ArrayLV.getBaseInfo();
|
||||
} else {
|
||||
Address Base = emitOMPArraySectionBase(*this, E->getBase(), AlignSource,
|
||||
Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo,
|
||||
BaseTy, ResultExprTy, IsLowerBound);
|
||||
EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy,
|
||||
!getLangOpts().isSignedOverflowDefined());
|
||||
}
|
||||
|
||||
return MakeAddrLValue(EltPtr, ResultExprTy, AlignSource);
|
||||
return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo);
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::
|
||||
@ -3387,10 +3406,10 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
|
||||
if (E->isArrow()) {
|
||||
// If it is a pointer to a vector, emit the address and form an lvalue with
|
||||
// it.
|
||||
AlignmentSource AlignSource;
|
||||
Address Ptr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
|
||||
LValueBaseInfo BaseInfo;
|
||||
Address Ptr = EmitPointerWithAlignment(E->getBase(), &BaseInfo);
|
||||
const PointerType *PT = E->getBase()->getType()->getAs<PointerType>();
|
||||
Base = MakeAddrLValue(Ptr, PT->getPointeeType(), AlignSource);
|
||||
Base = MakeAddrLValue(Ptr, PT->getPointeeType(), BaseInfo);
|
||||
Base.getQuals().removeObjCGCAttr();
|
||||
} else if (E->getBase()->isGLValue()) {
|
||||
// Otherwise, if the base is an lvalue ( as in the case of foo.x.x),
|
||||
@ -3407,7 +3426,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
|
||||
Address VecMem = CreateMemTemp(E->getBase()->getType());
|
||||
Builder.CreateStore(Vec, VecMem);
|
||||
Base = MakeAddrLValue(VecMem, E->getBase()->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
QualType type =
|
||||
@ -3421,7 +3440,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
|
||||
llvm::Constant *CV =
|
||||
llvm::ConstantDataVector::get(getLLVMContext(), Indices);
|
||||
return LValue::MakeExtVectorElt(Base.getAddress(), CV, type,
|
||||
Base.getAlignmentSource());
|
||||
Base.getBaseInfo());
|
||||
}
|
||||
assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!");
|
||||
|
||||
@ -3432,17 +3451,16 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
|
||||
CElts.push_back(BaseElts->getAggregateElement(Indices[i]));
|
||||
llvm::Constant *CV = llvm::ConstantVector::get(CElts);
|
||||
return LValue::MakeExtVectorElt(Base.getExtVectorAddress(), CV, type,
|
||||
Base.getAlignmentSource());
|
||||
Base.getBaseInfo());
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
|
||||
Expr *BaseExpr = E->getBase();
|
||||
|
||||
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
|
||||
LValue BaseLV;
|
||||
if (E->isArrow()) {
|
||||
AlignmentSource AlignSource;
|
||||
Address Addr = EmitPointerWithAlignment(BaseExpr, &AlignSource);
|
||||
LValueBaseInfo BaseInfo;
|
||||
Address Addr = EmitPointerWithAlignment(BaseExpr, &BaseInfo);
|
||||
QualType PtrTy = BaseExpr->getType()->getPointeeType();
|
||||
SanitizerSet SkippedChecks;
|
||||
bool IsBaseCXXThis = IsWrappedCXXThis(BaseExpr);
|
||||
@ -3452,7 +3470,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
|
||||
SkippedChecks.set(SanitizerKind::Null, true);
|
||||
EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy,
|
||||
/*Alignment=*/CharUnits::Zero(), SkippedChecks);
|
||||
BaseLV = MakeAddrLValue(Addr, PtrTy, AlignSource);
|
||||
BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo);
|
||||
} else
|
||||
BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess);
|
||||
|
||||
@ -3512,8 +3530,10 @@ static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
|
||||
|
||||
LValue CodeGenFunction::EmitLValueForField(LValue base,
|
||||
const FieldDecl *field) {
|
||||
LValueBaseInfo BaseInfo = base.getBaseInfo();
|
||||
AlignmentSource fieldAlignSource =
|
||||
getFieldAlignmentSource(base.getAlignmentSource());
|
||||
getFieldAlignmentSource(BaseInfo.getAlignmentSource());
|
||||
LValueBaseInfo FieldBaseInfo(fieldAlignSource, BaseInfo.getMayAlias());
|
||||
|
||||
if (field->isBitField()) {
|
||||
const CGRecordLayout &RL =
|
||||
@ -3533,7 +3553,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
|
||||
|
||||
QualType fieldType =
|
||||
field->getType().withCVRQualifiers(base.getVRQualifiers());
|
||||
return LValue::MakeBitfield(Addr, Info, fieldType, fieldAlignSource);
|
||||
return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo);
|
||||
}
|
||||
|
||||
const RecordDecl *rec = field->getParent();
|
||||
@ -3574,7 +3594,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
|
||||
type = refType->getPointeeType();
|
||||
|
||||
CharUnits alignment =
|
||||
getNaturalTypeAlignment(type, &fieldAlignSource, /*pointee*/ true);
|
||||
getNaturalTypeAlignment(type, &FieldBaseInfo, /*pointee*/ true);
|
||||
FieldBaseInfo.setMayAlias(false);
|
||||
addr = Address(load, alignment);
|
||||
|
||||
// Qualifiers on the struct don't apply to the referencee, and
|
||||
@ -3595,7 +3616,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
|
||||
if (field->hasAttr<AnnotateAttr>())
|
||||
addr = EmitFieldAnnotations(field, addr);
|
||||
|
||||
LValue LV = MakeAddrLValue(addr, type, fieldAlignSource);
|
||||
LValue LV = MakeAddrLValue(addr, type, FieldBaseInfo);
|
||||
LV.getQuals().addCVRQualifiers(cvr);
|
||||
if (TBAAPath) {
|
||||
const ASTRecordLayout &Layout =
|
||||
@ -3636,14 +3657,18 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
|
||||
V = Builder.CreateElementBitCast(V, llvmType, Field->getName());
|
||||
|
||||
// TODO: access-path TBAA?
|
||||
auto FieldAlignSource = getFieldAlignmentSource(Base.getAlignmentSource());
|
||||
return MakeAddrLValue(V, FieldType, FieldAlignSource);
|
||||
LValueBaseInfo BaseInfo = Base.getBaseInfo();
|
||||
LValueBaseInfo FieldBaseInfo(
|
||||
getFieldAlignmentSource(BaseInfo.getAlignmentSource()),
|
||||
BaseInfo.getMayAlias());
|
||||
return MakeAddrLValue(V, FieldType, FieldBaseInfo);
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
if (E->isFileScope()) {
|
||||
ConstantAddress GlobalPtr = CGM.GetAddrOfConstantCompoundLiteral(E);
|
||||
return MakeAddrLValue(GlobalPtr, E->getType(), AlignmentSource::Decl);
|
||||
return MakeAddrLValue(GlobalPtr, E->getType(), BaseInfo);
|
||||
}
|
||||
if (E->getType()->isVariablyModifiedType())
|
||||
// make sure to emit the VLA size.
|
||||
@ -3651,7 +3676,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
|
||||
|
||||
Address DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral");
|
||||
const Expr *InitExpr = E->getInitializer();
|
||||
LValue Result = MakeAddrLValue(DeclPtr, E->getType(), AlignmentSource::Decl);
|
||||
LValue Result = MakeAddrLValue(DeclPtr, E->getType(), BaseInfo);
|
||||
|
||||
EmitAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(),
|
||||
/*Init*/ true);
|
||||
@ -3748,8 +3773,12 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
|
||||
phi->addIncoming(rhs->getPointer(), rhsBlock);
|
||||
Address result(phi, std::min(lhs->getAlignment(), rhs->getAlignment()));
|
||||
AlignmentSource alignSource =
|
||||
std::max(lhs->getAlignmentSource(), rhs->getAlignmentSource());
|
||||
return MakeAddrLValue(result, expr->getType(), alignSource);
|
||||
std::max(lhs->getBaseInfo().getAlignmentSource(),
|
||||
rhs->getBaseInfo().getAlignmentSource());
|
||||
bool MayAlias = lhs->getBaseInfo().getMayAlias() ||
|
||||
rhs->getBaseInfo().getMayAlias();
|
||||
return MakeAddrLValue(result, expr->getType(),
|
||||
LValueBaseInfo(alignSource, MayAlias));
|
||||
} else {
|
||||
assert((lhs || rhs) &&
|
||||
"both operands of glvalue conditional are throw-expressions?");
|
||||
@ -3847,7 +3876,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
||||
This, DerivedClassDecl, E->path_begin(), E->path_end(),
|
||||
/*NullCheckValue=*/false, E->getExprLoc());
|
||||
|
||||
return MakeAddrLValue(Base, E->getType(), LV.getAlignmentSource());
|
||||
return MakeAddrLValue(Base, E->getType(), LV.getBaseInfo());
|
||||
}
|
||||
case CK_ToUnion:
|
||||
return EmitAggExprToLValue(E);
|
||||
@ -3874,7 +3903,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
||||
/*MayBeNull=*/false,
|
||||
CFITCK_DerivedCast, E->getLocStart());
|
||||
|
||||
return MakeAddrLValue(Derived, E->getType(), LV.getAlignmentSource());
|
||||
return MakeAddrLValue(Derived, E->getType(), LV.getBaseInfo());
|
||||
}
|
||||
case CK_LValueBitCast: {
|
||||
// This must be a reinterpret_cast (or c-style equivalent).
|
||||
@ -3890,13 +3919,13 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
||||
/*MayBeNull=*/false,
|
||||
CFITCK_UnrelatedCast, E->getLocStart());
|
||||
|
||||
return MakeAddrLValue(V, E->getType(), LV.getAlignmentSource());
|
||||
return MakeAddrLValue(V, E->getType(), LV.getBaseInfo());
|
||||
}
|
||||
case CK_ObjCObjectLValueCast: {
|
||||
LValue LV = EmitLValue(E->getSubExpr());
|
||||
Address V = Builder.CreateElementBitCast(LV.getAddress(),
|
||||
ConvertType(E->getType()));
|
||||
return MakeAddrLValue(V, E->getType(), LV.getAlignmentSource());
|
||||
return MakeAddrLValue(V, E->getType(), LV.getBaseInfo());
|
||||
}
|
||||
case CK_ZeroToOCLQueue:
|
||||
llvm_unreachable("NULL to OpenCL queue lvalue cast is not valid");
|
||||
@ -4085,7 +4114,7 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
|
||||
|
||||
if (!RV.isScalar())
|
||||
return MakeAddrLValue(RV.getAggregateAddress(), E->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
|
||||
assert(E->getCallReturnType(getContext())->isReferenceType() &&
|
||||
"Can't have a scalar return unless the return type is a "
|
||||
@ -4105,7 +4134,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
|
||||
AggValueSlot Slot = CreateAggTemp(E->getType());
|
||||
EmitCXXConstructExpr(E, Slot);
|
||||
return MakeAddrLValue(Slot.getAddress(), E->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
LValue
|
||||
@ -4120,7 +4149,7 @@ Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) {
|
||||
|
||||
LValue CodeGenFunction::EmitCXXUuidofLValue(const CXXUuidofExpr *E) {
|
||||
return MakeAddrLValue(EmitCXXUuidofExpr(E), E->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
LValue
|
||||
@ -4130,7 +4159,7 @@ CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
|
||||
EmitAggExpr(E->getSubExpr(), Slot);
|
||||
EmitCXXTemporary(E->getTemporary(), E->getType(), Slot.getAddress());
|
||||
return MakeAddrLValue(Slot.getAddress(), E->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
LValue
|
||||
@ -4138,7 +4167,7 @@ CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) {
|
||||
AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue");
|
||||
EmitLambdaExpr(E, Slot);
|
||||
return MakeAddrLValue(Slot.getAddress(), E->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
|
||||
@ -4146,7 +4175,7 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
|
||||
|
||||
if (!RV.isScalar())
|
||||
return MakeAddrLValue(RV.getAggregateAddress(), E->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
|
||||
assert(E->getMethodDecl()->getReturnType()->isReferenceType() &&
|
||||
"Can't have a scalar return unless the return type is a "
|
||||
@ -4158,7 +4187,8 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
|
||||
LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) {
|
||||
Address V =
|
||||
CGM.getObjCRuntime().GetAddrOfSelector(*this, E->getSelector());
|
||||
return MakeAddrLValue(V, E->getType(), AlignmentSource::Decl);
|
||||
return MakeAddrLValue(V, E->getType(),
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface,
|
||||
@ -4202,7 +4232,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
|
||||
// Can only get l-value for message expression returning aggregate type
|
||||
RValue RV = EmitAnyExprToTemp(E);
|
||||
return MakeAddrLValue(RV.getAggregateAddress(), E->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee,
|
||||
@ -4394,12 +4424,11 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
|
||||
const MemberPointerType *MPT
|
||||
= E->getRHS()->getType()->getAs<MemberPointerType>();
|
||||
|
||||
AlignmentSource AlignSource;
|
||||
LValueBaseInfo BaseInfo;
|
||||
Address MemberAddr =
|
||||
EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT,
|
||||
&AlignSource);
|
||||
EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT, &BaseInfo);
|
||||
|
||||
return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), AlignSource);
|
||||
return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), BaseInfo);
|
||||
}
|
||||
|
||||
/// Given the address of a temporary variable, produce an r-value of
|
||||
@ -4407,7 +4436,8 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
|
||||
RValue CodeGenFunction::convertTempToRValue(Address addr,
|
||||
QualType type,
|
||||
SourceLocation loc) {
|
||||
LValue lvalue = MakeAddrLValue(addr, type, AlignmentSource::Decl);
|
||||
LValue lvalue = MakeAddrLValue(addr, type,
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
switch (getEvaluationKind(type)) {
|
||||
case TEK_Complex:
|
||||
return RValue::getComplex(EmitLoadOfComplex(lvalue, loc));
|
||||
@ -4462,9 +4492,9 @@ static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,
|
||||
if (ov == resultExpr && ov->isRValue() && !forLValue &&
|
||||
CodeGenFunction::hasAggregateEvaluationKind(ov->getType())) {
|
||||
CGF.EmitAggExpr(ov->getSourceExpr(), slot);
|
||||
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
LValue LV = CGF.MakeAddrLValue(slot.getAddress(), ov->getType(),
|
||||
AlignmentSource::Decl);
|
||||
BaseInfo);
|
||||
opaqueData = OVMA::bind(CGF, ov, LV);
|
||||
result.RV = slot.asRValue();
|
||||
|
||||
|
@ -1531,13 +1531,13 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
||||
assert(E->getNumPlacementArgs() == 1);
|
||||
const Expr *arg = *E->placement_arguments().begin();
|
||||
|
||||
AlignmentSource alignSource;
|
||||
allocation = EmitPointerWithAlignment(arg, &alignSource);
|
||||
LValueBaseInfo BaseInfo;
|
||||
allocation = EmitPointerWithAlignment(arg, &BaseInfo);
|
||||
|
||||
// The pointer expression will, in many cases, be an opaque void*.
|
||||
// In these cases, discard the computed alignment and use the
|
||||
// formal alignment of the allocated type.
|
||||
if (alignSource != AlignmentSource::Decl)
|
||||
if (BaseInfo.getAlignmentSource() != AlignmentSource::Decl)
|
||||
allocation = Address(allocation.getPointer(), allocAlign);
|
||||
|
||||
// Set up allocatorArgs for the call to operator delete if it's not
|
||||
@ -1658,8 +1658,9 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
||||
|
||||
// Passing pointer through invariant.group.barrier to avoid propagation of
|
||||
// vptrs information which may be included in previous type.
|
||||
// To not break LTO with different optimizations levels, we do it regardless
|
||||
// of optimization level.
|
||||
if (CGM.getCodeGenOpts().StrictVTablePointers &&
|
||||
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
|
||||
allocator->isReservedGlobalPlacementOperator())
|
||||
result = Address(Builder.CreateInvariantGroupBarrier(result.getPointer()),
|
||||
result.getAlignment());
|
||||
|
@ -1579,10 +1579,9 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
|
||||
}
|
||||
// Since target may map different address spaces in AST to the same address
|
||||
// space, an address space conversion may end up as a bitcast.
|
||||
auto *Src = Visit(E);
|
||||
return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGF, Src,
|
||||
E->getType(),
|
||||
DestTy);
|
||||
return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast(
|
||||
CGF, Visit(E), E->getType()->getPointeeType().getAddressSpace(),
|
||||
DestTy->getPointeeType().getAddressSpace(), ConvertType(DestTy));
|
||||
}
|
||||
case CK_AtomicToNonAtomic:
|
||||
case CK_NonAtomicToAtomic:
|
||||
|
@ -162,7 +162,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
|
||||
const Expr *Rhs = ALE->getElement(i);
|
||||
LValue LV = MakeAddrLValue(
|
||||
Builder.CreateConstArrayGEP(Objects, i, getPointerSize()),
|
||||
ElementType, AlignmentSource::Decl);
|
||||
ElementType, LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
|
||||
llvm::Value *value = EmitScalarExpr(Rhs);
|
||||
EmitStoreThroughLValue(RValue::get(value), LV, true);
|
||||
@ -174,7 +174,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
|
||||
const Expr *Key = DLE->getKeyValueElement(i).Key;
|
||||
LValue KeyLV = MakeAddrLValue(
|
||||
Builder.CreateConstArrayGEP(Keys, i, getPointerSize()),
|
||||
ElementType, AlignmentSource::Decl);
|
||||
ElementType, LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
llvm::Value *keyValue = EmitScalarExpr(Key);
|
||||
EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true);
|
||||
|
||||
@ -182,7 +182,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
|
||||
const Expr *Value = DLE->getKeyValueElement(i).Value;
|
||||
LValue ValueLV = MakeAddrLValue(
|
||||
Builder.CreateConstArrayGEP(Objects, i, getPointerSize()),
|
||||
ElementType, AlignmentSource::Decl);
|
||||
ElementType, LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
llvm::Value *valueValue = EmitScalarExpr(Value);
|
||||
EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true);
|
||||
if (TrackNeededObjects) {
|
||||
|
@ -138,7 +138,8 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
|
||||
Addr = CGF.Builder.CreateElementBitCast(Addr,
|
||||
llvm::Type::getIntNTy(CGF.getLLVMContext(),
|
||||
Info->StorageSize));
|
||||
return LValue::MakeBitfield(Addr, *Info, IvarTy, AlignmentSource::Decl);
|
||||
return LValue::MakeBitfield(Addr, *Info, IvarTy,
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -720,7 +720,7 @@ LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
|
||||
CodeGenFunction &CGF) {
|
||||
return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
|
||||
getThreadIDVariable()->getType(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
}
|
||||
|
||||
CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
|
||||
@ -3565,7 +3565,9 @@ static void emitPrivatesInit(CodeGenFunction &CGF,
|
||||
auto SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
|
||||
SharedRefLValue = CGF.MakeAddrLValue(
|
||||
Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
|
||||
SharedRefLValue.getType(), AlignmentSource::Decl);
|
||||
SharedRefLValue.getType(),
|
||||
LValueBaseInfo(AlignmentSource::Decl,
|
||||
SharedRefLValue.getBaseInfo().getMayAlias()));
|
||||
QualType Type = OriginalVD->getType();
|
||||
if (Type->isArrayType()) {
|
||||
// Initialize firstprivate array.
|
||||
|
@ -327,14 +327,15 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
|
||||
LValue ArgLVal =
|
||||
MakeAddrLValue(GetAddrOfLocalVar(Args[Cnt]), Args[Cnt]->getType(),
|
||||
AlignmentSource::Decl);
|
||||
BaseInfo);
|
||||
if (FD->hasCapturedVLAType()) {
|
||||
LValue CastedArgLVal =
|
||||
MakeAddrLValue(castValueFromUintptr(*this, FD->getType(),
|
||||
Args[Cnt]->getName(), ArgLVal),
|
||||
FD->getType(), AlignmentSource::Decl);
|
||||
FD->getType(), BaseInfo);
|
||||
auto *ExprArg =
|
||||
EmitLoadOfLValue(CastedArgLVal, SourceLocation()).getScalarVal();
|
||||
auto VAT = FD->getCapturedVLAType();
|
||||
@ -991,7 +992,7 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
|
||||
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
|
||||
BaseLV.getPointer(), CGF.ConvertTypeForMem(ElTy)->getPointerTo()),
|
||||
BaseLV.getAlignment()),
|
||||
BaseLV.getType(), BaseLV.getAlignmentSource());
|
||||
BaseLV.getType(), BaseLV.getBaseInfo());
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitOMPReductionClauseInit(
|
||||
|
@ -146,6 +146,25 @@ static inline AlignmentSource getFieldAlignmentSource(AlignmentSource Source) {
|
||||
return AlignmentSource::Decl;
|
||||
}
|
||||
|
||||
class LValueBaseInfo {
|
||||
AlignmentSource AlignSource;
|
||||
bool MayAlias;
|
||||
|
||||
public:
|
||||
explicit LValueBaseInfo(AlignmentSource Source = AlignmentSource::Type,
|
||||
bool Alias = false)
|
||||
: AlignSource(Source), MayAlias(Alias) {}
|
||||
AlignmentSource getAlignmentSource() const { return AlignSource; }
|
||||
void setAlignmentSource(AlignmentSource Source) { AlignSource = Source; }
|
||||
bool getMayAlias() const { return MayAlias; }
|
||||
void setMayAlias(bool Alias) { MayAlias = Alias; }
|
||||
|
||||
void mergeForCast(const LValueBaseInfo &Info) {
|
||||
setAlignmentSource(Info.getAlignmentSource());
|
||||
setMayAlias(getMayAlias() || Info.getMayAlias());
|
||||
}
|
||||
};
|
||||
|
||||
/// LValue - This represents an lvalue references. Because C/C++ allow
|
||||
/// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a
|
||||
/// bitrange.
|
||||
@ -200,7 +219,7 @@ class LValue {
|
||||
// to make the default bitfield pattern all-zeroes.
|
||||
bool ImpreciseLifetime : 1;
|
||||
|
||||
unsigned AlignSource : 2;
|
||||
LValueBaseInfo BaseInfo;
|
||||
|
||||
// This flag shows if a nontemporal load/stores should be used when accessing
|
||||
// this lvalue.
|
||||
@ -218,7 +237,7 @@ class LValue {
|
||||
|
||||
private:
|
||||
void Initialize(QualType Type, Qualifiers Quals,
|
||||
CharUnits Alignment, AlignmentSource AlignSource,
|
||||
CharUnits Alignment, LValueBaseInfo BaseInfo,
|
||||
llvm::MDNode *TBAAInfo = nullptr) {
|
||||
assert((!Alignment.isZero() || Type->isIncompleteType()) &&
|
||||
"initializing l-value with zero alignment!");
|
||||
@ -227,7 +246,7 @@ class LValue {
|
||||
this->Alignment = Alignment.getQuantity();
|
||||
assert(this->Alignment == Alignment.getQuantity() &&
|
||||
"Alignment exceeds allowed max!");
|
||||
this->AlignSource = unsigned(AlignSource);
|
||||
this->BaseInfo = BaseInfo;
|
||||
|
||||
// Initialize Objective-C flags.
|
||||
this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
|
||||
@ -316,12 +335,8 @@ class LValue {
|
||||
CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); }
|
||||
void setAlignment(CharUnits A) { Alignment = A.getQuantity(); }
|
||||
|
||||
AlignmentSource getAlignmentSource() const {
|
||||
return AlignmentSource(AlignSource);
|
||||
}
|
||||
void setAlignmentSource(AlignmentSource Source) {
|
||||
AlignSource = unsigned(Source);
|
||||
}
|
||||
LValueBaseInfo getBaseInfo() const { return BaseInfo; }
|
||||
void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; }
|
||||
|
||||
// simple lvalue
|
||||
llvm::Value *getPointer() const {
|
||||
@ -370,7 +385,7 @@ class LValue {
|
||||
|
||||
static LValue MakeAddr(Address address, QualType type,
|
||||
ASTContext &Context,
|
||||
AlignmentSource alignSource,
|
||||
LValueBaseInfo BaseInfo,
|
||||
llvm::MDNode *TBAAInfo = nullptr) {
|
||||
Qualifiers qs = type.getQualifiers();
|
||||
qs.setObjCGCAttr(Context.getObjCGCAttrKind(type));
|
||||
@ -379,29 +394,29 @@ class LValue {
|
||||
R.LVType = Simple;
|
||||
assert(address.getPointer()->getType()->isPointerTy());
|
||||
R.V = address.getPointer();
|
||||
R.Initialize(type, qs, address.getAlignment(), alignSource, TBAAInfo);
|
||||
R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo);
|
||||
return R;
|
||||
}
|
||||
|
||||
static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx,
|
||||
QualType type, AlignmentSource alignSource) {
|
||||
QualType type, LValueBaseInfo BaseInfo) {
|
||||
LValue R;
|
||||
R.LVType = VectorElt;
|
||||
R.V = vecAddress.getPointer();
|
||||
R.VectorIdx = Idx;
|
||||
R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
|
||||
alignSource);
|
||||
BaseInfo);
|
||||
return R;
|
||||
}
|
||||
|
||||
static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts,
|
||||
QualType type, AlignmentSource alignSource) {
|
||||
QualType type, LValueBaseInfo BaseInfo) {
|
||||
LValue R;
|
||||
R.LVType = ExtVectorElt;
|
||||
R.V = vecAddress.getPointer();
|
||||
R.VectorElts = Elts;
|
||||
R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
|
||||
alignSource);
|
||||
BaseInfo);
|
||||
return R;
|
||||
}
|
||||
|
||||
@ -414,12 +429,12 @@ class LValue {
|
||||
static LValue MakeBitfield(Address Addr,
|
||||
const CGBitFieldInfo &Info,
|
||||
QualType type,
|
||||
AlignmentSource alignSource) {
|
||||
LValueBaseInfo BaseInfo) {
|
||||
LValue R;
|
||||
R.LVType = BitField;
|
||||
R.V = Addr.getPointer();
|
||||
R.BitFieldInfo = &Info;
|
||||
R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), alignSource);
|
||||
R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo);
|
||||
return R;
|
||||
}
|
||||
|
||||
@ -428,7 +443,7 @@ class LValue {
|
||||
R.LVType = GlobalReg;
|
||||
R.V = Reg.getPointer();
|
||||
R.Initialize(type, type.getQualifiers(), Reg.getAlignment(),
|
||||
AlignmentSource::Decl);
|
||||
LValueBaseInfo(AlignmentSource::Decl, false));
|
||||
return R;
|
||||
}
|
||||
|
||||
|
@ -117,25 +117,27 @@ CodeGenFunction::~CodeGenFunction() {
|
||||
}
|
||||
|
||||
CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
|
||||
AlignmentSource *Source) {
|
||||
return getNaturalTypeAlignment(T->getPointeeType(), Source,
|
||||
LValueBaseInfo *BaseInfo) {
|
||||
return getNaturalTypeAlignment(T->getPointeeType(), BaseInfo,
|
||||
/*forPointee*/ true);
|
||||
}
|
||||
|
||||
CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T,
|
||||
AlignmentSource *Source,
|
||||
LValueBaseInfo *BaseInfo,
|
||||
bool forPointeeType) {
|
||||
// Honor alignment typedef attributes even on incomplete types.
|
||||
// We also honor them straight for C++ class types, even as pointees;
|
||||
// there's an expressivity gap here.
|
||||
if (auto TT = T->getAs<TypedefType>()) {
|
||||
if (auto Align = TT->getDecl()->getMaxAlignment()) {
|
||||
if (Source) *Source = AlignmentSource::AttributedType;
|
||||
if (BaseInfo)
|
||||
*BaseInfo = LValueBaseInfo(AlignmentSource::AttributedType, false);
|
||||
return getContext().toCharUnitsFromBits(Align);
|
||||
}
|
||||
}
|
||||
|
||||
if (Source) *Source = AlignmentSource::Type;
|
||||
if (BaseInfo)
|
||||
*BaseInfo = LValueBaseInfo(AlignmentSource::Type, false);
|
||||
|
||||
CharUnits Alignment;
|
||||
if (T->isIncompleteType()) {
|
||||
@ -165,9 +167,9 @@ CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T,
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
|
||||
AlignmentSource AlignSource;
|
||||
CharUnits Alignment = getNaturalTypeAlignment(T, &AlignSource);
|
||||
return LValue::MakeAddr(Address(V, Alignment), T, getContext(), AlignSource,
|
||||
LValueBaseInfo BaseInfo;
|
||||
CharUnits Alignment = getNaturalTypeAlignment(T, &BaseInfo);
|
||||
return LValue::MakeAddr(Address(V, Alignment), T, getContext(), BaseInfo,
|
||||
CGM.getTBAAInfo(T));
|
||||
}
|
||||
|
||||
@ -175,9 +177,9 @@ LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
|
||||
/// construct an l-value with the natural pointee alignment of T.
|
||||
LValue
|
||||
CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) {
|
||||
AlignmentSource AlignSource;
|
||||
CharUnits Align = getNaturalTypeAlignment(T, &AlignSource, /*pointee*/ true);
|
||||
return MakeAddrLValue(Address(V, Align), T, AlignSource);
|
||||
LValueBaseInfo BaseInfo;
|
||||
CharUnits Align = getNaturalTypeAlignment(T, &BaseInfo, /*pointee*/ true);
|
||||
return MakeAddrLValue(Address(V, Align), T, BaseInfo);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1886,31 +1886,33 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
LValue MakeAddrLValue(Address Addr, QualType T,
|
||||
AlignmentSource AlignSource = AlignmentSource::Type) {
|
||||
return LValue::MakeAddr(Addr, T, getContext(), AlignSource,
|
||||
LValueBaseInfo BaseInfo =
|
||||
LValueBaseInfo(AlignmentSource::Type)) {
|
||||
return LValue::MakeAddr(Addr, T, getContext(), BaseInfo,
|
||||
CGM.getTBAAInfo(T));
|
||||
}
|
||||
|
||||
LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment,
|
||||
AlignmentSource AlignSource = AlignmentSource::Type) {
|
||||
LValueBaseInfo BaseInfo =
|
||||
LValueBaseInfo(AlignmentSource::Type)) {
|
||||
return LValue::MakeAddr(Address(V, Alignment), T, getContext(),
|
||||
AlignSource, CGM.getTBAAInfo(T));
|
||||
BaseInfo, CGM.getTBAAInfo(T));
|
||||
}
|
||||
|
||||
LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T);
|
||||
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T);
|
||||
CharUnits getNaturalTypeAlignment(QualType T,
|
||||
AlignmentSource *Source = nullptr,
|
||||
LValueBaseInfo *BaseInfo = nullptr,
|
||||
bool forPointeeType = false);
|
||||
CharUnits getNaturalPointeeTypeAlignment(QualType T,
|
||||
AlignmentSource *Source = nullptr);
|
||||
LValueBaseInfo *BaseInfo = nullptr);
|
||||
|
||||
Address EmitLoadOfReference(Address Ref, const ReferenceType *RefTy,
|
||||
AlignmentSource *Source = nullptr);
|
||||
LValueBaseInfo *BaseInfo = nullptr);
|
||||
LValue EmitLoadOfReferenceLValue(Address Ref, const ReferenceType *RefTy);
|
||||
|
||||
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy,
|
||||
AlignmentSource *Source = nullptr);
|
||||
LValueBaseInfo *BaseInfo = nullptr);
|
||||
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy);
|
||||
|
||||
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
|
||||
@ -2992,8 +2994,8 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
/// the LLVM value representation.
|
||||
llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty,
|
||||
SourceLocation Loc,
|
||||
AlignmentSource AlignSource =
|
||||
AlignmentSource::Type,
|
||||
LValueBaseInfo BaseInfo =
|
||||
LValueBaseInfo(AlignmentSource::Type),
|
||||
llvm::MDNode *TBAAInfo = nullptr,
|
||||
QualType TBAABaseTy = QualType(),
|
||||
uint64_t TBAAOffset = 0,
|
||||
@ -3010,7 +3012,8 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
/// the LLVM value representation.
|
||||
void EmitStoreOfScalar(llvm::Value *Value, Address Addr,
|
||||
bool Volatile, QualType Ty,
|
||||
AlignmentSource AlignSource = AlignmentSource::Type,
|
||||
LValueBaseInfo BaseInfo =
|
||||
LValueBaseInfo(AlignmentSource::Type),
|
||||
llvm::MDNode *TBAAInfo = nullptr, bool isInit = false,
|
||||
QualType TBAABaseTy = QualType(),
|
||||
uint64_t TBAAOffset = 0, bool isNontemporal = false);
|
||||
@ -3083,7 +3086,7 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc);
|
||||
|
||||
Address EmitArrayToPointerDecay(const Expr *Array,
|
||||
AlignmentSource *AlignSource = nullptr);
|
||||
LValueBaseInfo *BaseInfo = nullptr);
|
||||
|
||||
class ConstantEmission {
|
||||
llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference;
|
||||
@ -3224,7 +3227,7 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base,
|
||||
llvm::Value *memberPtr,
|
||||
const MemberPointerType *memberPtrType,
|
||||
AlignmentSource *AlignSource = nullptr);
|
||||
LValueBaseInfo *BaseInfo = nullptr);
|
||||
RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
|
||||
ReturnValueSlot ReturnValue);
|
||||
|
||||
@ -3743,29 +3746,25 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
unsigned ParamsToSkip = 0,
|
||||
EvaluationOrder Order = EvaluationOrder::Default);
|
||||
|
||||
/// EmitPointerWithAlignment - Given an expression with a pointer
|
||||
/// type, emit the value and compute our best estimate of the
|
||||
/// alignment of the pointee.
|
||||
/// EmitPointerWithAlignment - Given an expression with a pointer type,
|
||||
/// emit the value and compute our best estimate of the alignment of the
|
||||
/// pointee.
|
||||
///
|
||||
/// Note that this function will conservatively fall back on the type
|
||||
/// when it doesn't
|
||||
/// \param BaseInfo - If non-null, this will be initialized with
|
||||
/// information about the source of the alignment and the may-alias
|
||||
/// attribute. Note that this function will conservatively fall back on
|
||||
/// the type when it doesn't recognize the expression and may-alias will
|
||||
/// be set to false.
|
||||
///
|
||||
/// \param Source - If non-null, this will be initialized with
|
||||
/// information about the source of the alignment. Note that this
|
||||
/// function will conservatively fall back on the type when it
|
||||
/// doesn't recognize the expression, which means that sometimes
|
||||
///
|
||||
/// a worst-case One
|
||||
/// reasonable way to use this information is when there's a
|
||||
/// language guarantee that the pointer must be aligned to some
|
||||
/// stricter value, and we're simply trying to ensure that
|
||||
/// sufficiently obvious uses of under-aligned objects don't get
|
||||
/// miscompiled; for example, a placement new into the address of
|
||||
/// a local variable. In such a case, it's quite reasonable to
|
||||
/// just ignore the returned alignment when it isn't from an
|
||||
/// explicit source.
|
||||
/// One reasonable way to use this information is when there's a language
|
||||
/// guarantee that the pointer must be aligned to some stricter value, and
|
||||
/// we're simply trying to ensure that sufficiently obvious uses of under-
|
||||
/// aligned objects don't get miscompiled; for example, a placement new
|
||||
/// into the address of a local variable. In such a case, it's quite
|
||||
/// reasonable to just ignore the returned alignment when it isn't from an
|
||||
/// explicit source.
|
||||
Address EmitPointerWithAlignment(const Expr *Addr,
|
||||
AlignmentSource *Source = nullptr);
|
||||
LValueBaseInfo *BaseInfo = nullptr);
|
||||
|
||||
void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK);
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "clang/Frontend/CodeGenOptions.h"
|
||||
#include "clang/Sema/SemaDiagnostic.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/CallingConv.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
@ -113,6 +114,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
|
||||
Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
|
||||
AllocaInt8PtrTy = Int8Ty->getPointerTo(
|
||||
M.getDataLayout().getAllocaAddrSpace());
|
||||
ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace();
|
||||
|
||||
RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
|
||||
BuiltinCC = getTargetCodeGenInfo().getABIInfo().getBuiltinCC();
|
||||
@ -464,18 +466,24 @@ void CodeGenModule::Release() {
|
||||
getModule().addModuleFlag(llvm::Module::Warning, "Debug Info Version",
|
||||
llvm::DEBUG_METADATA_VERSION);
|
||||
|
||||
// Width of wchar_t in bytes
|
||||
uint64_t WCharWidth =
|
||||
Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
|
||||
assert(LangOpts.ShortWChar ||
|
||||
llvm::TargetLibraryInfoImpl::getTargetWCharSize(Target.getTriple()) ==
|
||||
Target.getWCharWidth() / 8 &&
|
||||
"LLVM wchar_t size out of sync");
|
||||
|
||||
// We need to record the widths of enums and wchar_t, so that we can generate
|
||||
// the correct build attributes in the ARM backend.
|
||||
// the correct build attributes in the ARM backend. wchar_size is also used by
|
||||
// TargetLibraryInfo.
|
||||
getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
|
||||
|
||||
llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
|
||||
if ( Arch == llvm::Triple::arm
|
||||
|| Arch == llvm::Triple::armeb
|
||||
|| Arch == llvm::Triple::thumb
|
||||
|| Arch == llvm::Triple::thumbeb) {
|
||||
// Width of wchar_t in bytes
|
||||
uint64_t WCharWidth =
|
||||
Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
|
||||
getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
|
||||
|
||||
// The minimum width of an enum in bytes
|
||||
uint64_t EnumWidth = Context.getLangOpts().ShortEnums ? 1 : 4;
|
||||
getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth);
|
||||
|
@ -94,6 +94,8 @@ struct CodeGenTypeCache {
|
||||
unsigned char SizeAlignInBytes;
|
||||
};
|
||||
|
||||
unsigned ASTAllocaAddressSpace;
|
||||
|
||||
CharUnits getSizeSize() const {
|
||||
return CharUnits::fromQuantity(SizeSizeInBytes);
|
||||
}
|
||||
@ -111,6 +113,8 @@ struct CodeGenTypeCache {
|
||||
llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
|
||||
llvm::CallingConv::ID BuiltinCC;
|
||||
llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; }
|
||||
|
||||
unsigned getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; }
|
||||
};
|
||||
|
||||
} // end namespace CodeGen
|
||||
|
@ -407,12 +407,11 @@ llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &
|
||||
}
|
||||
|
||||
llvm::Value *TargetCodeGenInfo::performAddrSpaceCast(
|
||||
CodeGen::CodeGenFunction &CGF, llvm::Value *Src, QualType SrcTy,
|
||||
QualType DestTy) const {
|
||||
CodeGen::CodeGenFunction &CGF, llvm::Value *Src, unsigned SrcAddr,
|
||||
unsigned DestAddr, llvm::Type *DestTy, bool isNonNull) const {
|
||||
// Since target may map different address spaces in AST to the same address
|
||||
// space, an address space conversion may end up as a bitcast.
|
||||
return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Src,
|
||||
CGF.ConvertType(DestTy));
|
||||
return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Src, DestTy);
|
||||
}
|
||||
|
||||
static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
|
||||
@ -6558,6 +6557,11 @@ class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
|
||||
Fn->addFnAttr("nomips16");
|
||||
}
|
||||
|
||||
if (FD->hasAttr<MicroMipsAttr>())
|
||||
Fn->addFnAttr("micromips");
|
||||
else if (FD->hasAttr<NoMicroMipsAttr>())
|
||||
Fn->addFnAttr("nomicromips");
|
||||
|
||||
const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>();
|
||||
if (!Attr)
|
||||
return;
|
||||
@ -7292,6 +7296,11 @@ class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo {
|
||||
|
||||
llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
|
||||
llvm::PointerType *T, QualType QT) const override;
|
||||
|
||||
unsigned getASTAllocaAddressSpace() const override {
|
||||
return LangAS::FirstTargetAddressSpace +
|
||||
getABIInfo().getDataLayout().getAllocaAddrSpace();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -229,13 +229,20 @@ class TargetCodeGenInfo {
|
||||
virtual llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
|
||||
llvm::PointerType *T, QualType QT) const;
|
||||
|
||||
/// Get the AST address space for alloca.
|
||||
virtual unsigned getASTAllocaAddressSpace() const { return LangAS::Default; }
|
||||
|
||||
/// Perform address space cast of an expression of pointer type.
|
||||
/// \param V is the LLVM value to be casted to another address space.
|
||||
/// \param SrcTy is the QualType of \p V.
|
||||
/// \param DestTy is the destination QualType.
|
||||
/// \param SrcAddr is the language address space of \p V.
|
||||
/// \param DestAddr is the targeted language address space.
|
||||
/// \param DestTy is the destination LLVM pointer type.
|
||||
/// \param IsNonNull is the flag indicating \p V is known to be non null.
|
||||
virtual llvm::Value *performAddrSpaceCast(CodeGen::CodeGenFunction &CGF,
|
||||
llvm::Value *V, QualType SrcTy, QualType DestTy) const;
|
||||
|
||||
llvm::Value *V, unsigned SrcAddr,
|
||||
unsigned DestAddr,
|
||||
llvm::Type *DestTy,
|
||||
bool IsNonNull = false) const;
|
||||
};
|
||||
|
||||
} // namespace CodeGen
|
||||
|
@ -41,7 +41,8 @@ static bool IsBlank(char C) {
|
||||
}
|
||||
|
||||
static StringRef getLineCommentIndentPrefix(StringRef Comment) {
|
||||
static const char *const KnownPrefixes[] = {"///", "//", "//!"};
|
||||
static const char *const KnownPrefixes[] = {
|
||||
"///<", "//!<", "///", "//", "//!"};
|
||||
StringRef LongestPrefix;
|
||||
for (StringRef KnownPrefix : KnownPrefixes) {
|
||||
if (Comment.startswith(KnownPrefix)) {
|
||||
@ -77,6 +78,14 @@ static BreakableToken::Split getCommentSplit(StringRef Text,
|
||||
}
|
||||
|
||||
StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);
|
||||
|
||||
// Do not split before a number followed by a dot: this would be interpreted
|
||||
// as a numbered list, which would prevent re-flowing in subsequent passes.
|
||||
static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\.");
|
||||
if (SpaceOffset != StringRef::npos &&
|
||||
kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks)))
|
||||
SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
|
||||
|
||||
if (SpaceOffset == StringRef::npos ||
|
||||
// Don't break at leading whitespace.
|
||||
Text.find_last_not_of(Blanks, SpaceOffset) == StringRef::npos) {
|
||||
@ -298,8 +307,9 @@ const FormatToken &BreakableComment::tokenAt(unsigned LineIndex) const {
|
||||
static bool mayReflowContent(StringRef Content) {
|
||||
Content = Content.trim(Blanks);
|
||||
// Lines starting with '@' commonly have special meaning.
|
||||
static const SmallVector<StringRef, 4> kSpecialMeaningPrefixes = {
|
||||
"@", "TODO", "FIXME", "XXX"};
|
||||
// Lines starting with '-', '-#', '+' or '*' are bulleted/numbered lists.
|
||||
static const SmallVector<StringRef, 8> kSpecialMeaningPrefixes = {
|
||||
"@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* " };
|
||||
bool hasSpecialMeaningPrefix = false;
|
||||
for (StringRef Prefix : kSpecialMeaningPrefixes) {
|
||||
if (Content.startswith(Prefix)) {
|
||||
@ -307,6 +317,14 @@ static bool mayReflowContent(StringRef Content) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Numbered lists may also start with a number followed by '.'
|
||||
// To avoid issues if a line starts with a number which is actually the end
|
||||
// of a previous line, we only consider numbers with up to 2 digits.
|
||||
static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\. ");
|
||||
hasSpecialMeaningPrefix = hasSpecialMeaningPrefix ||
|
||||
kNumberedListRegexp.match(Content);
|
||||
|
||||
// Simple heuristic for what to reflow: content should contain at least two
|
||||
// characters and either the first or second character must be
|
||||
// non-punctuation.
|
||||
@ -692,6 +710,10 @@ BreakableLineCommentSection::BreakableLineCommentSection(
|
||||
Prefix[i] = "/// ";
|
||||
else if (Prefix[i] == "//!")
|
||||
Prefix[i] = "//! ";
|
||||
else if (Prefix[i] == "///<")
|
||||
Prefix[i] = "///< ";
|
||||
else if (Prefix[i] == "//!<")
|
||||
Prefix[i] = "//!< ";
|
||||
}
|
||||
|
||||
Tokens[i] = LineTok;
|
||||
|
@ -207,7 +207,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
|
||||
// ...
|
||||
// }.bind(...));
|
||||
// FIXME: We should find a more generic solution to this problem.
|
||||
!(State.Column <= NewLineColumn &&
|
||||
!(State.Column <= NewLineColumn && Previous.isNot(tok::r_paren) &&
|
||||
Style.Language == FormatStyle::LK_JavaScript))
|
||||
return true;
|
||||
|
||||
@ -587,8 +587,10 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
|
||||
if (!DryRun) {
|
||||
unsigned Newlines = std::max(
|
||||
1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1));
|
||||
bool ContinuePPDirective =
|
||||
State.Line->InPPDirective && State.Line->Type != LT_ImportStatement;
|
||||
Whitespaces.replaceWhitespace(Current, Newlines, State.Column, State.Column,
|
||||
State.Line->InPPDirective);
|
||||
ContinuePPDirective);
|
||||
}
|
||||
|
||||
if (!Current.isTrailingComment())
|
||||
|
@ -343,6 +343,8 @@ template <> struct MappingTraits<FormatStyle> {
|
||||
IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
|
||||
IO.mapOptional("ObjCSpaceBeforeProtocolList",
|
||||
Style.ObjCSpaceBeforeProtocolList);
|
||||
IO.mapOptional("PenaltyBreakAssignment",
|
||||
Style.PenaltyBreakAssignment);
|
||||
IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
|
||||
Style.PenaltyBreakBeforeFirstCallParameter);
|
||||
IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
|
||||
@ -582,6 +584,7 @@ FormatStyle getLLVMStyle() {
|
||||
LLVMStyle.SpaceBeforeAssignmentOperators = true;
|
||||
LLVMStyle.SpacesInAngles = false;
|
||||
|
||||
LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
|
||||
LLVMStyle.PenaltyBreakComment = 300;
|
||||
LLVMStyle.PenaltyBreakFirstLessLess = 120;
|
||||
LLVMStyle.PenaltyBreakString = 1000;
|
||||
|
@ -576,12 +576,13 @@ class AnnotatingParser {
|
||||
}
|
||||
break;
|
||||
case tok::kw_for:
|
||||
if (Style.Language == FormatStyle::LK_JavaScript)
|
||||
if (Style.Language == FormatStyle::LK_JavaScript) {
|
||||
if (Tok->Previous && Tok->Previous->is(tok::period))
|
||||
break;
|
||||
// JS' for async ( ...
|
||||
if (CurrentToken->is(Keywords.kw_async))
|
||||
// JS' for await ( ...
|
||||
if (CurrentToken && CurrentToken->is(Keywords.kw_await))
|
||||
next();
|
||||
}
|
||||
Contexts.back().ColonIsForRangeExpr = true;
|
||||
next();
|
||||
if (!parseParens())
|
||||
@ -703,9 +704,12 @@ class AnnotatingParser {
|
||||
|
||||
void parseIncludeDirective() {
|
||||
if (CurrentToken && CurrentToken->is(tok::less)) {
|
||||
next();
|
||||
while (CurrentToken) {
|
||||
if (CurrentToken->isNot(tok::comment) || CurrentToken->Next)
|
||||
next();
|
||||
while (CurrentToken) {
|
||||
// Mark tokens up to the trailing line comments as implicit string
|
||||
// literals.
|
||||
if (CurrentToken->isNot(tok::comment) &&
|
||||
!CurrentToken->TokenText.startswith("//"))
|
||||
CurrentToken->Type = TT_ImplicitStringLiteral;
|
||||
next();
|
||||
}
|
||||
@ -2089,9 +2093,10 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
|
||||
if (Left.is(TT_ConditionalExpr))
|
||||
return prec::Conditional;
|
||||
prec::Level Level = Left.getPrecedence();
|
||||
if (Level != prec::Unknown)
|
||||
return Level;
|
||||
Level = Right.getPrecedence();
|
||||
if (Level == prec::Unknown)
|
||||
Level = Right.getPrecedence();
|
||||
if (Level == prec::Assignment)
|
||||
return Style.PenaltyBreakAssignment;
|
||||
if (Level != prec::Unknown)
|
||||
return Level;
|
||||
|
||||
@ -2252,8 +2257,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
||||
} else if (Style.Language == FormatStyle::LK_JavaScript) {
|
||||
if (Left.is(TT_JsFatArrow))
|
||||
return true;
|
||||
// for async ( ...
|
||||
if (Right.is(tok::l_paren) && Left.is(Keywords.kw_async) &&
|
||||
// for await ( ...
|
||||
if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) &&
|
||||
Left.Previous && Left.Previous->is(tok::kw_for))
|
||||
return true;
|
||||
if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&
|
||||
@ -2472,22 +2477,25 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
|
||||
|
||||
// If the last token before a '}', ']', or ')' is a comma or a trailing
|
||||
// comment, the intention is to insert a line break after it in order to make
|
||||
// shuffling around entries easier.
|
||||
const FormatToken *BeforeClosingBrace = nullptr;
|
||||
if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
|
||||
(Style.Language == FormatStyle::LK_JavaScript &&
|
||||
Left.is(tok::l_paren))) &&
|
||||
Left.BlockKind != BK_Block && Left.MatchingParen)
|
||||
BeforeClosingBrace = Left.MatchingParen->Previous;
|
||||
else if (Right.MatchingParen &&
|
||||
(Right.MatchingParen->isOneOf(tok::l_brace,
|
||||
TT_ArrayInitializerLSquare) ||
|
||||
(Style.Language == FormatStyle::LK_JavaScript &&
|
||||
Right.MatchingParen->is(tok::l_paren))))
|
||||
BeforeClosingBrace = &Left;
|
||||
if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||
|
||||
BeforeClosingBrace->isTrailingComment()))
|
||||
return true;
|
||||
// shuffling around entries easier. Import statements, especially in
|
||||
// JavaScript, can be an exception to this rule.
|
||||
if (Style.JavaScriptWrapImports || Line.Type != LT_ImportStatement) {
|
||||
const FormatToken *BeforeClosingBrace = nullptr;
|
||||
if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
|
||||
(Style.Language == FormatStyle::LK_JavaScript &&
|
||||
Left.is(tok::l_paren))) &&
|
||||
Left.BlockKind != BK_Block && Left.MatchingParen)
|
||||
BeforeClosingBrace = Left.MatchingParen->Previous;
|
||||
else if (Right.MatchingParen &&
|
||||
(Right.MatchingParen->isOneOf(tok::l_brace,
|
||||
TT_ArrayInitializerLSquare) ||
|
||||
(Style.Language == FormatStyle::LK_JavaScript &&
|
||||
Right.MatchingParen->is(tok::l_paren))))
|
||||
BeforeClosingBrace = &Left;
|
||||
if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||
|
||||
BeforeClosingBrace->isTrailingComment()))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Right.is(tok::comment))
|
||||
return Left.BlockKind != BK_BracedInit &&
|
||||
@ -2562,7 +2570,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
|
||||
Keywords.kw_interface, Keywords.kw_type, tok::kw_static,
|
||||
tok::kw_public, tok::kw_private, tok::kw_protected,
|
||||
Keywords.kw_abstract, Keywords.kw_get, Keywords.kw_set))
|
||||
return false; // Otherwise a semicolon is inserted.
|
||||
return false; // Otherwise automatic semicolon insertion would trigger.
|
||||
if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
|
||||
return false;
|
||||
if (Left.is(TT_JsTypeColon))
|
||||
|
@ -611,7 +611,8 @@ class NoLineBreakFormatter : public LineFormatter {
|
||||
LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);
|
||||
while (State.NextToken) {
|
||||
formatChildren(State, /*Newline=*/false, DryRun, Penalty);
|
||||
Indenter->addTokenToState(State, /*Newline=*/false, DryRun);
|
||||
Indenter->addTokenToState(
|
||||
State, /*Newline=*/State.NextToken->MustBreakBefore, DryRun);
|
||||
}
|
||||
return Penalty;
|
||||
}
|
||||
|
@ -55,13 +55,33 @@ class ScopedDeclarationState {
|
||||
std::vector<bool> &Stack;
|
||||
};
|
||||
|
||||
static bool isLineComment(const FormatToken &FormatTok) {
|
||||
return FormatTok.is(tok::comment) &&
|
||||
FormatTok.TokenText.startswith("//");
|
||||
}
|
||||
|
||||
// Checks if \p FormatTok is a line comment that continues the line comment
|
||||
// \p Previous. The original column of \p MinColumnToken is used to determine
|
||||
// whether \p FormatTok is indented enough to the right to continue \p Previous.
|
||||
static bool continuesLineComment(const FormatToken &FormatTok,
|
||||
const FormatToken *Previous,
|
||||
const FormatToken *MinColumnToken) {
|
||||
if (!Previous || !MinColumnToken)
|
||||
return false;
|
||||
unsigned MinContinueColumn =
|
||||
MinColumnToken->OriginalColumn + (isLineComment(*MinColumnToken) ? 0 : 1);
|
||||
return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 &&
|
||||
isLineComment(*Previous) &&
|
||||
FormatTok.OriginalColumn >= MinContinueColumn;
|
||||
}
|
||||
|
||||
class ScopedMacroState : public FormatTokenSource {
|
||||
public:
|
||||
ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
|
||||
FormatToken *&ResetToken)
|
||||
: Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
|
||||
PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource),
|
||||
Token(nullptr) {
|
||||
Token(nullptr), PreviousToken(nullptr) {
|
||||
TokenSource = this;
|
||||
Line.Level = 0;
|
||||
Line.InPPDirective = true;
|
||||
@ -78,6 +98,7 @@ class ScopedMacroState : public FormatTokenSource {
|
||||
// The \c UnwrappedLineParser guards against this by never calling
|
||||
// \c getNextToken() after it has encountered the first eof token.
|
||||
assert(!eof());
|
||||
PreviousToken = Token;
|
||||
Token = PreviousTokenSource->getNextToken();
|
||||
if (eof())
|
||||
return getFakeEOF();
|
||||
@ -87,12 +108,17 @@ class ScopedMacroState : public FormatTokenSource {
|
||||
unsigned getPosition() override { return PreviousTokenSource->getPosition(); }
|
||||
|
||||
FormatToken *setPosition(unsigned Position) override {
|
||||
PreviousToken = nullptr;
|
||||
Token = PreviousTokenSource->setPosition(Position);
|
||||
return Token;
|
||||
}
|
||||
|
||||
private:
|
||||
bool eof() { return Token && Token->HasUnescapedNewline; }
|
||||
bool eof() {
|
||||
return Token && Token->HasUnescapedNewline &&
|
||||
!continuesLineComment(*Token, PreviousToken,
|
||||
/*MinColumnToken=*/PreviousToken);
|
||||
}
|
||||
|
||||
FormatToken *getFakeEOF() {
|
||||
static bool EOFInitialized = false;
|
||||
@ -112,6 +138,7 @@ class ScopedMacroState : public FormatTokenSource {
|
||||
FormatTokenSource *PreviousTokenSource;
|
||||
|
||||
FormatToken *Token;
|
||||
FormatToken *PreviousToken;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@ -429,8 +456,9 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
|
||||
parseParens();
|
||||
|
||||
addUnwrappedLine();
|
||||
size_t OpeningLineIndex =
|
||||
Lines.empty() ? (UnwrappedLine::kInvalidIndex) : (Lines.size() - 1);
|
||||
size_t OpeningLineIndex = CurrentLines->empty()
|
||||
? (UnwrappedLine::kInvalidIndex)
|
||||
: (CurrentLines->size() - 1);
|
||||
|
||||
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
|
||||
MustBeDeclaration);
|
||||
@ -1635,9 +1663,9 @@ void UnwrappedLineParser::parseForOrWhileLoop() {
|
||||
assert(FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) &&
|
||||
"'for', 'while' or foreach macro expected");
|
||||
nextToken();
|
||||
// JS' for async ( ...
|
||||
// JS' for await ( ...
|
||||
if (Style.Language == FormatStyle::LK_JavaScript &&
|
||||
FormatTok->is(Keywords.kw_async))
|
||||
FormatTok->is(Keywords.kw_await))
|
||||
nextToken();
|
||||
if (FormatTok->Tok.is(tok::l_paren))
|
||||
parseParens();
|
||||
@ -2091,16 +2119,11 @@ bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
|
||||
FormatTok.NewlinesBefore > 0;
|
||||
}
|
||||
|
||||
static bool isLineComment(const FormatToken &FormatTok) {
|
||||
return FormatTok.is(tok::comment) &&
|
||||
FormatTok.TokenText.startswith("//");
|
||||
}
|
||||
|
||||
// Checks if \p FormatTok is a line comment that continues the line comment
|
||||
// section on \p Line.
|
||||
static bool continuesLineComment(const FormatToken &FormatTok,
|
||||
const UnwrappedLine &Line,
|
||||
llvm::Regex &CommentPragmasRegex) {
|
||||
static bool continuesLineCommentSection(const FormatToken &FormatTok,
|
||||
const UnwrappedLine &Line,
|
||||
llvm::Regex &CommentPragmasRegex) {
|
||||
if (Line.Tokens.empty())
|
||||
return false;
|
||||
|
||||
@ -2199,12 +2222,8 @@ static bool continuesLineComment(const FormatToken &FormatTok,
|
||||
MinColumnToken = PreviousToken;
|
||||
}
|
||||
|
||||
unsigned MinContinueColumn =
|
||||
MinColumnToken->OriginalColumn +
|
||||
(isLineComment(*MinColumnToken) ? 0 : 1);
|
||||
return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 &&
|
||||
isLineComment(*(Line.Tokens.back().Tok)) &&
|
||||
FormatTok.OriginalColumn >= MinContinueColumn;
|
||||
return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok,
|
||||
MinColumnToken);
|
||||
}
|
||||
|
||||
void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
|
||||
@ -2222,7 +2241,7 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
|
||||
// FIXME: Consider putting separate line comment sections as children to the
|
||||
// unwrapped line instead.
|
||||
(*I)->ContinuesLineCommentSection =
|
||||
continuesLineComment(**I, *Line, CommentPragmasRegex);
|
||||
continuesLineCommentSection(**I, *Line, CommentPragmasRegex);
|
||||
if (isOnNewLine(**I) && JustComments && !(*I)->ContinuesLineCommentSection)
|
||||
addUnwrappedLine();
|
||||
pushToken(*I);
|
||||
@ -2255,7 +2274,7 @@ void UnwrappedLineParser::distributeComments(
|
||||
const SmallVectorImpl<FormatToken *> &Comments,
|
||||
const FormatToken *NextTok) {
|
||||
// Whether or not a line comment token continues a line is controlled by
|
||||
// the method continuesLineComment, with the following caveat:
|
||||
// the method continuesLineCommentSection, with the following caveat:
|
||||
//
|
||||
// Define a trail of Comments to be a nonempty proper postfix of Comments such
|
||||
// that each comment line from the trail is aligned with the next token, if
|
||||
@ -2293,7 +2312,7 @@ void UnwrappedLineParser::distributeComments(
|
||||
FormatTok->ContinuesLineCommentSection = false;
|
||||
} else {
|
||||
FormatTok->ContinuesLineCommentSection =
|
||||
continuesLineComment(*FormatTok, *Line, CommentPragmasRegex);
|
||||
continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex);
|
||||
}
|
||||
if (!FormatTok->ContinuesLineCommentSection &&
|
||||
(isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
|
||||
|
@ -246,6 +246,9 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
|
||||
}
|
||||
|
||||
bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
|
||||
if (E->isClassReceiver())
|
||||
IndexCtx.handleReference(E->getClassReceiver(), E->getReceiverLocation(),
|
||||
Parent, ParentDC);
|
||||
if (E->isExplicitProperty()) {
|
||||
SmallVector<SymbolRelation, 2> Relations;
|
||||
SymbolRoleSet Roles = getRolesForRef(E, Relations);
|
||||
|
@ -63,6 +63,17 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
|
||||
case TemplateArgument::Type:
|
||||
IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
|
||||
break;
|
||||
case TemplateArgument::Template:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),
|
||||
Parent, DC);
|
||||
if (const TemplateDecl *TD = TALoc.getArgument()
|
||||
.getAsTemplateOrTemplatePattern()
|
||||
.getAsTemplateDecl()) {
|
||||
if (const NamedDecl *TTD = TD->getTemplatedDecl())
|
||||
IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -98,6 +109,17 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Index the default parameter value for function definitions.
|
||||
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
if (FD->isThisDeclarationADefinition()) {
|
||||
for (const auto *PV : FD->parameters()) {
|
||||
if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() &&
|
||||
!PV->hasUnparsedDefaultArg())
|
||||
IndexCtx.indexBody(PV->getDefaultArg(), D);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,9 +228,6 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
|
||||
}
|
||||
|
||||
bool VisitFunctionDecl(const FunctionDecl *D) {
|
||||
if (D->isDeleted())
|
||||
return true;
|
||||
|
||||
SymbolRoleSet Roles{};
|
||||
SmallVector<SymbolRelation, 4> Relations;
|
||||
if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
|
||||
@ -568,8 +587,12 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
|
||||
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
|
||||
const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
|
||||
|
||||
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
|
||||
D->getLexicalDeclContext());
|
||||
// NNS for the local 'using namespace' directives is visited by the body
|
||||
// visitor.
|
||||
if (!D->getParentFunctionOrMethod())
|
||||
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
|
||||
D->getLexicalDeclContext());
|
||||
|
||||
return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
|
||||
D->getLocation(), Parent,
|
||||
D->getLexicalDeclContext(),
|
||||
@ -598,8 +621,43 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
|
||||
if (!D)
|
||||
return false;
|
||||
// We want to index the template parameters only once when indexing the
|
||||
// canonical declaration.
|
||||
if (const auto *FD = dyn_cast<FunctionDecl>(D))
|
||||
return FD->getCanonicalDecl() == FD;
|
||||
else if (const auto *TD = dyn_cast<TagDecl>(D))
|
||||
return TD->getCanonicalDecl() == TD;
|
||||
else if (const auto *VD = dyn_cast<VarDecl>(D))
|
||||
return VD->getCanonicalDecl() == VD;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitTemplateDecl(const TemplateDecl *D) {
|
||||
// FIXME: Template parameters.
|
||||
|
||||
// Index the default values for the template parameters.
|
||||
const NamedDecl *Parent = D->getTemplatedDecl();
|
||||
if (D->getTemplateParameters() &&
|
||||
shouldIndexTemplateParameterDefaultValue(Parent)) {
|
||||
const TemplateParameterList *Params = D->getTemplateParameters();
|
||||
for (const NamedDecl *TP : *Params) {
|
||||
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
|
||||
if (TTP->hasDefaultArgument())
|
||||
IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
|
||||
} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
|
||||
if (NTTP->hasDefaultArgument())
|
||||
IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
|
||||
} else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
|
||||
if (TTPD->hasDefaultArgument())
|
||||
handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
|
||||
/*DC=*/nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Visit(D->getTemplatedDecl());
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,8 @@ bool index::isFunctionLocalSymbol(const Decl *D) {
|
||||
if (isa<ObjCTypeParamDecl>(D))
|
||||
return true;
|
||||
|
||||
if (isa<UsingDirectiveDecl>(D))
|
||||
return false;
|
||||
if (!D->getParentFunctionOrMethod())
|
||||
return false;
|
||||
|
||||
@ -318,16 +320,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
|
||||
if (Info.Properties & (unsigned)SymbolProperty::Generic)
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
|
||||
auto getExternalSymAttr = [](const Decl *D) -> ExternalSourceSymbolAttr* {
|
||||
if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>())
|
||||
return attr;
|
||||
if (auto *dcd = dyn_cast<Decl>(D->getDeclContext())) {
|
||||
if (auto *attr = dcd->getAttr<ExternalSourceSymbolAttr>())
|
||||
return attr;
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
if (auto *attr = getExternalSymAttr(D)) {
|
||||
if (auto *attr = D->getExternalSourceSymbolAttr()) {
|
||||
if (attr->getLanguage() == "Swift")
|
||||
Info.Lang = SymbolLanguage::Swift;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc,
|
||||
static StringRef GetExternalSourceContainer(const NamedDecl *D) {
|
||||
if (!D)
|
||||
return StringRef();
|
||||
if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
|
||||
if (auto *attr = D->getExternalSourceSymbolAttr()) {
|
||||
return attr->getDefinedIn();
|
||||
}
|
||||
return StringRef();
|
||||
|
@ -950,39 +950,6 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
|
||||
return !Mod->UnresolvedConflicts.empty();
|
||||
}
|
||||
|
||||
Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
|
||||
if (Loc.isInvalid())
|
||||
return nullptr;
|
||||
|
||||
if (UmbrellaDirs.empty() && Headers.empty())
|
||||
return nullptr;
|
||||
|
||||
// Use the expansion location to determine which module we're in.
|
||||
FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
|
||||
if (!ExpansionLoc.isFileID())
|
||||
return nullptr;
|
||||
|
||||
const SourceManager &SrcMgr = Loc.getManager();
|
||||
FileID ExpansionFileID = ExpansionLoc.getFileID();
|
||||
|
||||
while (const FileEntry *ExpansionFile
|
||||
= SrcMgr.getFileEntryForID(ExpansionFileID)) {
|
||||
// Find the module that owns this header (if any).
|
||||
if (Module *Mod = findModuleForHeader(ExpansionFile).getModule())
|
||||
return Mod;
|
||||
|
||||
// No module owns this header, so look up the inclusion chain to see if
|
||||
// any included header has an associated module.
|
||||
SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
|
||||
if (IncludeLoc.isInvalid())
|
||||
return nullptr;
|
||||
|
||||
ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Module map file parser
|
||||
//----------------------------------------------------------------------------//
|
||||
|
@ -667,24 +667,17 @@ Module *Preprocessor::getModuleForLocation(SourceLocation Loc) {
|
||||
: HeaderInfo.lookupModule(getLangOpts().CurrentModule);
|
||||
}
|
||||
|
||||
Module *Preprocessor::getModuleContainingLocation(SourceLocation Loc) {
|
||||
return HeaderInfo.getModuleMap().inferModuleFromLocation(
|
||||
FullSourceLoc(Loc, SourceMgr));
|
||||
}
|
||||
|
||||
const FileEntry *
|
||||
Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
|
||||
Module *M,
|
||||
SourceLocation Loc) {
|
||||
assert(M && "no module to include");
|
||||
|
||||
// If we have a module import syntax, we shouldn't include a header to
|
||||
// make a particular module visible.
|
||||
if (getLangOpts().ObjC2)
|
||||
return nullptr;
|
||||
|
||||
// Figure out which module we'd want to import.
|
||||
Module *M = getModuleContainingLocation(Loc);
|
||||
if (!M)
|
||||
return nullptr;
|
||||
|
||||
Module *TopM = M->getTopLevelModule();
|
||||
Module *IncM = getModuleForLocation(IncLoc);
|
||||
|
||||
|
@ -731,7 +731,7 @@ Module *Preprocessor::LeaveSubmodule(bool ForPragma) {
|
||||
Module *LeavingMod = Info.M;
|
||||
SourceLocation ImportLoc = Info.ImportLoc;
|
||||
|
||||
if (!needModuleMacros() ||
|
||||
if (!needModuleMacros() ||
|
||||
(!getLangOpts().ModulesLocalVisibility &&
|
||||
LeavingMod->getTopLevelModuleName() != getLangOpts().CurrentModule)) {
|
||||
// If we don't need module macros, or this is not a module for which we
|
||||
@ -777,17 +777,6 @@ Module *Preprocessor::LeaveSubmodule(bool ForPragma) {
|
||||
for (auto *MD = Macro.getLatest(); MD != OldMD; MD = MD->getPrevious()) {
|
||||
assert(MD && "broken macro directive chain");
|
||||
|
||||
// Stop on macros defined in other submodules of this module that we
|
||||
// #included along the way. There's no point doing this if we're
|
||||
// tracking local submodule visibility, since there can be no such
|
||||
// directives in our list.
|
||||
if (!getLangOpts().ModulesLocalVisibility) {
|
||||
Module *Mod = getModuleContainingLocation(MD->getLocation());
|
||||
if (Mod != LeavingMod &&
|
||||
Mod->getTopLevelModule() == LeavingMod->getTopLevelModule())
|
||||
break;
|
||||
}
|
||||
|
||||
if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
|
||||
// The latest visibility directive for a name in a submodule affects
|
||||
// all the directives that come before it.
|
||||
@ -809,6 +798,13 @@ Module *Preprocessor::LeaveSubmodule(bool ForPragma) {
|
||||
if (Def || !Macro.getOverriddenMacros().empty())
|
||||
addModuleMacro(LeavingMod, II, Def,
|
||||
Macro.getOverriddenMacros(), IsNew);
|
||||
|
||||
if (!getLangOpts().ModulesLocalVisibility) {
|
||||
// This macro is exposed to the rest of this compilation as a
|
||||
// ModuleMacro; we don't need to track its MacroDirective any more.
|
||||
Macro.setLatest(nullptr);
|
||||
Macro.setOverriddenMacros(*this, {});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -731,19 +731,6 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
|
||||
ConsumeBrace();
|
||||
break;
|
||||
|
||||
case tok::code_completion:
|
||||
Toks.push_back(Tok);
|
||||
ConsumeCodeCompletionToken();
|
||||
break;
|
||||
|
||||
case tok::string_literal:
|
||||
case tok::wide_string_literal:
|
||||
case tok::utf8_string_literal:
|
||||
case tok::utf16_string_literal:
|
||||
case tok::utf32_string_literal:
|
||||
Toks.push_back(Tok);
|
||||
ConsumeStringToken();
|
||||
break;
|
||||
case tok::semi:
|
||||
if (StopAtSemi)
|
||||
return false;
|
||||
@ -751,7 +738,7 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
|
||||
default:
|
||||
// consume this token.
|
||||
Toks.push_back(Tok);
|
||||
ConsumeToken();
|
||||
ConsumeAnyToken(/*ConsumeCodeCompletionTok*/true);
|
||||
break;
|
||||
}
|
||||
isFirstTokenConsumed = false;
|
||||
|
@ -2989,7 +2989,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
}
|
||||
|
||||
DS.getTypeSpecScope() = SS;
|
||||
ConsumeToken(); // The C++ scope.
|
||||
ConsumeAnnotationToken(); // The C++ scope.
|
||||
assert(Tok.is(tok::annot_template_id) &&
|
||||
"ParseOptionalCXXScopeSpecifier not working");
|
||||
AnnotateTemplateIdTokenAsType();
|
||||
@ -2998,7 +2998,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
|
||||
if (Next.is(tok::annot_typename)) {
|
||||
DS.getTypeSpecScope() = SS;
|
||||
ConsumeToken(); // The C++ scope.
|
||||
ConsumeAnnotationToken(); // The C++ scope.
|
||||
if (Tok.getAnnotationValue()) {
|
||||
ParsedType T = getTypeAnnotation(Tok);
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
|
||||
@ -3010,7 +3010,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
else
|
||||
DS.SetTypeSpecError();
|
||||
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
|
||||
ConsumeToken(); // The typename
|
||||
ConsumeAnnotationToken(); // The typename
|
||||
}
|
||||
|
||||
if (Next.isNot(tok::identifier))
|
||||
@ -3037,7 +3037,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
// C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the
|
||||
// typename.
|
||||
if (!TypeRep) {
|
||||
ConsumeToken(); // Eat the scope spec so the identifier is current.
|
||||
// Eat the scope spec so the identifier is current.
|
||||
ConsumeAnnotationToken();
|
||||
ParsedAttributesWithRange Attrs(AttrFactory);
|
||||
if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) {
|
||||
if (!Attrs.empty()) {
|
||||
@ -3050,7 +3051,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
}
|
||||
|
||||
DS.getTypeSpecScope() = SS;
|
||||
ConsumeToken(); // The C++ scope.
|
||||
ConsumeAnnotationToken(); // The C++ scope.
|
||||
|
||||
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
|
||||
DiagID, TypeRep, Policy);
|
||||
@ -3080,7 +3081,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
break;
|
||||
|
||||
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
|
||||
ConsumeToken(); // The typename
|
||||
ConsumeAnnotationToken(); // The typename
|
||||
|
||||
continue;
|
||||
}
|
||||
@ -4836,10 +4837,12 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) {
|
||||
}
|
||||
|
||||
// Parse the constructor name.
|
||||
if (Tok.isOneOf(tok::identifier, tok::annot_template_id)) {
|
||||
if (Tok.is(tok::identifier)) {
|
||||
// We already know that we have a constructor name; just consume
|
||||
// the token.
|
||||
ConsumeToken();
|
||||
} else if (Tok.is(tok::annot_template_id)) {
|
||||
ConsumeAnnotationToken();
|
||||
} else {
|
||||
TPA.Revert();
|
||||
return false;
|
||||
@ -4895,7 +4898,7 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) {
|
||||
// be a constructor declaration with an invalid argument type. Keep
|
||||
// looking.
|
||||
if (Tok.is(tok::annot_cxxscope))
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
ConsumeToken();
|
||||
|
||||
// If this is not a constructor, we must be parsing a declarator,
|
||||
@ -5539,11 +5542,28 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||
D.SetRangeEnd(Tok.getLocation());
|
||||
ConsumeToken();
|
||||
goto PastIdentifier;
|
||||
} else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) {
|
||||
// A virt-specifier isn't treated as an identifier if it appears after a
|
||||
// trailing-return-type.
|
||||
if (D.getContext() != Declarator::TrailingReturnContext ||
|
||||
!isCXX11VirtSpecifier(Tok)) {
|
||||
} else if (Tok.is(tok::identifier) && !D.mayHaveIdentifier()) {
|
||||
// We're not allowed an identifier here, but we got one. Try to figure out
|
||||
// if the user was trying to attach a name to the type, or whether the name
|
||||
// is some unrelated trailing syntax.
|
||||
bool DiagnoseIdentifier = false;
|
||||
if (D.hasGroupingParens())
|
||||
// An identifier within parens is unlikely to be intended to be anything
|
||||
// other than a name being "declared".
|
||||
DiagnoseIdentifier = true;
|
||||
else if (D.getContext() == Declarator::TemplateTypeArgContext)
|
||||
// T<int N> is an accidental identifier; T<int N indicates a missing '>'.
|
||||
DiagnoseIdentifier =
|
||||
NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater);
|
||||
else if (D.getContext() == Declarator::AliasDeclContext ||
|
||||
D.getContext() == Declarator::AliasTemplateContext)
|
||||
// The most likely error is that the ';' was forgotten.
|
||||
DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
|
||||
else if (D.getContext() == Declarator::TrailingReturnContext &&
|
||||
!isCXX11VirtSpecifier(Tok))
|
||||
DiagnoseIdentifier = NextToken().isOneOf(
|
||||
tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);
|
||||
if (DiagnoseIdentifier) {
|
||||
Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
|
||||
<< FixItHint::CreateRemoval(Tok.getLocation());
|
||||
D.SetIdentifier(nullptr, Tok.getLocation());
|
||||
|
@ -901,7 +901,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
|
||||
if (Tok.is(tok::annot_decltype)) {
|
||||
Result = getExprAnnotation(Tok);
|
||||
EndLoc = Tok.getAnnotationEndLoc();
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
if (Result.isInvalid()) {
|
||||
DS.SetTypeSpecError();
|
||||
return EndLoc;
|
||||
@ -1105,7 +1105,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
|
||||
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
|
||||
ParsedType Type = getTypeAnnotation(Tok);
|
||||
EndLocation = Tok.getAnnotationEndLoc();
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
|
||||
if (Type)
|
||||
return Type;
|
||||
@ -1162,7 +1162,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
|
||||
// return.
|
||||
EndLocation = Tok.getAnnotationEndLoc();
|
||||
ParsedType Type = getTypeAnnotation(Tok);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return Type;
|
||||
}
|
||||
|
||||
@ -1565,7 +1565,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
||||
}
|
||||
} else if (Tok.is(tok::annot_template_id)) {
|
||||
TemplateId = takeTemplateIdAnnotation(Tok);
|
||||
NameLoc = ConsumeToken();
|
||||
NameLoc = ConsumeAnnotationToken();
|
||||
|
||||
if (TemplateId->Kind != TNK_Type_template &&
|
||||
TemplateId->Kind != TNK_Dependent_template_name) {
|
||||
@ -3405,38 +3405,41 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
|
||||
// parse '::'[opt] nested-name-specifier[opt]
|
||||
CXXScopeSpec SS;
|
||||
ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false);
|
||||
|
||||
// : identifier
|
||||
IdentifierInfo *II = nullptr;
|
||||
SourceLocation IdLoc = Tok.getLocation();
|
||||
// : declype(...)
|
||||
DeclSpec DS(AttrFactory);
|
||||
// : template_name<...>
|
||||
ParsedType TemplateTypeTy;
|
||||
if (Tok.is(tok::annot_template_id)) {
|
||||
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
|
||||
if (TemplateId->Kind == TNK_Type_template ||
|
||||
TemplateId->Kind == TNK_Dependent_template_name) {
|
||||
|
||||
if (Tok.is(tok::identifier)) {
|
||||
// Get the identifier. This may be a member name or a class name,
|
||||
// but we'll let the semantic analysis determine which it is.
|
||||
II = Tok.getIdentifierInfo();
|
||||
ConsumeToken();
|
||||
} else if (Tok.is(tok::annot_decltype)) {
|
||||
// Get the decltype expression, if there is one.
|
||||
// Uses of decltype will already have been converted to annot_decltype by
|
||||
// ParseOptionalCXXScopeSpecifier at this point.
|
||||
// FIXME: Can we get here with a scope specifier?
|
||||
ParseDecltypeSpecifier(DS);
|
||||
} else {
|
||||
TemplateIdAnnotation *TemplateId = Tok.is(tok::annot_template_id)
|
||||
? takeTemplateIdAnnotation(Tok)
|
||||
: nullptr;
|
||||
if (TemplateId && (TemplateId->Kind == TNK_Type_template ||
|
||||
TemplateId->Kind == TNK_Dependent_template_name)) {
|
||||
AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
|
||||
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
|
||||
TemplateTypeTy = getTypeAnnotation(Tok);
|
||||
ConsumeAnnotationToken();
|
||||
} else {
|
||||
Diag(Tok, diag::err_expected_member_or_base_name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Uses of decltype will already have been converted to annot_decltype by
|
||||
// ParseOptionalCXXScopeSpecifier at this point.
|
||||
if (!TemplateTypeTy && Tok.isNot(tok::identifier)
|
||||
&& Tok.isNot(tok::annot_decltype)) {
|
||||
Diag(Tok, diag::err_expected_member_or_base_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
IdentifierInfo *II = nullptr;
|
||||
DeclSpec DS(AttrFactory);
|
||||
SourceLocation IdLoc = Tok.getLocation();
|
||||
if (Tok.is(tok::annot_decltype)) {
|
||||
// Get the decltype expression, if there is one.
|
||||
ParseDecltypeSpecifier(DS);
|
||||
} else {
|
||||
if (Tok.is(tok::identifier))
|
||||
// Get the identifier. This may be a member name or a class name,
|
||||
// but we'll let the semantic analysis determine which it is.
|
||||
II = Tok.getIdentifierInfo();
|
||||
ConsumeToken();
|
||||
}
|
||||
|
||||
|
||||
// Parse the '('.
|
||||
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
|
||||
|
@ -192,6 +192,16 @@ Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
|
||||
return ParseRHSOfBinaryExpression(R, prec::Assignment);
|
||||
}
|
||||
|
||||
ExprResult
|
||||
Parser::ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast) {
|
||||
assert(Actions.ExprEvalContexts.back().Context ==
|
||||
Sema::ExpressionEvaluationContext::ConstantEvaluated &&
|
||||
"Call this function only if your ExpressionEvaluationContext is "
|
||||
"already ConstantEvaluated");
|
||||
ExprResult LHS(ParseCastExpression(false, false, isTypeCast));
|
||||
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
|
||||
return Actions.ActOnConstantExpression(Res);
|
||||
}
|
||||
|
||||
ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
|
||||
// C++03 [basic.def.odr]p2:
|
||||
@ -200,10 +210,7 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
|
||||
// C++98 and C++11 have no such rule, but this is only a defect in C++98.
|
||||
EnterExpressionEvaluationContext ConstantEvaluated(
|
||||
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
|
||||
|
||||
ExprResult LHS(ParseCastExpression(false, false, isTypeCast));
|
||||
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
|
||||
return Actions.ActOnConstantExpression(Res);
|
||||
return ParseConstantExpressionInExprEvalContext(isTypeCast);
|
||||
}
|
||||
|
||||
/// \brief Parse a constraint-expression.
|
||||
@ -804,7 +811,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
||||
case tok::annot_primary_expr:
|
||||
assert(Res.get() == nullptr && "Stray primary-expression annotation?");
|
||||
Res = getExprAnnotation(Tok);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
break;
|
||||
|
||||
case tok::kw___super:
|
||||
@ -1199,7 +1206,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
||||
if (Ty.isInvalid())
|
||||
break;
|
||||
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
|
||||
Ty.get(), nullptr);
|
||||
break;
|
||||
|
@ -160,7 +160,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
||||
Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
|
||||
Tok.getAnnotationRange(),
|
||||
SS);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -346,7 +346,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
||||
*LastII = TemplateId->Name;
|
||||
|
||||
// Consume the template-id token.
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
|
||||
assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
|
||||
SourceLocation CCLoc = ConsumeToken();
|
||||
@ -920,7 +920,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
|
||||
PP.AnnotateCachedTokens(Tok);
|
||||
|
||||
// Consume the annotated initializer.
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
}
|
||||
}
|
||||
} else
|
||||
@ -1528,7 +1528,7 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
|
||||
// store it in the pseudo-dtor node (to be used when instantiating it).
|
||||
FirstTypeName.setTemplateId(
|
||||
(TemplateIdAnnotation *)Tok.getAnnotationValue());
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
|
||||
CCLoc = ConsumeToken();
|
||||
} else {
|
||||
@ -1882,7 +1882,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
|
||||
DS.SetTypeSpecError();
|
||||
|
||||
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
|
||||
DS.Finish(Actions, Policy);
|
||||
return;
|
||||
@ -1951,11 +1951,8 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
|
||||
DS.Finish(Actions, Policy);
|
||||
return;
|
||||
}
|
||||
if (Tok.is(tok::annot_typename))
|
||||
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
|
||||
else
|
||||
DS.SetRangeEnd(Tok.getLocation());
|
||||
ConsumeToken();
|
||||
ConsumeAnyToken();
|
||||
DS.SetRangeEnd(PrevTokLocation);
|
||||
DS.Finish(Actions, Policy);
|
||||
}
|
||||
|
||||
@ -2529,12 +2526,12 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
||||
/*NontrivialTypeSourceInfo=*/true);
|
||||
Result.setConstructorName(Ty, TemplateId->TemplateNameLoc,
|
||||
TemplateId->RAngleLoc);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return false;
|
||||
}
|
||||
|
||||
Result.setConstructorTemplateId(TemplateId);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2542,7 +2539,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
||||
// our unqualified-id.
|
||||
Result.setTemplateId(TemplateId);
|
||||
TemplateKWLoc = TemplateId->TemplateKWLoc;
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -532,7 +532,7 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
|
||||
ConsumeAnyToken();
|
||||
}
|
||||
// Skip the last annot_pragma_openmp_end.
|
||||
SourceLocation EndLoc = ConsumeToken();
|
||||
SourceLocation EndLoc = ConsumeAnnotationToken();
|
||||
if (!IsError) {
|
||||
return Actions.ActOnOpenMPDeclareSimdDirective(
|
||||
Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
|
||||
@ -562,7 +562,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
|
||||
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
||||
|
||||
SourceLocation Loc = ConsumeToken();
|
||||
SourceLocation Loc = ConsumeAnnotationToken();
|
||||
auto DKind = ParseOpenMPDirectiveKind(*this);
|
||||
|
||||
switch (DKind) {
|
||||
@ -578,7 +578,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
||||
}
|
||||
// Skip the last annot_pragma_openmp_end.
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return Actions.ActOnOpenMPThreadprivateDirective(Loc,
|
||||
Helper.getIdentifiers());
|
||||
}
|
||||
@ -596,7 +596,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||
ConsumeAnyToken();
|
||||
}
|
||||
// Skip the last annot_pragma_openmp_end.
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return Res;
|
||||
}
|
||||
break;
|
||||
@ -686,7 +686,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||
ParseExternalDeclaration(attrs);
|
||||
if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
|
||||
TentativeParsingAction TPA(*this);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
DKind = ParseOpenMPDirectiveKind(*this);
|
||||
if (DKind != OMPD_end_declare_target)
|
||||
TPA.Revert();
|
||||
@ -814,7 +814,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
|
||||
FirstClauses(OMPC_unknown + 1);
|
||||
unsigned ScopeFlags =
|
||||
Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
|
||||
SourceLocation Loc = ConsumeToken(), EndLoc;
|
||||
SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
|
||||
auto DKind = ParseOpenMPDirectiveKind(*this);
|
||||
OpenMPDirectiveKind CancelRegion = OMPD_unknown;
|
||||
// Name of critical directive.
|
||||
@ -973,7 +973,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
|
||||
// End location of the directive.
|
||||
EndLoc = Tok.getLocation();
|
||||
// Consume final annot_pragma_openmp_end.
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
|
||||
// OpenMP [2.13.8, ordered Construct, Syntax]
|
||||
// If the depend clause is specified, the ordered construct is a stand-alone
|
||||
|
@ -382,7 +382,7 @@ void Parser::resetPragmaHandlers() {
|
||||
/// annot_pragma_unused 'x' annot_pragma_unused 'y'
|
||||
void Parser::HandlePragmaUnused() {
|
||||
assert(Tok.is(tok::annot_pragma_unused));
|
||||
SourceLocation UnusedLoc = ConsumeToken();
|
||||
SourceLocation UnusedLoc = ConsumeAnnotationToken();
|
||||
Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
|
||||
ConsumeToken(); // The argument token.
|
||||
}
|
||||
@ -391,7 +391,7 @@ void Parser::HandlePragmaVisibility() {
|
||||
assert(Tok.is(tok::annot_pragma_vis));
|
||||
const IdentifierInfo *VisType =
|
||||
static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
|
||||
SourceLocation VisLoc = ConsumeToken();
|
||||
SourceLocation VisLoc = ConsumeAnnotationToken();
|
||||
Actions.ActOnPragmaVisibility(VisType, VisLoc);
|
||||
}
|
||||
|
||||
@ -407,7 +407,7 @@ void Parser::HandlePragmaPack() {
|
||||
assert(Tok.is(tok::annot_pragma_pack));
|
||||
PragmaPackInfo *Info =
|
||||
static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
|
||||
SourceLocation PragmaLoc = ConsumeToken();
|
||||
SourceLocation PragmaLoc = ConsumeAnnotationToken();
|
||||
ExprResult Alignment;
|
||||
if (Info->Alignment.is(tok::numeric_constant)) {
|
||||
Alignment = Actions.ActOnNumericConstant(Info->Alignment);
|
||||
@ -423,7 +423,7 @@ void Parser::HandlePragmaMSStruct() {
|
||||
PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
|
||||
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
|
||||
Actions.ActOnPragmaMSStruct(Kind);
|
||||
ConsumeToken(); // The annotation token.
|
||||
ConsumeAnnotationToken();
|
||||
}
|
||||
|
||||
void Parser::HandlePragmaAlign() {
|
||||
@ -431,7 +431,7 @@ void Parser::HandlePragmaAlign() {
|
||||
Sema::PragmaOptionsAlignKind Kind =
|
||||
static_cast<Sema::PragmaOptionsAlignKind>(
|
||||
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
|
||||
SourceLocation PragmaLoc = ConsumeToken();
|
||||
SourceLocation PragmaLoc = ConsumeAnnotationToken();
|
||||
Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
|
||||
}
|
||||
|
||||
@ -440,12 +440,12 @@ void Parser::HandlePragmaDump() {
|
||||
IdentifierInfo *II =
|
||||
reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
|
||||
Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
}
|
||||
|
||||
void Parser::HandlePragmaWeak() {
|
||||
assert(Tok.is(tok::annot_pragma_weak));
|
||||
SourceLocation PragmaLoc = ConsumeToken();
|
||||
SourceLocation PragmaLoc = ConsumeAnnotationToken();
|
||||
Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
|
||||
Tok.getLocation());
|
||||
ConsumeToken(); // The weak name.
|
||||
@ -453,7 +453,7 @@ void Parser::HandlePragmaWeak() {
|
||||
|
||||
void Parser::HandlePragmaWeakAlias() {
|
||||
assert(Tok.is(tok::annot_pragma_weakalias));
|
||||
SourceLocation PragmaLoc = ConsumeToken();
|
||||
SourceLocation PragmaLoc = ConsumeAnnotationToken();
|
||||
IdentifierInfo *WeakName = Tok.getIdentifierInfo();
|
||||
SourceLocation WeakNameLoc = Tok.getLocation();
|
||||
ConsumeToken();
|
||||
@ -467,7 +467,7 @@ void Parser::HandlePragmaWeakAlias() {
|
||||
|
||||
void Parser::HandlePragmaRedefineExtname() {
|
||||
assert(Tok.is(tok::annot_pragma_redefine_extname));
|
||||
SourceLocation RedefLoc = ConsumeToken();
|
||||
SourceLocation RedefLoc = ConsumeAnnotationToken();
|
||||
IdentifierInfo *RedefName = Tok.getIdentifierInfo();
|
||||
SourceLocation RedefNameLoc = Tok.getLocation();
|
||||
ConsumeToken();
|
||||
@ -498,13 +498,13 @@ void Parser::HandlePragmaFPContract() {
|
||||
}
|
||||
|
||||
Actions.ActOnPragmaFPContract(FPC);
|
||||
ConsumeToken(); // The annotation token.
|
||||
ConsumeAnnotationToken();
|
||||
}
|
||||
|
||||
StmtResult Parser::HandlePragmaCaptured()
|
||||
{
|
||||
assert(Tok.is(tok::annot_pragma_captured));
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
|
||||
if (Tok.isNot(tok::l_brace)) {
|
||||
PP.Diag(Tok, diag::err_expected) << tok::l_brace;
|
||||
@ -541,7 +541,7 @@ void Parser::HandlePragmaOpenCLExtension() {
|
||||
auto State = Data->second;
|
||||
auto Ident = Data->first;
|
||||
SourceLocation NameLoc = Tok.getLocation();
|
||||
ConsumeToken(); // The annotation token.
|
||||
ConsumeAnnotationToken();
|
||||
|
||||
auto &Opt = Actions.getOpenCLOptions();
|
||||
auto Name = Ident->getName();
|
||||
@ -580,7 +580,7 @@ void Parser::HandlePragmaMSPointersToMembers() {
|
||||
LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
|
||||
static_cast<LangOptions::PragmaMSPointersToMembersKind>(
|
||||
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
|
||||
SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
|
||||
SourceLocation PragmaLoc = ConsumeAnnotationToken();
|
||||
Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
|
||||
}
|
||||
|
||||
@ -590,7 +590,7 @@ void Parser::HandlePragmaMSVtorDisp() {
|
||||
Sema::PragmaMsStackAction Action =
|
||||
static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
|
||||
MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
|
||||
SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
|
||||
SourceLocation PragmaLoc = ConsumeAnnotationToken();
|
||||
Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
|
||||
}
|
||||
|
||||
@ -600,7 +600,7 @@ void Parser::HandlePragmaMSPragma() {
|
||||
auto TheTokens =
|
||||
(std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
|
||||
PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
|
||||
SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
|
||||
SourceLocation PragmaLocation = ConsumeAnnotationToken();
|
||||
assert(Tok.isAnyIdentifier());
|
||||
StringRef PragmaName = Tok.getIdentifierInfo()->getName();
|
||||
PP.Lex(Tok); // pragma kind
|
||||
@ -896,7 +896,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
|
||||
bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
|
||||
bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
|
||||
if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
|
||||
ConsumeToken(); // The annotation token.
|
||||
ConsumeAnnotationToken();
|
||||
Hint.Range = Info->PragmaName.getLocation();
|
||||
return true;
|
||||
}
|
||||
@ -923,7 +923,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
|
||||
bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
|
||||
// Verify loop hint has an argument.
|
||||
if (Toks[0].is(tok::eof)) {
|
||||
ConsumeToken(); // The annotation token.
|
||||
ConsumeAnnotationToken();
|
||||
Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
|
||||
<< /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
|
||||
<< /*AssumeSafetyKeyword=*/AssumeSafetyArg;
|
||||
@ -932,7 +932,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
|
||||
|
||||
// Validate the argument.
|
||||
if (StateOption) {
|
||||
ConsumeToken(); // The annotation token.
|
||||
ConsumeAnnotationToken();
|
||||
SourceLocation StateLoc = Toks[0].getLocation();
|
||||
IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
|
||||
|
||||
@ -955,7 +955,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
|
||||
} else {
|
||||
// Enter constant expression including eof terminator into token stream.
|
||||
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
|
||||
ConsumeToken(); // The annotation token.
|
||||
ConsumeAnnotationToken();
|
||||
|
||||
ExprResult R = ParseConstantExpression();
|
||||
|
||||
@ -1241,7 +1241,7 @@ void Parser::HandlePragmaAttribute() {
|
||||
SourceLocation PragmaLoc = Tok.getLocation();
|
||||
auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
|
||||
if (Info->Action == PragmaAttributeInfo::Pop) {
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
Actions.ActOnPragmaAttributePop(PragmaLoc);
|
||||
return;
|
||||
}
|
||||
@ -1249,7 +1249,7 @@ void Parser::HandlePragmaAttribute() {
|
||||
assert(Info->Action == PragmaAttributeInfo::Push &&
|
||||
"Unexpected #pragma attribute command");
|
||||
PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
|
||||
ParsedAttributes &Attrs = Info->Attributes;
|
||||
Attrs.clearListOnly();
|
||||
@ -2526,7 +2526,7 @@ void Parser::HandlePragmaFP() {
|
||||
}
|
||||
|
||||
Actions.ActOnPragmaFPContract(FPC);
|
||||
ConsumeToken(); // The annotation token.
|
||||
ConsumeAnnotationToken();
|
||||
}
|
||||
|
||||
/// \brief Parses loop or unroll pragma hint value and fills in Info.
|
||||
|
@ -338,13 +338,13 @@ Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
|
||||
case tok::annot_pragma_fp_contract:
|
||||
ProhibitAttributes(Attrs);
|
||||
Diag(Tok, diag::err_pragma_fp_contract_scope);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return StmtError();
|
||||
|
||||
case tok::annot_pragma_fp:
|
||||
ProhibitAttributes(Attrs);
|
||||
Diag(Tok, diag::err_pragma_fp_scope);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return StmtError();
|
||||
|
||||
case tok::annot_pragma_opencl_extension:
|
||||
|
@ -1186,7 +1186,13 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
|
||||
// expression is resolved to a type-id, regardless of the form of
|
||||
// the corresponding template-parameter.
|
||||
//
|
||||
// Therefore, we initially try to parse a type-id.
|
||||
// Therefore, we initially try to parse a type-id - and isCXXTypeId might look
|
||||
// up and annotate an identifier as an id-expression during disambiguation,
|
||||
// so enter the appropriate context for a constant expression template
|
||||
// argument before trying to disambiguate.
|
||||
|
||||
EnterExpressionEvaluationContext EnterConstantEvaluated(
|
||||
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
|
||||
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr,
|
||||
@ -1216,7 +1222,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
|
||||
|
||||
// Parse a non-type template argument.
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
ExprResult ExprArg = ParseConstantExpression(MaybeTypeCast);
|
||||
ExprResult ExprArg = ParseConstantExpressionInExprEvalContext(MaybeTypeCast);
|
||||
if (ExprArg.isInvalid() || !ExprArg.get())
|
||||
return ParsedTemplateArgument();
|
||||
|
||||
@ -1234,7 +1240,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
|
||||
} Tentative(*this);
|
||||
|
||||
while (Skip) {
|
||||
ConsumeToken();
|
||||
ConsumeAnyToken();
|
||||
--Skip;
|
||||
}
|
||||
|
||||
@ -1248,7 +1254,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
|
||||
|
||||
// See whether we have declaration specifiers, which indicate a type.
|
||||
while (isCXXDeclarationSpecifier() == TPResult::True)
|
||||
ConsumeToken();
|
||||
ConsumeAnyToken();
|
||||
|
||||
// If we have a '>' or a ',' then this is a template argument list.
|
||||
return Tok.isOneOf(tok::greater, tok::comma);
|
||||
@ -1262,9 +1268,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
|
||||
/// template-argument-list ',' template-argument
|
||||
bool
|
||||
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
|
||||
// Template argument lists are constant-evaluation contexts.
|
||||
EnterExpressionEvaluationContext EvalContext(
|
||||
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
|
||||
|
||||
ColonProtectionRAIIObject ColonProtection(*this, false);
|
||||
|
||||
do {
|
||||
|
@ -208,17 +208,20 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
|
||||
TryAnnotateCXXScopeToken())
|
||||
return TPResult::Error;
|
||||
if (Tok.is(tok::annot_cxxscope))
|
||||
ConsumeAnnotationToken();
|
||||
if (Tok.is(tok::identifier))
|
||||
ConsumeToken();
|
||||
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
|
||||
else if (Tok.is(tok::annot_template_id))
|
||||
ConsumeAnnotationToken();
|
||||
else
|
||||
return TPResult::Error;
|
||||
ConsumeToken();
|
||||
break;
|
||||
|
||||
case tok::annot_cxxscope:
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
// Fall through.
|
||||
default:
|
||||
ConsumeToken();
|
||||
ConsumeAnyToken();
|
||||
|
||||
if (getLangOpts().ObjC1 && Tok.is(tok::less))
|
||||
return TryParseProtocolQualifiers();
|
||||
@ -478,10 +481,10 @@ Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement) {
|
||||
/// the corresponding ')'. If the context is
|
||||
/// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
|
||||
/// before this template argument, and will cease lookahead when we
|
||||
/// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
|
||||
/// and false for an expression. If during the disambiguation
|
||||
/// process a parsing error is encountered, the function returns
|
||||
/// true to let the declaration parsing code handle it.
|
||||
/// hit a '>', '>>' (in C++0x), or ','; or, in C++0x, an ellipsis immediately
|
||||
/// preceding such. Returns true for a type-id and false for an expression.
|
||||
/// If during the disambiguation process a parsing error is encountered,
|
||||
/// the function returns true to let the declaration parsing code handle it.
|
||||
///
|
||||
/// type-id:
|
||||
/// type-specifier-seq abstract-declarator[opt]
|
||||
@ -530,10 +533,15 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
|
||||
|
||||
// We are supposed to be inside a template argument, so if after
|
||||
// the abstract declarator we encounter a '>', '>>' (in C++0x), or
|
||||
// ',', this is a type-id. Otherwise, it's an expression.
|
||||
// ','; or, in C++0x, an ellipsis immediately preceding such, this
|
||||
// is a type-id. Otherwise, it's an expression.
|
||||
} else if (Context == TypeIdAsTemplateArgument &&
|
||||
(Tok.isOneOf(tok::greater, tok::comma) ||
|
||||
(getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) {
|
||||
(getLangOpts().CPlusPlus11 &&
|
||||
(Tok.is(tok::greatergreater) ||
|
||||
(Tok.is(tok::ellipsis) &&
|
||||
NextToken().isOneOf(tok::greater, tok::greatergreater,
|
||||
tok::comma)))))) {
|
||||
TPR = TPResult::True;
|
||||
isAmbiguous = true;
|
||||
|
||||
@ -706,7 +714,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() {
|
||||
if (Tok.isOneOf(tok::star, tok::amp, tok::caret, tok::ampamp) ||
|
||||
(Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
|
||||
// ptr-operator
|
||||
ConsumeToken();
|
||||
ConsumeAnyToken();
|
||||
while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict,
|
||||
tok::kw__Nonnull, tok::kw__Nullable,
|
||||
tok::kw__Null_unspecified))
|
||||
@ -826,14 +834,14 @@ Parser::TPResult Parser::TryParseOperatorId() {
|
||||
/// abstract-declarator:
|
||||
/// ptr-operator abstract-declarator[opt]
|
||||
/// direct-abstract-declarator
|
||||
/// ...
|
||||
///
|
||||
/// direct-abstract-declarator:
|
||||
/// direct-abstract-declarator[opt]
|
||||
/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
|
||||
/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
|
||||
/// exception-specification[opt]
|
||||
/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
|
||||
/// '(' abstract-declarator ')'
|
||||
/// [C++0x] ...
|
||||
///
|
||||
/// ptr-operator:
|
||||
/// '*' cv-qualifier-seq[opt]
|
||||
@ -883,7 +891,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
|
||||
mayHaveIdentifier) {
|
||||
// declarator-id
|
||||
if (Tok.is(tok::annot_cxxscope))
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
else if (Tok.is(tok::identifier))
|
||||
TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());
|
||||
if (Tok.is(tok::kw_operator)) {
|
||||
@ -925,10 +933,6 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
|
||||
while (1) {
|
||||
TPResult TPR(TPResult::Ambiguous);
|
||||
|
||||
// abstract-declarator: ...
|
||||
if (Tok.is(tok::ellipsis))
|
||||
ConsumeToken();
|
||||
|
||||
if (Tok.is(tok::l_paren)) {
|
||||
// Check whether we have a function declarator or a possible ctor-style
|
||||
// initializer that follows the declarator. Note that ctor-style
|
||||
@ -1399,7 +1403,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
|
||||
SS);
|
||||
if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {
|
||||
RevertingTentativeParsingAction PA(*this);
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
ConsumeToken();
|
||||
bool isIdentifier = Tok.is(tok::identifier);
|
||||
TPResult TPR = TPResult::False;
|
||||
@ -1471,7 +1475,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
|
||||
if (getLangOpts().ObjC1 && NextToken().is(tok::less)) {
|
||||
// Tentatively parse the protocol qualifiers.
|
||||
RevertingTentativeParsingAction PA(*this);
|
||||
ConsumeToken(); // The type token
|
||||
ConsumeAnyToken(); // The type token
|
||||
|
||||
TPResult TPR = TryParseProtocolQualifiers();
|
||||
bool isFollowedByParen = Tok.is(tok::l_paren);
|
||||
|
@ -337,21 +337,13 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
|
||||
ConsumeBrace();
|
||||
break;
|
||||
|
||||
case tok::string_literal:
|
||||
case tok::wide_string_literal:
|
||||
case tok::utf8_string_literal:
|
||||
case tok::utf16_string_literal:
|
||||
case tok::utf32_string_literal:
|
||||
ConsumeStringToken();
|
||||
break;
|
||||
|
||||
case tok::semi:
|
||||
if (HasFlagsSet(Flags, StopAtSemi))
|
||||
return false;
|
||||
// FALL THROUGH.
|
||||
default:
|
||||
// Skip this token.
|
||||
ConsumeToken();
|
||||
ConsumeAnyToken();
|
||||
break;
|
||||
}
|
||||
isFirstTokenSkipped = false;
|
||||
@ -578,19 +570,19 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
|
||||
Actions.ActOnModuleInclude(Tok.getLocation(),
|
||||
reinterpret_cast<Module *>(
|
||||
Tok.getAnnotationValue()));
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return false;
|
||||
|
||||
case tok::annot_module_begin:
|
||||
Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast<Module *>(
|
||||
Tok.getAnnotationValue()));
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return false;
|
||||
|
||||
case tok::annot_module_end:
|
||||
Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast<Module *>(
|
||||
Tok.getAnnotationValue()));
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
return false;
|
||||
|
||||
case tok::annot_pragma_attribute:
|
||||
@ -2169,7 +2161,7 @@ bool Parser::parseMisplacedModuleImport() {
|
||||
Actions.ActOnModuleEnd(Tok.getLocation(),
|
||||
reinterpret_cast<Module *>(
|
||||
Tok.getAnnotationValue()));
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
continue;
|
||||
}
|
||||
// Inform caller that recovery failed, the error must be handled at upper
|
||||
@ -2181,7 +2173,7 @@ bool Parser::parseMisplacedModuleImport() {
|
||||
Actions.ActOnModuleBegin(Tok.getLocation(),
|
||||
reinterpret_cast<Module *>(
|
||||
Tok.getAnnotationValue()));
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
++MisplacedModuleBeginCount;
|
||||
continue;
|
||||
case tok::annot_module_include:
|
||||
@ -2190,7 +2182,7 @@ bool Parser::parseMisplacedModuleImport() {
|
||||
Actions.ActOnModuleInclude(Tok.getLocation(),
|
||||
reinterpret_cast<Module *>(
|
||||
Tok.getAnnotationValue()));
|
||||
ConsumeToken();
|
||||
ConsumeAnnotationToken();
|
||||
// If there is another module import, process it.
|
||||
continue;
|
||||
default:
|
||||
|
@ -2021,7 +2021,7 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
|
||||
Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef)
|
||||
<< Kind << NewType;
|
||||
if (Old->getLocation().isValid())
|
||||
notePreviousDefinition(Old->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(Old, New->getLocation());
|
||||
New->setInvalidDecl();
|
||||
return true;
|
||||
}
|
||||
@ -2034,7 +2034,7 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
|
||||
Diag(New->getLocation(), diag::err_redefinition_different_typedef)
|
||||
<< Kind << NewType << OldType;
|
||||
if (Old->getLocation().isValid())
|
||||
notePreviousDefinition(Old->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(Old, New->getLocation());
|
||||
New->setInvalidDecl();
|
||||
return true;
|
||||
}
|
||||
@ -2101,7 +2101,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
|
||||
|
||||
NamedDecl *OldD = OldDecls.getRepresentativeDecl();
|
||||
if (OldD->getLocation().isValid())
|
||||
notePreviousDefinition(OldD->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(OldD, New->getLocation());
|
||||
|
||||
return New->setInvalidDecl();
|
||||
}
|
||||
@ -2193,7 +2193,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
|
||||
|
||||
Diag(New->getLocation(), diag::err_redefinition)
|
||||
<< New->getDeclName();
|
||||
notePreviousDefinition(Old->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(Old, New->getLocation());
|
||||
return New->setInvalidDecl();
|
||||
}
|
||||
|
||||
@ -2214,7 +2214,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
|
||||
|
||||
Diag(New->getLocation(), diag::ext_redefinition_of_typedef)
|
||||
<< New->getDeclName();
|
||||
notePreviousDefinition(Old->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(Old, New->getLocation());
|
||||
}
|
||||
|
||||
/// DeclhasAttr - returns true if decl Declaration already has the target
|
||||
@ -2448,7 +2448,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
|
||||
return false;
|
||||
}
|
||||
|
||||
static const Decl *getDefinition(const Decl *D) {
|
||||
static const NamedDecl *getDefinition(const Decl *D) {
|
||||
if (const TagDecl *TD = dyn_cast<TagDecl>(D))
|
||||
return TD->getDefinition();
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||
@ -2475,7 +2475,7 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
|
||||
if (!New->hasAttrs())
|
||||
return;
|
||||
|
||||
const Decl *Def = getDefinition(Old);
|
||||
const NamedDecl *Def = getDefinition(Old);
|
||||
if (!Def || Def == New)
|
||||
return;
|
||||
|
||||
@ -2502,7 +2502,7 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
|
||||
: diag::err_redefinition;
|
||||
S.Diag(VD->getLocation(), Diag) << VD->getDeclName();
|
||||
if (Diag == diag::err_redefinition)
|
||||
S.notePreviousDefinition(Def->getLocation(), VD->getLocation());
|
||||
S.notePreviousDefinition(Def, VD->getLocation());
|
||||
else
|
||||
S.Diag(Def->getLocation(), diag::note_previous_definition);
|
||||
VD->setInvalidDecl();
|
||||
@ -2891,7 +2891,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
|
||||
} else {
|
||||
Diag(New->getLocation(), diag::err_redefinition_different_kind)
|
||||
<< New->getDeclName();
|
||||
notePreviousDefinition(OldD->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(OldD, New->getLocation());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2928,7 +2928,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
|
||||
!Old->hasAttr<InternalLinkageAttr>()) {
|
||||
Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)
|
||||
<< New->getDeclName();
|
||||
notePreviousDefinition(Old->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(Old, New->getLocation());
|
||||
New->dropAttr<InternalLinkageAttr>();
|
||||
}
|
||||
|
||||
@ -3657,7 +3657,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||
if (!Old) {
|
||||
Diag(New->getLocation(), diag::err_redefinition_different_kind)
|
||||
<< New->getDeclName();
|
||||
notePreviousDefinition(Previous.getRepresentativeDecl()->getLocation(),
|
||||
notePreviousDefinition(Previous.getRepresentativeDecl(),
|
||||
New->getLocation());
|
||||
return New->setInvalidDecl();
|
||||
}
|
||||
@ -3687,7 +3687,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||
Old->getStorageClass() == SC_None &&
|
||||
!Old->hasAttr<WeakImportAttr>()) {
|
||||
Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName();
|
||||
notePreviousDefinition(Old->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(Old, New->getLocation());
|
||||
// Remove weak_import attribute on new declaration.
|
||||
New->dropAttr<WeakImportAttr>();
|
||||
}
|
||||
@ -3696,7 +3696,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||
!Old->hasAttr<InternalLinkageAttr>()) {
|
||||
Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)
|
||||
<< New->getDeclName();
|
||||
notePreviousDefinition(Old->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(Old, New->getLocation());
|
||||
New->dropAttr<InternalLinkageAttr>();
|
||||
}
|
||||
|
||||
@ -3853,29 +3853,22 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||
New->setImplicitlyInline();
|
||||
}
|
||||
|
||||
void Sema::notePreviousDefinition(SourceLocation Old, SourceLocation New) {
|
||||
void Sema::notePreviousDefinition(const NamedDecl *Old, SourceLocation New) {
|
||||
SourceManager &SrcMgr = getSourceManager();
|
||||
auto FNewDecLoc = SrcMgr.getDecomposedLoc(New);
|
||||
auto FOldDecLoc = SrcMgr.getDecomposedLoc(Old);
|
||||
auto FOldDecLoc = SrcMgr.getDecomposedLoc(Old->getLocation());
|
||||
auto *FNew = SrcMgr.getFileEntryForID(FNewDecLoc.first);
|
||||
auto *FOld = SrcMgr.getFileEntryForID(FOldDecLoc.first);
|
||||
auto &HSI = PP.getHeaderSearchInfo();
|
||||
StringRef HdrFilename = SrcMgr.getFilename(SrcMgr.getSpellingLoc(Old));
|
||||
StringRef HdrFilename =
|
||||
SrcMgr.getFilename(SrcMgr.getSpellingLoc(Old->getLocation()));
|
||||
|
||||
auto noteFromModuleOrInclude = [&](SourceLocation &Loc,
|
||||
SourceLocation &IncLoc) -> bool {
|
||||
Module *Mod = nullptr;
|
||||
auto noteFromModuleOrInclude = [&](Module *Mod,
|
||||
SourceLocation IncLoc) -> bool {
|
||||
// Redefinition errors with modules are common with non modular mapped
|
||||
// headers, example: a non-modular header H in module A that also gets
|
||||
// included directly in a TU. Pointing twice to the same header/definition
|
||||
// is confusing, try to get better diagnostics when modules is on.
|
||||
if (getLangOpts().Modules) {
|
||||
auto ModLoc = SrcMgr.getModuleImportLoc(Old);
|
||||
if (!ModLoc.first.isInvalid())
|
||||
Mod = HSI.getModuleMap().inferModuleFromLocation(
|
||||
FullSourceLoc(Loc, SrcMgr));
|
||||
}
|
||||
|
||||
if (IncLoc.isValid()) {
|
||||
if (Mod) {
|
||||
Diag(IncLoc, diag::note_redefinition_modules_same_file)
|
||||
@ -3899,19 +3892,19 @@ void Sema::notePreviousDefinition(SourceLocation Old, SourceLocation New) {
|
||||
if (FNew == FOld && FNewDecLoc.second == FOldDecLoc.second) {
|
||||
SourceLocation OldIncLoc = SrcMgr.getIncludeLoc(FOldDecLoc.first);
|
||||
SourceLocation NewIncLoc = SrcMgr.getIncludeLoc(FNewDecLoc.first);
|
||||
EmittedDiag = noteFromModuleOrInclude(Old, OldIncLoc);
|
||||
EmittedDiag |= noteFromModuleOrInclude(New, NewIncLoc);
|
||||
EmittedDiag = noteFromModuleOrInclude(Old->getOwningModule(), OldIncLoc);
|
||||
EmittedDiag |= noteFromModuleOrInclude(getCurrentModule(), NewIncLoc);
|
||||
|
||||
// If the header has no guards, emit a note suggesting one.
|
||||
if (FOld && !HSI.isFileMultipleIncludeGuarded(FOld))
|
||||
Diag(Old, diag::note_use_ifdef_guards);
|
||||
Diag(Old->getLocation(), diag::note_use_ifdef_guards);
|
||||
|
||||
if (EmittedDiag)
|
||||
return;
|
||||
}
|
||||
|
||||
// Redefinition coming from different files or couldn't do better above.
|
||||
Diag(Old, diag::note_previous_definition);
|
||||
Diag(Old->getLocation(), diag::note_previous_definition);
|
||||
}
|
||||
|
||||
/// We've just determined that \p Old and \p New both appear to be definitions
|
||||
@ -3934,7 +3927,7 @@ bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) {
|
||||
return false;
|
||||
} else {
|
||||
Diag(New->getLocation(), diag::err_redefinition) << New;
|
||||
notePreviousDefinition(Old->getLocation(), New->getLocation());
|
||||
notePreviousDefinition(Old, New->getLocation());
|
||||
New->setInvalidDecl();
|
||||
return true;
|
||||
}
|
||||
@ -6942,7 +6935,7 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
|
||||
}
|
||||
}
|
||||
|
||||
DeclContext *OldDC = ShadowedDecl->getDeclContext();
|
||||
DeclContext *OldDC = ShadowedDecl->getDeclContext()->getRedeclContext();
|
||||
|
||||
unsigned WarningDiag = diag::warn_decl_shadow;
|
||||
SourceLocation CaptureLoc;
|
||||
@ -7198,7 +7191,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
|
||||
// ISO/IEC TR 18037 S5.1.2
|
||||
if (!getLangOpts().OpenCL
|
||||
&& NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
|
||||
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
|
||||
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 0;
|
||||
NewVD->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
@ -7278,6 +7271,11 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
|
||||
NewVD->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
} else if (T.getAddressSpace() != LangAS::Default) {
|
||||
// Do not allow other address spaces on automatic variable.
|
||||
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1;
|
||||
NewVD->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13503,9 +13501,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||
} else if (TUK == TUK_Reference &&
|
||||
(PrevTagDecl->getFriendObjectKind() ==
|
||||
Decl::FOK_Undeclared ||
|
||||
PP.getModuleContainingLocation(
|
||||
PrevDecl->getLocation()) !=
|
||||
PP.getModuleContainingLocation(KWLoc)) &&
|
||||
PrevDecl->getOwningModule() != getCurrentModule()) &&
|
||||
SS.isEmpty()) {
|
||||
// This declaration is a reference to an existing entity, but
|
||||
// has different visibility from that entity: it either makes
|
||||
@ -13561,7 +13557,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||
Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name;
|
||||
else
|
||||
Diag(NameLoc, diag::err_redefinition) << Name;
|
||||
notePreviousDefinition(Def->getLocation(),
|
||||
notePreviousDefinition(Def,
|
||||
NameLoc.isValid() ? NameLoc : KWLoc);
|
||||
// If this is a redefinition, recover by making this
|
||||
// struct be anonymous, which will make any later
|
||||
@ -13652,7 +13648,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||
// The tag name clashes with something else in the target scope,
|
||||
// issue an error and recover by making this tag be anonymous.
|
||||
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
|
||||
notePreviousDefinition(PrevDecl->getLocation(), NameLoc);
|
||||
notePreviousDefinition(PrevDecl, NameLoc);
|
||||
Name = nullptr;
|
||||
Invalid = true;
|
||||
}
|
||||
@ -15356,7 +15352,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
|
||||
Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
|
||||
else
|
||||
Diag(IdLoc, diag::err_redefinition) << Id;
|
||||
notePreviousDefinition(PrevDecl->getLocation(), IdLoc);
|
||||
notePreviousDefinition(PrevDecl, IdLoc);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -16052,8 +16048,10 @@ void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) {
|
||||
// FIXME: Consider creating a child DeclContext to hold the entities
|
||||
// lexically within the module.
|
||||
if (getLangOpts().trackLocalOwningModule()) {
|
||||
cast<Decl>(CurContext)->setHidden(true);
|
||||
cast<Decl>(CurContext)->setLocalOwningModule(Mod);
|
||||
for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
|
||||
cast<Decl>(DC)->setHidden(true);
|
||||
cast<Decl>(DC)->setLocalOwningModule(Mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16086,9 +16084,13 @@ void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) {
|
||||
|
||||
// Any further declarations are in whatever module we returned to.
|
||||
if (getLangOpts().trackLocalOwningModule()) {
|
||||
cast<Decl>(CurContext)->setLocalOwningModule(getCurrentModule());
|
||||
if (!getCurrentModule())
|
||||
cast<Decl>(CurContext)->setHidden(false);
|
||||
// The parser guarantees that this is the same context that we entered
|
||||
// the module within.
|
||||
for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
|
||||
cast<Decl>(DC)->setLocalOwningModule(getCurrentModule());
|
||||
if (!getCurrentModule())
|
||||
cast<Decl>(DC)->setHidden(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5935,12 +5935,18 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
||||
handleDLLAttr(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_Mips16:
|
||||
handleSimpleAttributeWithExclusions<Mips16Attr, MipsInterruptAttr>(S, D,
|
||||
Attr);
|
||||
handleSimpleAttributeWithExclusions<Mips16Attr, MicroMipsAttr,
|
||||
MipsInterruptAttr>(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_NoMips16:
|
||||
handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_MicroMips:
|
||||
handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_NoMicroMips:
|
||||
handleSimpleAttribute<NoMicroMipsAttr>(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_AMDGPUFlatWorkGroupSize:
|
||||
handleAMDGPUFlatWorkGroupSizeAttr(S, D, Attr);
|
||||
break;
|
||||
@ -7252,6 +7258,12 @@ class DiagnoseUnguardedAvailability
|
||||
|
||||
bool TraverseLambdaExpr(LambdaExpr *E) { return true; }
|
||||
|
||||
bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) {
|
||||
if (PRE->isClassReceiver())
|
||||
DiagnoseDeclAvailability(PRE->getClassReceiver(), PRE->getReceiverLocation());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) {
|
||||
if (ObjCMethodDecl *D = Msg->getMethodDecl())
|
||||
DiagnoseDeclAvailability(
|
||||
@ -7381,6 +7393,9 @@ bool DiagnoseUnguardedAvailability::VisitTypeLoc(TypeLoc Ty) {
|
||||
const Type *TyPtr = Ty.getTypePtr();
|
||||
SourceRange Range{Ty.getBeginLoc(), Ty.getEndLoc()};
|
||||
|
||||
if (Range.isInvalid())
|
||||
return true;
|
||||
|
||||
if (const TagType *TT = dyn_cast<TagType>(TyPtr)) {
|
||||
TagDecl *TD = TT->getDecl();
|
||||
DiagnoseDeclAvailability(TD, Range);
|
||||
|
@ -1420,11 +1420,46 @@ bool Sema::hasVisibleDefaultArgument(const NamedDecl *D,
|
||||
Modules);
|
||||
}
|
||||
|
||||
template<typename Filter>
|
||||
static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
|
||||
llvm::SmallVectorImpl<Module *> *Modules,
|
||||
Filter F) {
|
||||
for (auto *Redecl : D->redecls()) {
|
||||
auto *R = cast<NamedDecl>(Redecl);
|
||||
if (!F(R))
|
||||
continue;
|
||||
|
||||
if (S.isVisible(R))
|
||||
return true;
|
||||
|
||||
if (Modules) {
|
||||
Modules->push_back(R->getOwningModule());
|
||||
const auto &Merged = S.Context.getModulesWithMergedDefinition(R);
|
||||
Modules->insert(Modules->end(), Merged.begin(), Merged.end());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sema::hasVisibleExplicitSpecialization(
|
||||
const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) {
|
||||
return hasVisibleDeclarationImpl(*this, D, Modules, [](const NamedDecl *D) {
|
||||
if (auto *RD = dyn_cast<CXXRecordDecl>(D))
|
||||
return RD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(D))
|
||||
return FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
|
||||
if (auto *VD = dyn_cast<VarDecl>(D))
|
||||
return VD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
|
||||
llvm_unreachable("unknown explicit specialization kind");
|
||||
});
|
||||
}
|
||||
|
||||
bool Sema::hasVisibleMemberSpecialization(
|
||||
const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) {
|
||||
assert(isa<CXXRecordDecl>(D->getDeclContext()) &&
|
||||
"not a member specialization");
|
||||
for (auto *Redecl : D->redecls()) {
|
||||
return hasVisibleDeclarationImpl(*this, D, Modules, [](const NamedDecl *D) {
|
||||
// If the specialization is declared at namespace scope, then it's a member
|
||||
// specialization declaration. If it's lexically inside the class
|
||||
// definition then it was instantiated.
|
||||
@ -1432,19 +1467,8 @@ bool Sema::hasVisibleMemberSpecialization(
|
||||
// FIXME: This is a hack. There should be a better way to determine this.
|
||||
// FIXME: What about MS-style explicit specializations declared within a
|
||||
// class definition?
|
||||
if (Redecl->getLexicalDeclContext()->isFileContext()) {
|
||||
auto *NonConstR = const_cast<NamedDecl*>(cast<NamedDecl>(Redecl));
|
||||
|
||||
if (isVisible(NonConstR))
|
||||
return true;
|
||||
|
||||
if (Modules) {
|
||||
Modules->push_back(getOwningModule(NonConstR));
|
||||
const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR);
|
||||
Modules->insert(Modules->end(), Merged.begin(), Merged.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
return D->getLexicalDeclContext()->isFileContext();
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1459,23 +1483,19 @@ bool Sema::hasVisibleMemberSpecialization(
|
||||
/// your module can see, including those later on in your module).
|
||||
bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
|
||||
assert(D->isHidden() && "should not call this: not in slow case");
|
||||
Module *DeclModule = nullptr;
|
||||
|
||||
if (SemaRef.getLangOpts().ModulesLocalVisibility) {
|
||||
DeclModule = SemaRef.getOwningModule(D);
|
||||
if (!DeclModule) {
|
||||
assert(!D->isHidden() && "hidden decl not from a module");
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the owning module is visible, and the decl is not module private,
|
||||
// then the decl is visible too. (Module private is ignored within the same
|
||||
// top-level module.)
|
||||
if ((!D->isFromASTFile() || !D->isModulePrivate()) &&
|
||||
(SemaRef.isModuleVisible(DeclModule) ||
|
||||
SemaRef.hasVisibleMergedDefinition(D)))
|
||||
return true;
|
||||
}
|
||||
Module *DeclModule = SemaRef.getOwningModule(D);
|
||||
assert(DeclModule && "hidden decl not from a module");
|
||||
|
||||
// If the owning module is visible, and the decl is not module private,
|
||||
// then the decl is visible too. (Module private is ignored within the same
|
||||
// top-level module.)
|
||||
// FIXME: Check the owning module for module-private declarations rather than
|
||||
// assuming "same AST file" is the same thing as "same module".
|
||||
if ((!D->isFromASTFile() || !D->isModulePrivate()) &&
|
||||
(SemaRef.isModuleVisible(DeclModule) ||
|
||||
SemaRef.hasVisibleMergedDefinition(D)))
|
||||
return true;
|
||||
|
||||
// If this declaration is not at namespace scope nor module-private,
|
||||
// then it is visible if its lexical parent has a visible definition.
|
||||
@ -1571,20 +1591,8 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
|
||||
bool Sema::hasVisibleDeclarationSlow(const NamedDecl *D,
|
||||
llvm::SmallVectorImpl<Module *> *Modules) {
|
||||
assert(!isVisible(D) && "not in slow case");
|
||||
|
||||
for (auto *Redecl : D->redecls()) {
|
||||
auto *NonConstR = const_cast<NamedDecl*>(cast<NamedDecl>(Redecl));
|
||||
if (isVisible(NonConstR))
|
||||
return true;
|
||||
|
||||
if (Modules) {
|
||||
Modules->push_back(getOwningModule(NonConstR));
|
||||
const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR);
|
||||
Modules->insert(Modules->end(), Merged.begin(), Merged.end());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return hasVisibleDeclarationImpl(*this, D, Modules,
|
||||
[](const NamedDecl *) { return true; });
|
||||
}
|
||||
|
||||
NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
|
||||
@ -4957,6 +4965,14 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
|
||||
MissingImportKind MIK, bool Recover) {
|
||||
assert(!Modules.empty());
|
||||
|
||||
// Weed out duplicates from module list.
|
||||
llvm::SmallVector<Module*, 8> UniqueModules;
|
||||
llvm::SmallDenseSet<Module*, 8> UniqueModuleSet;
|
||||
for (auto *M : Modules)
|
||||
if (UniqueModuleSet.insert(M).second)
|
||||
UniqueModules.push_back(M);
|
||||
Modules = UniqueModules;
|
||||
|
||||
if (Modules.size() > 1) {
|
||||
std::string ModuleList;
|
||||
unsigned N = 0;
|
||||
@ -4971,8 +4987,8 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
|
||||
|
||||
Diag(UseLoc, diag::err_module_unimported_use_multiple)
|
||||
<< (int)MIK << Decl << ModuleList;
|
||||
} else if (const FileEntry *E =
|
||||
PP.getModuleHeaderToIncludeForDiagnostics(UseLoc, DeclLoc)) {
|
||||
} else if (const FileEntry *E = PP.getModuleHeaderToIncludeForDiagnostics(
|
||||
UseLoc, Modules[0], DeclLoc)) {
|
||||
// The right way to make the declaration visible is to include a header;
|
||||
// suggest doing so.
|
||||
//
|
||||
|
@ -7901,6 +7901,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
|
||||
TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind();
|
||||
if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) {
|
||||
Specialization->setLocation(FD->getLocation());
|
||||
Specialization->setLexicalDeclContext(FD->getLexicalDeclContext());
|
||||
// C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr
|
||||
// function can differ from the template declaration with respect to
|
||||
// the constexpr specifier.
|
||||
@ -7961,6 +7962,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
|
||||
// FIXME: We need an update record for this AST mutation.
|
||||
Specialization->setDeletedAsWritten(false);
|
||||
}
|
||||
// FIXME: We need an update record for this AST mutation.
|
||||
SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
|
||||
MarkUnusedFileScopedDecl(Specialization);
|
||||
}
|
||||
@ -9745,7 +9747,7 @@ class ExplicitSpecializationVisibilityChecker {
|
||||
IsHiddenExplicitSpecialization =
|
||||
Spec->getMemberSpecializationInfo()
|
||||
? !S.hasVisibleMemberSpecialization(Spec, &Modules)
|
||||
: !S.hasVisibleDeclaration(Spec);
|
||||
: !S.hasVisibleExplicitSpecialization(Spec, &Modules);
|
||||
} else {
|
||||
checkInstantiated(Spec);
|
||||
}
|
||||
|
@ -1540,8 +1540,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
||||
// DR1484 clarifies that the members of a local class are instantiated as part
|
||||
// of the instantiation of their enclosing entity.
|
||||
if (D->isCompleteDefinition() && D->isLocalClass()) {
|
||||
Sema::SavePendingLocalImplicitInstantiationsRAII
|
||||
SavedPendingLocalImplicitInstantiations(SemaRef);
|
||||
Sema::LocalEagerInstantiationScope LocalInstantiations(SemaRef);
|
||||
|
||||
SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs,
|
||||
TSK_ImplicitInstantiation,
|
||||
@ -1555,7 +1554,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
||||
|
||||
// This class may have local implicit instantiations that need to be
|
||||
// performed within this scope.
|
||||
SemaRef.PerformPendingInstantiations(/*LocalOnly=*/true);
|
||||
LocalInstantiations.perform();
|
||||
}
|
||||
|
||||
SemaRef.DiagnoseUnusedNestedTypedefs(Record);
|
||||
@ -3812,10 +3811,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
// while we're still within our own instantiation context.
|
||||
// This has to happen before LateTemplateParser below is called, so that
|
||||
// it marks vtables used in late parsed templates as used.
|
||||
SavePendingLocalImplicitInstantiationsRAII
|
||||
SavedPendingLocalImplicitInstantiations(*this);
|
||||
SavePendingInstantiationsAndVTableUsesRAII
|
||||
SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive);
|
||||
GlobalEagerInstantiationScope GlobalInstantiations(*this,
|
||||
/*Enabled=*/Recursive);
|
||||
LocalEagerInstantiationScope LocalInstantiations(*this);
|
||||
|
||||
// Call the LateTemplateParser callback if there is a need to late parse
|
||||
// a templated function definition.
|
||||
@ -3942,20 +3940,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
|
||||
// This class may have local implicit instantiations that need to be
|
||||
// instantiation within this scope.
|
||||
PerformPendingInstantiations(/*LocalOnly=*/true);
|
||||
LocalInstantiations.perform();
|
||||
Scope.Exit();
|
||||
|
||||
if (Recursive) {
|
||||
// Define any pending vtables.
|
||||
DefineUsedVTables();
|
||||
|
||||
// Instantiate any pending implicit instantiations found during the
|
||||
// instantiation of this template.
|
||||
PerformPendingInstantiations();
|
||||
|
||||
// PendingInstantiations and VTableUses are restored through
|
||||
// SavePendingInstantiationsAndVTableUses's destructor.
|
||||
}
|
||||
GlobalInstantiations.perform();
|
||||
}
|
||||
|
||||
VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
|
||||
@ -4287,10 +4274,10 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
||||
// If we're performing recursive template instantiation, create our own
|
||||
// queue of pending implicit instantiations that we will instantiate
|
||||
// later, while we're still within our own instantiation context.
|
||||
SavePendingInstantiationsAndVTableUsesRAII
|
||||
SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive);
|
||||
|
||||
GlobalEagerInstantiationScope GlobalInstantiations(*this,
|
||||
/*Enabled=*/Recursive);
|
||||
LocalInstantiationScope Local(*this);
|
||||
LocalEagerInstantiationScope LocalInstantiations(*this);
|
||||
|
||||
// Enter the scope of this instantiation. We don't use
|
||||
// PushDeclContext because we don't have a scope.
|
||||
@ -4303,21 +4290,9 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
||||
|
||||
// This variable may have local implicit instantiations that need to be
|
||||
// instantiated within this scope.
|
||||
PerformPendingInstantiations(/*LocalOnly=*/true);
|
||||
|
||||
LocalInstantiations.perform();
|
||||
Local.Exit();
|
||||
|
||||
if (Recursive) {
|
||||
// Define any newly required vtables.
|
||||
DefineUsedVTables();
|
||||
|
||||
// Instantiate any pending implicit instantiations found during the
|
||||
// instantiation of this template.
|
||||
PerformPendingInstantiations();
|
||||
|
||||
// PendingInstantiations and VTableUses are restored through
|
||||
// SavePendingInstantiationsAndVTableUses's destructor.
|
||||
}
|
||||
GlobalInstantiations.perform();
|
||||
}
|
||||
|
||||
// Find actual definition
|
||||
@ -4408,16 +4383,16 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
||||
// If we're performing recursive template instantiation, create our own
|
||||
// queue of pending implicit instantiations that we will instantiate later,
|
||||
// while we're still within our own instantiation context.
|
||||
SavePendingLocalImplicitInstantiationsRAII
|
||||
SavedPendingLocalImplicitInstantiations(*this);
|
||||
SavePendingInstantiationsAndVTableUsesRAII
|
||||
SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive);
|
||||
GlobalEagerInstantiationScope GlobalInstantiations(*this,
|
||||
/*Enabled=*/Recursive);
|
||||
|
||||
// Enter the scope of this instantiation. We don't use
|
||||
// PushDeclContext because we don't have a scope.
|
||||
ContextRAII PreviousContext(*this, Var->getDeclContext());
|
||||
LocalInstantiationScope Local(*this);
|
||||
|
||||
LocalEagerInstantiationScope LocalInstantiations(*this);
|
||||
|
||||
VarDecl *OldVar = Var;
|
||||
if (Def->isStaticDataMember() && !Def->isOutOfLine()) {
|
||||
// We're instantiating an inline static data member whose definition was
|
||||
@ -4470,21 +4445,9 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
||||
|
||||
// This variable may have local implicit instantiations that need to be
|
||||
// instantiated within this scope.
|
||||
PerformPendingInstantiations(/*LocalOnly=*/true);
|
||||
|
||||
LocalInstantiations.perform();
|
||||
Local.Exit();
|
||||
|
||||
if (Recursive) {
|
||||
// Define any newly required vtables.
|
||||
DefineUsedVTables();
|
||||
|
||||
// Instantiate any pending implicit instantiations found during the
|
||||
// instantiation of this template.
|
||||
PerformPendingInstantiations();
|
||||
|
||||
// PendingInstantiations and VTableUses are restored through
|
||||
// SavePendingInstantiationsAndVTableUses's destructor.
|
||||
}
|
||||
GlobalInstantiations.perform();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3735,16 +3735,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
// inner pointers.
|
||||
complainAboutMissingNullability = CAMN_InnerPointers;
|
||||
|
||||
auto isDependentNonPointerType = [](QualType T) -> bool {
|
||||
// Note: This is intended to be the same check as Type::canHaveNullability
|
||||
// except with all of the ambiguous cases being treated as 'false' rather
|
||||
// than 'true'.
|
||||
return T->isDependentType() && !T->isAnyPointerType() &&
|
||||
!T->isBlockPointerType() && !T->isMemberPointerType();
|
||||
};
|
||||
|
||||
if (T->canHaveNullability() && !T->getNullability(S.Context) &&
|
||||
!isDependentNonPointerType(T)) {
|
||||
if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
|
||||
!T->getNullability(S.Context)) {
|
||||
// Note that we allow but don't require nullability on dependent types.
|
||||
++NumPointersRemaining;
|
||||
}
|
||||
@ -3962,7 +3954,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||
// If the type itself could have nullability but does not, infer pointer
|
||||
// nullability and perform consistency checking.
|
||||
if (S.CodeSynthesisContexts.empty()) {
|
||||
if (T->canHaveNullability() && !T->getNullability(S.Context)) {
|
||||
if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
|
||||
!T->getNullability(S.Context)) {
|
||||
if (isVaList(T)) {
|
||||
// Record that we've seen a pointer, but do nothing else.
|
||||
if (NumPointersRemaining > 0)
|
||||
@ -5531,14 +5524,15 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
|
||||
addrSpace.setIsSigned(false);
|
||||
}
|
||||
llvm::APSInt max(addrSpace.getBitWidth());
|
||||
max = Qualifiers::MaxAddressSpace - LangAS::Count;
|
||||
max = Qualifiers::MaxAddressSpace - LangAS::FirstTargetAddressSpace;
|
||||
if (addrSpace > max) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
|
||||
<< (unsigned)max.getZExtValue() << ASArgExpr->getSourceRange();
|
||||
Attr.setInvalid();
|
||||
return;
|
||||
}
|
||||
ASIdx = static_cast<unsigned>(addrSpace.getZExtValue()) + LangAS::Count;
|
||||
ASIdx = static_cast<unsigned>(addrSpace.getZExtValue()) +
|
||||
LangAS::FirstTargetAddressSpace;
|
||||
} else {
|
||||
// The keyword-based type attributes imply which address space to use.
|
||||
switch (Attr.getKind()) {
|
||||
|
@ -2756,7 +2756,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
||||
// If we've already loaded the decl, perform the updates when we finish
|
||||
// loading this block.
|
||||
if (Decl *D = GetExistingDecl(ID))
|
||||
PendingUpdateRecords.push_back(std::make_pair(ID, D));
|
||||
PendingUpdateRecords.push_back(
|
||||
PendingUpdateRecord(ID, D, /*JustLoaded=*/false));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3086,7 +3087,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
||||
// If we've already loaded the decl, perform the updates when we finish
|
||||
// loading this block.
|
||||
if (Decl *D = GetExistingDecl(ID))
|
||||
PendingUpdateRecords.push_back(std::make_pair(ID, D));
|
||||
PendingUpdateRecords.push_back(
|
||||
PendingUpdateRecord(ID, D, /*JustLoaded=*/false));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -8956,7 +8958,7 @@ void ASTReader::finishPendingActions() {
|
||||
while (!PendingUpdateRecords.empty()) {
|
||||
auto Update = PendingUpdateRecords.pop_back_val();
|
||||
ReadingKindTracker ReadingKind(Read_Decl, *this);
|
||||
loadDeclUpdateRecords(Update.first, Update.second);
|
||||
loadDeclUpdateRecords(Update);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3612,7 +3612,8 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
||||
assert(Record.getIdx() == Record.size());
|
||||
|
||||
// Load any relevant update records.
|
||||
PendingUpdateRecords.push_back(std::make_pair(ID, D));
|
||||
PendingUpdateRecords.push_back(
|
||||
PendingUpdateRecord(ID, D, /*JustLoaded=*/true));
|
||||
|
||||
// Load the categories after recursive loading is finished.
|
||||
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
|
||||
@ -3657,20 +3658,24 @@ void ASTReader::PassInterestingDeclsToConsumer() {
|
||||
}
|
||||
}
|
||||
|
||||
void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
|
||||
void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
|
||||
// The declaration may have been modified by files later in the chain.
|
||||
// If this is the case, read the record containing the updates from each file
|
||||
// and pass it to ASTDeclReader to make the modifications.
|
||||
serialization::GlobalDeclID ID = Record.ID;
|
||||
Decl *D = Record.D;
|
||||
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
|
||||
DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
|
||||
if (UpdI != DeclUpdateOffsets.end()) {
|
||||
auto UpdateOffsets = std::move(UpdI->second);
|
||||
DeclUpdateOffsets.erase(UpdI);
|
||||
|
||||
// FIXME: This call to isConsumerInterestedIn is not safe because
|
||||
// we could be deserializing declarations at the moment. We should
|
||||
// delay calling this in the same way as done in D30793.
|
||||
bool WasInteresting = isConsumerInterestedIn(Context, D, false);
|
||||
// Check if this decl was interesting to the consumer. If we just loaded
|
||||
// the declaration, then we know it was interesting and we skip the call
|
||||
// to isConsumerInterestedIn because it is unsafe to call in the
|
||||
// current ASTReader state.
|
||||
bool WasInteresting =
|
||||
Record.JustLoaded || isConsumerInterestedIn(Context, D, false);
|
||||
for (auto &FileAndOffset : UpdateOffsets) {
|
||||
ModuleFile *F = FileAndOffset.first;
|
||||
uint64_t Offset = FileAndOffset.second;
|
||||
|
@ -2841,25 +2841,6 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
||||
"non-imported submodule?");
|
||||
}
|
||||
|
||||
serialization::SubmoduleID
|
||||
ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) {
|
||||
if (Loc.isInvalid() || !WritingModule)
|
||||
return 0; // No submodule
|
||||
|
||||
// Find the module that owns this location.
|
||||
ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
|
||||
Module *OwningMod
|
||||
= ModMap.inferModuleFromLocation(FullSourceLoc(Loc,PP->getSourceManager()));
|
||||
if (!OwningMod)
|
||||
return 0;
|
||||
|
||||
// Check whether this submodule is part of our own module.
|
||||
if (WritingModule != OwningMod && !OwningMod->isSubModuleOf(WritingModule))
|
||||
return 0;
|
||||
|
||||
return getSubmoduleID(OwningMod);
|
||||
}
|
||||
|
||||
void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
|
||||
bool isModule) {
|
||||
llvm::SmallDenseMap<const DiagnosticsEngine::DiagState *, unsigned, 64>
|
||||
|
@ -299,7 +299,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
|
||||
Record.push_back(D->isTopLevelDeclInObjCContainer());
|
||||
Record.push_back(D->getAccess());
|
||||
Record.push_back(D->isModulePrivate());
|
||||
Record.push_back(Writer.inferSubmoduleIDFromLocation(D->getLocation()));
|
||||
Record.push_back(Writer.getSubmoduleID(D->getOwningModule()));
|
||||
|
||||
// If this declaration injected a name into a context different from its
|
||||
// lexical context, and that context is an imported namespace, we need to
|
||||
|
@ -3448,14 +3448,12 @@ void BugReporter::FlushReport(BugReport *exampleReport,
|
||||
// the BugReporterVisitors may mark this bug as a false positive.
|
||||
assert(!bugReports.empty());
|
||||
|
||||
MaxBugClassSize =
|
||||
std::max(bugReports.size(), static_cast<size_t>(MaxBugClassSize));
|
||||
MaxBugClassSize.updateMax(bugReports.size());
|
||||
|
||||
if (!generatePathDiagnostic(*D.get(), PD, bugReports))
|
||||
return;
|
||||
|
||||
MaxValidBugClassSize =
|
||||
std::max(bugReports.size(), static_cast<size_t>(MaxValidBugClassSize));
|
||||
MaxValidBugClassSize.updateMax(bugReports.size());
|
||||
|
||||
// Examine the report and see if the last piece is in a header. Reset the
|
||||
// report location to the last piece in the main source file.
|
||||
|
@ -674,10 +674,8 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
|
||||
|
||||
DisplayFunction(D, Mode, IMode);
|
||||
CFG *DeclCFG = Mgr->getCFG(D);
|
||||
if (DeclCFG) {
|
||||
unsigned CFGSize = DeclCFG->size();
|
||||
MaxCFGSize = MaxCFGSize < CFGSize ? CFGSize : MaxCFGSize;
|
||||
}
|
||||
if (DeclCFG)
|
||||
MaxCFGSize.updateMax(DeclCFG->size());
|
||||
|
||||
BugReporter BR(*Mgr);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -check-prefixes=CHECK,GIZ %s
|
||||
// RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -check-prefixes=CHECK,PIZ %s
|
||||
// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHeCK,GIZ %s
|
||||
// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHECK,GIZ %s
|
||||
|
||||
// CHECK: @foo = common addrspace(1) global
|
||||
int foo __attribute__((address_space(1)));
|
||||
@ -40,8 +40,10 @@ typedef struct {
|
||||
} MyStruct;
|
||||
|
||||
// CHECK-LABEL: define void @test4(
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p2i8
|
||||
// CHECK: call void @llvm.memcpy.p2i8.p0i8
|
||||
// GIZ: call void @llvm.memcpy.p0i8.p2i8
|
||||
// GIZ: call void @llvm.memcpy.p2i8.p0i8
|
||||
// PIZ: call void @llvm.memcpy.p4i8.p2i8
|
||||
// PIZ: call void @llvm.memcpy.p2i8.p4i8
|
||||
void test4(MyStruct __attribute__((address_space(2))) *pPtr) {
|
||||
MyStruct s = pPtr[0];
|
||||
pPtr[0] = s;
|
||||
|
12
test/CodeGen/micromips-attr.c
Normal file
12
test/CodeGen/micromips-attr.c
Normal file
@ -0,0 +1,12 @@
|
||||
// RUN: %clang_cc1 -triple mips-linux-gnu -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
void __attribute__((micromips)) foo (void) {}
|
||||
|
||||
// CHECK: define void @foo() [[MICROMIPS:#[0-9]+]]
|
||||
|
||||
void __attribute__((nomicromips)) nofoo (void) {}
|
||||
|
||||
// CHECK: define void @nofoo() [[NOMICROMIPS:#[0-9]+]]
|
||||
|
||||
// CHECK: attributes [[MICROMIPS]] = { noinline nounwind {{.*}} "micromips" {{.*}} }
|
||||
// CHECK: attributes [[NOMICROMIPS]] = { noinline nounwind {{.*}} "nomicromips" {{.*}} }
|
8
test/CodeGen/wchar-size.c
Normal file
8
test/CodeGen/wchar-size.c
Normal file
@ -0,0 +1,8 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s -check-prefix=LONG-WCHAR
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -emit-llvm -o - %s | FileCheck %s -check-prefix=SHORT-WCHAR
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - -fshort-wchar %s | FileCheck %s -check-prefix=SHORT-WCHAR
|
||||
// Note: -fno-short-wchar implies the target default is used; so there is no
|
||||
// need to test this separately here.
|
||||
|
||||
// LONG-WCHAR: !{{[0-9]+}} = !{i32 {{[0-9]+}}, !"wchar_size", i32 4}
|
||||
// SHORT-WCHAR: !{{[0-9]+}} = !{i32 {{[0-9]+}}, !"wchar_size", i32 2}
|
@ -18,8 +18,8 @@ extern "C" __device__ void foo() {}
|
||||
// FTZ: attributes #0 = {{.*}} "nvptx-f32ftz"="true"
|
||||
// NOFTZ-NOT: attributes #0 = {{.*}} "nvptx-f32ftz"
|
||||
|
||||
// FTZ:!llvm.module.flags = !{[[MODFLAG:![0-9]+]]}
|
||||
// FTZ:!llvm.module.flags = !{{{.*}}[[MODFLAG:![0-9]+]]}
|
||||
// FTZ:[[MODFLAG]] = !{i32 4, !"nvvm-reflect-ftz", i32 1}
|
||||
|
||||
// NOFTZ:!llvm.module.flags = !{[[MODFLAG:![0-9]+]]}
|
||||
// NOFTZ:!llvm.module.flags = !{{{.*}}[[MODFLAG:![0-9]+]]}
|
||||
// NOFTZ:[[MODFLAG]] = !{i32 4, !"nvvm-reflect-ftz", i32 0}
|
||||
|
72
test/CodeGenCXX/amdgcn-automatic-variable.cpp
Normal file
72
test/CodeGenCXX/amdgcn-automatic-variable.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
// RUN: %clang_cc1 -O0 -triple amdgcn---amdgiz -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// CHECK-LABEL: define void @_Z5func1Pi(i32* %x)
|
||||
void func1(int *x) {
|
||||
// CHECK: %[[x_addr:.*]] = alloca i32*{{.*}}addrspace(5)
|
||||
// CHECK: store i32* %x, i32* addrspace(5)* %[[x_addr]]
|
||||
// CHECK: %[[r0:.*]] = load i32*, i32* addrspace(5)* %[[x_addr]]
|
||||
// CHECK: store i32 1, i32* %[[r0]]
|
||||
*x = 1;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @_Z5func2v()
|
||||
void func2(void) {
|
||||
// CHECK: %lv1 = alloca i32, align 4, addrspace(5)
|
||||
// CHECK: %lv2 = alloca i32, align 4, addrspace(5)
|
||||
// CHECK: %la = alloca [100 x i32], align 4, addrspace(5)
|
||||
// CHECK: %lp1 = alloca i32*, align 4, addrspace(5)
|
||||
// CHECK: %lp2 = alloca i32*, align 4, addrspace(5)
|
||||
// CHECK: %lvc = alloca i32, align 4, addrspace(5)
|
||||
|
||||
// CHECK: %[[r0:.*]] = addrspacecast i32 addrspace(5)* %lv1 to i32*
|
||||
// CHECK: store i32 1, i32* %[[r0]]
|
||||
int lv1;
|
||||
lv1 = 1;
|
||||
// CHECK: %[[r1:.*]] = addrspacecast i32 addrspace(5)* %lv2 to i32*
|
||||
// CHECK: store i32 2, i32* %[[r1]]
|
||||
int lv2 = 2;
|
||||
|
||||
// CHECK: %[[r2:.*]] = addrspacecast [100 x i32] addrspace(5)* %la to [100 x i32]*
|
||||
// CHECK: %[[arrayidx:.*]] = getelementptr inbounds [100 x i32], [100 x i32]* %[[r2]], i64 0, i64 0
|
||||
// CHECK: store i32 3, i32* %[[arrayidx]], align 4
|
||||
int la[100];
|
||||
la[0] = 3;
|
||||
|
||||
// CHECK: %[[r3:.*]] = addrspacecast i32* addrspace(5)* %lp1 to i32**
|
||||
// CHECK: store i32* %[[r0]], i32** %[[r3]], align 4
|
||||
int *lp1 = &lv1;
|
||||
|
||||
// CHECK: %[[r4:.*]] = addrspacecast i32* addrspace(5)* %lp2 to i32**
|
||||
// CHECK: %[[arraydecay:.*]] = getelementptr inbounds [100 x i32], [100 x i32]* %[[r2]], i32 0, i32 0
|
||||
// CHECK: store i32* %[[arraydecay]], i32** %[[r4]], align 4
|
||||
int *lp2 = la;
|
||||
|
||||
// CHECK: call void @_Z5func1Pi(i32* %[[r0]])
|
||||
func1(&lv1);
|
||||
|
||||
// CHECK: %[[r5:.*]] = addrspacecast i32 addrspace(5)* %lvc to i32*
|
||||
// CHECK: store i32 4, i32* %[[r5]]
|
||||
// CHECK: store i32 4, i32* %[[r0]]
|
||||
const int lvc = 4;
|
||||
lv1 = lvc;
|
||||
}
|
||||
|
||||
void destroy(int x);
|
||||
|
||||
class A {
|
||||
int x;
|
||||
public:
|
||||
A():x(0) {}
|
||||
~A() {
|
||||
destroy(x);
|
||||
}
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define void @_Z5func3v
|
||||
void func3() {
|
||||
// CHECK: %[[a:.*]] = alloca %class.A, align 4, addrspace(5)
|
||||
// CHECK: %[[r0:.*]] = addrspacecast %class.A addrspace(5)* %[[a]] to %class.A*
|
||||
// CHECK: call void @_ZN1AC1Ev(%class.A* %[[r0]])
|
||||
// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r0]])
|
||||
A a;
|
||||
}
|
@ -211,7 +211,7 @@ struct DynamicFromStatic;
|
||||
// CHECK-DTORS-LABEL: {{^}}}
|
||||
|
||||
|
||||
// CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:.*]], ![[SEC:.*]]{{.*}}}
|
||||
// CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:[0-9]+]], ![[SEC:[0-9]+]]{{.*}}}
|
||||
|
||||
// CHECK-LINK-REQ: ![[FIRST]] = !{i32 1, !"StrictVTablePointers", i32 1}
|
||||
// CHECK-LINK-REQ: ![[SEC]] = !{i32 3, !"StrictVTablePointersRequirement", ![[META:.*]]}
|
||||
|
60
test/CodeGenOpenCL/amdgcn-automatic-variable.cl
Normal file
60
test/CodeGenOpenCL/amdgcn-automatic-variable.cl
Normal file
@ -0,0 +1,60 @@
|
||||
// RUN: %clang_cc1 -O0 -cl-std=CL1.2 -triple amdgcn---amdgizcl -emit-llvm %s -o - | FileCheck -check-prefixes=CHECK,CL12 %s
|
||||
// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -triple amdgcn---amdgizcl -emit-llvm %s -o - | FileCheck -check-prefixes=CHECK,CL20 %s
|
||||
|
||||
// CL12-LABEL: define void @func1(i32 addrspace(5)* %x)
|
||||
// CL20-LABEL: define void @func1(i32* %x)
|
||||
void func1(int *x) {
|
||||
// CL12: %[[x_addr:.*]] = alloca i32 addrspace(5)*{{.*}}addrspace(5)
|
||||
// CL12: store i32 addrspace(5)* %x, i32 addrspace(5)* addrspace(5)* %[[x_addr]]
|
||||
// CL12: %[[r0:.*]] = load i32 addrspace(5)*, i32 addrspace(5)* addrspace(5)* %[[x_addr]]
|
||||
// CL12: store i32 1, i32 addrspace(5)* %[[r0]]
|
||||
// CL20: %[[x_addr:.*]] = alloca i32*{{.*}}addrspace(5)
|
||||
// CL20: store i32* %x, i32* addrspace(5)* %[[x_addr]]
|
||||
// CL20: %[[r0:.*]] = load i32*, i32* addrspace(5)* %[[x_addr]]
|
||||
// CL20: store i32 1, i32* %[[r0]]
|
||||
*x = 1;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @func2()
|
||||
void func2(void) {
|
||||
// CHECK: %lv1 = alloca i32, align 4, addrspace(5)
|
||||
// CHECK: %lv2 = alloca i32, align 4, addrspace(5)
|
||||
// CHECK: %la = alloca [100 x i32], align 4, addrspace(5)
|
||||
// CL12: %lp1 = alloca i32 addrspace(5)*, align 4, addrspace(5)
|
||||
// CL12: %lp2 = alloca i32 addrspace(5)*, align 4, addrspace(5)
|
||||
// CL20: %lp1 = alloca i32*, align 4, addrspace(5)
|
||||
// CL20: %lp2 = alloca i32*, align 4, addrspace(5)
|
||||
// CHECK: %lvc = alloca i32, align 4, addrspace(5)
|
||||
|
||||
// CHECK: store i32 1, i32 addrspace(5)* %lv1
|
||||
int lv1;
|
||||
lv1 = 1;
|
||||
// CHECK: store i32 2, i32 addrspace(5)* %lv2
|
||||
int lv2 = 2;
|
||||
|
||||
// CHECK: %[[arrayidx:.*]] = getelementptr inbounds [100 x i32], [100 x i32] addrspace(5)* %la, i64 0, i64 0
|
||||
// CHECK: store i32 3, i32 addrspace(5)* %[[arrayidx]], align 4
|
||||
int la[100];
|
||||
la[0] = 3;
|
||||
|
||||
// CL12: store i32 addrspace(5)* %lv1, i32 addrspace(5)* addrspace(5)* %lp1, align 4
|
||||
// CL20: %[[r0:.*]] = addrspacecast i32 addrspace(5)* %lv1 to i32*
|
||||
// CL20: store i32* %[[r0]], i32* addrspace(5)* %lp1, align 4
|
||||
int *lp1 = &lv1;
|
||||
|
||||
// CHECK: %[[arraydecay:.*]] = getelementptr inbounds [100 x i32], [100 x i32] addrspace(5)* %la, i32 0, i32 0
|
||||
// CL12: store i32 addrspace(5)* %[[arraydecay]], i32 addrspace(5)* addrspace(5)* %lp2, align 4
|
||||
// CL20: %[[r1:.*]] = addrspacecast i32 addrspace(5)* %[[arraydecay]] to i32*
|
||||
// CL20: store i32* %[[r1]], i32* addrspace(5)* %lp2, align 4
|
||||
int *lp2 = la;
|
||||
|
||||
// CL12: call void @func1(i32 addrspace(5)* %lv1)
|
||||
// CL20: %[[r2:.*]] = addrspacecast i32 addrspace(5)* %lv1 to i32*
|
||||
// CL20: call void @func1(i32* %[[r2]])
|
||||
func1(&lv1);
|
||||
|
||||
// CHECK: store i32 4, i32 addrspace(5)* %lvc
|
||||
// CHECK: store i32 4, i32 addrspace(5)* %lv1
|
||||
const int lvc = 4;
|
||||
lv1 = lvc;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// REQUIRES: amdgpu-registered-target
|
||||
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -S -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown-opencl -S -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa -mcpu=fiji -o - %s | FileCheck %s
|
||||
// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa-opencl -mcpu=fiji -o - %s | FileCheck %s
|
||||
|
||||
// CHECK-DAG: ![[DWARF_ADDRESS_SPACE_NONE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{[0-9]+}}, size: {{[0-9]+}})
|
||||
// CHECK-DAG: ![[DWARF_ADDRESS_SPACE_LOCAL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{[0-9]+}}, size: {{[0-9]+}}, dwarfAddressSpace: 2)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa -mcpu=fiji -o - %s | FileCheck %s
|
||||
// RUN: %clang -cl-std=CL2.0 -emit-llvm -g -O0 -S -target amdgcn-amd-amdhsa-opencl -mcpu=fiji -o - %s | FileCheck %s
|
||||
|
||||
// CHECK-DAG: ![[LOCAL:[0-9]+]] = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
|
||||
// CHECK-DAG: ![[PRIVATE:[0-9]+]] = !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// RUN: %clang_cc1 %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 %s -O0 -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck --check-prefix=NOOPT %s
|
||||
// RUN: %clang_cc1 %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn---opencl -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 %s -O0 -cl-std=CL2.0 -include opencl-c.h -triple amdgcn---opencl -emit-llvm -o - | FileCheck --check-prefix=NOOPT %s
|
||||
|
||||
typedef struct {
|
||||
private char *p1;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// REQUIRES: amdgpu-registered-target
|
||||
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown-opencl -S -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---opencl %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---amdgizcl %s | FileCheck %s -check-prefix=AMDGIZ
|
||||
|
||||
struct A {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir-unknown-unknown -o - | FileCheck --check-prefix=SZ32 %s
|
||||
// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir64-unknown-unknown -o - | FileCheck --check-prefix=SZ64 --check-prefix=SZ64ONLY %s
|
||||
// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn-- -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDONLY %s
|
||||
// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn---opencl -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDONLY %s
|
||||
|
||||
//SZ32: define{{.*}} i32 @test_ptrtoint_private(i8* %x)
|
||||
//SZ32: ptrtoint i8* %{{.*}} to i32
|
||||
|
@ -4,6 +4,10 @@
|
||||
#define GEN_DECL(mod_name) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name, generated_declaration)))
|
||||
#define PUSH_GEN_DECL(mod_name) push(GEN_DECL(mod_name), apply_to=any(enum, objc_interface, objc_category, objc_protocol))
|
||||
|
||||
// Forward declarations should not affect module namespacing below
|
||||
@class I1;
|
||||
@class I2;
|
||||
|
||||
// This should not be indexed.
|
||||
GEN_DECL("some_module")
|
||||
@interface I1
|
||||
|
@ -141,3 +141,20 @@ void undefinedTemplateLookup2(UserOfUndefinedTemplateClass<T> &x) {
|
||||
x.lookup;
|
||||
typename UserOfUndefinedTemplateClass<T>::Type y;
|
||||
}
|
||||
|
||||
template<typename T> struct Dropper;
|
||||
|
||||
template<typename T> struct Trait;
|
||||
|
||||
template<typename T>
|
||||
struct Recurse : Trait<typename Dropper<T>::Type> { };
|
||||
|
||||
template<typename T>
|
||||
struct Trait : Recurse<T> {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void infiniteTraitRecursion(Trait<T> &t) {
|
||||
// Shouldn't crash!
|
||||
t.lookup;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s
|
||||
|
||||
// CHECK: [[@LINE+1]]:7 | class/C++ | Cls | [[Cls_USR:.*]] | <no-cgname> | Def | rel: 0
|
||||
class Cls {
|
||||
class Cls { public:
|
||||
// CHECK: [[@LINE+3]]:3 | constructor/C++ | Cls | c:@S@Cls@F@Cls#I# | __ZN3ClsC1Ei | Decl,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | Cls | c:@S@Cls
|
||||
// CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
@ -339,3 +339,97 @@ void ::ns::inner::func() {
|
||||
// CHECK: [[@LINE-1]]:3 | namespace/C++ | ns | c:@N@ns | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-2]]:7 | namespace-alias/C++ | innerAlias | c:@N@ns@NA@innerAlias | <no-cgname> | Ref,RelCont | rel: 1
|
||||
}
|
||||
|
||||
void innerUsingNamespace() {
|
||||
using namespace ns;
|
||||
// CHECK: [[@LINE-1]]:19 | namespace/C++ | ns | c:@N@ns | <no-cgname> | Ref,RelCont | rel: 1
|
||||
{
|
||||
using namespace ns::innerAlias;
|
||||
// CHECK: [[@LINE-1]]:25 | namespace-alias/C++ | innerAlias | c:@N@ns@NA@innerAlias | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-2]]:21 | namespace/C++ | ns | c:@N@ns | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK-NOT: [[@LINE-3]]:21
|
||||
}
|
||||
}
|
||||
|
||||
void indexDefaultValueInDefn(Cls cls = Cls(gvi), Record param = Record()) {
|
||||
// CHECK: [[@LINE-1]]:40 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-2]]:44 | variable/C | gvi | c:@gvi | _gvi | Ref,Read,RelCont | rel: 1
|
||||
// CHECK-NOT: [[@LINE-3]]:44
|
||||
// CHECK: [[@LINE-4]]:65 | struct/C++ | Record | c:@S@Record | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK-NOT: [[@LINE-5]]:65
|
||||
}
|
||||
|
||||
template<template <typename> class T>
|
||||
struct IndexDefaultValue {
|
||||
IndexDefaultValue(int k = Record::C) {
|
||||
// CHECK: [[@LINE-1]]:38 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-2]]:30 | struct/C++ | Record | c:@S@Record | <no-cgname> | Ref,RelCont | rel: 1
|
||||
}
|
||||
};
|
||||
|
||||
struct DeletedMethods {
|
||||
DeletedMethods(const DeletedMethods &) = delete;
|
||||
// CHECK: [[@LINE-1]]:3 | constructor/cxx-copy-ctor/C++ | DeletedMethods | c:@S@DeletedMethods@F@DeletedMethods#&1$@S@DeletedMethods# | __ZN14DeletedMethodsC1ERKS_ | Def,RelChild | rel: 1
|
||||
// CHECK: RelChild | DeletedMethods | c:@S@DeletedMethods
|
||||
// CHECK: [[@LINE-3]]:24 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-4]]:3 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | <no-cgname> | Ref,RelCont | rel: 1
|
||||
};
|
||||
|
||||
namespace ns2 {
|
||||
template<typename T> struct ACollectionDecl { };
|
||||
}
|
||||
|
||||
template<typename T = Cls,
|
||||
// CHECK: [[@LINE-1]]:23 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK-NEXT: RelCont | TemplateDefaultValues | c:@ST>3#T#NI#t>1#T@TemplateDefaultValues
|
||||
int x = Record::C,
|
||||
// CHECK: [[@LINE-1]]:26 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read,RelCont | rel: 1
|
||||
// CHECK-NEXT: RelCont | TemplateDefaultValues | c:@ST>3#T#NI#t>1#T@TemplateDefaultValues
|
||||
// CHECK: [[@LINE-3]]:18 | struct/C++ | Record | c:@S@Record | <no-cgname> | Ref,RelCont | rel: 1
|
||||
template <typename> class Collection = ns2::ACollectionDecl>
|
||||
// CHECK: [[@LINE-1]]:49 | namespace/C++ | ns2 | c:@N@ns2 | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK-NEXT: RelCont | TemplateDefaultValues | c:@ST>3#T#NI#t>1#T@TemplateDefaultValues
|
||||
// CHECK: [[@LINE-3]]:54 | struct(Gen)/C++ | ACollectionDecl | c:@N@ns2@ST>1#T@ACollectionDecl | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK-NEXT: RelCont | TemplateDefaultValues | c:@ST>3#T#NI#t>1#T@TemplateDefaultValues
|
||||
struct TemplateDefaultValues { };
|
||||
|
||||
template<typename T = Record,
|
||||
// CHECK: [[@LINE-1]]:23 | struct/C++ | Record | c:@S@Record | <no-cgname> | Ref,RelCont | rel: 1
|
||||
int x = sizeof(Cls)>
|
||||
// CHECK: [[@LINE-1]]:25 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
void functionTemplateDefaultValues() { }
|
||||
|
||||
namespace ensureDefaultTemplateParamsAreRecordedOnce {
|
||||
|
||||
template<typename T = Cls>
|
||||
// CHECK: [[@LINE-1]]:23 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK-NOT: [[@LINE-2]]:23
|
||||
void functionDecl();
|
||||
|
||||
template<typename T>
|
||||
void functionDecl() { }
|
||||
|
||||
template<typename T = Cls>
|
||||
// CHECK: [[@LINE-1]]:23 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK-NOT: [[@LINE-2]]:23
|
||||
class TagDecl;
|
||||
|
||||
template<typename T>
|
||||
class TagDecl;
|
||||
|
||||
template<typename T>
|
||||
class TagDecl { };
|
||||
|
||||
template<typename T = Cls>
|
||||
// CHECK: [[@LINE-1]]:23 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
using TypeAlias = TagDecl<T>;
|
||||
|
||||
template<typename T = Cls>
|
||||
// CHECK: [[@LINE-1]]:23 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK-NOT: [[@LINE-2]]:23
|
||||
extern T varDecl;
|
||||
|
||||
template<typename T>
|
||||
T varDecl = T();
|
||||
|
||||
} // end namespace ensureDefaultTemplateParamsAreRecordedOnce
|
||||
|
@ -385,3 +385,22 @@ Separate separateT;
|
||||
// CHECK: [[@LINE-1]]:1 | type-alias/C | Separate | {{.*}} | {{.*}} | Ref,RelCont | rel: 1
|
||||
struct Separate separateE;
|
||||
// CHECK: [[@LINE-1]]:8 | struct/C | Separate | {{.*}} | {{.*}} | Ref,RelCont | rel: 1
|
||||
|
||||
@interface ClassReceivers
|
||||
|
||||
@property(class) int p1;
|
||||
+ (int)implicit;
|
||||
+ (void)setImplicit:(int)x;
|
||||
|
||||
@end
|
||||
|
||||
void classReceivers() {
|
||||
ClassReceivers.p1 = 0;
|
||||
// CHECK: [[@LINE-1]]:3 | class/ObjC | ClassReceivers | c:objc(cs)ClassReceivers | _OBJC_CLASS_$_ClassReceivers | Ref,RelCont | rel: 1
|
||||
(void)ClassReceivers.p1;
|
||||
// CHECK: [[@LINE-1]]:9 | class/ObjC | ClassReceivers | c:objc(cs)ClassReceivers | _OBJC_CLASS_$_ClassReceivers | Ref,RelCont | rel: 1
|
||||
ClassReceivers.implicit = 0;
|
||||
// CHECK: [[@LINE-1]]:3 | class/ObjC | ClassReceivers | c:objc(cs)ClassReceivers | _OBJC_CLASS_$_ClassReceivers | Ref,RelCont | rel: 1
|
||||
(void)ClassReceivers.implicit;
|
||||
// CHECK: [[@LINE-1]]:9 | class/ObjC | ClassReceivers | c:objc(cs)ClassReceivers | _OBJC_CLASS_$_ClassReceivers | Ref,RelCont | rel: 1
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
// The number of supported attributes should never go down!
|
||||
|
||||
// CHECK: #pragma clang attribute supports 60 attributes:
|
||||
// CHECK: #pragma clang attribute supports 62 attributes:
|
||||
// CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function)
|
||||
@ -30,8 +30,10 @@
|
||||
// CHECK-NEXT: IFunc (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
|
||||
// CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record)
|
||||
// CHECK-NEXT: MicroMips (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: NoDebug (SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter)
|
||||
// CHECK-NEXT: NoDuplicate (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: NoMicroMips (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
|
||||
// CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global)
|
||||
// CHECK-NEXT: NoSplitStack (SubjectMatchRule_function)
|
||||
|
25
test/Modules/extern_cxx.cpp
Normal file
25
test/Modules/extern_cxx.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// RUN: %clang_cc1 -x c++-module-map -fmodule-name=A -verify %s -fmodules-local-submodule-visibility
|
||||
module A { module B {} module C {} }
|
||||
|
||||
#pragma clang module contents
|
||||
|
||||
#pragma clang module begin A.B
|
||||
extern "C++" {
|
||||
#pragma clang module begin A.C
|
||||
template<typename T> void f(T t);
|
||||
#pragma clang module end
|
||||
|
||||
void g() { f(0); } // ok
|
||||
}
|
||||
|
||||
extern "C++" {
|
||||
#pragma clang module begin A.C
|
||||
} // expected-error {{extraneous closing brace}}
|
||||
#pragma clang module end
|
||||
|
||||
#pragma clang module begin A.C
|
||||
extern "C++" { // expected-note {{to match this '{'}}
|
||||
#pragma clang module end // expected-error {{expected '}' at end of module}}
|
||||
}
|
||||
|
||||
#pragma clang module end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user