summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp3
-rw-r--r--lib/AST/ExprClassification.cpp4
-rw-r--r--lib/AST/ExprConstant.cpp33
-rw-r--r--lib/AST/ItaniumMangle.cpp2
-rw-r--r--lib/AST/ODRHash.cpp47
-rw-r--r--lib/CodeGen/BackendUtil.cpp8
-rw-r--r--lib/CodeGen/CGBuiltin.cpp21
-rw-r--r--lib/CodeGen/CGCall.cpp2
-rw-r--r--lib/CodeGen/CGCoroutine.cpp66
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp18
-rw-r--r--lib/CodeGen/CGExpr.cpp47
-rw-r--r--lib/CodeGen/CGExprScalar.cpp51
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.h4
-rw-r--r--lib/CodeGen/CodeGenModule.cpp10
-rw-r--r--lib/CodeGen/CodeGenModule.h7
-rw-r--r--lib/Driver/ToolChains/Clang.cpp3
-rw-r--r--lib/Format/Format.cpp16
-rw-r--r--lib/Format/NamespaceEndCommentsFixer.cpp64
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp80
-rw-r--r--lib/Format/UnwrappedLineParser.cpp5
-rw-r--r--lib/Format/WhitespaceManager.h4
-rw-r--r--lib/Frontend/ASTConsumers.cpp2
-rw-r--r--lib/Frontend/CompilerInvocation.cpp10
-rw-r--r--lib/Index/IndexDecl.cpp13
-rw-r--r--lib/Index/IndexSymbol.cpp4
-rw-r--r--lib/Lex/MacroArgs.cpp20
-rw-r--r--lib/Sema/SemaCodeComplete.cpp10
-rw-r--r--lib/Sema/SemaCoroutine.cpp35
-rw-r--r--lib/Sema/SemaDeclAttr.cpp14
-rw-r--r--lib/Sema/SemaExpr.cpp8
-rw-r--r--lib/Sema/SemaExprCXX.cpp9
-rw-r--r--lib/Sema/SemaLambda.cpp16
-rw-r--r--lib/Sema/SemaStmt.cpp58
-rw-r--r--lib/Serialization/ASTReader.cpp154
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp85
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp6
37 files changed, 692 insertions, 249 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 62b19685c677..2300801c1a9c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3565,7 +3565,7 @@ QualType ASTContext::getSubstTemplateTypeParmPackType(
= new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon,
ArgPack);
Types.push_back(SubstParm);
- SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
+ SubstTemplateTypeParmPackTypes.InsertNode(SubstParm, InsertPos);
return QualType(SubstParm, 0);
}
@@ -8547,6 +8547,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
HowLong = 2;
break;
}
+ break;
}
}
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index c035a42439a3..d149bdd0cdf9 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -190,7 +190,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::DesignatedInitUpdateExprClass:
- case Expr::CoyieldExprClass:
return Cl::CL_PRValue;
// Next come the complicated cases.
@@ -414,7 +413,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return ClassifyInternal(Ctx, cast<InitListExpr>(E)->getInit(0));
case Expr::CoawaitExprClass:
- return ClassifyInternal(Ctx, cast<CoawaitExpr>(E)->getResumeExpr());
+ case Expr::CoyieldExprClass:
+ return ClassifyInternal(Ctx, cast<CoroutineSuspendExpr>(E)->getResumeExpr());
}
llvm_unreachable("unhandled expression kind in classification");
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 17d0ce67dcf9..768947d00ac4 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -4588,7 +4588,7 @@ public:
}
bool handleCallExpr(const CallExpr *E, APValue &Result,
- const LValue *ResultSlot) {
+ const LValue *ResultSlot) {
const Expr *Callee = E->getCallee()->IgnoreParens();
QualType CalleeType = Callee->getType();
@@ -4597,23 +4597,6 @@ public:
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;
@@ -4663,12 +4646,10 @@ public:
if (Args.empty())
return Error(E);
- const Expr *FirstArg = Args[0];
- Args = Args.drop_front();
- EvalArguments.drop_front();
- if (!EvaluateObjectArgument(Info, FirstArg, ThisVal))
+ if (!EvaluateObjectArgument(Info, Args[0], 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
@@ -4720,12 +4701,8 @@ public:
const FunctionDecl *Definition = nullptr;
Stmt *Body = FD->getBody(Definition);
- if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
- return false;
-
- EvalArguments.cancel();
-
- if (!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
+ if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
+ !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
Result, ResultSlot))
return false;
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index c9bb45a37eb5..dc25e5213bae 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -4550,9 +4550,11 @@ CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) {
const FunctionProtoType *Proto =
cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>());
+ FunctionTypeDepthState saved = TrackReturnTypeTags.FunctionTypeDepth.push();
TrackReturnTypeTags.FunctionTypeDepth.enterResultType();
TrackReturnTypeTags.mangleType(Proto->getReturnType());
TrackReturnTypeTags.FunctionTypeDepth.leaveResultType();
+ TrackReturnTypeTags.FunctionTypeDepth.pop(saved);
return TrackReturnTypeTags.AbiTagsRoot.getSortedUniqueUsedAbiTags();
}
diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp
index 08593da89bbd..05bed658f3fc 100644
--- a/lib/AST/ODRHash.cpp
+++ b/lib/AST/ODRHash.cpp
@@ -140,7 +140,33 @@ void ODRHash::AddTemplateName(TemplateName Name) {
}
}
-void ODRHash::AddTemplateArgument(TemplateArgument TA) {}
+void ODRHash::AddTemplateArgument(TemplateArgument TA) {
+ const auto Kind = TA.getKind();
+ ID.AddInteger(Kind);
+
+ switch (Kind) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Type:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::NullPtr:
+ case TemplateArgument::Integral:
+ break;
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ AddTemplateName(TA.getAsTemplateOrTemplatePattern());
+ break;
+ case TemplateArgument::Expression:
+ AddStmt(TA.getAsExpr());
+ break;
+ case TemplateArgument::Pack:
+ ID.AddInteger(TA.pack_size());
+ for (auto SubTA : TA.pack_elements()) {
+ AddTemplateArgument(SubTA);
+ }
+ break;
+ }
+}
+
void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {}
void ODRHash::clear() {
@@ -226,6 +252,17 @@ public:
Inherited::VisitValueDecl(D);
}
+ void VisitVarDecl(const VarDecl *D) {
+ Hash.AddBoolean(D->isStaticLocal());
+ Hash.AddBoolean(D->isConstexpr());
+ const bool HasInit = D->hasInit();
+ Hash.AddBoolean(HasInit);
+ if (HasInit) {
+ AddStmt(D->getInit());
+ }
+ Inherited::VisitVarDecl(D);
+ }
+
void VisitParmVarDecl(const ParmVarDecl *D) {
// TODO: Handle default arguments.
Inherited::VisitParmVarDecl(D);
@@ -310,6 +347,7 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
case Decl::StaticAssert:
case Decl::TypeAlias:
case Decl::Typedef:
+ case Decl::Var:
return true;
}
}
@@ -527,6 +565,13 @@ public:
Hash.AddTemplateName(T->getTemplateName());
VisitType(T);
}
+
+ void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
+ ID.AddInteger(T->getDepth());
+ ID.AddInteger(T->getIndex());
+ Hash.AddBoolean(T->isParameterPack());
+ AddDecl(T->getDecl());
+ }
};
void ODRHash::AddType(const Type *T) {
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 9c4316fb1cd5..bd01902a032b 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -964,11 +964,11 @@ Expected<BitcodeModule> clang::FindThinLTOModule(MemoryBufferRef MBRef) {
if (!BMsOrErr)
return BMsOrErr.takeError();
- // The bitcode file may contain multiple modules, we want the one with a
- // summary.
+ // The bitcode file may contain multiple modules, we want the one that is
+ // marked as being the ThinLTO module.
for (BitcodeModule &BM : *BMsOrErr) {
- Expected<bool> HasSummary = BM.hasSummary();
- if (HasSummary && *HasSummary)
+ Expected<BitcodeLTOInfo> LTOInfo = BM.getLTOInfo();
+ if (LTOInfo && LTOInfo->IsThinLTO)
return BM;
}
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 3b4f8854a9ca..8f0c22d1f7ef 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -7923,6 +7923,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
}
// We can't handle 8-31 immediates with native IR, use the intrinsic.
+ // Except for predicates that create constants.
Intrinsic::ID ID;
switch (BuiltinID) {
default: llvm_unreachable("Unsupported intrinsic!");
@@ -7930,12 +7931,32 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
ID = Intrinsic::x86_sse_cmp_ps;
break;
case X86::BI__builtin_ia32_cmpps256:
+ // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector
+ // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0...
+ if (CC == 0xf || CC == 0xb || CC == 0x1b || CC == 0x1f) {
+ Value *Constant = (CC == 0xf || CC == 0x1f) ?
+ llvm::Constant::getAllOnesValue(Builder.getInt32Ty()) :
+ llvm::Constant::getNullValue(Builder.getInt32Ty());
+ Value *Vec = Builder.CreateVectorSplat(
+ Ops[0]->getType()->getVectorNumElements(), Constant);
+ return Builder.CreateBitCast(Vec, Ops[0]->getType());
+ }
ID = Intrinsic::x86_avx_cmp_ps_256;
break;
case X86::BI__builtin_ia32_cmppd:
ID = Intrinsic::x86_sse2_cmp_pd;
break;
case X86::BI__builtin_ia32_cmppd256:
+ // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector
+ // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0...
+ if (CC == 0xf || CC == 0xb || CC == 0x1b || CC == 0x1f) {
+ Value *Constant = (CC == 0xf || CC == 0x1f) ?
+ llvm::Constant::getAllOnesValue(Builder.getInt64Ty()) :
+ llvm::Constant::getNullValue(Builder.getInt64Ty());
+ Value *Vec = Builder.CreateVectorSplat(
+ Ops[0]->getType()->getVectorNumElements(), Constant);
+ return Builder.CreateBitCast(Vec, Ops[0]->getType());
+ }
ID = Intrinsic::x86_avx_cmp_pd_256;
break;
}
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 079064733585..c65dc18be306 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1795,6 +1795,8 @@ void CodeGenModule::ConstructAttributeList(
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
if (TargetDecl->hasAttr<NoReturnAttr>())
FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
+ if (TargetDecl->hasAttr<ColdAttr>())
+ FuncAttrs.addAttribute(llvm::Attribute::Cold);
if (TargetDecl->hasAttr<NoDuplicateAttr>())
FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
if (TargetDecl->hasAttr<ConvergentAttr>())
diff --git a/lib/CodeGen/CGCoroutine.cpp b/lib/CodeGen/CGCoroutine.cpp
index bc5f6327c9a0..a65faa602b33 100644
--- a/lib/CodeGen/CGCoroutine.cpp
+++ b/lib/CodeGen/CGCoroutine.cpp
@@ -148,25 +148,18 @@ static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) {
//
// See llvm's docs/Coroutines.rst for more details.
//
-static RValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro,
+namespace {
+ struct LValueOrRValue {
+ LValue LV;
+ RValue RV;
+ };
+}
+static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro,
CoroutineSuspendExpr const &S,
AwaitKind Kind, AggValueSlot aggSlot,
- bool ignoreResult) {
+ bool ignoreResult, bool forLValue) {
auto *E = S.getCommonExpr();
- // FIXME: rsmith 5/22/2017. Does it still make sense for us to have a
- // UO_Coawait at all? As I recall, the only purpose it ever had was to
- // represent a dependent co_await expression that couldn't yet be resolved to
- // a CoawaitExpr. But now we have (and need!) a separate DependentCoawaitExpr
- // node to store unqualified lookup results, it seems that the UnaryOperator
- // portion of the representation serves no purpose (and as seen in this patch,
- // it's getting in the way). Can we remove it?
-
- // Skip passthrough operator co_await (present when awaiting on an LValue).
- if (auto *UO = dyn_cast<UnaryOperator>(E))
- if (UO->getOpcode() == UO_Coawait)
- E = UO->getSubExpr();
-
auto Binder =
CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E);
auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); });
@@ -217,7 +210,12 @@ static RValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro,
// Emit await_resume expression.
CGF.EmitBlock(ReadyBlock);
- return CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult);
+ LValueOrRValue Res;
+ if (forLValue)
+ Res.LV = CGF.EmitLValue(S.getResumeExpr());
+ else
+ Res.RV = CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult);
+ return Res;
}
RValue CodeGenFunction::EmitCoawaitExpr(const CoawaitExpr &E,
@@ -225,13 +223,13 @@ RValue CodeGenFunction::EmitCoawaitExpr(const CoawaitExpr &E,
bool ignoreResult) {
return emitSuspendExpression(*this, *CurCoro.Data, E,
CurCoro.Data->CurrentAwaitKind, aggSlot,
- ignoreResult);
+ ignoreResult, /*forLValue*/false).RV;
}
RValue CodeGenFunction::EmitCoyieldExpr(const CoyieldExpr &E,
AggValueSlot aggSlot,
bool ignoreResult) {
return emitSuspendExpression(*this, *CurCoro.Data, E, AwaitKind::Yield,
- aggSlot, ignoreResult);
+ aggSlot, ignoreResult, /*forLValue*/false).RV;
}
void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) {
@@ -240,6 +238,38 @@ void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) {
EmitBranchThroughCleanup(CurCoro.Data->FinalJD);
}
+
+#ifndef NDEBUG
+static QualType getCoroutineSuspendExprReturnType(const ASTContext &Ctx,
+ const CoroutineSuspendExpr *E) {
+ const auto *RE = E->getResumeExpr();
+ // Is it possible for RE to be a CXXBindTemporaryExpr wrapping
+ // a MemberCallExpr?
+ assert(isa<CallExpr>(RE) && "unexpected suspend expression type");
+ return cast<CallExpr>(RE)->getCallReturnType(Ctx);
+}
+#endif
+
+LValue
+CodeGenFunction::EmitCoawaitLValue(const CoawaitExpr *E) {
+ assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() &&
+ "Can't have a scalar return unless the return type is a "
+ "reference type!");
+ return emitSuspendExpression(*this, *CurCoro.Data, *E,
+ CurCoro.Data->CurrentAwaitKind, AggValueSlot::ignored(),
+ /*ignoreResult*/false, /*forLValue*/true).LV;
+}
+
+LValue
+CodeGenFunction::EmitCoyieldLValue(const CoyieldExpr *E) {
+ assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() &&
+ "Can't have a scalar return unless the return type is a "
+ "reference type!");
+ return emitSuspendExpression(*this, *CurCoro.Data, *E,
+ AwaitKind::Yield, AggValueSlot::ignored(),
+ /*ignoreResult*/false, /*forLValue*/true).LV;
+}
+
// Hunts for the parameter reference in the parameter copy/move declaration.
namespace {
struct GetParamRef : public StmtVisitor<GetParamRef> {
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index ebb264eb61c9..b00d296fe34a 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1041,7 +1041,13 @@ llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl,
assert(SizeInBits > 0 && "found named 0-width bitfield");
uint64_t StorageOffsetInBits =
CGM.getContext().toBits(BitFieldInfo.StorageOffset);
- uint64_t OffsetInBits = StorageOffsetInBits + BitFieldInfo.Offset;
+ uint64_t Offset = BitFieldInfo.Offset;
+ // The bit offsets for big endian machines are reversed for big
+ // endian target, compensate for that as the DIDerivedType requires
+ // un-reversed offsets.
+ if (CGM.getDataLayout().isBigEndian())
+ Offset = BitFieldInfo.StorageSize - BitFieldInfo.Size - Offset;
+ uint64_t OffsetInBits = StorageOffsetInBits + Offset;
llvm::DINode::DIFlags Flags = getAccessFlag(BitFieldDecl->getAccess(), RD);
return DBuilder.createBitFieldMemberType(
RecordTy, Name, File, Line, SizeInBits, OffsetInBits, StorageOffsetInBits,
@@ -3484,13 +3490,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
if (VD->hasAttr<BlocksAttr>()) {
// Here, we need an offset *into* the alloca.
CharUnits offset = CharUnits::fromQuantity(32);
- Expr.push_back(llvm::dwarf::DW_OP_plus);
+ Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
// offset of __forwarding field
offset = CGM.getContext().toCharUnitsFromBits(
CGM.getTarget().getPointerWidth(0));
Expr.push_back(offset.getQuantity());
Expr.push_back(llvm::dwarf::DW_OP_deref);
- Expr.push_back(llvm::dwarf::DW_OP_plus);
+ Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
// offset of x field
offset = CGM.getContext().toCharUnitsFromBits(XOffset);
Expr.push_back(offset.getQuantity());
@@ -3599,17 +3605,17 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
SmallVector<int64_t, 9> addr;
addr.push_back(llvm::dwarf::DW_OP_deref);
- addr.push_back(llvm::dwarf::DW_OP_plus);
+ addr.push_back(llvm::dwarf::DW_OP_plus_uconst);
addr.push_back(offset.getQuantity());
if (isByRef) {
addr.push_back(llvm::dwarf::DW_OP_deref);
- addr.push_back(llvm::dwarf::DW_OP_plus);
+ addr.push_back(llvm::dwarf::DW_OP_plus_uconst);
// offset of __forwarding field
offset =
CGM.getContext().toCharUnitsFromBits(target.getPointerSizeInBits(0));
addr.push_back(offset.getQuantity());
addr.push_back(llvm::dwarf::DW_OP_deref);
- addr.push_back(llvm::dwarf::DW_OP_plus);
+ addr.push_back(llvm::dwarf::DW_OP_plus_uconst);
// offset of x field
offset = CGM.getContext().toCharUnitsFromBits(XOffset);
addr.push_back(offset.getQuantity());
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 9f800a75b5bc..7359006677f4 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -549,6 +549,11 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
if (Ptr->getType()->getPointerAddressSpace())
return;
+ // Don't check pointers to volatile data. The behavior here is implementation-
+ // defined.
+ if (Ty.isVolatileQualified())
+ return;
+
SanitizerScope SanScope(this);
SmallVector<std::pair<llvm::Value *, SanitizerMask>, 3> Checks;
@@ -1158,6 +1163,11 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
case Expr::MaterializeTemporaryExprClass:
return EmitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(E));
+
+ case Expr::CoawaitExprClass:
+ return EmitCoawaitLValue(cast<CoawaitExpr>(E));
+ case Expr::CoyieldExprClass:
+ return EmitCoyieldLValue(cast<CoyieldExpr>(E));
}
}
@@ -3002,10 +3012,11 @@ static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF,
llvm::Value *ptr,
ArrayRef<llvm::Value*> indices,
bool inbounds,
+ bool signedIndices,
SourceLocation loc,
const llvm::Twine &name = "arrayidx") {
if (inbounds) {
- return CGF.EmitCheckedInBoundsGEP(ptr, indices, loc, name);
+ return CGF.EmitCheckedInBoundsGEP(ptr, indices, signedIndices, loc, name);
} else {
return CGF.Builder.CreateGEP(ptr, indices, name);
}
@@ -3038,7 +3049,7 @@ static QualType getFixedSizeElementType(const ASTContext &ctx,
static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr,
ArrayRef<llvm::Value *> indices,
QualType eltType, bool inbounds,
- SourceLocation loc,
+ bool signedIndices, SourceLocation loc,
const llvm::Twine &name = "arrayidx") {
// All the indices except that last must be zero.
#ifndef NDEBUG
@@ -3058,8 +3069,8 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr,
CharUnits eltAlign =
getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
- llvm::Value *eltPtr =
- emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, loc, name);
+ llvm::Value *eltPtr = emitArraySubscriptGEP(
+ CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name);
return Address(eltPtr, eltAlign);
}
@@ -3069,6 +3080,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// in lexical order (this complexity is, sadly, required by C++17).
llvm::Value *IdxPre =
(E->getLHS() == E->getIdx()) ? EmitScalarExpr(E->getIdx()) : nullptr;
+ bool SignedIndices = false;
auto EmitIdxAfterBase = [&, IdxPre](bool Promote) -> llvm::Value * {
auto *Idx = IdxPre;
if (E->getLHS() != E->getIdx()) {
@@ -3078,6 +3090,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
QualType IdxTy = E->getIdx()->getType();
bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType();
+ SignedIndices |= IdxSigned;
if (SanOpts.has(SanitizerKind::ArrayBounds))
EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, Accessed);
@@ -3113,7 +3126,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
QualType EltType = LV.getType()->castAs<VectorType>()->getElementType();
Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true,
- E->getExprLoc());
+ SignedIndices, E->getExprLoc());
return MakeAddrLValue(Addr, EltType, LV.getBaseInfo());
}
@@ -3142,7 +3155,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(),
!getLangOpts().isSignedOverflowDefined(),
- E->getExprLoc());
+ SignedIndices, E->getExprLoc());
} else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
// Indexing over an interface, as in "NSString *P; P[4];"
@@ -3167,8 +3180,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// Do the GEP.
CharUnits EltAlign =
getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize);
- llvm::Value *EltPtr = emitArraySubscriptGEP(
- *this, Addr.getPointer(), ScaledIdx, false, E->getExprLoc());
+ llvm::Value *EltPtr =
+ emitArraySubscriptGEP(*this, Addr.getPointer(), ScaledIdx, false,
+ SignedIndices, E->getExprLoc());
Addr = Address(EltPtr, EltAlign);
// Cast back.
@@ -3190,11 +3204,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
// Propagate the alignment from the array itself to the result.
- Addr = emitArraySubscriptGEP(*this, ArrayLV.getAddress(),
- {CGM.getSize(CharUnits::Zero()), Idx},
- E->getType(),
- !getLangOpts().isSignedOverflowDefined(),
- E->getExprLoc());
+ Addr = emitArraySubscriptGEP(
+ *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx},
+ E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices,
+ E->getExprLoc());
BaseInfo = ArrayLV.getBaseInfo();
} else {
// The base must be a pointer; emit it with an estimate of its alignment.
@@ -3202,7 +3215,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(),
!getLangOpts().isSignedOverflowDefined(),
- E->getExprLoc());
+ SignedIndices, E->getExprLoc());
}
LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo);
@@ -3375,7 +3388,7 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
Idx = Builder.CreateNSWMul(Idx, NumElements);
EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(),
!getLangOpts().isSignedOverflowDefined(),
- E->getExprLoc());
+ /*SignedIndices=*/false, E->getExprLoc());
} else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) {
// If this is A[i] where A is an array, the frontend will have decayed the
// base to be a ArrayToPointerDecay implicit cast. While correct, it is
@@ -3395,14 +3408,14 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
EltPtr = emitArraySubscriptGEP(
*this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx},
ResultExprTy, !getLangOpts().isSignedOverflowDefined(),
- E->getExprLoc());
+ /*SignedIndices=*/false, E->getExprLoc());
BaseInfo = ArrayLV.getBaseInfo();
} else {
Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo,
BaseTy, ResultExprTy, IsLowerBound);
EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy,
!getLangOpts().isSignedOverflowDefined(),
- E->getExprLoc());
+ /*SignedIndices=*/false, E->getExprLoc());
}
return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index f9d1fe468748..43c86495f3d3 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1851,6 +1851,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::Value *input;
int amount = (isInc ? 1 : -1);
+ bool signedIndex = !isInc;
if (const AtomicType *atomicTy = type->getAs<AtomicType>()) {
type = atomicTy->getValueType();
@@ -1940,8 +1941,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, numElts, "vla.inc");
else
- value = CGF.EmitCheckedInBoundsGEP(value, numElts, E->getExprLoc(),
- "vla.inc");
+ value = CGF.EmitCheckedInBoundsGEP(value, numElts, signedIndex,
+ E->getExprLoc(), "vla.inc");
// Arithmetic on function pointers (!) is just +-1.
} else if (type->isFunctionType()) {
@@ -1951,8 +1952,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, amt, "incdec.funcptr");
else
- value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(),
- "incdec.funcptr");
+ value = CGF.EmitCheckedInBoundsGEP(value, amt, signedIndex,
+ E->getExprLoc(), "incdec.funcptr");
value = Builder.CreateBitCast(value, input->getType());
// For everything else, we can just do a simple increment.
@@ -1961,8 +1962,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, amt, "incdec.ptr");
else
- value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(),
- "incdec.ptr");
+ value = CGF.EmitCheckedInBoundsGEP(value, amt, signedIndex,
+ E->getExprLoc(), "incdec.ptr");
}
// Vector increment/decrement.
@@ -2043,8 +2044,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, sizeValue, "incdec.objptr");
else
- value = CGF.EmitCheckedInBoundsGEP(value, sizeValue, E->getExprLoc(),
- "incdec.objptr");
+ value = CGF.EmitCheckedInBoundsGEP(value, sizeValue, signedIndex,
+ E->getExprLoc(), "incdec.objptr");
value = Builder.CreateBitCast(value, input->getType());
}
@@ -2661,13 +2662,15 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
std::swap(pointerOperand, indexOperand);
}
+ bool isSigned = indexOperand->getType()->isSignedIntegerOrEnumerationType();
+ bool mayHaveNegativeGEPIndex = isSigned || isSubtraction;
+
unsigned width = cast<llvm::IntegerType>(index->getType())->getBitWidth();
auto &DL = CGF.CGM.getDataLayout();
auto PtrTy = cast<llvm::PointerType>(pointer->getType());
if (width != DL.getTypeSizeInBits(PtrTy)) {
// Zero-extend or sign-extend the pointer value according to
// whether the index is signed or not.
- bool isSigned = indexOperand->getType()->isSignedIntegerOrEnumerationType();
index = CGF.Builder.CreateIntCast(index, DL.getIntPtrType(PtrTy), isSigned,
"idx.ext");
}
@@ -2711,8 +2714,9 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
pointer = CGF.Builder.CreateGEP(pointer, index, "add.ptr");
} else {
index = CGF.Builder.CreateNSWMul(index, numElements, "vla.index");
- pointer = CGF.EmitCheckedInBoundsGEP(pointer, index, op.E->getExprLoc(),
- "add.ptr");
+ pointer =
+ CGF.EmitCheckedInBoundsGEP(pointer, index, mayHaveNegativeGEPIndex,
+ op.E->getExprLoc(), "add.ptr");
}
return pointer;
}
@@ -2729,8 +2733,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
if (CGF.getLangOpts().isSignedOverflowDefined())
return CGF.Builder.CreateGEP(pointer, index, "add.ptr");
- return CGF.EmitCheckedInBoundsGEP(pointer, index, op.E->getExprLoc(),
- "add.ptr");
+ return CGF.EmitCheckedInBoundsGEP(pointer, index, mayHaveNegativeGEPIndex,
+ op.E->getExprLoc(), "add.ptr");
}
// Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and
@@ -3848,6 +3852,7 @@ LValue CodeGenFunction::EmitCompoundAssignmentLValue(
Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr,
ArrayRef<Value *> IdxList,
+ bool SignedIndices,
SourceLocation Loc,
const Twine &Name) {
Value *GEPVal = Builder.CreateInBoundsGEP(Ptr, IdxList, Name);
@@ -3905,7 +3910,7 @@ Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr,
auto *ResultAndOverflow = Builder.CreateCall(
(Opcode == BO_Add) ? SAddIntrinsic : SMulIntrinsic, {LHS, RHS});
OffsetOverflows = Builder.CreateOr(
- OffsetOverflows, Builder.CreateExtractValue(ResultAndOverflow, 1));
+ Builder.CreateExtractValue(ResultAndOverflow, 1), OffsetOverflows);
return Builder.CreateExtractValue(ResultAndOverflow, 0);
};
@@ -3951,12 +3956,18 @@ Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr,
// 1) The total offset doesn't overflow, and
// 2) The sign of the difference between the computed address and the base
// pointer matches the sign of the total offset.
- llvm::Value *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr);
- llvm::Value *NegValid = Builder.CreateICmpULT(ComputedGEP, IntPtr);
- auto *PosOrZeroOffset = Builder.CreateICmpSGE(TotalOffset, Zero);
- llvm::Value *ValidGEP = Builder.CreateAnd(
- Builder.CreateNot(OffsetOverflows),
- Builder.CreateSelect(PosOrZeroOffset, PosOrZeroValid, NegValid));
+ llvm::Value *ValidGEP;
+ auto *NoOffsetOverflow = Builder.CreateNot(OffsetOverflows);
+ auto *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr);
+ if (SignedIndices) {
+ auto *PosOrZeroOffset = Builder.CreateICmpSGE(TotalOffset, Zero);
+ llvm::Value *NegValid = Builder.CreateICmpULT(ComputedGEP, IntPtr);
+ ValidGEP = Builder.CreateAnd(
+ Builder.CreateSelect(PosOrZeroOffset, PosOrZeroValid, NegValid),
+ NoOffsetOverflow);
+ } else {
+ ValidGEP = Builder.CreateAnd(PosOrZeroValid, NoOffsetOverflow);
+ }
llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc)};
// Pass the computed GEP to the runtime to avoid emitting poisoned arguments.
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index 468838e56e38..8d83255ac139 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6327,7 +6327,7 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
}
}
- // If we are in target mode we do not emit any global (declare target is not
+ // If we are in target mode, we do not emit any global (declare target is not
// implemented yet). Therefore we signal that GD was processed in this case.
return true;
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 42ffd0d3efcc..831eedf9e478 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2550,9 +2550,11 @@ public:
RValue EmitCoawaitExpr(const CoawaitExpr &E,
AggValueSlot aggSlot = AggValueSlot::ignored(),
bool ignoreResult = false);
+ LValue EmitCoawaitLValue(const CoawaitExpr *E);
RValue EmitCoyieldExpr(const CoyieldExpr &E,
AggValueSlot aggSlot = AggValueSlot::ignored(),
bool ignoreResult = false);
+ LValue EmitCoyieldLValue(const CoyieldExpr *E);
RValue EmitCoroutineIntrinsic(const CallExpr *E, unsigned int IID);
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
@@ -3554,8 +3556,10 @@ public:
/// Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to
/// detect undefined behavior when the pointer overflow sanitizer is enabled.
+ /// \p SignedIndices indicates whether any of the GEP indices are signed.
llvm::Value *EmitCheckedInBoundsGEP(llvm::Value *Ptr,
ArrayRef<llvm::Value *> IdxList,
+ bool SignedIndices,
SourceLocation Loc,
const Twine &Name = "");
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 77adf7b441a2..19a055075604 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1243,7 +1243,7 @@ void CodeGenModule::AddDependentLib(StringRef Lib) {
/// \brief Add link options implied by the given module, including modules
/// it depends on, using a postorder walk.
static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
- SmallVectorImpl<llvm::Metadata *> &Metadata,
+ SmallVectorImpl<llvm::MDNode *> &Metadata,
llvm::SmallPtrSet<Module *, 16> &Visited) {
// Import this module's parent.
if (Mod->Parent && Visited.insert(Mod->Parent).second) {
@@ -1331,7 +1331,7 @@ void CodeGenModule::EmitModuleLinkOptions() {
// Add link options for all of the imported modules in reverse topological
// order. We don't do anything to try to order import link flags with respect
// to linker options inserted by things like #pragma comment().
- SmallVector<llvm::Metadata *, 16> MetadataArgs;
+ SmallVector<llvm::MDNode *, 16> MetadataArgs;
Visited.clear();
for (Module *M : LinkModules)
if (Visited.insert(M).second)
@@ -1340,9 +1340,9 @@ void CodeGenModule::EmitModuleLinkOptions() {
LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end());
// Add the linker options metadata flag.
- getModule().addModuleFlag(llvm::Module::AppendUnique, "Linker Options",
- llvm::MDNode::get(getLLVMContext(),
- LinkerOptionsMetadata));
+ auto *NMD = getModule().getOrInsertNamedMetadata("llvm.linker.options");
+ for (auto *MD : LinkerOptionsMetadata)
+ NMD->addOperand(MD);
}
void CodeGenModule::EmitDeferred() {
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 0a71c635e8f0..59e56a6ba194 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -429,7 +429,7 @@ private:
llvm::SmallPtrSet<clang::Module *, 16> EmittedModuleInitializers;
/// \brief A vector of metadata strings.
- SmallVector<llvm::Metadata *, 16> LinkerOptionsMetadata;
+ SmallVector<llvm::MDNode *, 16> LinkerOptionsMetadata;
/// @name Cache for Objective-C runtime types
/// @{
@@ -1058,13 +1058,14 @@ public:
void RefreshTypeCacheForClass(const CXXRecordDecl *Class);
- /// \brief Appends Opts to the "Linker Options" metadata value.
+ /// \brief Appends Opts to the "llvm.linker.options" metadata value.
void AppendLinkerOptions(StringRef Opts);
/// \brief Appends a detect mismatch command to the linker options.
void AddDetectMismatch(StringRef Name, StringRef Value);
- /// \brief Appends a dependent lib to the "Linker Options" metadata value.
+ /// \brief Appends a dependent lib to the "llvm.linker.options" metadata
+ /// value.
void AddDependentLib(StringRef Lib);
llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD);
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 6d3dbb5b5204..bd4e894d6504 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -980,6 +980,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
DepTarget = Args.MakeArgString(llvm::sys::path::filename(P));
}
+ if (!A->getOption().matches(options::OPT_MD) && !A->getOption().matches(options::OPT_MMD)) {
+ CmdArgs.push_back("-w");
+ }
CmdArgs.push_back("-MT");
SmallString<128> Quoted;
QuoteTarget(DepTarget, Quoted);
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 2ef6516e02ee..39da87cf9988 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -310,6 +310,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("BreakBeforeBinaryOperators",
Style.BreakBeforeBinaryOperators);
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
+ IO.mapOptional("BreakBeforeInheritanceComma",
+ Style.BreakBeforeInheritanceComma);
IO.mapOptional("BreakBeforeTernaryOperators",
Style.BreakBeforeTernaryOperators);
@@ -330,8 +332,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
IO.mapOptional("ColumnLimit", Style.ColumnLimit);
IO.mapOptional("CommentPragmas", Style.CommentPragmas);
- IO.mapOptional("BreakBeforeInheritanceComma",
- Style.BreakBeforeInheritanceComma);
+ IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
IO.mapOptional("ConstructorInitializerIndentWidth",
@@ -410,6 +411,7 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
+ IO.mapOptional("SplitEmptyFunctionBody", Wrapping.SplitEmptyFunctionBody);
}
};
@@ -485,7 +487,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
return Style;
FormatStyle Expanded = Style;
Expanded.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false};
+ false, false, false, false, false, true};
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
@@ -498,6 +500,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.BraceWrapping.AfterFunction = true;
Expanded.BraceWrapping.AfterStruct = true;
Expanded.BraceWrapping.AfterUnion = true;
+ Expanded.BraceWrapping.SplitEmptyFunctionBody = false;
break;
case FormatStyle::BS_Stroustrup:
Expanded.BraceWrapping.AfterFunction = true;
@@ -517,7 +520,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
break;
case FormatStyle::BS_GNU:
Expanded.BraceWrapping = {true, true, true, true, true, true,
- true, true, true, true, true};
+ true, true, true, true, true, true};
break;
case FormatStyle::BS_WebKit:
Expanded.BraceWrapping.AfterFunction = true;
@@ -548,19 +551,20 @@ FormatStyle getLLVMStyle() {
LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
LLVMStyle.AlwaysBreakTemplateDeclarations = false;
- LLVMStyle.BinPackParameters = true;
LLVMStyle.BinPackArguments = true;
+ LLVMStyle.BinPackParameters = true;
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false};
+ false, false, false, false, false, true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakBeforeInheritanceComma = false;
LLVMStyle.BreakStringLiterals = true;
LLVMStyle.ColumnLimit = 80;
LLVMStyle.CommentPragmas = "^ IWYU pragma:";
+ LLVMStyle.CompactNamespaces = false;
LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
LLVMStyle.ConstructorInitializerIndentWidth = 4;
LLVMStyle.ContinuationIndentWidth = 4;
diff --git a/lib/Format/NamespaceEndCommentsFixer.cpp b/lib/Format/NamespaceEndCommentsFixer.cpp
index 88cf123c1899..1bbb41f757ae 100644
--- a/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -107,6 +107,24 @@ void updateEndComment(const FormatToken *RBraceTok, StringRef EndCommentText,
<< llvm::toString(std::move(Err)) << "\n";
}
}
+
+const FormatToken *
+getNamespaceToken(const AnnotatedLine *line,
+ const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
+ if (!line->Affected || line->InPPDirective || !line->startsWith(tok::r_brace))
+ return nullptr;
+ size_t StartLineIndex = line->MatchingOpeningBlockLineIndex;
+ if (StartLineIndex == UnwrappedLine::kInvalidIndex)
+ return nullptr;
+ assert(StartLineIndex < AnnotatedLines.size());
+ const FormatToken *NamespaceTok = AnnotatedLines[StartLineIndex]->First;
+ // Detect "(inline)? namespace" in the beginning of a line.
+ if (NamespaceTok->is(tok::kw_inline))
+ NamespaceTok = NamespaceTok->getNextNonComment();
+ if (!NamespaceTok || NamespaceTok->isNot(tok::kw_namespace))
+ return nullptr;
+ return NamespaceTok;
+}
} // namespace
NamespaceEndCommentsFixer::NamespaceEndCommentsFixer(const Environment &Env,
@@ -120,20 +138,14 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze(
AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
AnnotatedLines.end());
tooling::Replacements Fixes;
+ std::string AllNamespaceNames = "";
+ size_t StartLineIndex = SIZE_MAX;
+ unsigned int CompactedNamespacesCount = 0;
for (size_t I = 0, E = AnnotatedLines.size(); I != E; ++I) {
- if (!AnnotatedLines[I]->Affected || AnnotatedLines[I]->InPPDirective ||
- !AnnotatedLines[I]->startsWith(tok::r_brace))
- continue;
const AnnotatedLine *EndLine = AnnotatedLines[I];
- size_t StartLineIndex = EndLine->MatchingOpeningBlockLineIndex;
- if (StartLineIndex == UnwrappedLine::kInvalidIndex)
- continue;
- assert(StartLineIndex < E);
- const FormatToken *NamespaceTok = AnnotatedLines[StartLineIndex]->First;
- // Detect "(inline)? namespace" in the beginning of a line.
- if (NamespaceTok->is(tok::kw_inline))
- NamespaceTok = NamespaceTok->getNextNonComment();
- if (!NamespaceTok || NamespaceTok->isNot(tok::kw_namespace))
+ const FormatToken *NamespaceTok =
+ getNamespaceToken(EndLine, AnnotatedLines);
+ if (!NamespaceTok)
continue;
FormatToken *RBraceTok = EndLine->First;
if (RBraceTok->Finalized)
@@ -145,6 +157,27 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze(
if (RBraceTok->Next && RBraceTok->Next->is(tok::semi)) {
EndCommentPrevTok = RBraceTok->Next;
}
+ if (StartLineIndex == SIZE_MAX)
+ StartLineIndex = EndLine->MatchingOpeningBlockLineIndex;
+ std::string NamespaceName = computeName(NamespaceTok);
+ if (Style.CompactNamespaces) {
+ if ((I + 1 < E) &&
+ getNamespaceToken(AnnotatedLines[I + 1], AnnotatedLines) &&
+ StartLineIndex - CompactedNamespacesCount - 1 ==
+ AnnotatedLines[I + 1]->MatchingOpeningBlockLineIndex &&
+ !AnnotatedLines[I + 1]->First->Finalized) {
+ if (hasEndComment(EndCommentPrevTok)) {
+ // remove end comment, it will be merged in next one
+ updateEndComment(EndCommentPrevTok, std::string(), SourceMgr, &Fixes);
+ }
+ CompactedNamespacesCount++;
+ AllNamespaceNames = "::" + NamespaceName + AllNamespaceNames;
+ continue;
+ }
+ NamespaceName += std::move(AllNamespaceNames);
+ CompactedNamespacesCount = 0;
+ AllNamespaceNames = std::string();
+ }
// The next token in the token stream after the place where the end comment
// token must be. This is either the next token on the current line or the
// first token on the next line.
@@ -156,17 +189,16 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze(
bool AddNewline = EndCommentNextTok &&
EndCommentNextTok->NewlinesBefore == 0 &&
EndCommentNextTok->isNot(tok::eof);
- const std::string NamespaceName = computeName(NamespaceTok);
const std::string EndCommentText =
computeEndCommentText(NamespaceName, AddNewline);
if (!hasEndComment(EndCommentPrevTok)) {
bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1;
if (!isShort)
addEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
- continue;
- }
- if (!validEndComment(EndCommentPrevTok, NamespaceName))
+ } else if (!validEndComment(EndCommentPrevTok, NamespaceName)) {
updateEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
+ }
+ StartLineIndex = SIZE_MAX;
}
return Fixes;
}
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index 01504da0a29b..7f644651a6ab 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -66,6 +66,13 @@ public:
Indent += Offset;
}
+ /// \brief Update the indent state given that \p Line indent should be
+ /// skipped.
+ void skipLine(const AnnotatedLine &Line) {
+ while (IndentForLevel.size() <= Line.Level)
+ IndentForLevel.push_back(Indent);
+ }
+
/// \brief Update the level indent to adapt to the given \p Line.
///
/// When a line is not formatted, we move the subsequent lines on the same
@@ -127,12 +134,31 @@ private:
unsigned Indent = 0;
};
+bool isNamespaceDeclaration(const AnnotatedLine *Line) {
+ const FormatToken *NamespaceTok = Line->First;
+ // Detect "(inline)? namespace" in the beginning of a line.
+ if (NamespaceTok->is(tok::kw_inline))
+ NamespaceTok = NamespaceTok->getNextNonComment();
+ return NamespaceTok && NamespaceTok->is(tok::kw_namespace);
+}
+
+bool isEndOfNamespace(const AnnotatedLine *Line,
+ const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
+ if (!Line->startsWith(tok::r_brace))
+ return false;
+ size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex;
+ if (StartLineIndex == UnwrappedLine::kInvalidIndex)
+ return false;
+ assert(StartLineIndex < AnnotatedLines.size());
+ return isNamespaceDeclaration(AnnotatedLines[StartLineIndex]);
+}
+
class LineJoiner {
public:
LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords,
const SmallVectorImpl<AnnotatedLine *> &Lines)
- : Style(Style), Keywords(Keywords), End(Lines.end()),
- Next(Lines.begin()) {}
+ : Style(Style), Keywords(Keywords), End(Lines.end()), Next(Lines.begin()),
+ AnnotatedLines(Lines) {}
/// \brief Returns the next line, merging multiple lines into one if possible.
const AnnotatedLine *getNextMergedLine(bool DryRun,
@@ -142,7 +168,7 @@ public:
const AnnotatedLine *Current = *Next;
IndentTracker.nextLine(*Current);
unsigned MergedLines =
- tryFitMultipleLinesInOne(IndentTracker.getIndent(), Next, End);
+ tryFitMultipleLinesInOne(IndentTracker, Next, End);
if (MergedLines > 0 && Style.ColumnLimit == 0)
// Disallow line merging if there is a break at the start of one of the
// input lines.
@@ -159,9 +185,11 @@ public:
private:
/// \brief Calculates how many lines can be merged into 1 starting at \p I.
unsigned
- tryFitMultipleLinesInOne(unsigned Indent,
+ tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
SmallVectorImpl<AnnotatedLine *>::const_iterator I,
SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
+ const unsigned Indent = IndentTracker.getIndent();
+
// Can't join the last line with anything.
if (I + 1 == E)
return 0;
@@ -186,6 +214,12 @@ private:
? 0
: Limit - TheLine->Last->TotalLength;
+ if (TheLine->Last->is(TT_FunctionLBrace) &&
+ TheLine->First == TheLine->Last &&
+ !Style.BraceWrapping.SplitEmptyFunctionBody &&
+ I[1]->First->is(tok::r_brace))
+ return tryMergeSimpleBlock(I, E, Limit);
+
// FIXME: TheLine->Level != 0 might or might not be the right check to do.
// If necessary, change to something smarter.
bool MergeShortFunctions =
@@ -195,6 +229,38 @@ private:
(Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline &&
TheLine->Level != 0);
+ if (Style.CompactNamespaces) {
+ if (isNamespaceDeclaration(TheLine)) {
+ int i = 0;
+ unsigned closingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
+ for (; I + 1 + i != E && isNamespaceDeclaration(I[i + 1]) &&
+ closingLine == I[i + 1]->MatchingOpeningBlockLineIndex &&
+ I[i + 1]->Last->TotalLength < Limit;
+ i++, closingLine--) {
+ // No extra indent for compacted namespaces
+ IndentTracker.skipLine(*I[i + 1]);
+
+ Limit -= I[i + 1]->Last->TotalLength;
+ }
+ return i;
+ }
+
+ if (isEndOfNamespace(TheLine, AnnotatedLines)) {
+ int i = 0;
+ unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
+ for (; I + 1 + i != E && isEndOfNamespace(I[i + 1], AnnotatedLines) &&
+ openingLine == I[i + 1]->MatchingOpeningBlockLineIndex;
+ i++, openingLine--) {
+ // No space between consecutive braces
+ I[i + 1]->First->SpacesRequiredBefore = !I[i]->Last->is(tok::r_brace);
+
+ // Indent like the outer-most namespace
+ IndentTracker.nextLine(*I[i + 1]);
+ }
+ return i;
+ }
+ }
+
if (TheLine->Last->is(TT_FunctionLBrace) &&
TheLine->First != TheLine->Last) {
return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
@@ -215,7 +281,10 @@ private:
Limit -= 2;
unsigned MergedLines = 0;
- if (MergeShortFunctions) {
+ if (MergeShortFunctions ||
+ (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
+ I[1]->First == I[1]->Last && I + 2 != E &&
+ I[2]->First->is(tok::r_brace))) {
MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
// If we managed to merge the block, count the function header, which is
// on a separate line.
@@ -449,6 +518,7 @@ private:
const SmallVectorImpl<AnnotatedLine *>::const_iterator End;
SmallVectorImpl<AnnotatedLine *>::const_iterator Next;
+ const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
};
static void markFinalized(FormatToken *Tok) {
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index eda7ef36434d..27436dda67a7 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -492,6 +492,11 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
nextToken();
Line->Level = InitialLevel;
Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
+ if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
+ // Update the opening line to add the forward reference as well
+ (*CurrentLines)[OpeningLineIndex].MatchingOpeningBlockLineIndex =
+ CurrentLines->size() - 1;
+ }
}
static bool isGoogScope(const UnwrappedLine &Line) {
diff --git a/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h
index 6be4af262276..50df59d09641 100644
--- a/lib/Format/WhitespaceManager.h
+++ b/lib/Format/WhitespaceManager.h
@@ -43,6 +43,10 @@ public:
/// \brief Replaces the whitespace in front of \p Tok. Only call once for
/// each \c AnnotatedToken.
+ ///
+ /// \p StartOfTokenColumn is the column at which the token will start after
+ /// this replacement. It is needed for determining how \p Spaces is turned
+ /// into tabs and spaces for some format styles.
void replaceWhitespace(FormatToken &Tok, unsigned Newlines, unsigned Spaces,
unsigned StartOfTokenColumn,
bool InPPDirective = false);
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 720baa5e0f7a..7dc475e26f76 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -142,7 +142,7 @@ std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString,
bool DumpDecls,
bool Deserialize,
bool DumpLookups) {
- assert((DumpDecls || DumpLookups) && "nothing to dump");
+ assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
return llvm::make_unique<ASTPrinter>(nullptr,
Deserialize ? ASTPrinter::DumpFull :
DumpDecls ? ASTPrinter::Dump :
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index bb635b7ad714..1667af2d12bb 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -649,8 +649,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables);
Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ);
- const Arg *A = Args.getLastArg(OPT_flto, OPT_flto_EQ);
- Opts.EmitSummaryIndex = A && A->containsValue("thin");
+ Opts.EmitSummaryIndex = false;
+ if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
+ StringRef S = A->getValue();
+ if (S == "thin")
+ Opts.EmitSummaryIndex = true;
+ else if (S != "full")
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+ }
Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false);
if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
if (IK.getLanguage() != InputKind::LLVM_IR)
diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp
index 870b4e4fe825..2162c039c48b 100644
--- a/lib/Index/IndexDecl.cpp
+++ b/lib/Index/IndexDecl.cpp
@@ -293,6 +293,12 @@ public:
return true;
}
+ bool VisitDecompositionDecl(const DecompositionDecl *D) {
+ for (const auto *Binding : D->bindings())
+ TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
+ return Base::VisitDecompositionDecl(D);
+ }
+
bool VisitFieldDecl(const FieldDecl *D) {
SmallVector<SymbolRelation, 4> Relations;
gatherTemplatePseudoOverrides(D, Relations);
@@ -682,6 +688,13 @@ public:
bool VisitImportDecl(const ImportDecl *D) {
return IndexCtx.importedModule(D);
}
+
+ bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
+ IndexCtx.indexBody(D->getAssertExpr(),
+ dyn_cast<NamedDecl>(D->getDeclContext()),
+ D->getLexicalDeclContext());
+ return true;
+ }
};
} // anonymous namespace
diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index 0b20970acc3b..bf358a372149 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/lib/Index/IndexSymbol.cpp
@@ -301,6 +301,10 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
Info.Kind = SymbolKind::TypeAlias;
Info.Lang = SymbolLanguage::CXX;
break;
+ case Decl::Binding:
+ Info.Kind = SymbolKind::Variable;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
default:
break;
}
diff --git a/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp
index 1c1979d8e83d..a201d1659073 100644
--- a/lib/Lex/MacroArgs.cpp
+++ b/lib/Lex/MacroArgs.cpp
@@ -44,20 +44,22 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI,
// Otherwise, use the best fit.
ClosestMatch = (*Entry)->NumUnexpArgTokens;
}
-
+
MacroArgs *Result;
if (!ResultEnt) {
// Allocate memory for a MacroArgs object with the lexer tokens at the end.
- Result = (MacroArgs*)malloc(sizeof(MacroArgs) +
- UnexpArgTokens.size() * sizeof(Token));
+ Result = (MacroArgs *)malloc(sizeof(MacroArgs) +
+ UnexpArgTokens.size() * sizeof(Token));
// Construct the MacroArgs object.
- new (Result) MacroArgs(UnexpArgTokens.size(), VarargsElided);
+ new (Result)
+ MacroArgs(UnexpArgTokens.size(), VarargsElided, MI->getNumArgs());
} else {
Result = *ResultEnt;
// Unlink this node from the preprocessors singly linked list.
*ResultEnt = Result->ArgCache;
Result->NumUnexpArgTokens = UnexpArgTokens.size();
Result->VarargsElided = VarargsElided;
+ Result->NumMacroArgs = MI->getNumArgs();
}
// Copy the actual unexpanded tokens to immediately after the result ptr.
@@ -298,12 +300,10 @@ const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo,
Preprocessor &PP,
SourceLocation ExpansionLocStart,
SourceLocation ExpansionLocEnd) {
- assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!");
- if (StringifiedArgs.empty()) {
- StringifiedArgs.resize(getNumArguments());
- memset((void*)&StringifiedArgs[0], 0,
- sizeof(StringifiedArgs[0])*getNumArguments());
- }
+ assert(ArgNo < getNumMacroArguments() && "Invalid argument number!");
+ if (StringifiedArgs.empty())
+ StringifiedArgs.resize(getNumMacroArguments(), {});
+
if (StringifiedArgs[ArgNo].isNot(tok::string_literal))
StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP,
/*Charify=*/false,
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index b9349dc06bff..83c3bd27596c 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4542,8 +4542,10 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
bool EnteringContext) {
if (!SS.getScopeRep() || !CodeCompleter)
return;
-
- DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
+
+ // Always pretend to enter a context to ensure that a dependent type
+ // resolves to a dependent record.
+ DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
if (!Ctx)
return;
@@ -4573,7 +4575,9 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Results.ExitScope();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
+ LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
+ /*IncludeGlobalScope=*/true,
+ /*IncludeDependentBases=*/true);
HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp
index 06ae66076e8a..b05c0998d3dd 100644
--- a/lib/Sema/SemaCoroutine.cpp
+++ b/lib/Sema/SemaCoroutine.cpp
@@ -470,11 +470,11 @@ static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
return ScopeInfo;
}
-static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc,
- StringRef Keyword) {
- if (!checkCoroutineContext(S, KWLoc, Keyword))
+bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
+ StringRef Keyword) {
+ if (!checkCoroutineContext(*this, KWLoc, Keyword))
return false;
- auto *ScopeInfo = S.getCurFunction();
+ auto *ScopeInfo = getCurFunction();
assert(ScopeInfo->CoroutinePromise);
// If we have existing coroutine statements then we have already built
@@ -484,24 +484,24 @@ static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc,
ScopeInfo->setNeedsCoroutineSuspends(false);
- auto *Fn = cast<FunctionDecl>(S.CurContext);
+ auto *Fn = cast<FunctionDecl>(CurContext);
SourceLocation Loc = Fn->getLocation();
// Build the initial suspend point
auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {
ExprResult Suspend =
- buildPromiseCall(S, ScopeInfo->CoroutinePromise, Loc, Name, None);
+ buildPromiseCall(*this, ScopeInfo->CoroutinePromise, Loc, Name, None);
if (Suspend.isInvalid())
return StmtError();
- Suspend = buildOperatorCoawaitCall(S, SC, Loc, Suspend.get());
+ Suspend = buildOperatorCoawaitCall(*this, SC, Loc, Suspend.get());
if (Suspend.isInvalid())
return StmtError();
- Suspend = S.BuildResolvedCoawaitExpr(Loc, Suspend.get(),
- /*IsImplicit*/ true);
- Suspend = S.ActOnFinishFullExpr(Suspend.get());
+ Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(),
+ /*IsImplicit*/ true);
+ Suspend = ActOnFinishFullExpr(Suspend.get());
if (Suspend.isInvalid()) {
- S.Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
+ Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
<< ((Name == "initial_suspend") ? 0 : 1);
- S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
+ Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
return StmtError();
}
return cast<Stmt>(Suspend.get());
@@ -521,7 +521,7 @@ static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc,
}
ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
- if (!actOnCoroutineBodyStart(*this, S, Loc, "co_await")) {
+ if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) {
CorrectDelayedTyposInExpr(E);
return ExprError();
}
@@ -613,7 +613,7 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
}
ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
- if (!actOnCoroutineBodyStart(*this, S, Loc, "co_yield")) {
+ if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) {
CorrectDelayedTyposInExpr(E);
return ExprError();
}
@@ -658,14 +658,15 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
if (RSS.IsInvalid)
return ExprError();
- Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
- RSS.Results[2], RSS.OpaqueValue);
+ Expr *Res =
+ new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
+ RSS.Results[2], RSS.OpaqueValue);
return Res;
}
StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) {
- if (!actOnCoroutineBodyStart(*this, S, Loc, "co_return")) {
+ if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
CorrectDelayedTyposInExpr(E);
return StmtError();
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 6c492fac9eb9..b43642f5493b 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -313,8 +313,8 @@ static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range,
/// \returns true if IdxExpr is a valid index.
template <typename AttrInfo>
static bool checkFunctionOrMethodParameterIndex(
- Sema &S, const Decl *D, const AttrInfo& Attr,
- unsigned AttrArgNum, const Expr *IdxExpr, uint64_t &Idx) {
+ Sema &S, const Decl *D, const AttrInfo &Attr, unsigned AttrArgNum,
+ const Expr *IdxExpr, uint64_t &Idx, bool AllowImplicitThis = false) {
assert(isFunctionOrMethodOrBlock(D));
// In C++ the implicit 'this' function parameter also counts.
@@ -341,7 +341,7 @@ static bool checkFunctionOrMethodParameterIndex(
return false;
}
Idx--; // Convert to zero-based.
- if (HasImplicitThisParam) {
+ if (HasImplicitThisParam && !AllowImplicitThis) {
if (Idx == 0) {
S.Diag(getAttrLoc(Attr),
diag::err_attribute_invalid_implicit_this_argument)
@@ -4604,14 +4604,16 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
static void handleXRayLogArgsAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
uint64_t ArgCount;
+
if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, Attr.getArgAsExpr(0),
- ArgCount))
+ ArgCount,
+ true /* AllowImplicitThis*/))
return;
// ArgCount isn't a parameter index [0;n), it's a count [1;n] - hence + 1.
D->addAttr(::new (S.Context)
- XRayLogArgsAttr(Attr.getRange(), S.Context, ++ArgCount,
- Attr.getAttributeSpellingListIndex()));
+ XRayLogArgsAttr(Attr.getRange(), S.Context, ++ArgCount,
+ Attr.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0f8f5c253ac6..75a6903392ea 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -12057,11 +12057,17 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
}
break;
case UO_Extension:
- case UO_Coawait:
resultType = Input.get()->getType();
VK = Input.get()->getValueKind();
OK = Input.get()->getObjectKind();
break;
+ case UO_Coawait:
+ // It's unnessesary to represent the pass-through operator co_await in the
+ // AST; just return the input expression instead.
+ assert(!Input.get()->getType()->isDependentType() &&
+ "the co_await expression must be non-dependant before "
+ "building operator co_await");
+ return Input;
}
if (resultType.isNull() || Input.isInvalid())
return ExprError();
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 00a4b39f1423..a9ff21bc41ab 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -189,12 +189,15 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
// have one) and, if that fails to find a match, in the scope (if
// we're allowed to look there).
Found.clear();
- if (Step == 0 && LookupCtx)
+ if (Step == 0 && LookupCtx) {
+ if (RequireCompleteDeclContext(SS, LookupCtx))
+ return nullptr;
LookupQualifiedName(Found, LookupCtx);
- else if (Step == 1 && LookInScope && S)
+ } else if (Step == 1 && LookInScope && S) {
LookupName(Found, S);
- else
+ } else {
continue;
+ }
// FIXME: Should we be suppressing ambiguities here?
if (Found.isAmbiguous())
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index a6239283b47b..d6b70610d461 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -1492,6 +1492,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
bool ExplicitResultType;
CleanupInfo LambdaCleanup;
bool ContainsUnexpandedParameterPack;
+ bool IsGenericLambda;
{
CallOperator = LSI->CallOperator;
Class = LSI->Lambda;
@@ -1500,7 +1501,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
ExplicitResultType = !LSI->HasImplicitReturnType;
LambdaCleanup = LSI->Cleanup;
ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack;
-
+ IsGenericLambda = Class->isGenericLambda();
+
CallOperator->setLexicalDeclContext(Class);
Decl *TemplateOrNonTemplateCallOperatorDecl =
CallOperator->getDescribedFunctionTemplate()
@@ -1520,8 +1522,13 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
bool IsImplicit = I >= LSI->NumExplicitCaptures;
// Warn about unused explicit captures.
- if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed())
- DiagnoseUnusedLambdaCapture(From);
+ if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) {
+ // Initialized captures that are non-ODR used may not be eliminated.
+ bool NonODRUsedInitCapture =
+ IsGenericLambda && From.isNonODRUsed() && From.getInitExpr();
+ if (!NonODRUsedInitCapture)
+ DiagnoseUnusedLambdaCapture(From);
+ }
// Handle 'this' capture.
if (From.isThisCapture()) {
@@ -1568,8 +1575,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// same parameter and return types as the closure type's function call
// operator.
// FIXME: Fix generic lambda to block conversions.
- if (getLangOpts().Blocks && getLangOpts().ObjC1 &&
- !Class->isGenericLambda())
+ if (getLangOpts().Blocks && getLangOpts().ObjC1 && !IsGenericLambda)
addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
// Finalize the lambda class.
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 151b89ab8d2a..eed10b077eb8 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -1989,11 +1989,11 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
return StmtError();
}
- // Coroutines: 'for co_await' implicitly co_awaits its range.
- if (CoawaitLoc.isValid()) {
- ExprResult Coawait = ActOnCoawaitExpr(S, CoawaitLoc, Range);
- if (Coawait.isInvalid()) return StmtError();
- Range = Coawait.get();
+ // Build the coroutine state immediately and not later during template
+ // instantiation
+ if (!CoawaitLoc.isInvalid()) {
+ if (!ActOnCoroutineBodyStart(S, CoawaitLoc, "co_await"))
+ return StmtError();
}
// Build auto && __range = range-init
@@ -2031,16 +2031,12 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
/// BeginExpr and EndExpr are set and FRS_Success is returned on success;
/// CandidateSet and BEF are set and some non-success value is returned on
/// failure.
-static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef,
- Expr *BeginRange, Expr *EndRange,
- QualType RangeType,
- VarDecl *BeginVar,
- VarDecl *EndVar,
- SourceLocation ColonLoc,
- OverloadCandidateSet *CandidateSet,
- ExprResult *BeginExpr,
- ExprResult *EndExpr,
- BeginEndFunction *BEF) {
+static Sema::ForRangeStatus
+BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange,
+ QualType RangeType, VarDecl *BeginVar, VarDecl *EndVar,
+ SourceLocation ColonLoc, SourceLocation CoawaitLoc,
+ OverloadCandidateSet *CandidateSet, ExprResult *BeginExpr,
+ ExprResult *EndExpr, BeginEndFunction *BEF) {
DeclarationNameInfo BeginNameInfo(
&SemaRef.PP.getIdentifierTable().get("begin"), ColonLoc);
DeclarationNameInfo EndNameInfo(&SemaRef.PP.getIdentifierTable().get("end"),
@@ -2087,6 +2083,15 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef,
<< ColonLoc << BEF_begin << BeginRange->getType();
return RangeStatus;
}
+ if (!CoawaitLoc.isInvalid()) {
+ // FIXME: getCurScope() should not be used during template instantiation.
+ // We should pick up the set of unqualified lookup results for operator
+ // co_await during the initial parse.
+ *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc,
+ BeginExpr->get());
+ if (BeginExpr->isInvalid())
+ return Sema::FRS_DiagnosticIssued;
+ }
if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc,
diag::err_for_range_iter_deduction_failure)) {
NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF);
@@ -2206,8 +2211,12 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill
// them in properly when we instantiate the loop.
- if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check)
+ if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) {
+ if (auto *DD = dyn_cast<DecompositionDecl>(LoopVar))
+ for (auto *Binding : DD->bindings())
+ Binding->setType(Context.DependentTy);
LoopVar->setType(SubstAutoType(LoopVar->getType(), Context.DependentTy));
+ }
} else if (!BeginDeclStmt.get()) {
SourceLocation RangeLoc = RangeVar->getLocation();
@@ -2249,6 +2258,11 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// begin-expr is __range.
BeginExpr = BeginRangeRef;
+ if (!CoawaitLoc.isInvalid()) {
+ BeginExpr = ActOnCoawaitExpr(S, ColonLoc, BeginExpr.get());
+ if (BeginExpr.isInvalid())
+ return StmtError();
+ }
if (FinishForRangeVarDecl(*this, BeginVar, BeginRangeRef.get(), ColonLoc,
diag::err_for_range_iter_deduction_failure)) {
NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
@@ -2331,11 +2345,10 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
OverloadCandidateSet CandidateSet(RangeLoc,
OverloadCandidateSet::CSK_Normal);
BeginEndFunction BEFFailure;
- ForRangeStatus RangeStatus =
- BuildNonArrayForRange(*this, BeginRangeRef.get(),
- EndRangeRef.get(), RangeType,
- BeginVar, EndVar, ColonLoc, &CandidateSet,
- &BeginExpr, &EndExpr, &BEFFailure);
+ ForRangeStatus RangeStatus = BuildNonArrayForRange(
+ *this, BeginRangeRef.get(), EndRangeRef.get(), RangeType, BeginVar,
+ EndVar, ColonLoc, CoawaitLoc, &CandidateSet, &BeginExpr, &EndExpr,
+ &BEFFailure);
if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction &&
BEFFailure == BEF_begin) {
@@ -2432,6 +2445,9 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get());
if (!IncrExpr.isInvalid() && CoawaitLoc.isValid())
+ // FIXME: getCurScope() should not be used during template instantiation.
+ // We should pick up the set of unqualified lookup results for operator
+ // co_await during the initial parse.
IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get());
if (!IncrExpr.isInvalid())
IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 94a8f609f57c..eeb0132c1690 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -9242,6 +9242,7 @@ void ASTReader::diagnoseOdrViolations() {
// Used with err_module_odr_violation_mismatch_decl and
// note_module_odr_violation_mismatch_decl
+ // This list should be the same Decl's as in ODRHash::isWhiteListedDecl
enum {
EndOfClass,
PublicSpecifer,
@@ -9250,6 +9251,9 @@ void ASTReader::diagnoseOdrViolations() {
StaticAssert,
Field,
CXXMethod,
+ TypeAlias,
+ TypeDef,
+ Var,
Other
} FirstDiffType = Other,
SecondDiffType = Other;
@@ -9277,6 +9281,12 @@ void ASTReader::diagnoseOdrViolations() {
return Field;
case Decl::CXXMethod:
return CXXMethod;
+ case Decl::TypeAlias:
+ return TypeAlias;
+ case Decl::Typedef:
+ return TypeDef;
+ case Decl::Var:
+ return Var;
}
};
@@ -9373,6 +9383,15 @@ void ASTReader::diagnoseOdrViolations() {
MethodNumberParameters,
MethodParameterType,
MethodParameterName,
+ MethodParameterSingleDefaultArgument,
+ MethodParameterDifferentDefaultArgument,
+ TypedefName,
+ TypedefType,
+ VarName,
+ VarType,
+ VarSingleInitializer,
+ VarDifferentInitializer,
+ VarConstexpr,
};
// These lambdas have the common portions of the ODR diagnostics. This
@@ -9739,6 +9758,38 @@ void ASTReader::diagnoseOdrViolations() {
ParameterMismatch = true;
break;
}
+
+ const Expr *FirstInit = FirstParam->getInit();
+ const Expr *SecondInit = SecondParam->getInit();
+ if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
+ ODRDiagError(FirstMethod->getLocation(),
+ FirstMethod->getSourceRange(),
+ MethodParameterSingleDefaultArgument)
+ << FirstName << (I + 1) << (FirstInit == nullptr)
+ << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
+ ODRDiagNote(SecondMethod->getLocation(),
+ SecondMethod->getSourceRange(),
+ MethodParameterSingleDefaultArgument)
+ << SecondName << (I + 1) << (SecondInit == nullptr)
+ << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (FirstInit && SecondInit &&
+ ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
+ ODRDiagError(FirstMethod->getLocation(),
+ FirstMethod->getSourceRange(),
+ MethodParameterDifferentDefaultArgument)
+ << FirstName << (I + 1) << FirstInit->getSourceRange();
+ ODRDiagNote(SecondMethod->getLocation(),
+ SecondMethod->getSourceRange(),
+ MethodParameterDifferentDefaultArgument)
+ << SecondName << (I + 1) << SecondInit->getSourceRange();
+ ParameterMismatch = true;
+ break;
+
+ }
}
if (ParameterMismatch) {
@@ -9748,6 +9799,109 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
+ case TypeAlias:
+ case TypeDef: {
+ TypedefNameDecl *FirstTD = cast<TypedefNameDecl>(FirstDecl);
+ TypedefNameDecl *SecondTD = cast<TypedefNameDecl>(SecondDecl);
+ auto FirstName = FirstTD->getDeclName();
+ auto SecondName = SecondTD->getDeclName();
+ if (FirstName != SecondName) {
+ ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(),
+ TypedefName)
+ << (FirstDiffType == TypeAlias) << FirstName;
+ ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(),
+ TypedefName)
+ << (FirstDiffType == TypeAlias) << SecondName;
+ Diagnosed = true;
+ break;
+ }
+
+ QualType FirstType = FirstTD->getUnderlyingType();
+ QualType SecondType = SecondTD->getUnderlyingType();
+ if (ComputeQualTypeODRHash(FirstType) !=
+ ComputeQualTypeODRHash(SecondType)) {
+ ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(),
+ TypedefType)
+ << (FirstDiffType == TypeAlias) << FirstName << FirstType;
+ ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(),
+ TypedefType)
+ << (FirstDiffType == TypeAlias) << SecondName << SecondType;
+ Diagnosed = true;
+ break;
+ }
+ break;
+ }
+ case Var: {
+ VarDecl *FirstVD = cast<VarDecl>(FirstDecl);
+ VarDecl *SecondVD = cast<VarDecl>(SecondDecl);
+ auto FirstName = FirstVD->getDeclName();
+ auto SecondName = SecondVD->getDeclName();
+ if (FirstName != SecondName) {
+ ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(),
+ VarName)
+ << FirstName;
+ ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(),
+ VarName)
+ << SecondName;
+ Diagnosed = true;
+ break;
+ }
+
+ QualType FirstType = FirstVD->getType();
+ QualType SecondType = SecondVD->getType();
+ if (ComputeQualTypeODRHash(FirstType) !=
+ ComputeQualTypeODRHash(SecondType)) {
+ ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(),
+ VarType)
+ << FirstName << FirstType;
+ ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(),
+ VarType)
+ << SecondName << SecondType;
+ Diagnosed = true;
+ break;
+ }
+
+ const Expr *FirstInit = FirstVD->getInit();
+ const Expr *SecondInit = SecondVD->getInit();
+ if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
+ ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(),
+ VarSingleInitializer)
+ << FirstName << (FirstInit == nullptr)
+ << (FirstInit ? FirstInit->getSourceRange(): SourceRange());
+ ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(),
+ VarSingleInitializer)
+ << SecondName << (SecondInit == nullptr)
+ << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
+ Diagnosed = true;
+ break;
+ }
+
+ if (FirstInit && SecondInit &&
+ ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
+ ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(),
+ VarDifferentInitializer)
+ << FirstName << FirstInit->getSourceRange();
+ ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(),
+ VarDifferentInitializer)
+ << SecondName << SecondInit->getSourceRange();
+ Diagnosed = true;
+ break;
+ }
+
+ const bool FirstIsConstexpr = FirstVD->isConstexpr();
+ const bool SecondIsConstexpr = SecondVD->isConstexpr();
+ if (FirstIsConstexpr != SecondIsConstexpr) {
+ ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(),
+ VarConstexpr)
+ << FirstName << FirstIsConstexpr;
+ ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(),
+ VarConstexpr)
+ << SecondName << SecondIsConstexpr;
+ Diagnosed = true;
+ break;
+ }
+ break;
+ }
}
if (Diagnosed == true)
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 9c467055fe55..ed103e629216 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -216,30 +216,6 @@ namespace clang {
TypedefNameForLinkage(nullptr), HasPendingBody(false),
IsDeclMarkedUsed(false) {}
- template <typename T> static
- void AddLazySpecializations(T *D,
- SmallVectorImpl<serialization::DeclID>& IDs) {
- if (IDs.empty())
- return;
-
- // FIXME: We should avoid this pattern of getting the ASTContext.
- ASTContext &C = D->getASTContext();
-
- auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations;
-
- if (auto &Old = LazySpecializations) {
- IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
- std::sort(IDs.begin(), IDs.end());
- IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
- }
-
- auto *Result = new (C) serialization::DeclID[1 + IDs.size()];
- *Result = IDs.size();
- std::copy(IDs.begin(), IDs.end(), Result + 1);
-
- LazySpecializations = Result;
- }
-
template <typename DeclT>
static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D);
static Decl *getMostRecentDeclImpl(...);
@@ -268,7 +244,7 @@ namespace clang {
void ReadFunctionDefinition(FunctionDecl *FD);
void Visit(Decl *D);
- void UpdateDecl(Decl *D, llvm::SmallVectorImpl<serialization::DeclID>&);
+ void UpdateDecl(Decl *D);
static void setNextObjCCategory(ObjCCategoryDecl *Cat,
ObjCCategoryDecl *Next) {
@@ -1976,6 +1952,21 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
return Redecl;
}
+static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old,
+ SmallVectorImpl<DeclID> &IDs) {
+ assert(!IDs.empty() && "no IDs to add to list");
+ if (Old) {
+ IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
+ std::sort(IDs.begin(), IDs.end());
+ IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
+ }
+
+ auto *Result = new (Context) DeclID[1 + IDs.size()];
+ *Result = IDs.size();
+ std::copy(IDs.begin(), IDs.end(), Result + 1);
+ return Result;
+}
+
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
@@ -1984,7 +1975,12 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// the specializations.
SmallVector<serialization::DeclID, 32> SpecIDs;
ReadDeclIDList(SpecIDs);
- ASTDeclReader::AddLazySpecializations(D, SpecIDs);
+
+ if (!SpecIDs.empty()) {
+ auto *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = newDeclIDList(
+ Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
+ }
}
if (D->getTemplatedDecl()->TemplateOrInstantiation) {
@@ -2011,7 +2007,12 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
// the specializations.
SmallVector<serialization::DeclID, 32> SpecIDs;
ReadDeclIDList(SpecIDs);
- ASTDeclReader::AddLazySpecializations(D, SpecIDs);
+
+ if (!SpecIDs.empty()) {
+ auto *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = newDeclIDList(
+ Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
+ }
}
}
@@ -2117,7 +2118,12 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
// This FunctionTemplateDecl owns a CommonPtr; read it.
SmallVector<serialization::DeclID, 32> SpecIDs;
ReadDeclIDList(SpecIDs);
- ASTDeclReader::AddLazySpecializations(D, SpecIDs);
+
+ if (!SpecIDs.empty()) {
+ auto *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = newDeclIDList(
+ Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
+ }
}
}
@@ -3661,9 +3667,6 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
Decl *D = Record.D;
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
-
- llvm::SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs;
-
if (UpdI != DeclUpdateOffsets.end()) {
auto UpdateOffsets = std::move(UpdI->second);
DeclUpdateOffsets.erase(UpdI);
@@ -3688,7 +3691,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID,
SourceLocation());
- Reader.UpdateDecl(D, PendingLazySpecializationIDs);
+ Reader.UpdateDecl(D);
// We might have made this declaration interesting. If so, remember that
// we need to hand it off to the consumer.
@@ -3700,17 +3703,6 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
}
}
}
- // Add the lazy specializations to the template.
- assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) ||
- isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) &&
- "Must not have pending specializations");
- if (auto *CTD = dyn_cast<ClassTemplateDecl>(D))
- ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs);
- else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
- ASTDeclReader::AddLazySpecializations(FTD, PendingLazySpecializationIDs);
- else if (auto *VTD = dyn_cast<VarTemplateDecl>(D))
- ASTDeclReader::AddLazySpecializations(VTD, PendingLazySpecializationIDs);
- PendingLazySpecializationIDs.clear();
// Load the pending visible updates for this decl context, if it has any.
auto I = PendingVisibleUpdates.find(ID);
@@ -3907,8 +3899,7 @@ static void forAllLaterRedecls(DeclT *D, Fn F) {
}
}
-void ASTDeclReader::UpdateDecl(Decl *D,
- llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) {
+void ASTDeclReader::UpdateDecl(Decl *D) {
while (Record.getIdx() < Record.size()) {
switch ((DeclUpdateKind)Record.readInt()) {
case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
@@ -3924,8 +3915,8 @@ void ASTDeclReader::UpdateDecl(Decl *D,
}
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
- // It will be added to the template's lazy specialization set.
- PendingLazySpecializationIDs.push_back(ReadDeclID());
+ // It will be added to the template's specializations set when loaded.
+ (void)Record.readDecl();
break;
case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp
index ee761689f479..1858bfd89637 100644
--- a/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -957,6 +957,12 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
return RuntimeDefinition();
DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver);
+ if (!DTI.isValid()) {
+ assert(isa<AllocaRegion>(Receiver) &&
+ "Unhandled untyped region class!");
+ return RuntimeDefinition();
+ }
+
QualType DynType = DTI.getType();
CanBeSubClassed = DTI.canBeASubClass();
ReceiverT = dyn_cast<ObjCObjectPointerType>(DynType.getCanonicalType());