summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-01-06 21:35:46 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-01-06 21:35:46 +0000
commitead8c8e4f12a52fe33a395d4dce984c89ab04a77 (patch)
tree370cd144f688870dbf79c8c799ada394855047d5 /lib
parent55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff)
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Decl.cpp6
-rw-r--r--lib/Basic/Targets/X86.cpp7
-rw-r--r--lib/Basic/Version.cpp2
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp4
-rw-r--r--lib/CodeGen/CGException.cpp55
-rw-r--r--lib/CodeGen/CGExpr.cpp7
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.cpp300
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.h565
-rw-r--r--lib/CodeGen/CGStmt.cpp9
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp127
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp3
-rw-r--r--lib/CodeGen/CodeGenFunction.h11
-rw-r--r--lib/CodeGen/CodeGenModule.cpp8
-rw-r--r--lib/Driver/Driver.cpp264
-rw-r--r--lib/Driver/ToolChains/Clang.cpp4
-rw-r--r--lib/Driver/ToolChains/Darwin.cpp47
-rw-r--r--lib/Frontend/CompilerInvocation.cpp14
-rw-r--r--lib/Frontend/InitPreprocessor.cpp4
-rw-r--r--lib/Headers/emmintrin.h111
-rw-r--r--lib/Headers/pmmintrin.h6
-rw-r--r--lib/Headers/smmintrin.h6
-rw-r--r--lib/Parse/ParseDecl.cpp217
-rw-r--r--lib/Parse/ParseDeclCXX.cpp72
-rw-r--r--lib/Parse/ParseExpr.cpp12
-rw-r--r--lib/Parse/ParseExprCXX.cpp63
-rw-r--r--lib/Parse/ParseObjc.cpp36
-rw-r--r--lib/Parse/ParseOpenMP.cpp3
-rw-r--r--lib/Parse/ParseStmt.cpp10
-rw-r--r--lib/Parse/ParseTemplate.cpp33
-rw-r--r--lib/Parse/Parser.cpp23
-rw-r--r--lib/Sema/DeclSpec.cpp14
-rw-r--r--lib/Sema/SemaCodeComplete.cpp4
-rw-r--r--lib/Sema/SemaDecl.cpp52
-rw-r--r--lib/Sema/SemaDeclCXX.cpp119
-rw-r--r--lib/Sema/SemaDeclObjC.cpp2
-rw-r--r--lib/Sema/SemaExpr.cpp15
-rw-r--r--lib/Sema/SemaExprCXX.cpp16
-rw-r--r--lib/Sema/SemaExprMember.cpp2
-rw-r--r--lib/Sema/SemaLambda.cpp55
-rw-r--r--lib/Sema/SemaOverload.cpp26
-rw-r--r--lib/Sema/SemaStmt.cpp7
-rw-r--r--lib/Sema/SemaTemplate.cpp24
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp177
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp30
-rw-r--r--lib/Sema/SemaType.cpp280
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp1
46 files changed, 2064 insertions, 789 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 4c1d591b41e9c..918466236bffd 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -779,7 +779,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// unique-external linkage, it's not legally usable from outside
// this translation unit. However, we should use the C linkage
// rules instead for extern "C" declarations.
- if (Context.getLangOpts().CPlusPlus && !Function->isInExternCContext()) {
+ if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Function)) {
// Only look at the type-as-written. Otherwise, deducing the return type
// of a function could change its linkage.
QualType TypeAsWritten = Function->getType();
@@ -1165,7 +1165,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
LVComputationKind computation) {
if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
if (Function->isInAnonymousNamespace() &&
- !Function->isInExternCContext())
+ !isFirstInExternCContext(Function))
return getInternalLinkageFor(Function);
// This is a "void f();" which got merged with a file static.
@@ -1188,7 +1188,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
if (const auto *Var = dyn_cast<VarDecl>(D)) {
if (Var->hasExternalStorage()) {
- if (Var->isInAnonymousNamespace() && !Var->isInExternCContext())
+ if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var))
return getInternalLinkageFor(Var);
LinkageInfo LV;
diff --git a/lib/Basic/Targets/X86.cpp b/lib/Basic/Targets/X86.cpp
index 3efba26a83731..70433ff066fc0 100644
--- a/lib/Basic/Targets/X86.cpp
+++ b/lib/Basic/Targets/X86.cpp
@@ -139,7 +139,6 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "avx512vnni", true);
setFeatureEnabledImpl(Features, "avx512vbmi2", true);
setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
- setFeatureEnabledImpl(Features, "clwb", true);
LLVM_FALLTHROUGH;
case CK_Cannonlake:
setFeatureEnabledImpl(Features, "avx512ifma", true);
@@ -152,10 +151,8 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "avx512dq", true);
setFeatureEnabledImpl(Features, "avx512bw", true);
setFeatureEnabledImpl(Features, "avx512vl", true);
- if (Kind == CK_SkylakeServer) {
- setFeatureEnabledImpl(Features, "pku", true);
- setFeatureEnabledImpl(Features, "clwb", true);
- }
+ setFeatureEnabledImpl(Features, "pku", true);
+ setFeatureEnabledImpl(Features, "clwb", true);
LLVM_FALLTHROUGH;
case CK_SkylakeClient:
setFeatureEnabledImpl(Features, "xsavec", true);
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index a1a67c2bc144d..2dd16da99104c 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -36,7 +36,7 @@ std::string getClangRepositoryPath() {
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
// pick up a tag in an SVN export, for example.
- StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $");
+ StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/branches/release_60/lib/Basic/Version.cpp $");
if (URL.empty()) {
URL = SVNRepository.slice(SVNRepository.find(':'),
SVNRepository.find("/lib/Basic"));
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 0429978317021..8c0e01e5624ae 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -173,10 +173,12 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
ConstantAddress DeclAddr(DeclPtr, getContext().getDeclAlign(&D));
if (!T->isReferenceType()) {
- if (getLangOpts().OpenMP && D.hasAttr<OMPThreadPrivateDeclAttr>())
+ if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
+ D.hasAttr<OMPThreadPrivateDeclAttr>()) {
(void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition(
&D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
PerformInit, this);
+ }
if (PerformInit)
EmitDeclInit(*this, D, DeclAddr);
if (CGM.isTypeConstant(D.getType(), true))
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 1ec084ff3f5b6..1978d2757ac51 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -646,7 +646,7 @@ CodeGenFunction::getMSVCDispatchBlock(EHScopeStack::stable_iterator SI) {
return DispatchBlock;
if (EHS.getKind() == EHScope::Terminate)
- DispatchBlock = getTerminateHandler();
+ DispatchBlock = getTerminateFunclet();
else
DispatchBlock = createBasicBlock();
CGBuilderTy Builder(*this, DispatchBlock);
@@ -1334,24 +1334,15 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
if (TerminateHandler)
return TerminateHandler;
- CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
-
// Set up the terminate handler. This block is inserted at the very
// end of the function by FinishFunction.
TerminateHandler = createBasicBlock("terminate.handler");
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
Builder.SetInsertPoint(TerminateHandler);
+
llvm::Value *Exn = nullptr;
- SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
- CurrentFuncletPad);
- if (EHPersonality::get(*this).usesFuncletPads()) {
- llvm::Value *ParentPad = CurrentFuncletPad;
- if (!ParentPad)
- ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
- CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad);
- } else {
- if (getLangOpts().CPlusPlus)
- Exn = getExceptionFromSlot();
- }
+ if (getLangOpts().CPlusPlus)
+ Exn = getExceptionFromSlot();
llvm::CallInst *terminateCall =
CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
terminateCall->setDoesNotReturn();
@@ -1363,6 +1354,42 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
return TerminateHandler;
}
+llvm::BasicBlock *CodeGenFunction::getTerminateFunclet() {
+ assert(EHPersonality::get(*this).usesFuncletPads() &&
+ "use getTerminateLandingPad for non-funclet EH");
+
+ llvm::BasicBlock *&TerminateFunclet = TerminateFunclets[CurrentFuncletPad];
+ if (TerminateFunclet)
+ return TerminateFunclet;
+
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+
+ // Set up the terminate handler. This block is inserted at the very
+ // end of the function by FinishFunction.
+ TerminateFunclet = createBasicBlock("terminate.handler");
+ Builder.SetInsertPoint(TerminateFunclet);
+
+ // Create the cleanuppad using the current parent pad as its token. Use 'none'
+ // if this is a top-level terminate scope, which is the common case.
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+ CurrentFuncletPad);
+ llvm::Value *ParentPad = CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+ CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad);
+
+ // Emit the __std_terminate call.
+ llvm::CallInst *terminateCall =
+ CGM.getCXXABI().emitTerminateForUnexpectedException(*this, nullptr);
+ terminateCall->setDoesNotReturn();
+ Builder.CreateUnreachable();
+
+ // Restore the saved insertion state.
+ Builder.restoreIP(SavedIP);
+
+ return TerminateFunclet;
+}
+
llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {
if (EHResumeBlock) return EHResumeBlock;
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index c7dc8337e19e0..3f81be00f32d5 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -2263,9 +2263,11 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
Address Addr(V, Alignment);
// Emit reference to the private copy of the variable if it is an OpenMP
// threadprivate variable.
- if (CGF.getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>())
+ if (CGF.getLangOpts().OpenMP && !CGF.getLangOpts().OpenMPSimd &&
+ VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
return EmitThreadPrivateVarDeclLValue(CGF, VD, T, Addr, RealVarTy,
E->getExprLoc());
+ }
LValue LV = VD->getType()->isReferenceType() ?
CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
AlignmentSource::Decl) :
@@ -2446,7 +2448,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// Check for OpenMP threadprivate variables.
- if (getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
+ if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
+ VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
return EmitThreadPrivateVarDeclLValue(
*this, VD, T, addr, getTypes().ConvertTypeForMem(VD->getType()),
E->getExprLoc());
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index fa38ee80bf41e..784c90a9eb912 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -397,6 +397,7 @@ class InlinedOpenMPRegionRAII {
CodeGenFunction &CGF;
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
FieldDecl *LambdaThisCaptureField = nullptr;
+ const CodeGen::CGBlockInfo *BlockInfo = nullptr;
public:
/// \brief Constructs region for combined constructs.
@@ -412,6 +413,8 @@ public:
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
LambdaThisCaptureField = CGF.LambdaThisCaptureField;
CGF.LambdaThisCaptureField = nullptr;
+ BlockInfo = CGF.BlockInfo;
+ CGF.BlockInfo = nullptr;
}
~InlinedOpenMPRegionRAII() {
@@ -422,6 +425,7 @@ public:
CGF.CapturedStmtInfo = OldCSI;
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
CGF.LambdaThisCaptureField = LambdaThisCaptureField;
+ CGF.BlockInfo = BlockInfo;
}
};
@@ -8014,3 +8018,299 @@ Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
const VarDecl *TargetParam) const {
return CGF.GetAddrOfLocalVar(NativeParam);
}
+
+llvm::Value *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+llvm::Value *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+llvm::Value *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ const VarDecl *PartIDVar, const VarDecl *TaskTVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
+ bool Tied, unsigned &NumberOfParts) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> CapturedVars,
+ const Expr *IfCond) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitCriticalRegion(
+ CodeGenFunction &CGF, StringRef CriticalName,
+ const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
+ const Expr *Hint) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &MasterOpGen,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
+ CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitSingleRegion(
+ CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
+ SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
+ ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
+ ArrayRef<const Expr *> AssignmentOps) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &OrderedOpGen,
+ SourceLocation Loc,
+ bool IsThreads) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ OpenMPDirectiveKind Kind,
+ bool EmitChecks,
+ bool ForceSimpleCall) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitForDispatchInit(
+ CodeGenFunction &CGF, SourceLocation Loc,
+ const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
+ bool Ordered, const DispatchRTInput &DispatchValues) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitForStaticInit(
+ CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
+ const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
+ CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ unsigned IVSize,
+ bool IVSigned) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ OpenMPDirectiveKind DKind) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ unsigned IVSize, bool IVSigned,
+ Address IL, Address LB,
+ Address UB, Address ST) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
+ llvm::Value *NumThreads,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
+ OpenMPProcBindClauseKind ProcBind,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
+ const VarDecl *VD,
+ Address VDAddr,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
+ const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
+ CodeGenFunction *CGF) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
+ CodeGenFunction &CGF, QualType VarType, StringRef Name) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
+ ArrayRef<const Expr *> Vars,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const OMPExecutableDirective &D,
+ llvm::Value *TaskFunction,
+ QualType SharedsTy, Address Shareds,
+ const Expr *IfCond,
+ const OMPTaskDataTy &Data) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskLoopCall(
+ CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
+ llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
+ const Expr *IfCond, const OMPTaskDataTy &Data) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitReduction(
+ CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
+ ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
+ assert(Options.SimpleReduction && "Only simple reduction is expected.");
+ CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
+ ReductionOps, Options);
+}
+
+llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
+ CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ ReductionCodeGen &RCG,
+ unsigned N) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ llvm::Value *ReductionsPtr,
+ LValue SharedLVal) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitCancellationPointCall(
+ CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind CancelRegion) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
+ SourceLocation Loc, const Expr *IfCond,
+ OpenMPDirectiveKind CancelRegion) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
+ const OMPExecutableDirective &D, StringRef ParentName,
+ llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
+ bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ llvm::Value *OutlinedFn,
+ llvm::Value *OutlinedFnID,
+ const Expr *IfCond, const Expr *Device,
+ ArrayRef<llvm::Value *> CapturedVars) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
+ return false;
+}
+
+llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() {
+ return nullptr;
+}
+
+void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ SourceLocation Loc,
+ llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> CapturedVars) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
+ const Expr *NumTeams,
+ const Expr *ThreadLimit,
+ SourceLocation Loc) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTargetDataCalls(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
+ const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
+ const Expr *Device) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
+ const OMPLoopDirective &D) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
+ const OMPDependClause *C) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+const VarDecl *
+CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
+ const VarDecl *NativeParam) const {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
+Address
+CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
+ const VarDecl *NativeParam,
+ const VarDecl *TargetParam) const {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index 94a143841373a..98e09e09b5ec8 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -1364,6 +1364,571 @@ public:
ArrayRef<llvm::Value *> Args = llvm::None) const;
};
+/// Class supports emissionof SIMD-only code.
+class CGOpenMPSIMDRuntime final : public CGOpenMPRuntime {
+public:
+ explicit CGOpenMPSIMDRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {}
+ ~CGOpenMPSIMDRuntime() override {}
+
+ /// \brief Emits outlined function for the specified OpenMP parallel directive
+ /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
+ /// kmp_int32 BoundID, struct context_vars*).
+ /// \param D OpenMP directive.
+ /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
+ /// \param InnermostKind Kind of innermost directive (for simple directives it
+ /// is a directive itself, for combined - its innermost directive).
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ llvm::Value *
+ emitParallelOutlinedFunction(const OMPExecutableDirective &D,
+ const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind,
+ const RegionCodeGenTy &CodeGen) override;
+
+ /// \brief Emits outlined function for the specified OpenMP teams directive
+ /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
+ /// kmp_int32 BoundID, struct context_vars*).
+ /// \param D OpenMP directive.
+ /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
+ /// \param InnermostKind Kind of innermost directive (for simple directives it
+ /// is a directive itself, for combined - its innermost directive).
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ llvm::Value *
+ emitTeamsOutlinedFunction(const OMPExecutableDirective &D,
+ const VarDecl *ThreadIDVar,
+ OpenMPDirectiveKind InnermostKind,
+ const RegionCodeGenTy &CodeGen) override;
+
+ /// \brief Emits outlined function for the OpenMP task directive \a D. This
+ /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t*
+ /// TaskT).
+ /// \param D OpenMP directive.
+ /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
+ /// \param PartIDVar Variable for partition id in the current OpenMP untied
+ /// task region.
+ /// \param TaskTVar Variable for task_t argument.
+ /// \param InnermostKind Kind of innermost directive (for simple directives it
+ /// is a directive itself, for combined - its innermost directive).
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ /// \param Tied true if task is generated for tied task, false otherwise.
+ /// \param NumberOfParts Number of parts in untied task. Ignored for tied
+ /// tasks.
+ ///
+ llvm::Value *emitTaskOutlinedFunction(
+ const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
+ const VarDecl *PartIDVar, const VarDecl *TaskTVar,
+ OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
+ bool Tied, unsigned &NumberOfParts) override;
+
+ /// \brief Emits code for parallel or serial call of the \a OutlinedFn with
+ /// variables captured in a record which address is stored in \a
+ /// CapturedStruct.
+ /// \param OutlinedFn Outlined function to be run in parallel threads. Type of
+ /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
+ /// \param CapturedVars A pointer to the record with the references to
+ /// variables used in \a OutlinedFn function.
+ /// \param IfCond Condition in the associated 'if' clause, if it was
+ /// specified, nullptr otherwise.
+ ///
+ void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> CapturedVars,
+ const Expr *IfCond) override;
+
+ /// \brief Emits a critical region.
+ /// \param CriticalName Name of the critical region.
+ /// \param CriticalOpGen Generator for the statement associated with the given
+ /// critical region.
+ /// \param Hint Value of the 'hint' clause (optional).
+ void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
+ const RegionCodeGenTy &CriticalOpGen,
+ SourceLocation Loc,
+ const Expr *Hint = nullptr) override;
+
+ /// \brief Emits a master region.
+ /// \param MasterOpGen Generator for the statement associated with the given
+ /// master region.
+ void emitMasterRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &MasterOpGen,
+ SourceLocation Loc) override;
+
+ /// \brief Emits code for a taskyield directive.
+ void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override;
+
+ /// \brief Emit a taskgroup region.
+ /// \param TaskgroupOpGen Generator for the statement associated with the
+ /// given taskgroup region.
+ void emitTaskgroupRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &TaskgroupOpGen,
+ SourceLocation Loc) override;
+
+ /// \brief Emits a single region.
+ /// \param SingleOpGen Generator for the statement associated with the given
+ /// single region.
+ void emitSingleRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &SingleOpGen, SourceLocation Loc,
+ ArrayRef<const Expr *> CopyprivateVars,
+ ArrayRef<const Expr *> DestExprs,
+ ArrayRef<const Expr *> SrcExprs,
+ ArrayRef<const Expr *> AssignmentOps) override;
+
+ /// \brief Emit an ordered region.
+ /// \param OrderedOpGen Generator for the statement associated with the given
+ /// ordered region.
+ void emitOrderedRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &OrderedOpGen,
+ SourceLocation Loc, bool IsThreads) override;
+
+ /// \brief Emit an implicit/explicit barrier for OpenMP threads.
+ /// \param Kind Directive for which this implicit barrier call must be
+ /// generated. Must be OMPD_barrier for explicit barrier generation.
+ /// \param EmitChecks true if need to emit checks for cancellation barriers.
+ /// \param ForceSimpleCall true simple barrier call must be emitted, false if
+ /// runtime class decides which one to emit (simple or with cancellation
+ /// checks).
+ ///
+ void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind Kind, bool EmitChecks = true,
+ bool ForceSimpleCall = false) override;
+
+ /// This is used for non static scheduled types and when the ordered
+ /// clause is present on the loop construct.
+ /// Depending on the loop schedule, it is necessary to call some runtime
+ /// routine before start of the OpenMP loop to get the loop upper / lower
+ /// bounds \a LB and \a UB and stride \a ST.
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
+ /// \param IVSize Size of the iteration variable in bits.
+ /// \param IVSigned Sign of the iteration variable.
+ /// \param Ordered true if loop is ordered, false otherwise.
+ /// \param DispatchValues struct containing llvm values for lower bound, upper
+ /// bound, and chunk expression.
+ /// For the default (nullptr) value, the chunk 1 will be used.
+ ///
+ void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc,
+ const OpenMPScheduleTy &ScheduleKind,
+ unsigned IVSize, bool IVSigned, bool Ordered,
+ const DispatchRTInput &DispatchValues) override;
+
+ /// \brief Call the appropriate runtime routine to initialize it before start
+ /// of loop.
+ ///
+ /// This is used only in case of static schedule, when the user did not
+ /// specify a ordered clause on the loop construct.
+ /// Depending on the loop schedule, it is necessary to call some runtime
+ /// routine before start of the OpenMP loop to get the loop upper / lower
+ /// bounds LB and UB and stride ST.
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param DKind Kind of the directive.
+ /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
+ /// \param Values Input arguments for the construct.
+ ///
+ void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind DKind,
+ const OpenMPScheduleTy &ScheduleKind,
+ const StaticRTInput &Values) override;
+
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause.
+ /// \param Values Input arguments for the construct.
+ ///
+ void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDistScheduleClauseKind SchedKind,
+ const StaticRTInput &Values) override;
+
+ /// \brief Call the appropriate runtime routine to notify that we finished
+ /// iteration of the ordered loop with the dynamic scheduling.
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param IVSize Size of the iteration variable in bits.
+ /// \param IVSigned Sign of the iteration variable.
+ ///
+ void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc,
+ unsigned IVSize, bool IVSigned) override;
+
+ /// \brief Call the appropriate runtime routine to notify that we finished
+ /// all the work with current loop.
+ ///
+ /// \param CGF Reference to current CodeGenFunction.
+ /// \param Loc Clang source location.
+ /// \param DKind Kind of the directive for which the static finish is emitted.
+ ///
+ void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind DKind) override;
+
+ /// Call __kmpc_dispatch_next(
+ /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
+ /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
+ /// kmp_int[32|64] *p_stride);
+ /// \param IVSize Size of the iteration variable in bits.
+ /// \param IVSigned Sign of the iteration variable.
+ /// \param IL Address of the output variable in which the flag of the
+ /// last iteration is returned.
+ /// \param LB Address of the output variable in which the lower iteration
+ /// number is returned.
+ /// \param UB Address of the output variable in which the upper iteration
+ /// number is returned.
+ /// \param ST Address of the output variable in which the stride value is
+ /// returned.
+ llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
+ unsigned IVSize, bool IVSigned, Address IL,
+ Address LB, Address UB, Address ST) override;
+
+ /// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
+ /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
+ /// clause.
+ /// \param NumThreads An integer value of threads.
+ void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads,
+ SourceLocation Loc) override;
+
+ /// \brief Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
+ /// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
+ void emitProcBindClause(CodeGenFunction &CGF,
+ OpenMPProcBindClauseKind ProcBind,
+ SourceLocation Loc) override;
+
+ /// \brief Returns address of the threadprivate variable for the current
+ /// thread.
+ /// \param VD Threadprivate variable.
+ /// \param VDAddr Address of the global variable \a VD.
+ /// \param Loc Location of the reference to threadprivate var.
+ /// \return Address of the threadprivate variable for the current thread.
+ Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD,
+ Address VDAddr, SourceLocation Loc) override;
+
+ /// \brief Emit a code for initialization of threadprivate variable. It emits
+ /// a call to runtime library which adds initial value to the newly created
+ /// threadprivate variable (if it is not constant) and registers destructor
+ /// for the variable (if any).
+ /// \param VD Threadprivate variable.
+ /// \param VDAddr Address of the global variable \a VD.
+ /// \param Loc Location of threadprivate declaration.
+ /// \param PerformInit true if initialization expression is not constant.
+ llvm::Function *
+ emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr,
+ SourceLocation Loc, bool PerformInit,
+ CodeGenFunction *CGF = nullptr) override;
+
+ /// Creates artificial threadprivate variable with name \p Name and type \p
+ /// VarType.
+ /// \param VarType Type of the artificial threadprivate variable.
+ /// \param Name Name of the artificial threadprivate variable.
+ Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
+ QualType VarType,
+ StringRef Name) override;
+
+ /// \brief Emit flush of the variables specified in 'omp flush' directive.
+ /// \param Vars List of variables to flush.
+ void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
+ SourceLocation Loc) override;
+
+ /// \brief Emit task region for the task directive. The task region is
+ /// emitted in several steps:
+ /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
+ /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
+ /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
+ /// function:
+ /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
+ /// TaskFunction(gtid, tt->part_id, tt->shareds);
+ /// return 0;
+ /// }
+ /// 2. Copy a list of shared variables to field shareds of the resulting
+ /// structure kmp_task_t returned by the previous call (if any).
+ /// 3. Copy a pointer to destructions function to field destructions of the
+ /// resulting structure kmp_task_t.
+ /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
+ /// kmp_task_t *new_task), where new_task is a resulting structure from
+ /// previous items.
+ /// \param D Current task directive.
+ /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
+ /// /*part_id*/, captured_struct */*__context*/);
+ /// \param SharedsTy A type which contains references the shared variables.
+ /// \param Shareds Context with the list of shared variables from the \p
+ /// TaskFunction.
+ /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
+ /// otherwise.
+ /// \param Data Additional data for task generation like tiednsee, final
+ /// state, list of privates etc.
+ void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const OMPExecutableDirective &D, llvm::Value *TaskFunction,
+ QualType SharedsTy, Address Shareds, const Expr *IfCond,
+ const OMPTaskDataTy &Data) override;
+
+ /// Emit task region for the taskloop directive. The taskloop region is
+ /// emitted in several steps:
+ /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
+ /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
+ /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
+ /// function:
+ /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
+ /// TaskFunction(gtid, tt->part_id, tt->shareds);
+ /// return 0;
+ /// }
+ /// 2. Copy a list of shared variables to field shareds of the resulting
+ /// structure kmp_task_t returned by the previous call (if any).
+ /// 3. Copy a pointer to destructions function to field destructions of the
+ /// resulting structure kmp_task_t.
+ /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t
+ /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int
+ /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task
+ /// is a resulting structure from
+ /// previous items.
+ /// \param D Current task directive.
+ /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
+ /// /*part_id*/, captured_struct */*__context*/);
+ /// \param SharedsTy A type which contains references the shared variables.
+ /// \param Shareds Context with the list of shared variables from the \p
+ /// TaskFunction.
+ /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
+ /// otherwise.
+ /// \param Data Additional data for task generation like tiednsee, final
+ /// state, list of privates etc.
+ void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const OMPLoopDirective &D, llvm::Value *TaskFunction,
+ QualType SharedsTy, Address Shareds, const Expr *IfCond,
+ const OMPTaskDataTy &Data) override;
+
+ /// \brief Emit a code for reduction clause. Next code should be emitted for
+ /// reduction:
+ /// \code
+ ///
+ /// static kmp_critical_name lock = { 0 };
+ ///
+ /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
+ /// ...
+ /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
+ /// ...
+ /// }
+ ///
+ /// ...
+ /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
+ /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
+ /// RedList, reduce_func, &<lock>)) {
+ /// case 1:
+ /// ...
+ /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
+ /// ...
+ /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
+ /// break;
+ /// case 2:
+ /// ...
+ /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
+ /// ...
+ /// break;
+ /// default:;
+ /// }
+ /// \endcode
+ ///
+ /// \param Privates List of private copies for original reduction arguments.
+ /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
+ /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
+ /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
+ /// or 'operator binop(LHS, RHS)'.
+ /// \param Options List of options for reduction codegen:
+ /// WithNowait true if parent directive has also nowait clause, false
+ /// otherwise.
+ /// SimpleReduction Emit reduction operation only. Used for omp simd
+ /// directive on the host.
+ /// ReductionKind The kind of reduction to perform.
+ void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> Privates,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ ArrayRef<const Expr *> ReductionOps,
+ ReductionOptionsTy Options) override;
+
+ /// Emit a code for initialization of task reduction clause. Next code
+ /// should be emitted for reduction:
+ /// \code
+ ///
+ /// _task_red_item_t red_data[n];
+ /// ...
+ /// red_data[i].shar = &origs[i];
+ /// red_data[i].size = sizeof(origs[i]);
+ /// red_data[i].f_init = (void*)RedInit<i>;
+ /// red_data[i].f_fini = (void*)RedDest<i>;
+ /// red_data[i].f_comb = (void*)RedOp<i>;
+ /// red_data[i].flags = <Flag_i>;
+ /// ...
+ /// void* tg1 = __kmpc_task_reduction_init(gtid, n, red_data);
+ /// \endcode
+ ///
+ /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations.
+ /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations.
+ /// \param Data Additional data for task generation like tiedness, final
+ /// state, list of privates, reductions etc.
+ llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> LHSExprs,
+ ArrayRef<const Expr *> RHSExprs,
+ const OMPTaskDataTy &Data) override;
+
+ /// Required to resolve existing problems in the runtime. Emits threadprivate
+ /// variables to store the size of the VLAs/array sections for
+ /// initializer/combiner/finalizer functions + emits threadprivate variable to
+ /// store the pointer to the original reduction item for the custom
+ /// initializer defined by declare reduction construct.
+ /// \param RCG Allows to reuse an existing data for the reductions.
+ /// \param N Reduction item for which fixups must be emitted.
+ void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc,
+ ReductionCodeGen &RCG, unsigned N) override;
+
+ /// Get the address of `void *` type of the privatue copy of the reduction
+ /// item specified by the \p SharedLVal.
+ /// \param ReductionsPtr Pointer to the reduction data returned by the
+ /// emitTaskReductionInit function.
+ /// \param SharedLVal Address of the original reduction item.
+ Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc,
+ llvm::Value *ReductionsPtr,
+ LValue SharedLVal) override;
+
+ /// \brief Emit code for 'taskwait' directive.
+ void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc) override;
+
+ /// \brief Emit code for 'cancellation point' construct.
+ /// \param CancelRegion Region kind for which the cancellation point must be
+ /// emitted.
+ ///
+ void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind CancelRegion) override;
+
+ /// \brief Emit code for 'cancel' construct.
+ /// \param IfCond Condition in the associated 'if' clause, if it was
+ /// specified, nullptr otherwise.
+ /// \param CancelRegion Region kind for which the cancel must be emitted.
+ ///
+ void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const Expr *IfCond,
+ OpenMPDirectiveKind CancelRegion) override;
+
+ /// \brief Emit outilined function for 'target' directive.
+ /// \param D Directive to emit.
+ /// \param ParentName Name of the function that encloses the target region.
+ /// \param OutlinedFn Outlined function value to be defined by this call.
+ /// \param OutlinedFnID Outlined function ID value to be defined by this call.
+ /// \param IsOffloadEntry True if the outlined function is an offload entry.
+ /// \param CodeGen Code generation sequence for the \a D directive.
+ /// An outlined function may not be an entry if, e.g. the if clause always
+ /// evaluates to false.
+ void emitTargetOutlinedFunction(const OMPExecutableDirective &D,
+ StringRef ParentName,
+ llvm::Function *&OutlinedFn,
+ llvm::Constant *&OutlinedFnID,
+ bool IsOffloadEntry,
+ const RegionCodeGenTy &CodeGen) override;
+
+ /// \brief Emit the target offloading code associated with \a D. The emitted
+ /// code attempts offloading the execution to the device, an the event of
+ /// a failure it executes the host version outlined in \a OutlinedFn.
+ /// \param D Directive to emit.
+ /// \param OutlinedFn Host version of the code to be offloaded.
+ /// \param OutlinedFnID ID of host version of the code to be offloaded.
+ /// \param IfCond Expression evaluated in if clause associated with the target
+ /// directive, or null if no if clause is used.
+ /// \param Device Expression evaluated in device clause associated with the
+ /// target directive, or null if no device clause is used.
+ /// \param CapturedVars Values captured in the current region.
+ void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D,
+ llvm::Value *OutlinedFn, llvm::Value *OutlinedFnID,
+ const Expr *IfCond, const Expr *Device,
+ ArrayRef<llvm::Value *> CapturedVars) override;
+
+ /// \brief Emit the target regions enclosed in \a GD function definition or
+ /// the function itself in case it is a valid device function. Returns true if
+ /// \a GD was dealt with successfully.
+ /// \param GD Function to scan.
+ bool emitTargetFunctions(GlobalDecl GD) override;
+
+ /// \brief Emit the global variable if it is a valid device global variable.
+ /// Returns true if \a GD was dealt with successfully.
+ /// \param GD Variable declaration to emit.
+ bool emitTargetGlobalVariable(GlobalDecl GD) override;
+
+ /// \brief Emit the global \a GD if it is meaningful for the target. Returns
+ /// if it was emitted successfully.
+ /// \param GD Global to scan.
+ bool emitTargetGlobal(GlobalDecl GD) override;
+
+ /// \brief Creates the offloading descriptor in the event any target region
+ /// was emitted in the current module and return the function that registers
+ /// it.
+ llvm::Function *emitRegistrationFunction() override;
+
+ /// \brief Emits code for teams call of the \a OutlinedFn with
+ /// variables captured in a record which address is stored in \a
+ /// CapturedStruct.
+ /// \param OutlinedFn Outlined function to be run by team masters. Type of
+ /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
+ /// \param CapturedVars A pointer to the record with the references to
+ /// variables used in \a OutlinedFn function.
+ ///
+ void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D,
+ SourceLocation Loc, llvm::Value *OutlinedFn,
+ ArrayRef<llvm::Value *> CapturedVars) override;
+
+ /// \brief Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
+ /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code
+ /// for num_teams clause.
+ /// \param NumTeams An integer expression of teams.
+ /// \param ThreadLimit An integer expression of threads.
+ void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
+ const Expr *ThreadLimit, SourceLocation Loc) override;
+
+ /// \brief Emit the target data mapping code associated with \a D.
+ /// \param D Directive to emit.
+ /// \param IfCond Expression evaluated in if clause associated with the
+ /// target directive, or null if no device clause is used.
+ /// \param Device Expression evaluated in device clause associated with the
+ /// target directive, or null if no device clause is used.
+ /// \param Info A record used to store information that needs to be preserved
+ /// until the region is closed.
+ void emitTargetDataCalls(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D, const Expr *IfCond,
+ const Expr *Device, const RegionCodeGenTy &CodeGen,
+ TargetDataInfo &Info) override;
+
+ /// \brief Emit the data mapping/movement code associated with the directive
+ /// \a D that should be of the form 'target [{enter|exit} data | update]'.
+ /// \param D Directive to emit.
+ /// \param IfCond Expression evaluated in if clause associated with the target
+ /// directive, or null if no if clause is used.
+ /// \param Device Expression evaluated in device clause associated with the
+ /// target directive, or null if no device clause is used.
+ void emitTargetDataStandAloneCall(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ const Expr *IfCond,
+ const Expr *Device) override;
+
+ /// Emit initialization for doacross loop nesting support.
+ /// \param D Loop-based construct used in doacross nesting construct.
+ void emitDoacrossInit(CodeGenFunction &CGF,
+ const OMPLoopDirective &D) override;
+
+ /// Emit code for doacross ordered directive with 'depend' clause.
+ /// \param C 'depend' clause with 'sink|source' dependency kind.
+ void emitDoacrossOrdered(CodeGenFunction &CGF,
+ const OMPDependClause *C) override;
+
+ /// Translates the native parameter of outlined function if this is required
+ /// for target.
+ /// \param FD Field decl from captured record for the paramater.
+ /// \param NativeParam Parameter itself.
+ const VarDecl *translateParameter(const FieldDecl *FD,
+ const VarDecl *NativeParam) const override;
+
+ /// Gets the address of the native argument basing on the address of the
+ /// target-specific parameter.
+ /// \param NativeParam Parameter itself.
+ /// \param TargetParam Corresponding target-specific parameter.
+ Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam,
+ const VarDecl *TargetParam) const override;
+};
+
} // namespace CodeGen
} // namespace clang
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 91fa49a46ef1e..97e35e2b6e8df 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -74,6 +74,15 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
// Generate a stoppoint if we are emitting debug info.
EmitStopPoint(S);
+ // Ignore all OpenMP directives except for simd if OpenMP with Simd is
+ // enabled.
+ if (getLangOpts().OpenMP && getLangOpts().OpenMPSimd) {
+ if (const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
+ EmitSimpleOMPExecutableDirective(*D);
+ return;
+ }
+ }
+
switch (S->getStmtClass()) {
case Stmt::NoStmtClass:
case Stmt::CXXCatchStmtClass:
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index f9861735832bf..26817ac330ba8 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -144,6 +144,71 @@ public:
}
};
+class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope {
+ CodeGenFunction::OMPPrivateScope InlinedShareds;
+
+ static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
+ return CGF.LambdaCaptureFields.lookup(VD) ||
+ (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
+ (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) &&
+ cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
+ }
+
+public:
+ OMPSimdLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
+ : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
+ InlinedShareds(CGF) {
+ for (const auto *C : S.clauses()) {
+ if (auto *CPI = OMPClauseWithPreInit::get(C)) {
+ if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
+ for (const auto *I : PreInit->decls()) {
+ if (!I->hasAttr<OMPCaptureNoInitAttr>())
+ CGF.EmitVarDecl(cast<VarDecl>(*I));
+ else {
+ CodeGenFunction::AutoVarEmission Emission =
+ CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
+ CGF.EmitAutoVarCleanups(Emission);
+ }
+ }
+ }
+ } else if (const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) {
+ for (const Expr *E : UDP->varlists()) {
+ const Decl *D = cast<DeclRefExpr>(E)->getDecl();
+ if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
+ CGF.EmitVarDecl(*OED);
+ }
+ }
+ }
+ if (!isOpenMPSimdDirective(S.getDirectiveKind()))
+ CGF.EmitOMPPrivateClause(S, InlinedShareds);
+ if (const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
+ if (const Expr *E = TG->getReductionRef())
+ CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()));
+ }
+ const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
+ while (CS) {
+ for (auto &C : CS->captures()) {
+ if (C.capturesVariable() || C.capturesVariableByCopy()) {
+ auto *VD = C.getCapturedVar();
+ assert(VD == VD->getCanonicalDecl() &&
+ "Canonical decl must be captured.");
+ DeclRefExpr DRE(const_cast<VarDecl *>(VD),
+ isCapturedVar(CGF, VD) ||
+ (CGF.CapturedStmtInfo &&
+ InlinedShareds.isGlobalVarCaptured(VD)),
+ VD->getType().getNonReferenceType(), VK_LValue,
+ SourceLocation());
+ InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
+ return CGF.EmitLValue(&DRE).getAddress();
+ });
+ }
+ }
+ CS = dyn_cast<CapturedStmt>(CS->getCapturedStmt());
+ }
+ (void)InlinedShareds.Privatize();
+ }
+};
+
} // namespace
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
@@ -863,7 +928,8 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
HasAtLeastOneLastprivate = true;
- if (isOpenMPTaskLoopDirective(D.getDirectiveKind()))
+ if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
+ !getLangOpts().OpenMPSimd)
break;
auto IRef = C->varlist_begin();
auto IDestRef = C->destination_exprs().begin();
@@ -1100,9 +1166,8 @@ void CodeGenFunction::EmitOMPReductionClauseFinal(
if (HasAtLeastOneReduction) {
bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
isOpenMPParallelDirective(D.getDirectiveKind()) ||
- D.getDirectiveKind() == OMPD_simd;
- bool SimpleReduction = D.getDirectiveKind() == OMPD_simd ||
- D.getDirectiveKind() == OMPD_distribute_simd;
+ ReductionKind == OMPD_simd;
+ bool SimpleReduction = ReductionKind == OMPD_simd;
// Emit nowait reduction if nowait clause is present or directive is a
// parallel directive (it always has implicit barrier).
CGM.getOpenMPRuntime().emitReduction(
@@ -1570,6 +1635,14 @@ static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF,
CGF.EmitStopPoint(&S);
}
+/// Emit a helper variable and return corresponding lvalue.
+static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
+ const DeclRefExpr *Helper) {
+ auto VDecl = cast<VarDecl>(Helper->getDecl());
+ CGF.EmitVarDecl(*VDecl);
+ return CGF.EmitLValue(Helper);
+}
+
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
PrePostActionTy &Action) {
Action.Enter(CGF);
@@ -1581,6 +1654,12 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
// <Final counter/linear vars updates>;
// }
//
+ if (isOpenMPDistributeDirective(S.getDirectiveKind()) ||
+ isOpenMPWorksharingDirective(S.getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(S.getDirectiveKind())) {
+ (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()));
+ (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()));
+ }
// Emit: if (PreCond) - begin.
// If the condition constant folds and can be elided, avoid emitting the
@@ -1933,14 +2012,6 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop(
emitEmptyOrdered);
}
-/// Emit a helper variable and return corresponding lvalue.
-static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
- const DeclRefExpr *Helper) {
- auto VDecl = cast<VarDecl>(Helper->getDecl());
- CGF.EmitVarDecl(*VDecl);
- return CGF.EmitLValue(Helper);
-}
-
static std::pair<LValue, LValue>
emitDistributeParallelForInnerBounds(CodeGenFunction &CGF,
const OMPExecutableDirective &S) {
@@ -4721,3 +4792,35 @@ void CodeGenFunction::EmitOMPTargetUpdateDirective(
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
}
+
+void CodeGenFunction::EmitSimpleOMPExecutableDirective(
+ const OMPExecutableDirective &D) {
+ if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
+ return;
+ auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ if (isOpenMPSimdDirective(D.getDirectiveKind())) {
+ emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action);
+ } else {
+ if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
+ for (const auto *E : LD->counters()) {
+ if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
+ cast<DeclRefExpr>(E)->getDecl())) {
+ // Emit only those that were not explicitly referenced in clauses.
+ if (!CGF.LocalDeclMap.count(VD))
+ CGF.EmitVarDecl(*VD);
+ }
+ }
+ }
+ const auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
+ while (const auto *CCS = dyn_cast<CapturedStmt>(CS->getCapturedStmt()))
+ CS = CCS;
+ CGF.EmitStmt(CS->getCapturedStmt());
+ }
+ };
+ OMPSimdLexicalScope Scope(*this, D);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this,
+ isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
+ : D.getDirectiveKind(),
+ CodeGen);
+}
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 9dbd7cc3fcbfb..664b51078424d 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -419,6 +419,9 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EmitIfUsed(*this, TerminateHandler);
EmitIfUsed(*this, UnreachableBlock);
+ for (const auto &FuncletAndParent : TerminateFunclets)
+ EmitIfUsed(*this, FuncletAndParent.second);
+
if (CGM.getCodeGenOpts().EmitDeclMetadata)
EmitDeclMetadata();
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index dd4c2e43ef64b..3e89586be3a5f 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -34,6 +34,7 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Debug.h"
@@ -1420,6 +1421,9 @@ private:
llvm::BasicBlock *TerminateHandler;
llvm::BasicBlock *TrapBB;
+ /// Terminate funclets keyed by parent funclet pad.
+ llvm::MapVector<llvm::Value *, llvm::BasicBlock *> TerminateFunclets;
+
/// True if we need emit the life-time markers.
const bool ShouldEmitLifetimeMarkers;
@@ -1808,6 +1812,10 @@ public:
/// getTerminateLandingPad - Return a landing pad that just calls terminate.
llvm::BasicBlock *getTerminateLandingPad();
+ /// getTerminateLandingPad - Return a cleanup funclet that just calls
+ /// terminate.
+ llvm::BasicBlock *getTerminateFunclet();
+
/// getTerminateHandler - Return a handler (not a landing pad, just
/// a catch handler) that just calls terminate. This is used when
/// a terminate scope encloses a try.
@@ -2655,6 +2663,9 @@ public:
llvm::Value *EmitSEHExceptionInfo();
llvm::Value *EmitSEHAbnormalTermination();
+ /// Emit simple code for OpenMP directives in Simd-only mode.
+ void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D);
+
/// Scan the outlined statement for captures from the parent function. For
/// each capture, mark the capture as escaped and emit a call to
/// llvm.localrecover. Insert the localrecover result into the LocalDeclMap.
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 5bdf81aaf66ed..df33fc3e82001 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -208,7 +208,10 @@ void CodeGenModule::createOpenMPRuntime() {
OpenMPRuntime.reset(new CGOpenMPRuntimeNVPTX(*this));
break;
default:
- OpenMPRuntime.reset(new CGOpenMPRuntime(*this));
+ if (LangOpts.OpenMPSimd)
+ OpenMPRuntime.reset(new CGOpenMPSIMDRuntime(*this));
+ else
+ OpenMPRuntime.reset(new CGOpenMPRuntime(*this));
break;
}
}
@@ -4515,6 +4518,9 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
}
void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
+ // Do not emit threadprivates in simd-only mode.
+ if (LangOpts.OpenMP && LangOpts.OpenMPSimd)
+ return;
for (auto RefExpr : D->varlists()) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(RefExpr)->getDecl());
bool PerformInit =
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 9ae33b80f8898..325b233ac5ec7 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -62,6 +62,7 @@
#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -70,6 +71,7 @@
#include "llvm/Support/Program.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/StringSaver.h"
#include <map>
#include <memory>
#include <utility>
@@ -92,7 +94,8 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false),
CCGenDiagnostics(false), DefaultTargetTriple(DefaultTargetTriple),
- CCCGenericGCCName(""), CheckInputsExist(true), CCCUsePCH(true),
+ CCCGenericGCCName(""), Saver(Alloc),
+ CheckInputsExist(true), CCCUsePCH(true),
GenReproducer(false), SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
@@ -103,6 +106,13 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
Dir = llvm::sys::path::parent_path(ClangExecutable);
InstalledDir = Dir; // Provide a sensible default installed dir.
+#if defined(CLANG_CONFIG_FILE_SYSTEM_DIR)
+ SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR;
+#endif
+#if defined(CLANG_CONFIG_FILE_USER_DIR)
+ UserConfigDir = CLANG_CONFIG_FILE_USER_DIR;
+#endif
+
// Compute the path to the resource directory.
StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
SmallString<128> P(Dir);
@@ -600,6 +610,216 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
//
}
+/// Looks the given directories for the specified file.
+///
+/// \param[out] FilePath File path, if the file was found.
+/// \param[in] Dirs Directories used for the search.
+/// \param[in] FileName Name of the file to search for.
+/// \return True if file was found.
+///
+/// Looks for file specified by FileName sequentially in directories specified
+/// by Dirs.
+///
+static bool searchForFile(SmallVectorImpl<char> &FilePath,
+ ArrayRef<std::string> Dirs,
+ StringRef FileName) {
+ SmallString<128> WPath;
+ for (const StringRef &Dir : Dirs) {
+ if (Dir.empty())
+ continue;
+ WPath.clear();
+ llvm::sys::path::append(WPath, Dir, FileName);
+ llvm::sys::path::native(WPath);
+ if (llvm::sys::fs::is_regular_file(WPath)) {
+ FilePath = std::move(WPath);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Driver::readConfigFile(StringRef FileName) {
+ // Try reading the given file.
+ SmallVector<const char *, 32> NewCfgArgs;
+ if (!llvm::cl::readConfigFile(FileName, Saver, NewCfgArgs)) {
+ Diag(diag::err_drv_cannot_read_config_file) << FileName;
+ return true;
+ }
+
+ // Read options from config file.
+ llvm::SmallString<128> CfgFileName(FileName);
+ llvm::sys::path::native(CfgFileName);
+ ConfigFile = CfgFileName.str();
+ bool ContainErrors;
+ CfgOptions = llvm::make_unique<InputArgList>(
+ ParseArgStrings(NewCfgArgs, ContainErrors));
+ if (ContainErrors) {
+ CfgOptions.reset();
+ return true;
+ }
+
+ if (CfgOptions->hasArg(options::OPT_config)) {
+ CfgOptions.reset();
+ Diag(diag::err_drv_nested_config_file);
+ return true;
+ }
+
+ // Claim all arguments that come from a configuration file so that the driver
+ // does not warn on any that is unused.
+ for (Arg *A : *CfgOptions)
+ A->claim();
+ return false;
+}
+
+bool Driver::loadConfigFile() {
+ std::string CfgFileName;
+ bool FileSpecifiedExplicitly = false;
+
+ // Process options that change search path for config files.
+ if (CLOptions) {
+ if (CLOptions->hasArg(options::OPT_config_system_dir_EQ)) {
+ SmallString<128> CfgDir;
+ CfgDir.append(
+ CLOptions->getLastArgValue(options::OPT_config_system_dir_EQ));
+ if (!CfgDir.empty()) {
+ if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
+ SystemConfigDir.clear();
+ else
+ SystemConfigDir = std::string(CfgDir.begin(), CfgDir.end());
+ }
+ }
+ if (CLOptions->hasArg(options::OPT_config_user_dir_EQ)) {
+ SmallString<128> CfgDir;
+ CfgDir.append(
+ CLOptions->getLastArgValue(options::OPT_config_user_dir_EQ));
+ if (!CfgDir.empty()) {
+ if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
+ UserConfigDir.clear();
+ else
+ UserConfigDir = std::string(CfgDir.begin(), CfgDir.end());
+ }
+ }
+ }
+
+ // First try to find config file specified in command line.
+ if (CLOptions) {
+ std::vector<std::string> ConfigFiles =
+ CLOptions->getAllArgValues(options::OPT_config);
+ if (ConfigFiles.size() > 1) {
+ Diag(diag::err_drv_duplicate_config);
+ return true;
+ }
+
+ if (!ConfigFiles.empty()) {
+ CfgFileName = ConfigFiles.front();
+ assert(!CfgFileName.empty());
+
+ // If argument contains directory separator, treat it as a path to
+ // configuration file.
+ if (llvm::sys::path::has_parent_path(CfgFileName)) {
+ SmallString<128> CfgFilePath;
+ if (llvm::sys::path::is_relative(CfgFileName))
+ llvm::sys::fs::current_path(CfgFilePath);
+ llvm::sys::path::append(CfgFilePath, CfgFileName);
+ if (!llvm::sys::fs::is_regular_file(CfgFilePath)) {
+ Diag(diag::err_drv_config_file_not_exist) << CfgFilePath;
+ return true;
+ }
+ return readConfigFile(CfgFilePath);
+ }
+
+ FileSpecifiedExplicitly = true;
+ }
+ }
+
+ // If config file is not specified explicitly, try to deduce configuration
+ // from executable name. For instance, an executable 'armv7l-clang' will
+ // search for config file 'armv7l-clang.cfg'.
+ if (CfgFileName.empty() && !ClangNameParts.TargetPrefix.empty())
+ CfgFileName = ClangNameParts.TargetPrefix + '-' + ClangNameParts.ModeSuffix;
+
+ if (CfgFileName.empty())
+ return false;
+
+ // Determine architecture part of the file name, if it is present.
+ StringRef CfgFileArch = CfgFileName;
+ size_t ArchPrefixLen = CfgFileArch.find('-');
+ if (ArchPrefixLen == StringRef::npos)
+ ArchPrefixLen = CfgFileArch.size();
+ llvm::Triple CfgTriple;
+ CfgFileArch = CfgFileArch.take_front(ArchPrefixLen);
+ CfgTriple = llvm::Triple(llvm::Triple::normalize(CfgFileArch));
+ if (CfgTriple.getArch() == llvm::Triple::ArchType::UnknownArch)
+ ArchPrefixLen = 0;
+
+ if (!StringRef(CfgFileName).endswith(".cfg"))
+ CfgFileName += ".cfg";
+
+ // If config file starts with architecture name and command line options
+ // redefine architecture (with options like -m32 -LE etc), try finding new
+ // config file with that architecture.
+ SmallString<128> FixedConfigFile;
+ size_t FixedArchPrefixLen = 0;
+ if (ArchPrefixLen) {
+ // Get architecture name from config file name like 'i386.cfg' or
+ // 'armv7l-clang.cfg'.
+ // Check if command line options changes effective triple.
+ llvm::Triple EffectiveTriple = computeTargetTriple(*this,
+ CfgTriple.getTriple(), *CLOptions);
+ if (CfgTriple.getArch() != EffectiveTriple.getArch()) {
+ FixedConfigFile = EffectiveTriple.getArchName();
+ FixedArchPrefixLen = FixedConfigFile.size();
+ // Append the rest of original file name so that file name transforms
+ // like: i386-clang.cfg -> x86_64-clang.cfg.
+ if (ArchPrefixLen < CfgFileName.size())
+ FixedConfigFile += CfgFileName.substr(ArchPrefixLen);
+ }
+ }
+
+ // Prepare list of directories where config file is searched for.
+ SmallVector<std::string, 3> CfgFileSearchDirs;
+ CfgFileSearchDirs.push_back(UserConfigDir);
+ CfgFileSearchDirs.push_back(SystemConfigDir);
+ CfgFileSearchDirs.push_back(Dir);
+
+ // Try to find config file. First try file with corrected architecture.
+ llvm::SmallString<128> CfgFilePath;
+ if (!FixedConfigFile.empty()) {
+ if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile))
+ return readConfigFile(CfgFilePath);
+ // If 'x86_64-clang.cfg' was not found, try 'x86_64.cfg'.
+ FixedConfigFile.resize(FixedArchPrefixLen);
+ FixedConfigFile.append(".cfg");
+ if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile))
+ return readConfigFile(CfgFilePath);
+ }
+
+ // Then try original file name.
+ if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName))
+ return readConfigFile(CfgFilePath);
+
+ // Finally try removing driver mode part: 'x86_64-clang.cfg' -> 'x86_64.cfg'.
+ if (!ClangNameParts.ModeSuffix.empty() &&
+ !ClangNameParts.TargetPrefix.empty()) {
+ CfgFileName.assign(ClangNameParts.TargetPrefix);
+ CfgFileName.append(".cfg");
+ if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName))
+ return readConfigFile(CfgFilePath);
+ }
+
+ // Report error but only if config file was specified explicitly, by option
+ // --config. If it was deduced from executable name, it is not an error.
+ if (FileSpecifiedExplicitly) {
+ Diag(diag::err_drv_config_file_not_found) << CfgFileName;
+ for (const std::string &SearchDir : CfgFileSearchDirs)
+ if (!SearchDir.empty())
+ Diag(diag::note_drv_config_file_searched_in) << SearchDir;
+ return true;
+ }
+
+ return false;
+}
+
Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
llvm::PrettyStackTraceString CrashInfo("Compilation construction");
@@ -623,12 +843,35 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// FIXME: What are we going to do with -V and -b?
+ // Arguments specified in command line.
+ bool ContainsError;
+ CLOptions = llvm::make_unique<InputArgList>(
+ ParseArgStrings(ArgList.slice(1), ContainsError));
+
+ // Try parsing configuration file.
+ if (!ContainsError)
+ ContainsError = loadConfigFile();
+ bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
+
+ // All arguments, from both config file and command line.
+ InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
+ : std::move(*CLOptions));
+ if (HasConfigFile)
+ for (auto *Opt : *CLOptions) {
+ const Arg *BaseArg = &Opt->getBaseArg();
+ if (BaseArg == Opt)
+ BaseArg = nullptr;
+ Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Opt->getSpelling(),
+ Args.size(), BaseArg);
+ Copy->getValues() = Opt->getValues();
+ if (Opt->isClaimed())
+ Copy->claim();
+ Args.append(Copy);
+ }
+
// FIXME: This stuff needs to go into the Compilation, not the driver.
bool CCCPrintPhases;
- bool ContainsError;
- InputArgList Args = ParseArgStrings(ArgList.slice(1), ContainsError);
-
// Silence driver warnings if requested
Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w));
@@ -1144,6 +1387,10 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
// Print out the install directory.
OS << "InstalledDir: " << InstalledDir << '\n';
+
+ // If configuration file was used, print its path.
+ if (!ConfigFile.empty())
+ OS << "Configuration file: " << ConfigFile << '\n';
}
/// PrintDiagnosticCategories - Implement the --print-diagnostic-categories
@@ -1250,6 +1497,15 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
SuppressMissingInputWarning = true;
}
+ if (C.getArgs().hasArg(options::OPT_v)) {
+ if (!SystemConfigDir.empty())
+ llvm::errs() << "System configuration file directory: "
+ << SystemConfigDir << "\n";
+ if (!UserConfigDir.empty())
+ llvm::errs() << "User configuration file directory: "
+ << UserConfigDir << "\n";
+ }
+
const ToolChain &TC = C.getDefaultToolChain();
if (C.getArgs().hasArg(options::OPT_v))
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 8b895c4514c45..c445669a5ad42 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -3901,6 +3901,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// semantic analysis, etc.
break;
}
+ } else {
+ Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
+ options::OPT_fno_openmp_simd);
+ Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
}
const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp
index 2250e82d9dbfe..802b89b070025 100644
--- a/lib/Driver/ToolChains/Darwin.cpp
+++ b/lib/Driver/ToolChains/Darwin.cpp
@@ -1192,6 +1192,13 @@ struct DarwinPlatform {
return OSVersion;
}
+ void setOSVersion(StringRef S) {
+ assert(Kind == TargetArg && "Unexpected kind!");
+ OSVersion = S;
+ }
+
+ bool hasOSVersion() const { return HasOSVersion; }
+
/// Returns true if the target OS was explicitly specified.
bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
@@ -1235,17 +1242,21 @@ struct DarwinPlatform {
llvm_unreachable("Unsupported Darwin Source Kind");
}
- static DarwinPlatform createFromTarget(llvm::Triple::OSType OS,
- StringRef OSVersion, Arg *A,
- llvm::Triple::EnvironmentType Env) {
- DarwinPlatform Result(TargetArg, getPlatformFromOS(OS), OSVersion, A);
- switch (Env) {
+ static DarwinPlatform createFromTarget(const llvm::Triple &TT,
+ StringRef OSVersion, Arg *A) {
+ DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
+ A);
+ switch (TT.getEnvironment()) {
case llvm::Triple::Simulator:
Result.Environment = DarwinEnvironmentKind::Simulator;
break;
default:
break;
}
+ unsigned Major, Minor, Micro;
+ TT.getOSVersion(Major, Minor, Micro);
+ if (Major == 0)
+ Result.HasOSVersion = false;
return Result;
}
static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
@@ -1295,6 +1306,7 @@ private:
DarwinPlatformKind Platform;
DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
std::string OSVersion;
+ bool HasOSVersion = true;
Arg *Argument;
StringRef EnvVarName;
};
@@ -1489,9 +1501,8 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
Triple.getOS() == llvm::Triple::UnknownOS)
return None;
std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
- return DarwinPlatform::createFromTarget(Triple.getOS(), OSVersion,
- Args.getLastArg(options::OPT_target),
- Triple.getEnvironment());
+ return DarwinPlatform::createFromTarget(Triple, OSVersion,
+ Args.getLastArg(options::OPT_target));
}
} // namespace
@@ -1537,12 +1548,20 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
(VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
TargetExtra != ArgExtra))) {
- // Warn about -m<os>-version-min that doesn't match the OS version
- // that's specified in the target.
- std::string OSVersionArg = OSVersionArgTarget->getAsString(Args, Opts);
- std::string TargetArg = OSTarget->getAsString(Args, Opts);
- getDriver().Diag(clang::diag::warn_drv_overriding_flag_option)
- << OSVersionArg << TargetArg;
+ // Select the OS version from the -m<os>-version-min argument when
+ // the -target does not include an OS version.
+ if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
+ !OSTarget->hasOSVersion()) {
+ OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
+ } else {
+ // Warn about -m<os>-version-min that doesn't match the OS version
+ // that's specified in the target.
+ std::string OSVersionArg =
+ OSVersionArgTarget->getAsString(Args, Opts);
+ std::string TargetArg = OSTarget->getAsString(Args, Opts);
+ getDriver().Diag(clang::diag::warn_drv_overriding_flag_option)
+ << OSVersionArg << TargetArg;
+ }
}
}
} else {
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 2e8a737de4e42..6ce719aac6733 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -2407,16 +2407,22 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Check if -fopenmp is specified.
Opts.OpenMP = Args.hasArg(options::OPT_fopenmp) ? 1 : 0;
+ // Check if -fopenmp-simd is specified.
+ Opts.OpenMPSimd = !Opts.OpenMP && Args.hasFlag(options::OPT_fopenmp_simd,
+ options::OPT_fno_openmp_simd,
+ /*Default=*/false);
Opts.OpenMPUseTLS =
Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
Opts.OpenMPIsDevice =
Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device);
- if (Opts.OpenMP) {
- int Version =
- getLastArgIntValue(Args, OPT_fopenmp_version_EQ, Opts.OpenMP, Diags);
- if (Version != 0)
+ if (Opts.OpenMP || Opts.OpenMPSimd) {
+ if (int Version =
+ getLastArgIntValue(Args, OPT_fopenmp_version_EQ,
+ Opts.OpenMPSimd ? 45 : Opts.OpenMP, Diags))
Opts.OpenMP = Version;
+ else if (Opts.OpenMPSimd)
+ Opts.OpenMP = 45;
// Provide diagnostic when a given target is not expected to be an OpenMP
// device or host.
if (!Opts.OpenMPIsDevice) {
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index d39890494323d..639050f7c64b8 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -1021,8 +1021,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("_OPENMP", "201511");
break;
default:
- // Default version is OpenMP 3.1
- Builder.defineMacro("_OPENMP", "201107");
+ // Default version is OpenMP 3.1, in Simd only mode - 4.5
+ Builder.defineMacro("_OPENMP", LangOpts.OpenMPSimd ? "201511" : "201107");
break;
}
diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h
index 3372508a7f818..b332eeec205ae 100644
--- a/lib/Headers/emmintrin.h
+++ b/lib/Headers/emmintrin.h
@@ -217,8 +217,8 @@ _mm_div_pd(__m128d __a, __m128d __b)
/// \brief Calculates the square root of the lower double-precision value of
/// the second operand and returns it in the lower 64 bits of the result.
-/// The upper 64 bits of the result are copied from the upper double-
-/// precision value of the first operand.
+/// The upper 64 bits of the result are copied from the upper
+/// double-precision value of the first operand.
///
/// \headerfile <x86intrin.h>
///
@@ -260,8 +260,8 @@ _mm_sqrt_pd(__m128d __a)
/// \brief Compares lower 64-bit double-precision values of both operands, and
/// returns the lesser of the pair of values in the lower 64-bits of the
-/// result. The upper 64 bits of the result are copied from the upper double-
-/// precision value of the first operand.
+/// result. The upper 64 bits of the result are copied from the upper
+/// double-precision value of the first operand.
///
/// \headerfile <x86intrin.h>
///
@@ -304,8 +304,8 @@ _mm_min_pd(__m128d __a, __m128d __b)
/// \brief Compares lower 64-bit double-precision values of both operands, and
/// returns the greater of the pair of values in the lower 64-bits of the
-/// result. The upper 64 bits of the result are copied from the upper double-
-/// precision value of the first operand.
+/// result. The upper 64 bits of the result are copied from the upper
+/// double-precision value of the first operand.
///
/// \headerfile <x86intrin.h>
///
@@ -983,8 +983,10 @@ _mm_cmpnge_sd(__m128d __a, __m128d __b)
}
/// \brief Compares the lower double-precision floating-point values in each of
-/// the two 128-bit floating-point vectors of [2 x double] for equality. The
-/// comparison yields 0 for false, 1 for true.
+/// the two 128-bit floating-point vectors of [2 x double] for equality.
+///
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -996,7 +998,8 @@ _mm_cmpnge_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comieq_sd(__m128d __a, __m128d __b)
{
@@ -1008,7 +1011,8 @@ _mm_comieq_sd(__m128d __a, __m128d __b)
/// the value in the first parameter is less than the corresponding value in
/// the second parameter.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1020,7 +1024,8 @@ _mm_comieq_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comilt_sd(__m128d __a, __m128d __b)
{
@@ -1032,7 +1037,8 @@ _mm_comilt_sd(__m128d __a, __m128d __b)
/// the value in the first parameter is less than or equal to the
/// corresponding value in the second parameter.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1044,7 +1050,8 @@ _mm_comilt_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comile_sd(__m128d __a, __m128d __b)
{
@@ -1056,7 +1063,8 @@ _mm_comile_sd(__m128d __a, __m128d __b)
/// the value in the first parameter is greater than the corresponding value
/// in the second parameter.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1068,7 +1076,8 @@ _mm_comile_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comigt_sd(__m128d __a, __m128d __b)
{
@@ -1080,7 +1089,8 @@ _mm_comigt_sd(__m128d __a, __m128d __b)
/// the value in the first parameter is greater than or equal to the
/// corresponding value in the second parameter.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1092,7 +1102,8 @@ _mm_comigt_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comige_sd(__m128d __a, __m128d __b)
{
@@ -1104,7 +1115,8 @@ _mm_comige_sd(__m128d __a, __m128d __b)
/// the value in the first parameter is unequal to the corresponding value in
/// the second parameter.
///
-/// The comparison yields 0 for false, 1 for true.
+/// The comparison yields 0 for false, 1 for true. If either of the two
+/// lower double-precision values is NaN, 1 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1116,7 +1128,8 @@ _mm_comige_sd(__m128d __a, __m128d __b)
/// \param __b
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results.
+/// \returns An integer containing the comparison results. If either of the two
+/// lower double-precision values is NaN, 1 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_comineq_sd(__m128d __a, __m128d __b)
{
@@ -1127,7 +1140,7 @@ _mm_comineq_sd(__m128d __a, __m128d __b)
/// the two 128-bit floating-point vectors of [2 x double] for equality. The
/// comparison yields 0 for false, 1 for true.
///
-/// If either of the two lower double-precision values is NaN, 1 is returned.
+/// If either of the two lower double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1140,7 +1153,7 @@ _mm_comineq_sd(__m128d __a, __m128d __b)
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
/// \returns An integer containing the comparison results. If either of the two
-/// lower double-precision values is NaN, 1 is returned.
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomieq_sd(__m128d __a, __m128d __b)
{
@@ -1153,7 +1166,7 @@ _mm_ucomieq_sd(__m128d __a, __m128d __b)
/// the second parameter.
///
/// The comparison yields 0 for false, 1 for true. If either of the two lower
-/// double-precision values is NaN, 1 is returned.
+/// double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1166,7 +1179,7 @@ _mm_ucomieq_sd(__m128d __a, __m128d __b)
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
/// \returns An integer containing the comparison results. If either of the two
-/// lower double-precision values is NaN, 1 is returned.
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomilt_sd(__m128d __a, __m128d __b)
{
@@ -1179,7 +1192,7 @@ _mm_ucomilt_sd(__m128d __a, __m128d __b)
/// corresponding value in the second parameter.
///
/// The comparison yields 0 for false, 1 for true. If either of the two lower
-/// double-precision values is NaN, 1 is returned.
+/// double-precision values is NaN, 0 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1192,7 +1205,7 @@ _mm_ucomilt_sd(__m128d __a, __m128d __b)
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
/// \returns An integer containing the comparison results. If either of the two
-/// lower double-precision values is NaN, 1 is returned.
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomile_sd(__m128d __a, __m128d __b)
{
@@ -1257,7 +1270,7 @@ _mm_ucomige_sd(__m128d __a, __m128d __b)
/// the second parameter.
///
/// The comparison yields 0 for false, 1 for true. If either of the two lower
-/// double-precision values is NaN, 0 is returned.
+/// double-precision values is NaN, 1 is returned.
///
/// \headerfile <x86intrin.h>
///
@@ -1270,7 +1283,7 @@ _mm_ucomige_sd(__m128d __a, __m128d __b)
/// A 128-bit vector of [2 x double]. The lower double-precision value is
/// compared to the lower double-precision value of \a __a.
/// \returns An integer containing the comparison result. If either of the two
-/// lower double-precision values is NaN, 0 is returned.
+/// lower double-precision values is NaN, 1 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_ucomineq_sd(__m128d __a, __m128d __b)
{
@@ -1935,14 +1948,15 @@ _mm_store_pd(double *__dp, __m128d __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c>VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction.
+/// This intrinsic corresponds to the
+/// <c> VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction.
///
/// \param __dp
/// A pointer to a memory location that can store two double-precision
/// values.
/// \param __a
/// A 128-bit vector of [2 x double] whose lower 64 bits are copied to each
-/// of the values in \a dp.
+/// of the values in \a __dp.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store1_pd(double *__dp, __m128d __a)
{
@@ -1950,18 +1964,20 @@ _mm_store1_pd(double *__dp, __m128d __a)
_mm_store_pd(__dp, __a);
}
-/// \brief Stores a 128-bit vector of [2 x double] into an aligned memory
-/// location.
+/// \brief Moves the lower 64 bits of a 128-bit vector of [2 x double] twice to
+/// the upper and lower 64 bits of a memory location.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVAPD / MOVAPD </c> instruction.
+/// This intrinsic corresponds to the
+/// <c> VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS </c> instruction.
///
/// \param __dp
-/// A pointer to a 128-bit memory location. The address of the memory
-/// location has to be 16-byte aligned.
+/// A pointer to a memory location that can store two double-precision
+/// values.
/// \param __a
-/// A 128-bit vector of [2 x double] containing the values to be stored.
+/// A 128-bit vector of [2 x double] whose lower 64 bits are copied to each
+/// of the values in \a __dp.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_pd1(double *__dp, __m128d __a)
{
@@ -3846,8 +3862,7 @@ _mm_set1_epi8(char __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VPUNPCKLQDQ / PUNPCKLQDQ </c>
-/// instruction.
+/// This intrinsic does not correspond to a specific instruction.
///
/// \param __q0
/// A 64-bit integral value used to initialize the lower 64 bits of the
@@ -4018,7 +4033,7 @@ _mm_storeu_si128(__m128i *__p, __m128i __b)
/// specified unaligned memory location. When a mask bit is 1, the
/// corresponding byte is written, otherwise it is not written.
///
-/// To minimize caching, the date is flagged as non-temporal (unlikely to be
+/// To minimize caching, the data is flagged as non-temporal (unlikely to be
/// used again soon). Exception and trap behavior for elements not selected
/// for storage to memory are implementation dependent.
///
@@ -4532,8 +4547,8 @@ _mm_unpackhi_epi32(__m128i __a, __m128i __b)
return (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si)__b, 2, 4+2, 3, 4+3);
}
-/// \brief Unpacks the high-order (odd-indexed) values from two 128-bit vectors
-/// of [2 x i64] and interleaves them into a 128-bit vector of [2 x i64].
+/// \brief Unpacks the high-order 64-bit elements from two 128-bit vectors of
+/// [2 x i64] and interleaves them into a 128-bit vector of [2 x i64].
///
/// \headerfile <x86intrin.h>
///
@@ -4665,7 +4680,7 @@ _mm_unpacklo_epi64(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic has no corresponding instruction.
+/// This intrinsic corresponds to the <c> MOVDQ2Q </c> instruction.
///
/// \param __a
/// A 128-bit integer vector operand. The lower 64 bits are moved to the
@@ -4682,7 +4697,7 @@ _mm_movepi64_pi64(__m128i __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVQ / MOVQ / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVD+VMOVQ </c> instruction.
///
/// \param __a
/// A 64-bit value.
@@ -4712,8 +4727,8 @@ _mm_move_epi64(__m128i __a)
return __builtin_shufflevector((__v2di)__a, (__m128i){ 0 }, 0, 2);
}
-/// \brief Unpacks the high-order (odd-indexed) values from two 128-bit vectors
-/// of [2 x double] and interleaves them into a 128-bit vector of [2 x
+/// \brief Unpacks the high-order 64-bit elements from two 128-bit vectors of
+/// [2 x double] and interleaves them into a 128-bit vector of [2 x
/// double].
///
/// \headerfile <x86intrin.h>
@@ -4733,7 +4748,7 @@ _mm_unpackhi_pd(__m128d __a, __m128d __b)
return __builtin_shufflevector((__v2df)__a, (__v2df)__b, 1, 2+1);
}
-/// \brief Unpacks the low-order (even-indexed) values from two 128-bit vectors
+/// \brief Unpacks the low-order 64-bit elements from two 128-bit vectors
/// of [2 x double] and interleaves them into a 128-bit vector of [2 x
/// double].
///
@@ -4792,9 +4807,9 @@ _mm_movemask_pd(__m128d __a)
/// A 128-bit vector of [2 x double].
/// \param i
/// An 8-bit immediate value. The least significant two bits specify which
-/// elements to copy from a and b: \n
-/// Bit[0] = 0: lower element of a copied to lower element of result. \n
-/// Bit[0] = 1: upper element of a copied to lower element of result. \n
+/// elements to copy from \a a and \a b: \n
+/// Bit[0] = 0: lower element of \a a copied to lower element of result. \n
+/// Bit[0] = 1: upper element of \a a copied to lower element of result. \n
/// Bit[1] = 0: lower element of \a b copied to upper element of result. \n
/// Bit[1] = 1: upper element of \a b copied to upper element of result. \n
/// \returns A 128-bit vector of [2 x double] containing the shuffled values.
diff --git a/lib/Headers/pmmintrin.h b/lib/Headers/pmmintrin.h
index 559ece2e3974f..7ec08a1bcbb37 100644
--- a/lib/Headers/pmmintrin.h
+++ b/lib/Headers/pmmintrin.h
@@ -115,8 +115,8 @@ _mm_hsub_ps(__m128 __a, __m128 __b)
return __builtin_ia32_hsubps((__v4sf)__a, (__v4sf)__b);
}
-/// \brief Moves and duplicates high-order (odd-indexed) values from a 128-bit
-/// vector of [4 x float] to float values stored in a 128-bit vector of
+/// \brief Moves and duplicates odd-indexed values from a 128-bit vector
+/// of [4 x float] to float values stored in a 128-bit vector of
/// [4 x float].
///
/// \headerfile <x86intrin.h>
@@ -137,7 +137,7 @@ _mm_movehdup_ps(__m128 __a)
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 1, 1, 3, 3);
}
-/// \brief Duplicates low-order (even-indexed) values from a 128-bit vector of
+/// \brief Duplicates even-indexed values from a 128-bit vector of
/// [4 x float] to float values stored in a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h
index c2fa5a452bcec..e02775cea358b 100644
--- a/lib/Headers/smmintrin.h
+++ b/lib/Headers/smmintrin.h
@@ -648,7 +648,7 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
/// input vectors are used as an input for dot product; otherwise that input
/// is treated as zero. Bits [1:0] determine which elements of the result
/// will receive a copy of the final dot product, with bit [0] corresponding
-/// to the lowest element and bit [3] corresponding to the highest element of
+/// to the lowest element and bit [1] corresponding to the highest element of
/// each [2 x double] vector. If a bit is set, the dot product is returned in
/// the corresponding element; otherwise that element is set to zero.
#define _mm_dp_pd(X, Y, M) __extension__ ({\
@@ -866,8 +866,8 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// 11: Copies the selected bits from \a Y to result bits [127:96]. \n
/// Bits[3:0]: If any of these bits are set, the corresponding result
/// element is cleared.
-/// \returns A 128-bit vector of [4 x float] containing the copied single-
-/// precision floating point elements from the operands.
+/// \returns A 128-bit vector of [4 x float] containing the copied
+/// single-precision floating point elements from the operands.
#define _mm_insert_ps(X, Y, N) __builtin_ia32_insertps128((X), (Y), (N))
/// \brief Extracts a 32-bit integer from a 128-bit vector of [4 x float] and
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 2a999399fb500..127e18439b8e0 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -43,13 +43,13 @@ using namespace clang;
///
/// Called type-id in C++.
TypeResult Parser::ParseTypeName(SourceRange *Range,
- Declarator::TheContext Context,
+ DeclaratorContext Context,
AccessSpecifier AS,
Decl **OwnedType,
ParsedAttributes *Attrs) {
DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);
- if (DSC == DSC_normal)
- DSC = DSC_type_specifier;
+ if (DSC == DeclSpecContext::DSC_normal)
+ DSC = DeclSpecContext::DSC_type_specifier;
// Parse the common declaration-specifiers piece.
DeclSpec DS(AttrFactory);
@@ -1639,7 +1639,7 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
/// ParseDeclaration - Parse a full 'declaration', which consists of
/// declaration-specifiers, some number of declarators, and a semicolon.
-/// 'Context' should be a Declarator::TheContext value. This returns the
+/// 'Context' should be a DeclaratorContext value. This returns the
/// location of the semicolon in DeclEnd.
///
/// declaration: [C99 6.7]
@@ -1653,7 +1653,7 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
/// [C++11/C11] static_assert-declaration
/// others... [FIXME]
///
-Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
+Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
SourceLocation &DeclEnd,
ParsedAttributesWithRange &attrs) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -1714,7 +1714,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
/// of a simple-declaration. If we find that we are, we also parse the
/// for-range-initializer, and place it here.
Parser::DeclGroupPtrTy
-Parser::ParseSimpleDeclaration(unsigned Context,
+Parser::ParseSimpleDeclaration(DeclaratorContext Context,
SourceLocation &DeclEnd,
ParsedAttributesWithRange &Attrs,
bool RequireSemi, ForRangeInit *FRI) {
@@ -1753,7 +1753,7 @@ Parser::ParseSimpleDeclaration(unsigned Context,
/// Returns true if this might be the start of a declarator, or a common typo
/// for a declarator.
-bool Parser::MightBeDeclarator(unsigned Context) {
+bool Parser::MightBeDeclarator(DeclaratorContext Context) {
switch (Tok.getKind()) {
case tok::annot_cxxscope:
case tok::annot_template_id:
@@ -1772,11 +1772,12 @@ bool Parser::MightBeDeclarator(unsigned Context) {
return getLangOpts().CPlusPlus;
case tok::l_square: // Might be an attribute on an unnamed bit-field.
- return Context == Declarator::MemberContext && getLangOpts().CPlusPlus11 &&
- NextToken().is(tok::l_square);
+ return Context == DeclaratorContext::MemberContext &&
+ getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square);
case tok::colon: // Might be a typo for '::' or an unnamed bit-field.
- return Context == Declarator::MemberContext || getLangOpts().CPlusPlus;
+ return Context == DeclaratorContext::MemberContext ||
+ getLangOpts().CPlusPlus;
case tok::identifier:
switch (NextToken().getKind()) {
@@ -1802,8 +1803,9 @@ bool Parser::MightBeDeclarator(unsigned Context) {
// At namespace scope, 'identifier:' is probably a typo for 'identifier::'
// and in block scope it's probably a label. Inside a class definition,
// this is a bit-field.
- return Context == Declarator::MemberContext ||
- (getLangOpts().CPlusPlus && Context == Declarator::FileContext);
+ return Context == DeclaratorContext::MemberContext ||
+ (getLangOpts().CPlusPlus &&
+ Context == DeclaratorContext::FileContext);
case tok::identifier: // Possible virt-specifier.
return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken());
@@ -1902,11 +1904,11 @@ void Parser::SkipMalformedDecl() {
/// definition or a group of object declarations, actually parse the
/// result.
Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
- unsigned Context,
+ DeclaratorContext Context,
SourceLocation *DeclEnd,
ForRangeInit *FRI) {
// Parse the first declarator.
- ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context));
+ ParsingDeclarator D(*this, DS, Context);
ParseDeclarator(D);
// Bail out if the first declarator didn't seem well-formed.
@@ -1953,7 +1955,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// Function definitions are only allowed at file scope and in C++ classes.
// The C++ inline method definition case is handled elsewhere, so we only
// need to handle the file scope definition case.
- if (Context == Declarator::FileContext) {
+ if (Context == DeclaratorContext::FileContext) {
if (isStartOfFunctionDefinition(D)) {
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
Diag(Tok, diag::err_function_declared_typedef);
@@ -2024,7 +2026,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
if (FirstDecl)
DeclsInGroup.push_back(FirstDecl);
- bool ExpectSemi = Context != Declarator::ForContext;
+ bool ExpectSemi = Context != DeclaratorContext::ForContext;
// If we don't have a comma, it is either the end of the list (a ';') or an
// error, bail out.
@@ -2070,7 +2072,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
*DeclEnd = Tok.getLocation();
if (ExpectSemi &&
- ExpectAndConsumeSemi(Context == Declarator::FileContext
+ ExpectAndConsumeSemi(Context == DeclaratorContext::FileContext
? diag::err_invalid_token_after_toplevel_declarator
: diag::err_expected_semi_declaration)) {
// Okay, there was no semicolon and one was expected. If we see a
@@ -2199,7 +2201,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
// FIXME: This check should be for a variable template instantiation only.
// Check that this is a valid instantiation
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
// If the declarator-id is not a template-id, issue a diagnostic and
// recover by ignoring the 'template' keyword.
Diag(Tok, diag::err_template_defn_explicit_instantiation)
@@ -2273,8 +2275,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
if (Init.isInvalid()) {
SmallVector<tok::TokenKind, 2> StopTokens;
StopTokens.push_back(tok::comma);
- if (D.getContext() == Declarator::ForContext ||
- D.getContext() == Declarator::InitStmtContext)
+ if (D.getContext() == DeclaratorContext::ForContext ||
+ D.getContext() == DeclaratorContext::InitStmtContext)
StopTokens.push_back(tok::r_paren);
SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch);
Actions.ActOnInitializerError(ThisDecl);
@@ -2397,7 +2399,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
}
// Issue diagnostic and remove constexpr specfier if present.
- if (DS.isConstexprSpecified() && DSC != DSC_condition) {
+ if (DS.isConstexprSpecified() && DSC != DeclSpecContext::DSC_condition) {
Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr);
DS.ClearConstexprSpec();
}
@@ -2486,7 +2488,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// classes.
if (ParsedType T = Actions.ActOnMSVCUnknownTypeName(
*Tok.getIdentifierInfo(), Tok.getLocation(),
- DSC == DSC_template_type_arg)) {
+ DSC == DeclSpecContext::DSC_template_type_arg)) {
const char *PrevSpec;
unsigned DiagID;
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
@@ -2540,18 +2542,20 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// Parse this as a tag as if the missing tag were present.
if (TagKind == tok::kw_enum)
- ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSC_normal);
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS,
+ DeclSpecContext::DSC_normal);
else
ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS,
- /*EnteringContext*/ false, DSC_normal, Attrs);
+ /*EnteringContext*/ false,
+ DeclSpecContext::DSC_normal, Attrs);
return true;
}
}
// Determine whether this identifier could plausibly be the name of something
// being declared (with a missing type).
- if (!isTypeSpecifier(DSC) &&
- (!SS || DSC == DSC_top_level || DSC == DSC_class)) {
+ if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level ||
+ DSC == DeclSpecContext::DSC_class)) {
// Look ahead to the next token to try to figure out what this declaration
// was supposed to be.
switch (NextToken().getKind()) {
@@ -2575,7 +2579,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// If we're in a context where we could be declaring a constructor,
// check whether this is a constructor declaration with a bogus name.
- if (DSC == DSC_class || (DSC == DSC_top_level && SS)) {
+ if (DSC == DeclSpecContext::DSC_class ||
+ (DSC == DeclSpecContext::DSC_top_level && SS)) {
IdentifierInfo *II = Tok.getIdentifierInfo();
if (Actions.isCurrentClassNameTypo(II, SS)) {
Diag(Loc, diag::err_constructor_bad_name)
@@ -2655,23 +2660,23 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
/// context.
///
/// \param Context the declarator context, which is one of the
-/// Declarator::TheContext enumerator values.
+/// DeclaratorContext enumerator values.
Parser::DeclSpecContext
-Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
- if (Context == Declarator::MemberContext)
- return DSC_class;
- if (Context == Declarator::FileContext)
- return DSC_top_level;
- if (Context == Declarator::TemplateParamContext)
- return DSC_template_param;
- if (Context == Declarator::TemplateTypeArgContext)
- return DSC_template_type_arg;
- if (Context == Declarator::TrailingReturnContext)
- return DSC_trailing;
- if (Context == Declarator::AliasDeclContext ||
- Context == Declarator::AliasTemplateContext)
- return DSC_alias_declaration;
- return DSC_normal;
+Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
+ if (Context == DeclaratorContext::MemberContext)
+ return DeclSpecContext::DSC_class;
+ if (Context == DeclaratorContext::FileContext)
+ return DeclSpecContext::DSC_top_level;
+ if (Context == DeclaratorContext::TemplateParamContext)
+ return DeclSpecContext::DSC_template_param;
+ if (Context == DeclaratorContext::TemplateTypeArgContext)
+ return DeclSpecContext::DSC_template_type_arg;
+ if (Context == DeclaratorContext::TrailingReturnContext)
+ return DeclSpecContext::DSC_trailing;
+ if (Context == DeclaratorContext::AliasDeclContext ||
+ Context == DeclaratorContext::AliasTemplateContext)
+ return DeclSpecContext::DSC_alias_declaration;
+ return DeclSpecContext::DSC_normal;
}
/// ParseAlignArgument - Parse the argument to an alignment-specifier.
@@ -2751,7 +2756,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
LateParsedAttrList *LateAttrs) {
assert(DS.hasTagDefinition() && "shouldn't call this");
- bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
+ bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
+ DSContext == DeclSpecContext::DSC_top_level);
if (getLangOpts().CPlusPlus &&
Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
@@ -2885,7 +2891,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DS.SetRangeEnd(SourceLocation());
}
- bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
+ bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
+ DSContext == DeclSpecContext::DSC_top_level);
bool AttrsLastTime = false;
ParsedAttributesWithRange attrs(AttrFactory);
// We use Sema's policy to get bool macros right.
@@ -2955,8 +2962,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
Scope::FunctionPrototypeScope |
Scope::AtCatchScope)) == 0;
bool AllowNestedNameSpecifiers
- = DSContext == DSC_top_level ||
- (DSContext == DSC_class && DS.isFriendSpecified());
+ = DSContext == DeclSpecContext::DSC_top_level ||
+ (DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified());
Actions.CodeCompleteDeclSpec(getCurScope(), DS,
AllowNonIdentifiers,
@@ -2967,9 +2974,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())
CCC = Sema::PCC_LocalDeclarationSpecifiers;
else if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
- CCC = DSContext == DSC_class? Sema::PCC_MemberTemplate
- : Sema::PCC_Template;
- else if (DSContext == DSC_class)
+ CCC = DSContext == DeclSpecContext::DSC_class ? Sema::PCC_MemberTemplate
+ : Sema::PCC_Template;
+ else if (DSContext == DeclSpecContext::DSC_class)
CCC = Sema::PCC_Class;
else if (CurParsedObjCImpl)
CCC = Sema::PCC_ObjCImplementation;
@@ -3013,10 +3020,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// To improve diagnostics for this case, parse the declaration as a
// constructor (and reject the extra template arguments later).
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next);
- if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
+ if ((DSContext == DeclSpecContext::DSC_top_level ||
+ DSContext == DeclSpecContext::DSC_class) &&
TemplateId->Name &&
Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) &&
- isConstructorDeclarator(/*Unqualified*/false)) {
+ isConstructorDeclarator(/*Unqualified*/ false)) {
// The user meant this to be an out-of-line constructor
// definition, but template arguments are not allowed
// there. Just allow this as a constructor; we'll
@@ -3055,7 +3063,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Check whether this is a constructor declaration. If we're in a
// context where the identifier could be a class name, and it has the
// shape of a constructor declaration, process it as one.
- if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
+ if ((DSContext == DeclSpecContext::DSC_top_level ||
+ DSContext == DeclSpecContext::DSC_class) &&
Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
&SS) &&
isConstructorDeclarator(/*Unqualified*/ false))
@@ -3193,7 +3202,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (DS.isTypeAltiVecVector())
goto DoneWithDeclSpec;
- if (DSContext == DSC_objc_method_result && isObjCInstancetype()) {
+ if (DSContext == DeclSpecContext::DSC_objc_method_result &&
+ isObjCInstancetype()) {
ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc);
assert(TypeRep);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
@@ -3227,7 +3237,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// If we're in a context where the identifier could be a class name,
// check whether this is a constructor declaration.
- if (getLangOpts().CPlusPlus && DSContext == DSC_class &&
+ if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
isConstructorDeclarator(/*Unqualified*/true))
goto DoneWithDeclSpec;
@@ -3235,7 +3245,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Likewise, if this is a context where the identifier could be a template
// name, check whether this is a deduction guide declaration.
if (getLangOpts().CPlusPlus17 &&
- (DSContext == DSC_class || DSContext == DSC_top_level) &&
+ (DSContext == DeclSpecContext::DSC_class ||
+ DSContext == DeclSpecContext::DSC_top_level) &&
Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),
Tok.getLocation()) &&
isConstructorDeclarator(/*Unqualified*/ true,
@@ -3281,7 +3292,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// If we're in a context where the template-id could be a
// constructor name or specialization, check whether this is a
// constructor declaration.
- if (getLangOpts().CPlusPlus && DSContext == DSC_class &&
+ if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&
isConstructorDeclarator(TemplateId->SS.isEmpty()))
goto DoneWithDeclSpec;
@@ -3451,7 +3462,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// friend
case tok::kw_friend:
- if (DSContext == DSC_class)
+ if (DSContext == DeclSpecContext::DSC_class)
isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
else {
PrevSpec = ""; // not actually used by the diagnostic
@@ -4070,7 +4081,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
// Enum definitions should not be parsed in a trailing-return-type.
- bool AllowDeclaration = DSC != DSC_trailing;
+ bool AllowDeclaration = DSC != DeclSpecContext::DSC_trailing;
bool AllowFixedUnderlyingType = AllowDeclaration &&
(getLangOpts().CPlusPlus11 || getLangOpts().MicrosoftExt ||
@@ -4296,14 +4307,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
bool IsDependent = false;
const char *PrevSpec = nullptr;
unsigned DiagID;
- Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
- StartLoc, SS, Name, NameLoc, attrs.getList(),
- AS, DS.getModulePrivateSpecLoc(), TParams,
- Owned, IsDependent, ScopedEnumKWLoc,
- IsScopedUsingClassTag, BaseType,
- DSC == DSC_type_specifier,
- DSC == DSC_template_param ||
- DSC == DSC_template_type_arg, &SkipBody);
+ Decl *TagDecl = Actions.ActOnTag(
+ getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc,
+ attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned,
+ IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType,
+ DSC == DeclSpecContext::DSC_type_specifier,
+ DSC == DeclSpecContext::DSC_template_param ||
+ DSC == DeclSpecContext::DSC_template_type_arg,
+ &SkipBody);
if (SkipBody.ShouldSkip) {
assert(TUK == Sema::TUK_Definition && "can only skip a definition");
@@ -5175,7 +5186,7 @@ void Parser::ParseDeclarator(Declarator &D) {
}
static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
- unsigned TheContext) {
+ DeclaratorContext TheContext) {
if (Kind == tok::star || Kind == tok::caret)
return true;
@@ -5194,8 +5205,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
// (The same thing can in theory happen after a trailing-return-type, but
// since those are a C++11 feature, there is no rejects-valid issue there.)
if (Kind == tok::ampamp)
- return Lang.CPlusPlus11 || (TheContext != Declarator::ConversionIdContext &&
- TheContext != Declarator::CXXNewContext);
+ return Lang.CPlusPlus11 ||
+ (TheContext != DeclaratorContext::ConversionIdContext &&
+ TheContext != DeclaratorContext::CXXNewContext);
return false;
}
@@ -5249,8 +5261,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
(Tok.is(tok::identifier) &&
(NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||
Tok.is(tok::annot_cxxscope))) {
- bool EnteringContext = D.getContext() == Declarator::FileContext ||
- D.getContext() == Declarator::MemberContext;
+ bool EnteringContext =
+ D.getContext() == DeclaratorContext::FileContext ||
+ D.getContext() == DeclaratorContext::MemberContext;
CXXScopeSpec SS;
ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext);
@@ -5316,9 +5329,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// GNU attributes are not allowed here in a new-type-id, but Declspec and
// C++11 attributes are allowed.
unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed |
- ((D.getContext() != Declarator::CXXNewContext)
- ? AR_GNUAttributesParsed
- : AR_GNUAttributesParsedAndRejected);
+ ((D.getContext() != DeclaratorContext::CXXNewContext)
+ ? AR_GNUAttributesParsed
+ : AR_GNUAttributesParsedAndRejected);
ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier());
D.ExtendWithDeclSpec(DS);
@@ -5470,15 +5483,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in
// this context it is a bitfield. Also in range-based for statement colon
// may delimit for-range-declaration.
- ColonProtectionRAIIObject X(*this,
- D.getContext() == Declarator::MemberContext ||
- (D.getContext() == Declarator::ForContext &&
- getLangOpts().CPlusPlus11));
+ ColonProtectionRAIIObject X(
+ *this, D.getContext() == DeclaratorContext::MemberContext ||
+ (D.getContext() == DeclaratorContext::ForContext &&
+ getLangOpts().CPlusPlus11));
// ParseDeclaratorInternal might already have parsed the scope.
if (D.getCXXScopeSpec().isEmpty()) {
- bool EnteringContext = D.getContext() == Declarator::FileContext ||
- D.getContext() == Declarator::MemberContext;
+ bool EnteringContext =
+ D.getContext() == DeclaratorContext::FileContext ||
+ D.getContext() == DeclaratorContext::MemberContext;
ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), nullptr,
EnteringContext);
}
@@ -5507,9 +5521,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// been expanded or contains auto; otherwise, it is parsed as part of the
// parameter-declaration-clause.
if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
- !((D.getContext() == Declarator::PrototypeContext ||
- D.getContext() == Declarator::LambdaExprParameterContext ||
- D.getContext() == Declarator::BlockLiteralContext) &&
+ !((D.getContext() == DeclaratorContext::PrototypeContext ||
+ D.getContext() == DeclaratorContext::LambdaExprParameterContext ||
+ D.getContext() == DeclaratorContext::BlockLiteralContext) &&
NextToken().is(tok::r_paren) &&
!D.hasGroupingParens() &&
!Actions.containsUnexpandedParameterPacks(D) &&
@@ -5541,14 +5555,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
AllowDeductionGuide = false;
} else if (D.getCXXScopeSpec().isSet()) {
AllowConstructorName =
- (D.getContext() == Declarator::FileContext ||
- D.getContext() == Declarator::MemberContext);
+ (D.getContext() == DeclaratorContext::FileContext ||
+ D.getContext() == DeclaratorContext::MemberContext);
AllowDeductionGuide = false;
} else {
- AllowConstructorName = (D.getContext() == Declarator::MemberContext);
+ AllowConstructorName =
+ (D.getContext() == DeclaratorContext::MemberContext);
AllowDeductionGuide =
- (D.getContext() == Declarator::FileContext ||
- D.getContext() == Declarator::MemberContext);
+ (D.getContext() == DeclaratorContext::FileContext ||
+ D.getContext() == DeclaratorContext::MemberContext);
}
SourceLocation TemplateKWLoc;
@@ -5604,15 +5619,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// 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)
+ else if (D.getContext() == DeclaratorContext::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)
+ else if (D.getContext() == DeclaratorContext::AliasDeclContext ||
+ D.getContext() == DeclaratorContext::AliasTemplateContext)
// The most likely error is that the ';' was forgotten.
DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
- else if (D.getContext() == Declarator::TrailingReturnContext &&
+ else if (D.getContext() == DeclaratorContext::TrailingReturnContext &&
!isCXX11VirtSpecifier(Tok))
DiagnoseIdentifier = NextToken().isOneOf(
tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);
@@ -5659,7 +5674,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
LLVM_BUILTIN_TRAP;
if (Tok.is(tok::l_square))
return ParseMisplacedBracketDeclarator(D);
- if (D.getContext() == Declarator::MemberContext) {
+ if (D.getContext() == DeclaratorContext::MemberContext) {
// Objective-C++: Detect C++ keywords and try to prevent further errors by
// treating these keyword as valid member names.
if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus &&
@@ -6042,9 +6057,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
bool IsCXX11MemberFunction =
getLangOpts().CPlusPlus11 &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
- (D.getContext() == Declarator::MemberContext
+ (D.getContext() == DeclaratorContext::MemberContext
? !D.getDeclSpec().isFriendSpecified()
- : D.getContext() == Declarator::FileContext &&
+ : D.getContext() == DeclaratorContext::FileContext &&
D.getCXXScopeSpec().isValid() &&
Actions.CurContext->isRecord());
Sema::CXXThisScopeRAII ThisScope(Actions,
@@ -6309,10 +6324,10 @@ void Parser::ParseParameterDeclarationClause(
// Parse the declarator. This is "PrototypeContext" or
// "LambdaExprParameterContext", because we must accept either
// 'declarator' or 'abstract-declarator' here.
- Declarator ParmDeclarator(DS,
- D.getContext() == Declarator::LambdaExprContext ?
- Declarator::LambdaExprParameterContext :
- Declarator::PrototypeContext);
+ Declarator ParmDeclarator(
+ DS, D.getContext() == DeclaratorContext::LambdaExprContext
+ ? DeclaratorContext::LambdaExprParameterContext
+ : DeclaratorContext::PrototypeContext);
ParseDeclarator(ParmDeclarator);
// Parse GNU attributes, if present.
@@ -6355,7 +6370,7 @@ void Parser::ParseParameterDeclarationClause(
SourceLocation EqualLoc = Tok.getLocation();
// Parse the default argument
- if (D.getContext() == Declarator::MemberContext) {
+ if (D.getContext() == DeclaratorContext::MemberContext) {
// If we're inside a class definition, cache the tokens
// corresponding to the default argument. We'll actually parse
// them when we see the end of the class definition.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 44e7a3512098b..68b73ca1d25f2 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -55,7 +55,7 @@ using namespace clang;
/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
/// 'namespace' identifier '=' qualified-namespace-specifier ';'
///
-Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context,
+Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
SourceLocation &DeclEnd,
SourceLocation InlineLoc) {
assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
@@ -307,7 +307,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
/// 'extern' string-literal '{' declaration-seq[opt] '}'
/// 'extern' string-literal declaration
///
-Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
+Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
assert(isTokenStringLiteral() && "Not a string literal!");
ExprResult Lang = ParseStringLiteralExpression(false);
@@ -434,7 +434,7 @@ Decl *Parser::ParseExportDeclaration() {
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
/// using-directive. Assumes that current token is 'using'.
Parser::DeclGroupPtrTy
-Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
+Parser::ParseUsingDirectiveOrDeclaration(DeclaratorContext Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation &DeclEnd,
ParsedAttributesWithRange &attrs) {
@@ -482,7 +482,7 @@ Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
/// namespace-name attributes[opt] ;
///
-Decl *Parser::ParseUsingDirective(unsigned Context,
+Decl *Parser::ParseUsingDirective(DeclaratorContext Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
ParsedAttributes &attrs) {
@@ -551,7 +551,8 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
/// using-declarator:
/// 'typename'[opt] nested-name-specifier unqualified-id
///
-bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
+bool Parser::ParseUsingDeclarator(DeclaratorContext Context,
+ UsingDeclarator &D) {
D.clear();
// Ignore optional 'typename'.
@@ -582,7 +583,8 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
// or the simple-template-id's template-name in the last component of the
// nested-name-specifier, the name is [...] considered to name the
// constructor.
- if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext &&
+ if (getLangOpts().CPlusPlus11 &&
+ Context == DeclaratorContext::MemberContext &&
Tok.is(tok::identifier) &&
(NextToken().is(tok::semi) || NextToken().is(tok::comma) ||
NextToken().is(tok::ellipsis)) &&
@@ -629,7 +631,7 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
/// 'using' identifier attribute-specifier-seq[opt] = type-id ;
///
Parser::DeclGroupPtrTy
-Parser::ParseUsingDeclaration(unsigned Context,
+Parser::ParseUsingDeclaration(DeclaratorContext Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation UsingLoc, SourceLocation &DeclEnd,
AccessSpecifier AS) {
@@ -699,7 +701,7 @@ Parser::ParseUsingDeclaration(unsigned Context,
// "typename" keyword is allowed for identifiers only,
// because it may be a type definition.
if (D.TypenameLoc.isValid() &&
- D.Name.getKind() != UnqualifiedId::IK_Identifier) {
+ D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {
Diag(D.Name.getSourceRange().getBegin(),
diag::err_typename_identifiers_only)
<< FixItHint::CreateRemoval(SourceRange(D.TypenameLoc));
@@ -753,7 +755,7 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
// Type alias templates cannot be specialized.
int SpecKind = -1;
if (TemplateInfo.Kind == ParsedTemplateInfo::Template &&
- D.Name.getKind() == UnqualifiedId::IK_TemplateId)
+ D.Name.getKind() == UnqualifiedIdKind::IK_TemplateId)
SpecKind = 0;
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization)
SpecKind = 1;
@@ -773,7 +775,7 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
}
// Name must be an identifier.
- if (D.Name.getKind() != UnqualifiedId::IK_Identifier) {
+ if (D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {
Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier);
// No removal fixit: can't recover from this.
SkipUntil(tok::semi);
@@ -791,11 +793,11 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
<< FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc));
Decl *DeclFromDeclSpec = nullptr;
- TypeResult TypeAlias =
- ParseTypeName(nullptr,
- TemplateInfo.Kind ? Declarator::AliasTemplateContext
- : Declarator::AliasDeclContext,
- AS, &DeclFromDeclSpec, &Attrs);
+ TypeResult TypeAlias = ParseTypeName(
+ nullptr,
+ TemplateInfo.Kind ? DeclaratorContext::AliasTemplateContext
+ : DeclaratorContext::AliasDeclContext,
+ AS, &DeclFromDeclSpec, &Attrs);
if (OwnedType)
*OwnedType = DeclFromDeclSpec;
@@ -1094,7 +1096,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
EndLocation = ParseDecltypeSpecifier(DS);
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
@@ -1195,7 +1197,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type,
Actions.getASTContext().getPrintingPolicy());
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
@@ -1612,14 +1614,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// new struct s;
// or
// &T::operator struct s;
- // For these, DSC is DSC_type_specifier or DSC_alias_declaration.
+ // For these, DSC is DeclSpecContext::DSC_type_specifier or
+ // DeclSpecContext::DSC_alias_declaration.
// If there are attributes after class name, parse them.
MaybeParseCXX11Attributes(Attributes);
const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
Sema::TagUseKind TUK;
- if (DSC == DSC_trailing)
+ if (DSC == DeclSpecContext::DSC_trailing)
TUK = Sema::TUK_Reference;
else if (Tok.is(tok::l_brace) ||
(getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
@@ -1881,15 +1884,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
stripTypeAttributesOffDeclSpec(attrs, DS, TUK);
// Declaration or definition of a class type
- TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
- SS, Name, NameLoc, attrs.getList(), AS,
- DS.getModulePrivateSpecLoc(),
- TParams, Owned, IsDependent,
- SourceLocation(), false,
- clang::TypeResult(),
- DSC == DSC_type_specifier,
- DSC == DSC_template_param ||
- DSC == DSC_template_type_arg, &SkipBody);
+ TagOrTempResult = Actions.ActOnTag(
+ getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc,
+ attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned,
+ IsDependent, SourceLocation(), false, clang::TypeResult(),
+ DSC == DeclSpecContext::DSC_type_specifier,
+ DSC == DeclSpecContext::DSC_template_param ||
+ DSC == DeclSpecContext::DSC_template_type_arg,
+ &SkipBody);
// If ActOnTag said the type was dependent, try again with the
// less common call.
@@ -2509,7 +2511,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SourceLocation DeclEnd;
return DeclGroupPtrTy::make(
DeclGroupRef(ParseTemplateDeclarationOrSpecialization(
- Declarator::MemberContext, DeclEnd, AS, AccessAttrs)));
+ DeclaratorContext::MemberContext, DeclEnd, AS, AccessAttrs)));
}
// Handle: member-declaration ::= '__extension__' member-declaration
@@ -2545,7 +2547,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
SourceLocation DeclEnd;
// Otherwise, it must be a using-declaration or an alias-declaration.
- return ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,
+ return ParseUsingDeclaration(DeclaratorContext::MemberContext, TemplateInfo,
UsingLoc, DeclEnd, AS);
}
@@ -2559,7 +2561,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (MalformedTypeSpec)
DS.SetTypeSpecError();
- ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DeclSpecContext::DSC_class,
&CommonLateParsedAttrs);
// Turn off colon protection that was set for declspec.
@@ -2569,7 +2571,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// may get this far before the problem becomes obvious.
if (DS.hasTagDefinition() &&
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate &&
- DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_class,
+ DiagnoseMissingSemiAfterTagDefinition(DS, AS, DeclSpecContext::DSC_class,
&CommonLateParsedAttrs))
return nullptr;
@@ -2593,7 +2595,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
+ ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::MemberContext);
VirtSpecifiers VS;
// Hold late-parsed attributes so we can attach a Decl to them later.
@@ -2852,7 +2854,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
break;
if (Tok.isAtStartOfLine() &&
- !MightBeDeclarator(Declarator::MemberContext)) {
+ !MightBeDeclarator(DeclaratorContext::MemberContext)) {
// This comma was followed by a line-break and something which can't be
// the start of a declarator. The comma was probably a typo for a
// semicolon.
@@ -3709,7 +3711,7 @@ TypeResult Parser::ParseTrailingReturnType(SourceRange &Range) {
ConsumeToken();
- return ParseTypeName(&Range, Declarator::TrailingReturnContext);
+ return ParseTypeName(&Range, DeclaratorContext::TrailingReturnContext);
}
/// \brief We have just started parsing the definition of a new class,
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index bc587628c954d..1b8865edb79aa 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1000,7 +1000,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,
Actions.getASTContext().getPrintingPolicy());
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
DeclaratorInfo);
if (Ty.isInvalid())
@@ -1209,7 +1209,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
PrevSpec, DiagID, Type,
Actions.getASTContext().getPrintingPolicy());
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
if (Ty.isInvalid())
break;
@@ -1824,7 +1824,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
if (isTypeIdUnambiguously()) {
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation());
@@ -2381,7 +2381,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Parse the type declarator.
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
// If our type is followed by an identifier and either ':' or ']', then
@@ -2858,7 +2858,7 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) {
ParseSpecifierQualifierList(DS);
// Parse the block-declarator.
- Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::BlockLiteralContext);
DeclaratorInfo.setFunctionDefinitionKind(FDK_Definition);
ParseDeclarator(DeclaratorInfo);
@@ -2897,7 +2897,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
// Parse the return type if present.
DeclSpec DS(AttrFactory);
- Declarator ParamInfo(DS, Declarator::BlockLiteralContext);
+ Declarator ParamInfo(DS, DeclaratorContext::BlockLiteralContext);
ParamInfo.setFunctionDefinitionKind(FDK_Definition);
// FIXME: Since the return type isn't actually parsed, it can't be used to
// fill ParamInfo with an initial valid range, so do it manually.
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 959cb7a61d3a7..554ab24b02e1c 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -292,8 +292,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
break;
}
- if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
- TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
+ if (TemplateName.getKind() != UnqualifiedIdKind::IK_OperatorFunctionId &&
+ TemplateName.getKind() != UnqualifiedIdKind::IK_LiteralOperatorId) {
Diag(TemplateName.getSourceRange().getBegin(),
diag::err_id_after_template_in_nested_name_spec)
<< TemplateName.getSourceRange();
@@ -1090,7 +1090,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// Parse lambda-declarator[opt].
DeclSpec DS(AttrFactory);
- Declarator D(DS, Declarator::LambdaExprContext);
+ Declarator D(DS, DeclaratorContext::LambdaExprContext);
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
Actions.PushLambdaScope();
@@ -1353,7 +1353,7 @@ ExprResult Parser::ParseCXXCasts() {
ParseSpecifierQualifierList(DS);
// Parse the abstract-declarator, if present.
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
SourceLocation RAngleBracketLoc = Tok.getLocation();
@@ -1660,7 +1660,7 @@ ExprResult Parser::ParseCXXThis() {
/// In C++1z onwards, the type specifier can also be a template-name.
ExprResult
Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
- Declarator DeclaratorInfo(DS, Declarator::FunctionalCastContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::FunctionalCastContext);
ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
assert((Tok.is(tok::l_paren) ||
@@ -1767,8 +1767,9 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
: diag::ext_init_statement)
<< (CK == Sema::ConditionKind::Switch);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy DG = ParseSimpleDeclaration(
- Declarator::InitStmtContext, DeclEnd, attrs, /*RequireSemi=*/true);
+ DeclGroupPtrTy DG =
+ ParseSimpleDeclaration(DeclaratorContext::InitStmtContext, DeclEnd,
+ attrs, /*RequireSemi=*/true);
*InitStmt = Actions.ActOnDeclStmt(DG, DeclStart, DeclEnd);
return ParseCXXCondition(nullptr, Loc, CK);
}
@@ -1781,10 +1782,10 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
// type-specifier-seq
DeclSpec DS(AttrFactory);
DS.takeAttributesFrom(attrs);
- ParseSpecifierQualifierList(DS, AS_none, DSC_condition);
+ ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_condition);
// declarator
- Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::ConditionContext);
ParseDeclarator(DeclaratorInfo);
// simple-asm-expr[opt]
@@ -1982,7 +1983,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
/// type-specifier type-specifier-seq[opt]
///
bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
- ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier);
+ ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_type_specifier);
DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
return false;
}
@@ -2033,9 +2034,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
TemplateTy Template;
TemplateNameKind TNK = TNK_Non_template;
switch (Id.getKind()) {
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
if (AssumeTemplateId) {
// We defer the injected-class-name checks until we've found whether
// this template-id is used to form a nested-name-specifier or not.
@@ -2058,11 +2059,11 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// parse correctly as a template, so suggest the keyword 'template'
// before 'getAs' and treat this as a dependent template name.
std::string Name;
- if (Id.getKind() == UnqualifiedId::IK_Identifier)
+ if (Id.getKind() == UnqualifiedIdKind::IK_Identifier)
Name = Id.Identifier->getName();
else {
Name = "operator ";
- if (Id.getKind() == UnqualifiedId::IK_OperatorFunctionId)
+ if (Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId)
Name += getOperatorSpelling(Id.OperatorFunctionId.Operator);
else
Name += Id.Identifier->getName();
@@ -2079,7 +2080,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
}
break;
- case UnqualifiedId::IK_ConstructorName: {
+ case UnqualifiedIdKind::IK_ConstructorName: {
UnqualifiedId TemplateName;
bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
@@ -2090,7 +2091,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
break;
}
- case UnqualifiedId::IK_DestructorName: {
+ case UnqualifiedIdKind::IK_DestructorName: {
UnqualifiedId TemplateName;
bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
@@ -2129,18 +2130,20 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
true, LAngleLoc, TemplateArgs, RAngleLoc))
return true;
- if (Id.getKind() == UnqualifiedId::IK_Identifier ||
- Id.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
- Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
+ if (Id.getKind() == UnqualifiedIdKind::IK_Identifier ||
+ Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId ||
+ Id.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) {
// Form a parsed representation of the template-id to be stored in the
// UnqualifiedId.
// FIXME: Store name for literal operator too.
IdentifierInfo *TemplateII =
- Id.getKind() == UnqualifiedId::IK_Identifier ? Id.Identifier : nullptr;
- OverloadedOperatorKind OpKind = Id.getKind() == UnqualifiedId::IK_Identifier
- ? OO_None
- : Id.OperatorFunctionId.Operator;
+ Id.getKind() == UnqualifiedIdKind::IK_Identifier ? Id.Identifier
+ : nullptr;
+ OverloadedOperatorKind OpKind =
+ Id.getKind() == UnqualifiedIdKind::IK_Identifier
+ ? OO_None
+ : Id.OperatorFunctionId.Operator;
TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
SS, TemplateKWLoc, Id.StartLocation, TemplateII, OpKind, Template, TNK,
@@ -2162,7 +2165,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
if (Type.isInvalid())
return true;
- if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
+ if (Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
else
Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
@@ -2395,7 +2398,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
// Parse the conversion-declarator, which is merely a sequence of
// ptr-operators.
- Declarator D(DS, Declarator::ConversionIdContext);
+ Declarator D(DS, DeclaratorContext::ConversionIdContext);
ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr);
// Finish up the type.
@@ -2556,8 +2559,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
//
// template-id:
// operator-function-id < template-argument-list[opt] >
- if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
- Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
+ if ((Result.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId ||
+ Result.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) &&
(TemplateSpecified || Tok.is(tok::less)))
return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
nullptr, SourceLocation(),
@@ -2696,7 +2699,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
SourceRange TypeIdParens;
DeclSpec DS(AttrFactory);
- Declarator DeclaratorInfo(DS, Declarator::CXXNewContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::CXXNewContext);
if (Tok.is(tok::l_paren)) {
// If it turns out to be a placement, we change the type location.
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -3172,7 +3175,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
if (ParseAs >= CompoundLiteral) {
// Parse the type declarator.
DeclSpec DS(AttrFactory);
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
{
ColonProtectionRAIIObject InnerColonProtection(*this);
ParseSpecifierQualifierList(DS);
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index fb8624a324b93..688376ca28e69 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -1140,14 +1140,14 @@ bool Parser::isTokIdentifier_in() const {
/// 'null_unspecified'
///
void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
- Declarator::TheContext Context) {
- assert(Context == Declarator::ObjCParameterContext ||
- Context == Declarator::ObjCResultContext);
+ DeclaratorContext Context) {
+ assert(Context == DeclaratorContext::ObjCParameterContext ||
+ Context == DeclaratorContext::ObjCResultContext);
while (1) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPassingType(getCurScope(), DS,
- Context == Declarator::ObjCParameterContext);
+ Context == DeclaratorContext::ObjCParameterContext);
return cutOffParsing();
}
@@ -1242,12 +1242,12 @@ static void takeDeclAttributes(ParsedAttributes &attrs,
/// '(' objc-type-qualifiers[opt] ')'
///
ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
- Declarator::TheContext context,
+ DeclaratorContext context,
ParsedAttributes *paramAttrs) {
- assert(context == Declarator::ObjCParameterContext ||
- context == Declarator::ObjCResultContext);
+ assert(context == DeclaratorContext::ObjCParameterContext ||
+ context == DeclaratorContext::ObjCResultContext);
assert((paramAttrs != nullptr) ==
- (context == Declarator::ObjCParameterContext));
+ (context == DeclaratorContext::ObjCParameterContext));
assert(Tok.is(tok::l_paren) && "expected (");
@@ -1265,9 +1265,9 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
// Parse an abstract declarator.
DeclSpec declSpec(AttrFactory);
declSpec.setObjCQualifiers(&DS);
- DeclSpecContext dsContext = DSC_normal;
- if (context == Declarator::ObjCResultContext)
- dsContext = DSC_objc_method_result;
+ DeclSpecContext dsContext = DeclSpecContext::DSC_normal;
+ if (context == DeclaratorContext::ObjCResultContext)
+ dsContext = DeclSpecContext::DSC_objc_method_result;
ParseSpecifierQualifierList(declSpec, AS_none, dsContext);
Declarator declarator(declSpec, context);
ParseDeclarator(declarator);
@@ -1288,7 +1288,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
// If we're parsing a parameter, steal all the decl attributes
// and add them to the decl spec.
- if (context == Declarator::ObjCParameterContext)
+ if (context == DeclaratorContext::ObjCParameterContext)
takeDeclAttributes(*paramAttrs, declarator);
}
}
@@ -1352,7 +1352,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ParsedType ReturnType;
ObjCDeclSpec DSRet;
if (Tok.is(tok::l_paren))
- ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext,
+ ReturnType = ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResultContext,
nullptr);
// If attributes exist before the method, parse them.
@@ -1416,7 +1416,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ArgInfo.Type = nullptr;
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec,
- Declarator::ObjCParameterContext,
+ DeclaratorContext::ObjCParameterContext,
&paramAttrs);
// If attributes exist before the argument name, parse them.
@@ -1494,7 +1494,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS);
// Parse the declarator.
- Declarator ParmDecl(DS, Declarator::PrototypeContext);
+ Declarator ParmDecl(DS, DeclaratorContext::PrototypeContext);
ParseDeclarator(ParmDecl);
IdentifierInfo *ParmII = ParmDecl.getIdentifier();
Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
@@ -1703,7 +1703,7 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers(
typeArg, Actions.getASTContext().getPrintingPolicy());
// Form a declarator to turn this into a type.
- Declarator D(DS, Declarator::TypeNameContext);
+ Declarator D(DS, DeclaratorContext::TypeNameContext);
TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D);
if (fullTypeArg.isUsable()) {
typeArgs.push_back(fullTypeArg.get());
@@ -2543,7 +2543,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
if (Tok.isNot(tok::ellipsis)) {
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS);
- Declarator ParmDecl(DS, Declarator::ObjCCatchContext);
+ Declarator ParmDecl(DS, DeclaratorContext::ObjCCatchContext);
ParseDeclarator(ParmDecl);
// Inform the actions module about the declarator, so it
@@ -2945,7 +2945,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
// We have a class message. Turn the simple-type-specifier or
// typename-specifier we parsed into a type and parse the
// remainder of the class message.
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
if (Type.isInvalid())
return true;
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index a67a5bbe0deaa..628c1f134ac5d 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -250,7 +250,8 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
do {
ColonProtectionRAIIObject ColonRAII(*this);
SourceRange Range;
- TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, AS);
+ TypeResult TR =
+ ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
if (TR.isUsable()) {
auto ReductionType =
Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 3f25610f4471f..09ae9d7f22f6d 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -211,7 +211,7 @@ Retry:
Allowed == ACK_Any) &&
isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext,
+ DeclGroupPtrTy Decl = ParseDeclaration(DeclaratorContext::BlockContext,
DeclEnd, Attrs);
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
}
@@ -1021,8 +1021,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
ExtensionRAIIObject O(Diags);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
- attrs);
+ DeclGroupPtrTy Res =
+ ParseDeclaration(DeclaratorContext::BlockContext, DeclEnd, attrs);
R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
} else {
// Otherwise this was a unary __extension__ marker.
@@ -1631,7 +1631,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy DG = ParseSimpleDeclaration(
- Declarator::ForContext, DeclEnd, attrs, false,
+ DeclaratorContext::ForContext, DeclEnd, attrs, false,
MightBeForRangeStmt ? &ForRangeInit : nullptr);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (ForRangeInit.ParsedForRangeDecl()) {
@@ -2181,7 +2181,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
if (ParseCXXTypeSpecifierSeq(DS))
return StmtError();
- Declarator ExDecl(DS, Declarator::CXXCatchContext);
+ Declarator ExDecl(DS, DeclaratorContext::CXXCatchContext);
ParseDeclarator(ExDecl);
ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
} else
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 56a16b9e02711..611c0779b1601 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -24,7 +24,7 @@ using namespace clang;
/// \brief Parse a template declaration, explicit instantiation, or
/// explicit specialization.
Decl *
-Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
+Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
SourceLocation &DeclEnd,
AccessSpecifier AS,
AttributeList *AccessAttrs) {
@@ -57,7 +57,7 @@ Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
/// explicit-specialization: [ C++ temp.expl.spec]
/// 'template' '<' '>' declaration
Decl *
-Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
+Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
SourceLocation &DeclEnd,
AccessSpecifier AS,
AttributeList *AccessAttrs) {
@@ -169,7 +169,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
/// \returns the new declaration.
Decl *
Parser::ParseSingleDeclarationAfterTemplate(
- unsigned Context,
+ DeclaratorContext Context,
const ParsedTemplateInfo &TemplateInfo,
ParsingDeclRAIIObject &DiagsFromTParams,
SourceLocation &DeclEnd,
@@ -186,7 +186,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
return ParseStaticAssertDeclaration(DeclEnd);
}
- if (Context == Declarator::MemberContext) {
+ if (Context == DeclaratorContext::MemberContext) {
// We are parsing a member template.
ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
&DiagsFromTParams);
@@ -234,7 +234,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
DS.takeAttributesFrom(prefixAttrs);
// Parse the declarator.
- ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
+ ParsingDeclarator DeclaratorInfo(*this, DS, (DeclaratorContext)Context);
ParseDeclarator(DeclaratorInfo);
// Error parsing the declarator?
if (!DeclaratorInfo.hasName()) {
@@ -255,7 +255,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
// Function definitions are only allowed at file scope and in C++ classes.
// The C++ inline method definition case is handled elsewhere, so we only
// need to handle the file scope definition case.
- if (Context != Declarator::FileContext) {
+ if (Context != DeclaratorContext::FileContext) {
Diag(Tok, diag::err_function_definition_not_allowed);
SkipMalformedDecl();
return nullptr;
@@ -271,7 +271,8 @@ Parser::ParseSingleDeclarationAfterTemplate(
}
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
- if (DeclaratorInfo.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ if (DeclaratorInfo.getName().getKind() !=
+ UnqualifiedIdKind::IK_TemplateId) {
// If the declarator-id is not a template-id, issue a diagnostic and
// recover by ignoring the 'template' keyword.
Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
@@ -369,7 +370,7 @@ bool Parser::ParseTemplateParameters(
/// template-parameter
/// template-parameter-list ',' template-parameter
bool
-Parser::ParseTemplateParameterList(unsigned Depth,
+Parser::ParseTemplateParameterList(const unsigned Depth,
SmallVectorImpl<NamedDecl*> &TemplateParams) {
while (1) {
@@ -546,7 +547,7 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
ParsedType DefaultArg;
if (TryConsumeToken(tok::equal, EqualLoc))
DefaultArg = ParseTypeName(/*Range=*/nullptr,
- Declarator::TemplateTypeArgContext).get();
+ DeclaratorContext::TemplateTypeArgContext).get();
return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc,
KeyLoc, ParamName, NameLoc, Depth, Position,
@@ -676,10 +677,10 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// declarators (parts of declarators?) are accepted for parameters.
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
- DSC_template_param);
+ DeclSpecContext::DSC_template_param);
// Parse this as a typename.
- Declarator ParamDecl(DS, Declarator::TemplateParamContext);
+ Declarator ParamDecl(DS, DeclaratorContext::TemplateParamContext);
ParseDeclarator(ParamDecl);
if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
Diag(Tok.getLocation(), diag::err_expected_template_parameter);
@@ -1015,12 +1016,12 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
Tok.setKind(tok::annot_template_id);
IdentifierInfo *TemplateII =
- TemplateName.getKind() == UnqualifiedId::IK_Identifier
+ TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier
? TemplateName.Identifier
: nullptr;
OverloadedOperatorKind OpKind =
- TemplateName.getKind() == UnqualifiedId::IK_Identifier
+ TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier
? OO_None
: TemplateName.OperatorFunctionId.Operator;
@@ -1193,8 +1194,8 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
SourceLocation Loc = Tok.getLocation();
- TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr,
- Declarator::TemplateTypeArgContext);
+ TypeResult TypeArg = ParseTypeName(
+ /*Range=*/nullptr, DeclaratorContext::TemplateTypeArgContext);
if (TypeArg.isInvalid())
return ParsedTemplateArgument();
@@ -1297,7 +1298,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
/// 'extern' [opt] 'template' declaration
///
/// Note that the 'extern' is a GNU extension and C++11 feature.
-Decl *Parser::ParseExplicitInstantiation(unsigned Context,
+Decl *Parser::ParseExplicitInstantiation(DeclaratorContext Context,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
SourceLocation &DeclEnd,
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 8aa50a2c7f2a5..a6f966eda1b99 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -783,7 +783,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
// A function definition cannot start with any of these keywords.
{
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
+ return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
case tok::kw_static:
@@ -793,7 +793,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
<< 0;
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
+ return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
goto dont_know;
@@ -804,7 +804,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
// Inline namespaces. Allowed as an extension even in C++03.
if (NextKind == tok::kw_namespace) {
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
+ return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
// Parse (then ignore) 'inline' prior to a template instantiation. This is
@@ -813,7 +813,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
<< 1;
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs);
+ return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs);
}
}
goto dont_know;
@@ -828,7 +828,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc);
SourceLocation DeclEnd;
return Actions.ConvertDeclToDeclGroup(
- ParseExplicitInstantiation(Declarator::FileContext,
+ ParseExplicitInstantiation(DeclaratorContext::FileContext,
ExternLoc, TemplateLoc, DeclEnd));
}
goto dont_know;
@@ -919,12 +919,13 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
AccessSpecifier AS) {
MaybeParseMicrosoftAttributes(DS.getAttributes());
// Parse the common declaration-specifiers piece.
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
+ ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS,
+ DeclSpecContext::DSC_top_level);
// If we had a free-standing type definition with a missing semicolon, we
// may get this far before the problem becomes obvious.
- if (DS.hasTagDefinition() &&
- DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_top_level))
+ if (DS.hasTagDefinition() && DiagnoseMissingSemiAfterTagDefinition(
+ DS, AS, DeclSpecContext::DSC_top_level))
return nullptr;
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -1004,11 +1005,11 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
if (getLangOpts().CPlusPlus && isTokenStringLiteral() &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
- Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext);
+ Decl *TheDecl = ParseLinkage(DS, DeclaratorContext::FileContext);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- return ParseDeclGroup(DS, Declarator::FileContext);
+ return ParseDeclGroup(DS, DeclaratorContext::FileContext);
}
Parser::DeclGroupPtrTy
@@ -1313,7 +1314,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
}
// Parse the first declarator attached to this declspec.
- Declarator ParmDeclarator(DS, Declarator::KNRTypeListContext);
+ Declarator ParmDeclarator(DS, DeclaratorContext::KNRTypeListContext);
ParseDeclarator(ParmDeclarator);
// Handle the full declarator list.
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 6fe2dcc9895fb..2fad5a18ba6bc 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -30,7 +30,7 @@ using namespace clang;
void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
assert(TemplateId && "NULL template-id annotation?");
- Kind = IK_TemplateId;
+ Kind = UnqualifiedIdKind::IK_TemplateId;
this->TemplateId = TemplateId;
StartLocation = TemplateId->TemplateNameLoc;
EndLocation = TemplateId->RAngleLoc;
@@ -38,7 +38,7 @@ void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
assert(TemplateId && "NULL template-id annotation?");
- Kind = IK_ConstructorTemplateId;
+ Kind = UnqualifiedIdKind::IK_ConstructorTemplateId;
this->TemplateId = TemplateId;
StartLocation = TemplateId->TemplateNameLoc;
EndLocation = TemplateId->RAngleLoc;
@@ -387,16 +387,16 @@ bool Declarator::isDeclarationOfFunction() const {
}
bool Declarator::isStaticMember() {
- assert(getContext() == MemberContext);
+ assert(getContext() == DeclaratorContext::MemberContext);
return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
- (getName().Kind == UnqualifiedId::IK_OperatorFunctionId &&
+ (getName().Kind == UnqualifiedIdKind::IK_OperatorFunctionId &&
CXXMethodDecl::isStaticOverloadedOperator(
getName().OperatorFunctionId.Operator));
}
bool Declarator::isCtorOrDtor() {
- return (getName().getKind() == UnqualifiedId::IK_ConstructorName) ||
- (getName().getKind() == UnqualifiedId::IK_DestructorName);
+ return (getName().getKind() == UnqualifiedIdKind::IK_ConstructorName) ||
+ (getName().getKind() == UnqualifiedIdKind::IK_DestructorName);
}
bool DeclSpec::hasTagDefinition() const {
@@ -1281,7 +1281,7 @@ bool DeclSpec::isMissingDeclaratorOk() {
void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
OverloadedOperatorKind Op,
SourceLocation SymbolLocations[3]) {
- Kind = IK_OperatorFunctionId;
+ Kind = UnqualifiedIdKind::IK_OperatorFunctionId;
StartLocation = OperatorLoc;
EndLocation = OperatorLoc;
OperatorFunctionId.Operator = Op;
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 9aed178763dc9..2acc896d53d71 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4171,8 +4171,8 @@ void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
AddTypeQualifierResults(DS, Results, LangOpts);
if (LangOpts.CPlusPlus11) {
Results.AddResult("noexcept");
- if (D.getContext() == Declarator::MemberContext && !D.isCtorOrDtor() &&
- !D.isStaticMember()) {
+ if (D.getContext() == DeclaratorContext::MemberContext &&
+ !D.isCtorOrDtor() && !D.isStaticMember()) {
if (!VS || !VS->isFinalSpecified())
Results.AddResult("final");
if (!VS || !VS->isOverrideSpecified())
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index a1fc725f8df47..743f4bb5e8228 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4746,7 +4746,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
}
// Mock up a declarator.
- Declarator Dc(DS, Declarator::MemberContext);
+ Declarator Dc(DS, DeclaratorContext::MemberContext);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct/union");
@@ -4843,7 +4843,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
assert(Record && "expected a record!");
// Mock up a declarator.
- Declarator Dc(DS, Declarator::TypeNameContext);
+ Declarator Dc(DS, DeclaratorContext::TypeNameContext);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct");
@@ -4897,13 +4897,13 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
switch (Name.getKind()) {
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_Identifier:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_Identifier:
NameInfo.setName(Name.Identifier);
NameInfo.setLoc(Name.StartLocation);
return NameInfo;
- case UnqualifiedId::IK_DeductionGuideName: {
+ case UnqualifiedIdKind::IK_DeductionGuideName: {
// C++ [temp.deduct.guide]p3:
// The simple-template-id shall name a class template specialization.
// The template-name shall be the same identifier as the template-name
@@ -4931,7 +4931,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator));
NameInfo.setLoc(Name.StartLocation);
@@ -4941,14 +4941,14 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
= Name.EndLocation.getRawEncoding();
return NameInfo;
- case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName(
Name.Identifier));
NameInfo.setLoc(Name.StartLocation);
NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation);
return NameInfo;
- case UnqualifiedId::IK_ConversionFunctionId: {
+ case UnqualifiedIdKind::IK_ConversionFunctionId: {
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo);
if (Ty.isNull())
@@ -4960,7 +4960,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_ConstructorName: {
+ case UnqualifiedIdKind::IK_ConstructorName: {
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo);
if (Ty.isNull())
@@ -4972,7 +4972,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_ConstructorTemplateId: {
+ case UnqualifiedIdKind::IK_ConstructorTemplateId: {
// In well-formed code, we can only have a constructor
// template-id that refers to the current context, so go there
// to find the actual type being constructed.
@@ -4995,7 +4995,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_DestructorName: {
+ case UnqualifiedIdKind::IK_DestructorName: {
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo);
if (Ty.isNull())
@@ -5007,7 +5007,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return NameInfo;
}
- case UnqualifiedId::IK_TemplateId: {
+ case UnqualifiedIdKind::IK_TemplateId: {
TemplateName TName = Name.TemplateId->Template.get();
SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc;
return Context.getNameForTemplate(TName, TNameLoc);
@@ -5670,8 +5670,8 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 1;
- if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
- if (D.getName().Kind == UnqualifiedId::IK_DeductionGuideName)
+ if (D.getName().Kind != UnqualifiedIdKind::IK_Identifier) {
+ if (D.getName().Kind == UnqualifiedIdKind::IK_DeductionGuideName)
Diag(D.getName().StartLocation,
diag::err_deduction_guide_invalid_specifier)
<< "typedef";
@@ -6425,7 +6425,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
TemplateParams = MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
D.getCXXScopeSpec(),
- D.getName().getKind() == UnqualifiedId::IK_TemplateId
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
? D.getName().TemplateId
: nullptr,
TemplateParamLists,
@@ -6433,7 +6433,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
if (TemplateParams) {
if (!TemplateParams->size() &&
- D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
// There is an extraneous 'template<>' for this variable. Complain
// about it, but allow the declaration of the variable.
Diag(TemplateParams->getTemplateLoc(),
@@ -6443,7 +6443,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
TemplateParams->getRAngleLoc());
TemplateParams = nullptr;
} else {
- if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
// This is an explicit specialization or a partial specialization.
// FIXME: Check that we can declare a specialization here.
IsVariableTemplateSpecialization = true;
@@ -6464,9 +6464,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
} else {
- assert(
- (Invalid || D.getName().getKind() != UnqualifiedId::IK_TemplateId) &&
- "should have a 'template<>' for this decl");
+ assert((Invalid ||
+ D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) &&
+ "should have a 'template<>' for this decl");
}
if (IsVariableTemplateSpecialization) {
@@ -8261,7 +8261,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
D.getCXXScopeSpec(),
- D.getName().getKind() == UnqualifiedId::IK_TemplateId
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
? D.getName().TemplateId
: nullptr,
TemplateParamLists, isFriend, isMemberSpecialization,
@@ -8318,7 +8318,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// and clearly the user wants a template specialization. So
// we need to insert '<>' after the name.
SourceLocation InsertLoc;
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
InsertLoc = D.getName().getSourceRange().getEnd();
InsertLoc = getLocForEndOfToken(InsertLoc);
}
@@ -8719,7 +8719,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// If the declarator is a template-id, translate the parser's template
// argument list into our AST format.
- if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
@@ -10893,7 +10893,7 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID,
getPrintingPolicy());
- Declarator D(DS, Declarator::ForContext);
+ Declarator D(DS, DeclaratorContext::ForContext);
D.SetIdentifier(Ident, IdentLoc);
D.takeAttributes(Attrs, AttrEnd);
@@ -11809,7 +11809,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
// Use the identifier location for the type source range.
DS.SetRangeStart(FTI.Params[i].IdentLoc);
DS.SetRangeEnd(FTI.Params[i].IdentLoc);
- Declarator ParamD(DS, Declarator::KNRTypeListContext);
+ Declarator ParamD(DS, DeclaratorContext::KNRTypeListContext);
ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc);
FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD);
}
@@ -12574,7 +12574,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
(void)Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
SourceLocation NoLoc;
- Declarator D(DS, Declarator::BlockContext);
+ Declarator D(DS, DeclaratorContext::BlockContext);
D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false,
/*IsAmbiguous=*/false,
/*LParenLoc=*/NoLoc,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index aa26b37f444d9..5e24649c71bea 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -712,7 +712,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
Diag(Decomp.getLSquareLoc(),
!getLangOpts().CPlusPlus17
? diag::ext_decomp_decl
- : D.getContext() == Declarator::ConditionContext
+ : D.getContext() == DeclaratorContext::ConditionContext
? diag::ext_decomp_decl_cond
: diag::warn_cxx14_compat_decomp_decl)
<< Decomp.getSourceRange();
@@ -8986,15 +8986,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
}
switch (Name.getKind()) {
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_LiteralOperatorId:
- case UnqualifiedId::IK_ConversionFunctionId:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_ConversionFunctionId:
break;
- case UnqualifiedId::IK_ConstructorName:
- case UnqualifiedId::IK_ConstructorTemplateId:
+ case UnqualifiedIdKind::IK_ConstructorName:
+ case UnqualifiedIdKind::IK_ConstructorTemplateId:
// C++11 inheriting constructors.
Diag(Name.getLocStart(),
getLangOpts().CPlusPlus11 ?
@@ -9006,17 +9006,17 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
return nullptr;
- case UnqualifiedId::IK_DestructorName:
+ case UnqualifiedIdKind::IK_DestructorName:
Diag(Name.getLocStart(), diag::err_using_decl_destructor)
<< SS.getRange();
return nullptr;
- case UnqualifiedId::IK_TemplateId:
+ case UnqualifiedIdKind::IK_TemplateId:
Diag(Name.getLocStart(), diag::err_using_decl_template_id)
<< SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
return nullptr;
- case UnqualifiedId::IK_DeductionGuideName:
+ case UnqualifiedIdKind::IK_DeductionGuideName:
llvm_unreachable("cannot parse qualified deduction guide name");
}
@@ -10040,7 +10040,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
Previous.clear();
}
- assert(Name.Kind == UnqualifiedId::IK_Identifier &&
+ assert(Name.Kind == UnqualifiedIdKind::IK_Identifier &&
"name in alias declaration must be an identifier");
TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc,
Name.StartLocation,
@@ -12215,30 +12215,27 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv) {
SynthesizedFunctionScope Scope(*this, Conv);
+ assert(!Conv->getReturnType()->isUndeducedType());
CXXRecordDecl *Lambda = Conv->getParent();
- CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
- // If we are defining a specialization of a conversion to function-ptr
- // cache the deduced template arguments for this specialization
- // so that we can use them to retrieve the corresponding call-operator
- // and static-invoker.
- const TemplateArgumentList *DeducedTemplateArgs = nullptr;
-
- // Retrieve the corresponding call-operator specialization.
- if (Lambda->isGenericLambda()) {
- assert(Conv->isFunctionTemplateSpecialization());
- FunctionTemplateDecl *CallOpTemplate =
- CallOp->getDescribedFunctionTemplate();
- DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
- void *InsertPos = nullptr;
- FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
- DeducedTemplateArgs->asArray(),
- InsertPos);
- assert(CallOpSpec &&
- "Conversion operator must have a corresponding call operator");
- CallOp = cast<CXXMethodDecl>(CallOpSpec);
+ FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
+ FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker();
+
+ if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) {
+ CallOp = InstantiateFunctionDeclaration(
+ CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
+ if (!CallOp)
+ return;
+
+ Invoker = InstantiateFunctionDeclaration(
+ Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
+ if (!Invoker)
+ return;
}
+ if (CallOp->isInvalidDecl())
+ return;
+
// Mark the call operator referenced (and add to pending instantiations
// if necessary).
// For both the conversion and static-invoker template specializations
@@ -12246,39 +12243,24 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
// to the PendingInstantiations.
MarkFunctionReferenced(CurrentLocation, CallOp);
- // Retrieve the static invoker...
- CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
- // ... and get the corresponding specialization for a generic lambda.
- if (Lambda->isGenericLambda()) {
- assert(DeducedTemplateArgs &&
- "Must have deduced template arguments from Conversion Operator");
- FunctionTemplateDecl *InvokeTemplate =
- Invoker->getDescribedFunctionTemplate();
- void *InsertPos = nullptr;
- FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
- DeducedTemplateArgs->asArray(),
- InsertPos);
- assert(InvokeSpec &&
- "Must have a corresponding static invoker specialization");
- Invoker = cast<CXXMethodDecl>(InvokeSpec);
- }
+ // Fill in the __invoke function with a dummy implementation. IR generation
+ // will fill in the actual details. Update its type in case it contained
+ // an 'auto'.
+ Invoker->markUsed(Context);
+ Invoker->setReferenced();
+ Invoker->setType(Conv->getReturnType()->getPointeeType());
+ Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
+
// Construct the body of the conversion function { return __invoke; }.
Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
- VK_LValue, Conv->getLocation()).get();
+ VK_LValue, Conv->getLocation()).get();
assert(FunctionRef && "Can't refer to __invoke function?");
Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get();
Conv->setBody(CompoundStmt::Create(Context, Return, Conv->getLocation(),
Conv->getLocation()));
-
Conv->markUsed(Context);
Conv->setReferenced();
- // Fill in the __invoke function with a dummy implementation. IR generation
- // will fill in the actual details.
- Invoker->markUsed(Context);
- Invoker->setReferenced();
- Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
-
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
L->CompletedImplicitDefinition(Invoker);
@@ -13625,7 +13607,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
- Declarator TheDeclarator(DS, Declarator::MemberContext);
+ Declarator TheDeclarator(DS, DeclaratorContext::MemberContext);
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())
@@ -13799,7 +13781,8 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// elaborated-type-specifier, the lookup to determine whether
// the entity has been previously declared shall not consider
// any scopes outside the innermost enclosing namespace.
- bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId;
+ bool isTemplateId =
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId;
// Find the appropriate context according to the above.
DC = CurContext;
@@ -13910,24 +13893,24 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
if (!DC->isRecord()) {
int DiagArg = -1;
switch (D.getName().getKind()) {
- case UnqualifiedId::IK_ConstructorTemplateId:
- case UnqualifiedId::IK_ConstructorName:
+ case UnqualifiedIdKind::IK_ConstructorTemplateId:
+ case UnqualifiedIdKind::IK_ConstructorName:
DiagArg = 0;
break;
- case UnqualifiedId::IK_DestructorName:
+ case UnqualifiedIdKind::IK_DestructorName:
DiagArg = 1;
break;
- case UnqualifiedId::IK_ConversionFunctionId:
+ case UnqualifiedIdKind::IK_ConversionFunctionId:
DiagArg = 2;
break;
- case UnqualifiedId::IK_DeductionGuideName:
+ case UnqualifiedIdKind::IK_DeductionGuideName:
DiagArg = 3;
break;
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_LiteralOperatorId:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_TemplateId:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_TemplateId:
break;
}
// This implies that it has to be an operator or function.
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index abbdc9574b8ce..ff3c07e938a80 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1538,7 +1538,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
DS.SetRangeEnd(loc);
// Form the declarator.
- Declarator D(DS, Declarator::TypeNameContext);
+ Declarator D(DS, DeclaratorContext::TypeNameContext);
// If we have a typedef of an Objective-C class type that is missing a '*',
// add the '*'.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 4746355e98003..7e01b058ab2d9 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1711,7 +1711,7 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
TemplateArgumentListInfo &Buffer,
DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *&TemplateArgs) {
- if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
+ if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId) {
Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
@@ -2070,9 +2070,10 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
IsAddressOfOperand, TemplateArgs);
// Perform the required lookup.
- LookupResult R(*this, NameInfo,
- (Id.getKind() == UnqualifiedId::IK_ImplicitSelfParam)
- ? LookupObjCImplicitSelfParam : LookupOrdinaryName);
+ LookupResult R(*this, NameInfo,
+ (Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam)
+ ? LookupObjCImplicitSelfParam
+ : LookupOrdinaryName);
if (TemplateArgs) {
// Lookup the template name again to correctly establish the context in
// which it was found. This is really unfortunate as we already did the
@@ -2243,7 +2244,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
// In C++1y, if this is a variable template id, then check it
// in BuildTemplateIdExpr().
// The single lookup result must be a variable template declaration.
- if (Id.getKind() == UnqualifiedId::IK_TemplateId && Id.TemplateId &&
+ if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId && Id.TemplateId &&
Id.TemplateId->Kind == TNK_Var_template) {
assert(R.getAsSingle<VarTemplateDecl>() &&
"There should only be one declaration found.");
@@ -2401,7 +2402,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
IdentifierInfo &II = Context.Idents.get("self");
UnqualifiedId SelfName;
SelfName.setIdentifier(&II, SourceLocation());
- SelfName.setKind(UnqualifiedId::IK_ImplicitSelfParam);
+ SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
CXXScopeSpec SelfScopeSpec;
SourceLocation TemplateKWLoc;
ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc,
@@ -12834,7 +12835,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
Scope *CurScope) {
assert(ParamInfo.getIdentifier() == nullptr &&
"block-id should have no identifier!");
- assert(ParamInfo.getContext() == Declarator::BlockLiteralContext);
+ assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteralContext);
BlockScopeInfo *CurBlock = getCurBlock();
TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index cff9fbbf491b2..89055aecd4b6d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -356,7 +356,7 @@ ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS,
bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
const UnqualifiedId &Name) {
- assert(Name.getKind() == UnqualifiedId::IK_LiteralOperatorId);
+ assert(Name.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId);
if (!SS.isValid())
return false;
@@ -6716,11 +6716,11 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
SourceLocation CCLoc,
SourceLocation TildeLoc,
UnqualifiedId &SecondTypeName) {
- assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
- FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+ assert((FirstTypeName.getKind() == UnqualifiedIdKind::IK_TemplateId ||
+ FirstTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) &&
"Invalid first type name in pseudo-destructor");
- assert((SecondTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
- SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+ assert((SecondTypeName.getKind() == UnqualifiedIdKind::IK_TemplateId ||
+ SecondTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) &&
"Invalid second type name in pseudo-destructor");
QualType ObjectType;
@@ -6742,7 +6742,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
QualType DestructedType;
TypeSourceInfo *DestructedTypeInfo = nullptr;
PseudoDestructorTypeStorage Destructed;
- if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+ if (SecondTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) {
ParsedType T = getTypeName(*SecondTypeName.Identifier,
SecondTypeName.StartLocation,
S, &SS, true, false, ObjectTypePtrForLookup,
@@ -6800,9 +6800,9 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
// Convert the name of the scope type (the type prior to '::') into a type.
TypeSourceInfo *ScopeTypeInfo = nullptr;
QualType ScopeType;
- if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+ if (FirstTypeName.getKind() == UnqualifiedIdKind::IK_TemplateId ||
FirstTypeName.Identifier) {
- if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+ if (FirstTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) {
ParsedType T = getTypeName(*FirstTypeName.Identifier,
FirstTypeName.StartLocation,
S, &SS, true, false, ObjectTypePtrForLookup,
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index dd516ea3b4284..f57f79e62efe0 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -1707,7 +1707,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
// Warn about the explicit constructor calls Microsoft extension.
if (getLangOpts().MicrosoftExt &&
- Id.getKind() == UnqualifiedId::IK_ConstructorName)
+ Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
Diag(Id.getSourceRange().getBegin(),
diag::ext_ms_explicit_constructor_call);
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index cbfc330ca60b2..19d2de719728d 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -1167,6 +1167,24 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
PopFunctionScopeInfo();
}
+QualType Sema::getLambdaConversionFunctionResultType(
+ const FunctionProtoType *CallOpProto) {
+ // The function type inside the pointer type is the same as the call
+ // operator with some tweaks. The calling convention is the default free
+ // function convention, and the type qualifications are lost.
+ const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
+ CallOpProto->getExtProtoInfo();
+ FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
+ CallingConv CC = Context.getDefaultCallingConvention(
+ CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
+ InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
+ InvokerExtInfo.TypeQuals = 0;
+ assert(InvokerExtInfo.RefQualifier == RQ_None &&
+ "Lambda's call operator should not have a reference qualifier");
+ return Context.getFunctionType(CallOpProto->getReturnType(),
+ CallOpProto->getParamTypes(), InvokerExtInfo);
+}
+
/// \brief Add a lambda's conversion to function pointer, as described in
/// C++11 [expr.prim.lambda]p6.
static void addFunctionPointerConversion(Sema &S,
@@ -1182,25 +1200,9 @@ static void addFunctionPointerConversion(Sema &S,
return;
// Add the conversion to function pointer.
- const FunctionProtoType *CallOpProto =
- CallOperator->getType()->getAs<FunctionProtoType>();
- const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
- CallOpProto->getExtProtoInfo();
- QualType PtrToFunctionTy;
- QualType InvokerFunctionTy;
- {
- FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
- CallingConv CC = S.Context.getDefaultCallingConvention(
- CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
- InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
- InvokerExtInfo.TypeQuals = 0;
- assert(InvokerExtInfo.RefQualifier == RQ_None &&
- "Lambda's call operator should not have a reference qualifier");
- InvokerFunctionTy =
- S.Context.getFunctionType(CallOpProto->getReturnType(),
- CallOpProto->getParamTypes(), InvokerExtInfo);
- PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
- }
+ QualType InvokerFunctionTy = S.getLambdaConversionFunctionResultType(
+ CallOperator->getType()->castAs<FunctionProtoType>());
+ QualType PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
// Create the type of the conversion function.
FunctionProtoType::ExtProtoInfo ConvExtInfo(
@@ -1357,19 +1359,8 @@ static void addBlockPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
- const FunctionProtoType *Proto =
- CallOperator->getType()->getAs<FunctionProtoType>();
-
- // The function type inside the block pointer type is the same as the call
- // operator with some tweaks. The calling convention is the default free
- // function convention, and the type qualifications are lost.
- FunctionProtoType::ExtProtoInfo BlockEPI = Proto->getExtProtoInfo();
- BlockEPI.ExtInfo =
- BlockEPI.ExtInfo.withCallingConv(S.Context.getDefaultCallingConvention(
- Proto->isVariadic(), /*IsCXXMethod=*/false));
- BlockEPI.TypeQuals = 0;
- QualType FunctionTy = S.Context.getFunctionType(
- Proto->getReturnType(), Proto->getParamTypes(), BlockEPI);
+ QualType FunctionTy = S.getLambdaConversionFunctionResultType(
+ CallOperator->getType()->castAs<FunctionProtoType>());
QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
FunctionProtoType::ExtProtoInfo ConversionEPI(
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2144845f4dd36..f2b1963df1ed2 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -5145,7 +5145,8 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
*this, From->getLocStart(), From->getType(), FromClassification, Method,
Method->getParent());
if (ICS.isBad()) {
- if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
+ switch (ICS.Bad.Kind) {
+ case BadConversionSequence::bad_qualifiers: {
Qualifiers FromQs = FromRecordType.getQualifiers();
Qualifiers ToQs = DestType.getQualifiers();
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
@@ -5158,10 +5159,28 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
<< Method->getDeclName();
return ExprError();
}
+ break;
+ }
+
+ case BadConversionSequence::lvalue_ref_to_rvalue:
+ case BadConversionSequence::rvalue_ref_to_lvalue: {
+ bool IsRValueQualified =
+ Method->getRefQualifier() == RefQualifierKind::RQ_RValue;
+ Diag(From->getLocStart(), diag::err_member_function_call_bad_ref)
+ << Method->getDeclName() << FromClassification.isRValue()
+ << IsRValueQualified;
+ Diag(Method->getLocation(), diag::note_previous_decl)
+ << Method->getDeclName();
+ return ExprError();
+ }
+
+ case BadConversionSequence::no_conversion:
+ case BadConversionSequence::unrelated_class:
+ break;
}
return Diag(From->getLocStart(),
- diag::err_implicit_object_parameter_init)
+ diag::err_member_function_call_bad_type)
<< ImplicitParamRecordType << FromRecordType << From->getSourceRange();
}
@@ -11309,9 +11328,6 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
return Matched;
}
-
-
-
// Resolve and fix an overloaded expression that can be resolved
// because it identifies a single function template specialization.
//
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 4474d62949a24..1ebc36716a881 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -14,6 +14,7 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -3228,6 +3229,12 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
SourceLocation ReturnLoc,
Expr *&RetExpr,
AutoType *AT) {
+ // If this is the conversion function for a lambda, we choose to deduce it
+ // type from the corresponding call operator, not from the synthesized return
+ // statement within it. See Sema::DeduceReturnType.
+ if (isLambdaConversionOperator(FD))
+ return false;
+
TypeLoc OrigResultType = getReturnTypeLoc(FD);
QualType Deduced;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index d94cb0d0f4854..7c6af5793fc55 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -169,16 +169,16 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
MemberOfUnknownSpecialization = false;
switch (Name.getKind()) {
- case UnqualifiedId::IK_Identifier:
+ case UnqualifiedIdKind::IK_Identifier:
TName = DeclarationName(Name.Identifier);
break;
- case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
TName = Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator);
break;
- case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier);
break;
@@ -3557,7 +3557,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
TemplateParameterList *TemplateParams, StorageClass SC,
bool IsPartialSpecialization) {
// D must be variable template id.
- assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
+ assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId &&
"Variable template specialization is declared with a template it.");
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
@@ -4084,8 +4084,8 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
// We found something; return it.
auto *LookupRD = dyn_cast<CXXRecordDecl>(LookupCtx);
if (!AllowInjectedClassName && SS.isSet() && LookupRD &&
- Name.getKind() == UnqualifiedId::IK_Identifier && Name.Identifier &&
- LookupRD->getIdentifier() == Name.Identifier) {
+ Name.getKind() == UnqualifiedIdKind::IK_Identifier &&
+ Name.Identifier && LookupRD->getIdentifier() == Name.Identifier) {
// C++14 [class.qual]p2:
// In a lookup in which function names are not ignored and the
// nested-name-specifier nominates a class C, if the name specified
@@ -4107,17 +4107,17 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
NestedNameSpecifier *Qualifier = SS.getScopeRep();
switch (Name.getKind()) {
- case UnqualifiedId::IK_Identifier:
+ case UnqualifiedIdKind::IK_Identifier:
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.Identifier));
return TNK_Dependent_template_name;
- case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.OperatorFunctionId.Operator));
return TNK_Function_template;
- case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
llvm_unreachable("literal operator id cannot have a dependent scope");
default:
@@ -9044,7 +9044,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return true;
}
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
// C++1y [temp.explicit]p3:
// If the explicit instantiation is for a variable, the unqualified-id
// in the declaration shall be a template-id.
@@ -9126,7 +9126,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// argument list into our AST format.
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo TemplateArgs;
- if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
HasExplicitTemplateArgs = true;
}
@@ -9292,7 +9292,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
//
// C++98 has the same restriction, just worded differently.
FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl &&
+ if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId && !FunTmpl &&
D.getCXXScopeSpec().isSet() &&
!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
Diag(D.getIdentifierLoc(),
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index f8ee602516988..3a0f2ff0004be 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -3940,117 +3940,6 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return TDK_Success;
}
-/// \brief Given a function declaration (e.g. a generic lambda conversion
-/// function) that contains an 'auto' in its result type, substitute it
-/// with TypeToReplaceAutoWith. Be careful to pass in the type you want
-/// to replace 'auto' with and not the actual result type you want
-/// to set the function to.
-static inline void
-SubstAutoWithinFunctionReturnType(FunctionDecl *F,
- QualType TypeToReplaceAutoWith, Sema &S) {
- assert(!TypeToReplaceAutoWith->getContainedAutoType());
- QualType AutoResultType = F->getReturnType();
- assert(AutoResultType->getContainedAutoType());
- QualType DeducedResultType = S.SubstAutoType(AutoResultType,
- TypeToReplaceAutoWith);
- S.Context.adjustDeducedFunctionResultType(F, DeducedResultType);
-}
-
-/// \brief Given a specialized conversion operator of a generic lambda
-/// create the corresponding specializations of the call operator and
-/// the static-invoker. If the return type of the call operator is auto,
-/// deduce its return type and check if that matches the
-/// return type of the destination function ptr.
-
-static inline Sema::TemplateDeductionResult
-SpecializeCorrespondingLambdaCallOperatorAndInvoker(
- CXXConversionDecl *ConversionSpecialized,
- SmallVectorImpl<DeducedTemplateArgument> &DeducedArguments,
- QualType ReturnTypeOfDestFunctionPtr,
- TemplateDeductionInfo &TDInfo,
- Sema &S) {
-
- CXXRecordDecl *LambdaClass = ConversionSpecialized->getParent();
- assert(LambdaClass && LambdaClass->isGenericLambda());
-
- CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
- QualType CallOpResultType = CallOpGeneric->getReturnType();
- const bool GenericLambdaCallOperatorHasDeducedReturnType =
- CallOpResultType->getContainedAutoType();
-
- FunctionTemplateDecl *CallOpTemplate =
- CallOpGeneric->getDescribedFunctionTemplate();
-
- FunctionDecl *CallOpSpecialized = nullptr;
- // Use the deduced arguments of the conversion function, to specialize our
- // generic lambda's call operator.
- if (Sema::TemplateDeductionResult Result
- = S.FinishTemplateArgumentDeduction(CallOpTemplate,
- DeducedArguments,
- 0, CallOpSpecialized, TDInfo))
- return Result;
-
- // If we need to deduce the return type, do so (instantiates the callop).
- if (GenericLambdaCallOperatorHasDeducedReturnType &&
- CallOpSpecialized->getReturnType()->isUndeducedType())
- S.DeduceReturnType(CallOpSpecialized,
- CallOpSpecialized->getPointOfInstantiation(),
- /*Diagnose*/ true);
-
- // Check to see if the return type of the destination ptr-to-function
- // matches the return type of the call operator.
- if (!S.Context.hasSameType(CallOpSpecialized->getReturnType(),
- ReturnTypeOfDestFunctionPtr))
- return Sema::TDK_NonDeducedMismatch;
- // Since we have succeeded in matching the source and destination
- // ptr-to-functions (now including return type), and have successfully
- // specialized our corresponding call operator, we are ready to
- // specialize the static invoker with the deduced arguments of our
- // ptr-to-function.
- FunctionDecl *InvokerSpecialized = nullptr;
- FunctionTemplateDecl *InvokerTemplate = LambdaClass->
- getLambdaStaticInvoker()->getDescribedFunctionTemplate();
-
-#ifndef NDEBUG
- Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result =
-#endif
- S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
- InvokerSpecialized, TDInfo);
- assert(Result == Sema::TDK_Success &&
- "If the call operator succeeded so should the invoker!");
- // Set the result type to match the corresponding call operator
- // specialization's result type.
- if (GenericLambdaCallOperatorHasDeducedReturnType &&
- InvokerSpecialized->getReturnType()->isUndeducedType()) {
- // Be sure to get the type to replace 'auto' with and not
- // the full result type of the call op specialization
- // to substitute into the 'auto' of the invoker and conversion
- // function.
- // For e.g.
- // int* (*fp)(int*) = [](auto* a) -> auto* { return a; };
- // We don't want to subst 'int*' into 'auto' to get int**.
-
- QualType TypeToReplaceAutoWith = CallOpSpecialized->getReturnType()
- ->getContainedAutoType()
- ->getDeducedType();
- SubstAutoWithinFunctionReturnType(InvokerSpecialized,
- TypeToReplaceAutoWith, S);
- SubstAutoWithinFunctionReturnType(ConversionSpecialized,
- TypeToReplaceAutoWith, S);
- }
-
- // Ensure that static invoker doesn't have a const qualifier.
- // FIXME: When creating the InvokerTemplate in SemaLambda.cpp
- // do not use the CallOperator's TypeSourceInfo which allows
- // the const qualifier to leak through.
- const FunctionProtoType *InvokerFPT = InvokerSpecialized->
- getType().getTypePtr()->castAs<FunctionProtoType>();
- FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
- EPI.TypeQuals = 0;
- InvokerSpecialized->setType(S.Context.getFunctionType(
- InvokerFPT->getReturnType(), InvokerFPT->getParamTypes(), EPI));
- return Sema::TDK_Success;
-}
/// \brief Deduce template arguments for a templated conversion
/// function (C++ [temp.deduct.conv]) and, if successful, produce a
/// conversion function template specialization.
@@ -4158,35 +4047,6 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
= FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
ConversionSpecialized, Info);
Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
-
- // If the conversion operator is being invoked on a lambda closure to convert
- // to a ptr-to-function, use the deduced arguments from the conversion
- // function to specialize the corresponding call operator.
- // e.g., int (*fp)(int) = [](auto a) { return a; };
- if (Result == TDK_Success && isLambdaConversionOperator(ConversionGeneric)) {
-
- // Get the return type of the destination ptr-to-function we are converting
- // to. This is necessary for matching the lambda call operator's return
- // type to that of the destination ptr-to-function's return type.
- assert(A->isPointerType() &&
- "Can only convert from lambda to ptr-to-function");
- const FunctionType *ToFunType =
- A->getPointeeType().getTypePtr()->getAs<FunctionType>();
- const QualType DestFunctionPtrReturnType = ToFunType->getReturnType();
-
- // Create the corresponding specializations of the call operator and
- // the static-invoker; and if the return type is auto,
- // deduce the return type and check if it matches the
- // DestFunctionPtrReturnType.
- // For instance:
- // auto L = [](auto a) { return f(a); };
- // int (*fp)(int) = L;
- // char (*fp2)(int) = L; <-- Not OK.
-
- Result = SpecializeCorrespondingLambdaCallOperatorAndInvoker(
- Specialization, Deduced, DestFunctionPtrReturnType,
- Info, *this);
- }
return Result;
}
@@ -4536,6 +4396,43 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose) {
assert(FD->getReturnType()->isUndeducedType());
+ // For a lambda's conversion operator, deduce any 'auto' or 'decltype(auto)'
+ // within the return type from the call operator's type.
+ if (isLambdaConversionOperator(FD)) {
+ CXXRecordDecl *Lambda = cast<CXXMethodDecl>(FD)->getParent();
+ FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
+
+ // For a generic lambda, instantiate the call operator if needed.
+ if (auto *Args = FD->getTemplateSpecializationArgs()) {
+ CallOp = InstantiateFunctionDeclaration(
+ CallOp->getDescribedFunctionTemplate(), Args, Loc);
+ if (!CallOp || CallOp->isInvalidDecl())
+ return true;
+
+ // We might need to deduce the return type by instantiating the definition
+ // of the operator() function.
+ if (CallOp->getReturnType()->isUndeducedType())
+ InstantiateFunctionDefinition(Loc, CallOp);
+ }
+
+ if (CallOp->isInvalidDecl())
+ return true;
+ assert(!CallOp->getReturnType()->isUndeducedType() &&
+ "failed to deduce lambda return type");
+
+ // Build the new return type from scratch.
+ QualType RetType = getLambdaConversionFunctionResultType(
+ CallOp->getType()->castAs<FunctionProtoType>());
+ if (FD->getReturnType()->getAs<PointerType>())
+ RetType = Context.getPointerType(RetType);
+ else {
+ assert(FD->getReturnType()->getAs<BlockPointerType>());
+ RetType = Context.getBlockPointerType(RetType);
+ }
+ Context.adjustDeducedFunctionResultType(FD, RetType);
+ return false;
+ }
+
if (FD->getTemplateInstantiationPattern())
InstantiateFunctionDefinition(Loc, FD);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d8af8f34530b1..ab68e7e671de6 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3729,6 +3729,30 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
return false;
}
+/// Instantiate (or find existing instantiation of) a function template with a
+/// given set of template arguments.
+///
+/// Usually this should not be used, and template argument deduction should be
+/// used in its place.
+FunctionDecl *
+Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
+ const TemplateArgumentList *Args,
+ SourceLocation Loc) {
+ FunctionDecl *FD = FTD->getTemplatedDecl();
+
+ sema::TemplateDeductionInfo Info(Loc);
+ InstantiatingTemplate Inst(
+ *this, Loc, FTD, Args->asArray(),
+ CodeSynthesisContext::ExplicitTemplateArgumentSubstitution, Info);
+ if (Inst.isInvalid())
+ return nullptr;
+
+ ContextRAII SavedContext(*this, FD);
+ MultiLevelTemplateArgumentList MArgs(*Args);
+
+ return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs));
+}
+
/// In the MS ABI, we need to instantiate default arguments of dllexported
/// default constructors along with the constructor definition. This allows IR
/// gen to emit a constructor closure which calls the default constructor with
@@ -3812,7 +3836,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
PendingInstantiations.push_back(
std::make_pair(Function, PointOfInstantiation));
} else if (TSK == TSK_ImplicitInstantiation) {
- if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
+ if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
+ !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
Diag(PointOfInstantiation, diag::warn_func_template_missing)
<< Function;
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
@@ -4347,7 +4372,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
std::make_pair(Var, PointOfInstantiation));
} else if (TSK == TSK_ImplicitInstantiation) {
// Warn about missing definition at the end of translation unit.
- if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
+ if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
+ !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
Diag(PointOfInstantiation, diag::warn_var_template_missing)
<< Var;
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 2530b766f5f72..af060cf21b5fa 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -47,7 +47,7 @@ enum TypeDiagSelector {
/// isOmittedBlockReturnType - Return true if this declarator is missing a
/// return type because this is a omitted return type on a block literal.
static bool isOmittedBlockReturnType(const Declarator &D) {
- if (D.getContext() != Declarator::BlockLiteralContext ||
+ if (D.getContext() != DeclaratorContext::BlockLiteralContext ||
D.getDeclSpec().hasTypeSpecifier())
return false;
@@ -1291,11 +1291,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// The declspec is always missing in a lambda expr context; it is either
// specified with a trailing return type or inferred.
if (S.getLangOpts().CPlusPlus14 &&
- declarator.getContext() == Declarator::LambdaExprContext) {
+ declarator.getContext() == DeclaratorContext::LambdaExprContext) {
// In C++1y, a lambda's implicit return type is 'auto'.
Result = Context.getAutoDeductType();
break;
- } else if (declarator.getContext() == Declarator::LambdaExprContext ||
+ } else if (declarator.getContext() ==
+ DeclaratorContext::LambdaExprContext ||
checkOmittedBlockReturnType(S, declarator,
Context.DependentTy)) {
Result = Context.DependentTy;
@@ -1572,7 +1573,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// Before we process any type attributes, synthesize a block literal
// function declarator if necessary.
- if (declarator.getContext() == Declarator::BlockLiteralContext)
+ if (declarator.getContext() == DeclaratorContext::BlockLiteralContext)
maybeSynthesizeBlockSignature(state, Result);
// Apply any type attributes from the decl spec. This may cause the
@@ -2702,7 +2703,7 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
// If the qualifiers come from a conversion function type, don't diagnose
// them -- they're not necessarily redundant, since such a conversion
// operator can be explicitly called as "x.operator const int()".
- if (D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId)
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
return;
// Just parens all the way out to the decl specifiers. Diagnose any qualifiers
@@ -2728,11 +2729,11 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
TagDecl *OwnedTagDecl = nullptr;
switch (D.getName().getKind()) {
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_LiteralOperatorId:
- case UnqualifiedId::IK_TemplateId:
+ case UnqualifiedIdKind::IK_ImplicitSelfParam:
+ case UnqualifiedIdKind::IK_OperatorFunctionId:
+ case UnqualifiedIdKind::IK_Identifier:
+ case UnqualifiedIdKind::IK_LiteralOperatorId:
+ case UnqualifiedIdKind::IK_TemplateId:
T = ConvertDeclSpecToType(state);
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
@@ -2742,9 +2743,9 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
}
break;
- case UnqualifiedId::IK_ConstructorName:
- case UnqualifiedId::IK_ConstructorTemplateId:
- case UnqualifiedId::IK_DestructorName:
+ case UnqualifiedIdKind::IK_ConstructorName:
+ case UnqualifiedIdKind::IK_ConstructorTemplateId:
+ case UnqualifiedIdKind::IK_DestructorName:
// Constructors and destructors don't have return types. Use
// "void" instead.
T = SemaRef.Context.VoidTy;
@@ -2752,13 +2753,13 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
D.getDeclSpec().getAttributes().getList());
break;
- case UnqualifiedId::IK_DeductionGuideName:
+ case UnqualifiedIdKind::IK_DeductionGuideName:
// Deduction guides have a trailing return type and no type in their
// decl-specifier sequence. Use a placeholder return type for now.
T = SemaRef.Context.DependentTy;
break;
- case UnqualifiedId::IK_ConversionFunctionId:
+ case UnqualifiedIdKind::IK_ConversionFunctionId:
// The result type of a conversion function is the type that it
// converts to.
T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
@@ -2780,16 +2781,16 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
(Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType);
switch (D.getContext()) {
- case Declarator::LambdaExprContext:
+ case DeclaratorContext::LambdaExprContext:
// Declared return type of a lambda-declarator is implicit and is always
// 'auto'.
break;
- case Declarator::ObjCParameterContext:
- case Declarator::ObjCResultContext:
- case Declarator::PrototypeContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::PrototypeContext:
Error = 0;
break;
- case Declarator::LambdaExprParameterContext:
+ case DeclaratorContext::LambdaExprParameterContext:
// In C++14, generic lambdas allow 'auto' in their parameters.
if (!SemaRef.getLangOpts().CPlusPlus14 ||
!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
@@ -2821,7 +2822,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
T, QualType(CorrespondingTemplateParam->getTypeForDecl(), 0));
}
break;
- case Declarator::MemberContext: {
+ case DeclaratorContext::MemberContext: {
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
D.isFunctionDeclarator())
break;
@@ -2837,57 +2838,57 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 20; // Friend type
break;
}
- case Declarator::CXXCatchContext:
- case Declarator::ObjCCatchContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
Error = 7; // Exception declaration
break;
- case Declarator::TemplateParamContext:
+ case DeclaratorContext::TemplateParamContext:
if (isa<DeducedTemplateSpecializationType>(Deduced))
Error = 19; // Template parameter
else if (!SemaRef.getLangOpts().CPlusPlus17)
Error = 8; // Template parameter (until C++17)
break;
- case Declarator::BlockLiteralContext:
+ case DeclaratorContext::BlockLiteralContext:
Error = 9; // Block literal
break;
- case Declarator::TemplateTypeArgContext:
+ case DeclaratorContext::TemplateTypeArgContext:
Error = 10; // Template type argument
break;
- case Declarator::AliasDeclContext:
- case Declarator::AliasTemplateContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
Error = 12; // Type alias
break;
- case Declarator::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 13; // Function return type
break;
- case Declarator::ConversionIdContext:
+ case DeclaratorContext::ConversionIdContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 14; // conversion-type-id
break;
- case Declarator::FunctionalCastContext:
+ case DeclaratorContext::FunctionalCastContext:
if (isa<DeducedTemplateSpecializationType>(Deduced))
break;
LLVM_FALLTHROUGH;
- case Declarator::TypeNameContext:
+ case DeclaratorContext::TypeNameContext:
Error = 15; // Generic
break;
- case Declarator::FileContext:
- case Declarator::BlockContext:
- case Declarator::ForContext:
- case Declarator::InitStmtContext:
- case Declarator::ConditionContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
// FIXME: P0091R3 (erroneously) does not permit class template argument
// deduction in conditions, for-init-statements, and other declarations
// that are not simple-declarations.
break;
- case Declarator::CXXNewContext:
+ case DeclaratorContext::CXXNewContext:
// FIXME: P0091R3 does not permit class template argument deduction here,
// but we follow GCC and allow it anyway.
if (!IsCXXAutoType && !isa<DeducedTemplateSpecializationType>(Deduced))
Error = 17; // 'new' type
break;
- case Declarator::KNRTypeListContext:
+ case DeclaratorContext::KNRTypeListContext:
Error = 18; // K&R function parameter
break;
}
@@ -2916,7 +2917,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
}
SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
- if (D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId)
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
AutoRange = D.getName().getSourceRange();
if (Error != -1) {
@@ -2959,47 +2960,47 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// or enumeration in a type-specifier-seq.
unsigned DiagID = 0;
switch (D.getContext()) {
- case Declarator::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnContext:
// Class and enumeration definitions are syntactically not allowed in
// trailing return types.
llvm_unreachable("parser should not have allowed this");
break;
- case Declarator::FileContext:
- case Declarator::MemberContext:
- case Declarator::BlockContext:
- case Declarator::ForContext:
- case Declarator::InitStmtContext:
- case Declarator::BlockLiteralContext:
- case Declarator::LambdaExprContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
// C++11 [dcl.type]p3:
// A type-specifier-seq shall not define a class or enumeration unless
// it appears in the type-id of an alias-declaration (7.1.3) that is not
// the declaration of a template-declaration.
- case Declarator::AliasDeclContext:
+ case DeclaratorContext::AliasDeclContext:
break;
- case Declarator::AliasTemplateContext:
+ case DeclaratorContext::AliasTemplateContext:
DiagID = diag::err_type_defined_in_alias_template;
break;
- case Declarator::TypeNameContext:
- case Declarator::FunctionalCastContext:
- case Declarator::ConversionIdContext:
- case Declarator::TemplateParamContext:
- case Declarator::CXXNewContext:
- case Declarator::CXXCatchContext:
- case Declarator::ObjCCatchContext:
- case Declarator::TemplateTypeArgContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::TemplateTypeArgContext:
DiagID = diag::err_type_defined_in_type_specifier;
break;
- case Declarator::PrototypeContext:
- case Declarator::LambdaExprParameterContext:
- case Declarator::ObjCParameterContext:
- case Declarator::ObjCResultContext:
- case Declarator::KNRTypeListContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::KNRTypeListContext:
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
DiagID = diag::err_type_defined_in_param_type;
break;
- case Declarator::ConditionContext:
+ case DeclaratorContext::ConditionContext:
// C++ 6.4p2:
// The type-specifier-seq shall not contain typedef and shall not declare
// a new class or enumeration.
@@ -3048,7 +3049,7 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
// Inside a condition, a direct initializer is not permitted. We allow one to
// be parsed in order to give better diagnostics in condition parsing.
- if (D.getContext() == Declarator::ConditionContext)
+ if (D.getContext() == DeclaratorContext::ConditionContext)
return;
SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
@@ -3164,7 +3165,7 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
case DeclaratorChunk::Function:
// In a new-type-id, function chunks require parentheses.
- if (D.getContext() == Declarator::CXXNewContext)
+ if (D.getContext() == DeclaratorContext::CXXNewContext)
return;
// FIXME: "A(f())" deserves a vexing-parse warning, not just a
// redundant-parens warning, but we don't know whether the function
@@ -3282,7 +3283,7 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
// in a member pointer.
IsCXXInstanceMethod =
D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
- } else if (D.getContext() == Declarator::LambdaExprContext) {
+ } else if (D.getContext() == DeclaratorContext::LambdaExprContext) {
// This can only be a call operator for a lambda, which is an instance
// method.
IsCXXInstanceMethod = true;
@@ -3779,8 +3780,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Does this declaration declare a typedef-name?
bool IsTypedefName =
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
- D.getContext() == Declarator::AliasDeclContext ||
- D.getContext() == Declarator::AliasTemplateContext;
+ D.getContext() == DeclaratorContext::AliasDeclContext ||
+ D.getContext() == DeclaratorContext::AliasTemplateContext;
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
bool IsQualifiedFunction = T->isFunctionProtoType() &&
@@ -3909,14 +3910,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
} else {
bool isFunctionOrMethod = false;
switch (auto context = state.getDeclarator().getContext()) {
- case Declarator::ObjCParameterContext:
- case Declarator::ObjCResultContext:
- case Declarator::PrototypeContext:
- case Declarator::TrailingReturnContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::TrailingReturnContext:
isFunctionOrMethod = true;
LLVM_FALLTHROUGH;
- case Declarator::MemberContext:
+ case DeclaratorContext::MemberContext:
if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) {
complainAboutMissingNullability = CAMN_No;
break;
@@ -3930,8 +3931,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
LLVM_FALLTHROUGH;
- case Declarator::FileContext:
- case Declarator::KNRTypeListContext: {
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::KNRTypeListContext: {
complainAboutMissingNullability = CAMN_Yes;
// Nullability inference depends on the type and declarator.
@@ -3947,8 +3948,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (inAssumeNonNullRegion) {
complainAboutInferringWithinChunk = wrappingKind;
inferNullability = NullabilityKind::NonNull;
- inferNullabilityCS = (context == Declarator::ObjCParameterContext ||
- context == Declarator::ObjCResultContext);
+ inferNullabilityCS =
+ (context == DeclaratorContext::ObjCParameterContext ||
+ context == DeclaratorContext::ObjCResultContext);
}
break;
@@ -3988,26 +3990,26 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
- case Declarator::ConversionIdContext:
+ case DeclaratorContext::ConversionIdContext:
complainAboutMissingNullability = CAMN_Yes;
break;
- case Declarator::AliasDeclContext:
- case Declarator::AliasTemplateContext:
- case Declarator::BlockContext:
- case Declarator::BlockLiteralContext:
- case Declarator::ConditionContext:
- case Declarator::CXXCatchContext:
- case Declarator::CXXNewContext:
- case Declarator::ForContext:
- case Declarator::InitStmtContext:
- case Declarator::LambdaExprContext:
- case Declarator::LambdaExprParameterContext:
- case Declarator::ObjCCatchContext:
- case Declarator::TemplateParamContext:
- case Declarator::TemplateTypeArgContext:
- case Declarator::TypeNameContext:
- case Declarator::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
// Don't infer in these contexts.
break;
}
@@ -4243,7 +4245,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// array type, ...
if (ASM == ArrayType::Static || ATI.TypeQuals) {
if (!(D.isPrototypeContext() ||
- D.getContext() == Declarator::KNRTypeListContext)) {
+ D.getContext() == DeclaratorContext::KNRTypeListContext)) {
S.Diag(DeclType.Loc, diag::err_array_static_outside_prototype) <<
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
// Remove the 'static' and the type qualifiers.
@@ -4267,7 +4269,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
const AutoType *AT = T->getContainedAutoType();
// Allow arrays of auto if we are a generic lambda parameter.
// i.e. [](auto (&array)[5]) { return array[0]; }; OK
- if (AT && D.getContext() != Declarator::LambdaExprParameterContext) {
+ if (AT &&
+ D.getContext() != DeclaratorContext::LambdaExprParameterContext) {
// We've already diagnosed this for decltype(auto).
if (!AT->isDecltypeAuto())
S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
@@ -4319,14 +4322,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getSourceRange();
D.setInvalidType(true);
} else if (D.getName().getKind() ==
- UnqualifiedId::IK_DeductionGuideName) {
+ UnqualifiedIdKind::IK_DeductionGuideName) {
if (T != Context.DependentTy) {
S.Diag(D.getDeclSpec().getLocStart(),
diag::err_deduction_guide_with_complex_decl)
<< D.getSourceRange();
D.setInvalidType(true);
}
- } else if (D.getContext() != Declarator::LambdaExprContext &&
+ } else if (D.getContext() != DeclaratorContext::LambdaExprContext &&
(T.hasQualifiers() || !isa<AutoType>(T) ||
cast<AutoType>(T)->getKeyword() !=
AutoTypeKeyword::Auto)) {
@@ -4347,12 +4350,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// C99 6.7.5.3p1: The return type may not be a function or array type.
// For conversion functions, we'll diagnose this particular error later.
if (!D.isInvalidType() && (T->isArrayType() || T->isFunctionType()) &&
- (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
+ (D.getName().getKind() !=
+ UnqualifiedIdKind::IK_ConversionFunctionId)) {
unsigned diagID = diag::err_func_returning_array_function;
// Last processing chunk in block context means this function chunk
// represents the block.
if (chunkIndex == 0 &&
- D.getContext() == Declarator::BlockLiteralContext)
+ D.getContext() == DeclaratorContext::BlockLiteralContext)
diagID = diag::err_block_returning_array_function;
S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
T = Context.IntTy;
@@ -4490,8 +4494,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus17)
S.Diag(FTI.getExceptionSpecLocBeg(),
diag::err_exception_spec_in_typedef)
- << (D.getContext() == Declarator::AliasDeclContext ||
- D.getContext() == Declarator::AliasTemplateContext);
+ << (D.getContext() == DeclaratorContext::AliasDeclContext ||
+ D.getContext() == DeclaratorContext::AliasTemplateContext);
// If we see "T var();" or "T var(T());" at block scope, it is probably
// an attempt to initialize a variable, not a function declaration.
@@ -4763,7 +4767,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
case DeclaratorChunk::Function: {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- if (FTI.NumParams == 0)
+ if (FTI.NumParams == 0 && !FTI.isVariadic)
S.Diag(DeclType.Loc, diag::warn_strict_prototypes)
<< IsBlock
<< FixItHint::CreateInsertion(FTI.getRParenLoc(), "void");
@@ -4791,11 +4795,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Core issue 547 also allows cv-qualifiers on function types that are
// top-level template type arguments.
enum { NonMember, Member, DeductionGuide } Kind = NonMember;
- if (D.getName().getKind() == UnqualifiedId::IK_DeductionGuideName)
+ if (D.getName().getKind() == UnqualifiedIdKind::IK_DeductionGuideName)
Kind = DeductionGuide;
else if (!D.getCXXScopeSpec().isSet()) {
- if ((D.getContext() == Declarator::MemberContext ||
- D.getContext() == Declarator::LambdaExprContext) &&
+ if ((D.getContext() == DeclaratorContext::MemberContext ||
+ D.getContext() == DeclaratorContext::LambdaExprContext) &&
!D.getDeclSpec().isFriendSpecified())
Kind = Member;
} else {
@@ -4824,7 +4828,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
!(Kind == Member &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
!IsTypedefName &&
- D.getContext() != Declarator::TemplateTypeArgContext) {
+ D.getContext() != DeclaratorContext::TemplateTypeArgContext) {
SourceLocation Loc = D.getLocStart();
SourceRange RemovalRange;
unsigned I;
@@ -4890,8 +4894,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// only be used in a parameter-declaration. Such a parameter-declaration
// is a parameter pack (14.5.3). [...]
switch (D.getContext()) {
- case Declarator::PrototypeContext:
- case Declarator::LambdaExprParameterContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
// C++0x [dcl.fct]p13:
// [...] When it is part of a parameter-declaration-clause, the
// parameter pack is a function parameter pack (14.5.3). The type T
@@ -4910,7 +4914,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
T = Context.getPackExpansionType(T, None);
}
break;
- case Declarator::TemplateParamContext:
+ case DeclaratorContext::TemplateParamContext:
// C++0x [temp.param]p15:
// If a template-parameter is a [...] is a parameter-declaration that
// declares a parameter pack (8.3.5), then the template-parameter is a
@@ -4928,27 +4932,29 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
: diag::ext_variadic_templates);
break;
- case Declarator::FileContext:
- case Declarator::KNRTypeListContext:
- case Declarator::ObjCParameterContext: // FIXME: special diagnostic here?
- case Declarator::ObjCResultContext: // FIXME: special diagnostic here?
- case Declarator::TypeNameContext:
- case Declarator::FunctionalCastContext:
- case Declarator::CXXNewContext:
- case Declarator::AliasDeclContext:
- case Declarator::AliasTemplateContext:
- case Declarator::MemberContext:
- case Declarator::BlockContext:
- case Declarator::ForContext:
- case Declarator::InitStmtContext:
- case Declarator::ConditionContext:
- case Declarator::CXXCatchContext:
- case Declarator::ObjCCatchContext:
- case Declarator::BlockLiteralContext:
- case Declarator::LambdaExprContext:
- case Declarator::ConversionIdContext:
- case Declarator::TrailingReturnContext:
- case Declarator::TemplateTypeArgContext:
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::ObjCParameterContext: // FIXME: special diagnostic
+ // here?
+ case DeclaratorContext::ObjCResultContext: // FIXME: special diagnostic
+ // here?
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TemplateTypeArgContext:
// FIXME: We may want to allow parameter packs in block-literal contexts
// in the future.
S.Diag(D.getEllipsisLoc(),
@@ -5637,9 +5643,9 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// to apply them to the actual parameter declaration.
// Likewise, we don't want to do this for alias declarations, because
// we are actually going to build a declaration from this eventually.
- if (D.getContext() != Declarator::ObjCParameterContext &&
- D.getContext() != Declarator::AliasDeclContext &&
- D.getContext() != Declarator::AliasTemplateContext)
+ if (D.getContext() != DeclaratorContext::ObjCParameterContext &&
+ D.getContext() != DeclaratorContext::AliasDeclContext &&
+ D.getContext() != DeclaratorContext::AliasTemplateContext)
checkUnusedDeclAttributes(D);
if (getLangOpts().CPlusPlus) {
@@ -7066,7 +7072,7 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
IsFuncReturnType || IsFuncType ||
// Do not deduce addr space for member types of struct, except the pointee
// type of a pointer member type.
- (D.getContext() == Declarator::MemberContext && !IsPointee) ||
+ (D.getContext() == DeclaratorContext::MemberContext && !IsPointee) ||
// Do not deduce addr space for types used to define a typedef and the
// typedef itself, except the pointee type of a pointer type which is used
// to define the typedef.
@@ -7098,7 +7104,7 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
if (IsPointee) {
ImpAddr = LangAS::opencl_generic;
} else {
- if (D.getContext() == Declarator::FileContext) {
+ if (D.getContext() == DeclaratorContext::FileContext) {
ImpAddr = LangAS::opencl_global;
} else {
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index dc284888eb032..de0e87bb82494 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -229,7 +229,6 @@ adjustCallLocations(PathPieces &Pieces,
PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(I->get());
if (!Call) {
- assert((*I)->getLocation().asLocation().isValid());
continue;
}