Vendor import of clang trunk r303571:

https://llvm.org/svn/llvm-project/cfe/trunk@303571
This commit is contained in:
dim 2017-05-22 19:43:45 +00:00
parent 6a6f323115
commit a398cb507e
123 changed files with 1748 additions and 896 deletions

View File

@ -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:

View File

@ -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.

View File

@ -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) {

View File

@ -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.

View File

@ -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];
}
}

View File

@ -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.
//

View File

@ -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 = [{

View File

@ -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<

View File

@ -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 {

View File

@ -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 &&

View File

@ -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,

View File

@ -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:

View File

@ -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.

View File

@ -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) {

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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];
}

View File

@ -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());

View File

@ -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>();
}

View File

@ -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;

View File

@ -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:

View File

@ -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 << ")))";
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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()}),

View File

@ -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(),

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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());

View File

@ -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:

View File

@ -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) {

View File

@ -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 {

View File

@ -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.

View File

@ -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(

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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();
}
};
}

View File

@ -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

View File

@ -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;

View File

@ -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())

View File

@ -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;

View File

@ -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))

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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);

View File

@ -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());
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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
//----------------------------------------------------------------------------//

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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());

View File

@ -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)) {

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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.

View File

@ -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:

View File

@ -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 {

View File

@ -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);

View File

@ -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:

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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.
//

View File

@ -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);
}

View File

@ -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

View File

@ -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()) {

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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>

View File

@ -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

View File

@ -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.

View 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);

View File

@ -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;

View 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" {{.*}} }

View 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}

View File

@ -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}

View 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;
}

View File

@ -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:.*]]}

View 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;
}

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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
}

View File

@ -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)

View 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