diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-03 15:20:48 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-03 15:20:48 +0000 |
commit | 551c698530debaae81139c7c76a29fb762793362 (patch) | |
tree | 547e0e59163c33f2142998714eb5f957e65d1a57 /lib | |
parent | 416ada0f75bab22b084a1776deb229cd4a669c4d (diff) |
Vendor import of clang trunk r304659:vendor/clang/clang-trunk-r304659
Notes
Notes:
svn path=/vendor/clang/dist/; revision=319525
svn path=/vendor/clang/clang-trunk-r304659/; revision=319526; tag=vendor/clang/clang-trunk-r304659
Diffstat (limited to 'lib')
70 files changed, 680 insertions, 226 deletions
diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp index f81133f3aad3..389f3655aa52 100644 --- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp @@ -78,6 +78,7 @@ public: } } // Pass through. + LLVM_FALLTHROUGH; case OMF_retain: case OMF_release: if (E->getReceiverKind() == ObjCMessageExpr::Instance) diff --git a/lib/ARCMigrate/TransformActions.cpp b/lib/ARCMigrate/TransformActions.cpp index c628b54ed414..4f3fb5845925 100644 --- a/lib/ARCMigrate/TransformActions.cpp +++ b/lib/ARCMigrate/TransformActions.cpp @@ -539,6 +539,7 @@ void TransformActionsImpl::addRemoval(CharSourceRange range) { return; case Range_Contains: RI->End = newRange.End; + LLVM_FALLTHROUGH; case Range_ExtendsBegin: newRange.End = RI->End; Removals.erase(RI); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 29d970e66d71..34c4d2617ec9 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -6240,6 +6240,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += "{objc_class=}"; return; } + // TODO: Double check to make sure this intentially falls through. + LLVM_FALLTHROUGH; } case Type::ObjCInterface: { diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 03e6115a0dba..b43c28deb362 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -360,6 +360,7 @@ void clang::FormatASTNodeDiagnosticArgument( Modifier = StringRef(); Argument = StringRef(); // Fall through + LLVM_FALLTHROUGH; } case DiagnosticsEngine::ak_qualtype: { assert(Modifier.empty() && Argument.empty() && diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index 9376ee1d4ee4..eff1aa5e323d 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -424,6 +424,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; // Fall through to check the bits common with FunctionNoProtoType. + LLVM_FALLTHROUGH; } case Type::FunctionNoProto: { diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index bc8a34c93653..6eeba88e4033 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -1189,7 +1189,9 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { for (const auto *PI : OMD->parameters()) { // FIXME: selector is missing here! pos = name.find_first_of(':', lastPos); - Out << " " << name.substr(lastPos, pos - lastPos) << ':'; + if (lastPos != 0) + Out << " "; + Out << name.substr(lastPos, pos - lastPos) << ':'; PrintObjCMethodType(OMD->getASTContext(), PI->getObjCDeclQualifier(), PI->getType()); @@ -1198,7 +1200,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { } if (OMD->param_begin() == OMD->param_end()) - Out << " " << name; + Out << name; if (OMD->isVariadic()) Out << ", ..."; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index d523a0f93cf6..c21cd3f65bd4 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1576,6 +1576,7 @@ bool CastExpr::CastConsistency() const { getSubExpr()->getType()->isBlockPointerType()); assert(getType()->getPointeeType().getAddressSpace() != getSubExpr()->getType()->getPointeeType().getAddressSpace()); + LLVM_FALLTHROUGH; // These should not have an inheritance path. case CK_Dynamic: case CK_ToUnion: @@ -2102,6 +2103,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, } // Fallthrough for generic call handling. + LLVM_FALLTHROUGH; } case CallExprClass: case CXXMemberCallExprClass: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index c19812e341c0..17d0ce67dcf9 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -736,6 +736,7 @@ namespace { if (!HasFoldFailureDiagnostic) break; // We've already failed to fold something. Keep that diagnostic. + LLVM_FALLTHROUGH; case EM_ConstantExpression: case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: @@ -10374,6 +10375,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { } // OffsetOf falls through here. + LLVM_FALLTHROUGH; } case Expr::OffsetOfExprClass: { // Note that per C99, offsetof must be an ICE. And AFAIK, using @@ -10476,6 +10478,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return Worst(LHSResult, RHSResult); } } + LLVM_FALLTHROUGH; } case Expr::ImplicitCastExprClass: case Expr::CStyleCastExprClass: diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 7db0b4d8e4ff..c9bb45a37eb5 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1459,8 +1459,6 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. MethodQuals.removeRestrict(); - // __unaligned is not currently mangled in any way, so remove it. - MethodQuals.removeUnaligned(); mangleQualifiers(MethodQuals); mangleRefQualifier(Method->getRefQualifier()); } @@ -2140,7 +2138,8 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { } void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { - // Vendor qualifiers come first. + // Vendor qualifiers come first and if they are order-insensitive they must + // be emitted in reversed alphabetical order, see Itanium ABI 5.1.5. // Address space qualifiers start with an ordinary letter. if (Quals.hasAddressSpace()) { @@ -2176,17 +2175,28 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { } // The ARC ownership qualifiers start with underscores. - switch (Quals.getObjCLifetime()) { // Objective-C ARC Extension: // // <type> ::= U "__strong" // <type> ::= U "__weak" // <type> ::= U "__autoreleasing" + // + // Note: we emit __weak first to preserve the order as + // required by the Itanium ABI. + if (Quals.getObjCLifetime() == Qualifiers::OCL_Weak) + mangleVendorQualifier("__weak"); + + // __unaligned (from -fms-extensions) + if (Quals.hasUnaligned()) + mangleVendorQualifier("__unaligned"); + + // Remaining ARC ownership qualifiers. + switch (Quals.getObjCLifetime()) { case Qualifiers::OCL_None: break; case Qualifiers::OCL_Weak: - mangleVendorQualifier("__weak"); + // Do nothing as we already handled this case above. break; case Qualifiers::OCL_Strong: @@ -3775,6 +3785,7 @@ recurse: Out << "v1U" << Kind.size() << Kind; } // Fall through to mangle the cast itself. + LLVM_FALLTHROUGH; case Expr::CStyleCastExprClass: mangleCastExpression(E, "cv"); @@ -4327,7 +4338,7 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { /// substitutions. static bool hasMangledSubstitutionQualifiers(QualType T) { Qualifiers Qs = T.getQualifiers(); - return Qs.getCVRQualifiers() || Qs.hasAddressSpace(); + return Qs.getCVRQualifiers() || Qs.hasAddressSpace() || Qs.hasUnaligned(); } bool CXXNameMangler::mangleSubstitution(QualType T) { diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index 514c7c9f5b33..e2e0dbeec0dd 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -290,6 +290,7 @@ NestedNameSpecifier::print(raw_ostream &OS, case TypeSpecWithTemplate: OS << "template "; // Fall through to print the type. + LLVM_FALLTHROUGH; case TypeSpec: { const Type *T = getAsType(); diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index ed7193ecb437..60556697113a 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -441,6 +441,7 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, case LengthModifier::AsShort: if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) return Ctx.IntTy; + LLVM_FALLTHROUGH; default: return ArgType::Invalid(); } diff --git a/lib/Analysis/PseudoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp index 614f676fb193..83b545a7be83 100644 --- a/lib/Analysis/PseudoConstantAnalysis.cpp +++ b/lib/Analysis/PseudoConstantAnalysis.cpp @@ -109,6 +109,7 @@ void PseudoConstantAnalysis::RunAnalysis() { // Do not visit the children continue; + LLVM_FALLTHROUGH; } case BO_AddAssign: case BO_SubAssign: diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp index 3b93f1a57f1f..534225985460 100644 --- a/lib/Analysis/ScanfFormatString.cpp +++ b/lib/Analysis/ScanfFormatString.cpp @@ -341,6 +341,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsShort: if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) return ArgType::PtrTo(ArgType::AnyCharTy); + LLVM_FALLTHROUGH; default: return ArgType::Invalid(); } @@ -357,6 +358,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsShort: if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) return ArgType::PtrTo(ArgType::AnyCharTy); + LLVM_FALLTHROUGH; default: return ArgType::Invalid(); } diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 74c85376c7db..372e0c417fd4 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -551,6 +551,7 @@ ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) { case 's': if (startsWithWord(name, "shared")) return OIT_ReturnsSelf; if (startsWithWord(name, "standard")) return OIT_Singleton; + break; case 'i': if (startsWithWord(name, "init")) return OIT_Init; default: diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index c8a774311efe..db81507aa209 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -29,9 +29,7 @@ void LangOptions::resetNonModularOptions() { Name = Default; #include "clang/Basic/LangOptions.def" - // FIXME: This should not be reset; modules can be different with different - // sanitizer options (this affects __has_feature(address_sanitizer) etc). - Sanitize.clear(); + // These options do not affect AST generation. SanitizerBlacklistFiles.clear(); XRayAlwaysInstrumentFiles.clear(); XRayNeverInstrumentFiles.clear(); diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index ac3d7c559679..83c524877ab0 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -394,11 +394,30 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { {"exclude ", HK_Excluded}}; for (auto &K : Kinds) { + assert(&K == &Kinds[K.Kind] && "kinds in wrong order"); for (auto &H : Headers[K.Kind]) { OS.indent(Indent + 2); OS << K.Prefix << "header \""; OS.write_escaped(H.NameAsWritten); - OS << "\"\n"; + OS << "\" { size " << H.Entry->getSize() + << " mtime " << H.Entry->getModificationTime() << " }\n"; + } + } + for (auto *Unresolved : {&UnresolvedHeaders, &MissingHeaders}) { + for (auto &U : *Unresolved) { + OS.indent(Indent + 2); + OS << Kinds[U.Kind].Prefix << "header \""; + OS.write_escaped(U.FileName); + OS << "\""; + if (U.Size || U.ModTime) { + OS << " {"; + if (U.Size) + OS << " size " << *U.Size; + if (U.ModTime) + OS << " mtime " << *U.ModTime; + OS << " }"; + } + OS << "\n"; } } diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index e19404dc54cb..8cfd8bde9cbb 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -143,9 +143,11 @@ const char *TargetInfo::getTypeConstantSuffix(IntType T) const { case UnsignedChar: if (getCharWidth() < getIntWidth()) return ""; + LLVM_FALLTHROUGH; case UnsignedShort: if (getShortWidth() < getIntWidth()) return ""; + LLVM_FALLTHROUGH; case UnsignedInt: return "U"; case UnsignedLong: return "UL"; case UnsignedLongLong: return "ULL"; diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 0f07169ac8b0..fd193bcf1a69 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -49,6 +49,7 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" @@ -186,6 +187,7 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, Opts.TracePC = CGOpts.SanitizeCoverageTracePC; Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard; Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune; + Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters; PM.add(createSanitizerCoverageModulePass(Opts)); } @@ -897,6 +899,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( // create that pass manager here and use it as needed below. legacy::PassManager CodeGenPasses; bool NeedCodeGen = false; + Optional<raw_fd_ostream> ThinLinkOS; // Append any output we need to the pass manager. switch (Action) { @@ -904,9 +907,24 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( break; case Backend_EmitBC: - MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, - CodeGenOpts.EmitSummaryIndex, - CodeGenOpts.EmitSummaryIndex)); + if (CodeGenOpts.EmitSummaryIndex) { + if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { + std::error_code EC; + ThinLinkOS.emplace(CodeGenOpts.ThinLinkBitcodeFile, EC, + llvm::sys::fs::F_None); + if (EC) { + Diags.Report(diag::err_fe_unable_to_open_output) + << CodeGenOpts.ThinLinkBitcodeFile << EC.message(); + return; + } + } + MPM.addPass( + ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &*ThinLinkOS : nullptr)); + } else { + MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, + CodeGenOpts.EmitSummaryIndex, + CodeGenOpts.EmitSummaryIndex)); + } break; case Backend_EmitLL: @@ -1029,6 +1047,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, Conf.CGOptLevel = getCGOptLevel(CGOpts); initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); Conf.SampleProfile = std::move(SampleProfile); + Conf.UseNewPM = CGOpts.ExperimentalNewPassManager; switch (Action) { case Backend_EmitNothing: Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) { diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 2134fb9e03e4..3b4f8854a9ca 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -2659,6 +2659,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), llvm::ArrayRef<llvm::Value *>(Args))); } + LLVM_FALLTHROUGH; } // OpenCL v2.0 s6.13.17.6 - Kernel query functions need bitcast of block // parameter. @@ -3813,6 +3814,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vcalt_v: case NEON::BI__builtin_neon_vcaltq_v: std::swap(Ops[0], Ops[1]); + LLVM_FALLTHROUGH; case NEON::BI__builtin_neon_vcage_v: case NEON::BI__builtin_neon_vcageq_v: case NEON::BI__builtin_neon_vcagt_v: @@ -5056,6 +5058,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vsri_n_v: case NEON::BI__builtin_neon_vsriq_n_v: rightShift = true; + LLVM_FALLTHROUGH; case NEON::BI__builtin_neon_vsli_n_v: case NEON::BI__builtin_neon_vsliq_n_v: Ops[2] = EmitNeonShiftVector(Ops[2], Ty, rightShift); diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 8f405eee6e52..079064733585 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -4259,6 +4259,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Builder.CreateStore(elt, eltAddr); } // FALLTHROUGH + LLVM_FALLTHROUGH; } case ABIArgInfo::InAlloca: diff --git a/lib/CodeGen/CGCoroutine.cpp b/lib/CodeGen/CGCoroutine.cpp index f65fb5b9232a..bc5f6327c9a0 100644 --- a/lib/CodeGen/CGCoroutine.cpp +++ b/lib/CodeGen/CGCoroutine.cpp @@ -625,6 +625,7 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_id has" " been used earlier in this function"); // Fallthrough to the next case to add TokenNone as the first argument. + LLVM_FALLTHROUGH; } // @llvm.coro.suspend takes a token parameter. Add token 'none' as the first // argument. diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 0a1dc09211c2..02db79159b58 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -2781,6 +2781,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { // them distinct if they are ODR-uniqued. if (FullName.empty()) break; + LLVM_FALLTHROUGH; case llvm::dwarf::DW_TAG_structure_type: case llvm::dwarf::DW_TAG_union_type: @@ -3263,7 +3264,7 @@ void CGDebugInfo::EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD) { void CGDebugInfo::EmitInlineFunctionEnd(CGBuilderTy &Builder) { assert(CurInlinedAt && "unbalanced inline scope stack"); - EmitFunctionEnd(Builder); + EmitFunctionEnd(Builder, nullptr); setInlinedAt(llvm::DebugLoc(CurInlinedAt).getInlinedAt()); } @@ -3332,7 +3333,7 @@ void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, LexicalBlockStack.pop_back(); } -void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { +void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn) { assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); unsigned RCount = FnBeginRegionCount.back(); assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch"); @@ -3344,6 +3345,9 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { LexicalBlockStack.pop_back(); } FnBeginRegionCount.pop_back(); + + if (Fn && Fn->getSubprogram()) + DBuilder.finalizeSubprogram(Fn->getSubprogram()); } llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 7de48f278994..39249c7cf4da 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -367,7 +367,7 @@ public: void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType); /// Constructs the debug code for exiting a function. - void EmitFunctionEnd(CGBuilderTy &Builder); + void EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn); /// Emit metadata to indicate the beginning of a new lexical block /// and push the block onto the stack. diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 84ce896506d5..2aa045879213 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1487,9 +1487,9 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, // Handle vectors differently to get better performance. if (Ty->isVectorType()) { llvm::Type *SrcTy = Value->getType(); - auto *VecTy = cast<llvm::VectorType>(SrcTy); + auto *VecTy = dyn_cast<llvm::VectorType>(SrcTy); // Handle vec3 special. - if (VecTy->getNumElements() == 3) { + if (VecTy && VecTy->getNumElements() == 3) { // Our source is a vec3, do a shuffle vector to make it a vec4. llvm::Constant *Mask[] = {Builder.getInt32(0), Builder.getInt32(1), Builder.getInt32(2), diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index d604b4130a23..f9d1fe468748 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -3887,7 +3887,7 @@ Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, /// Return the result of the given binary operation. auto eval = [&](BinaryOperator::Opcode Opcode, llvm::Value *LHS, llvm::Value *RHS) -> llvm::Value * { - assert(Opcode == BO_Add || Opcode == BO_Mul && "Can't eval binop"); + assert((Opcode == BO_Add || Opcode == BO_Mul) && "Can't eval binop"); // If the operands are constants, return a constant result. if (auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS)) { diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 85da3ae47db0..b6d7f0255017 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -348,7 +348,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // Emit debug descriptor for function end. if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitFunctionEnd(Builder); + DI->EmitFunctionEnd(Builder, CurFn); // Reset the debug location to that of the simple 'return' expression, if any // rather than that of the end of the function's scope '}'. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index c61a5f6ffa71..dde8f2e36920 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -3841,6 +3841,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { // Skip variable templates if (cast<VarDecl>(D)->getDescribedVarTemplate()) return; + LLVM_FALLTHROUGH; case Decl::VarTemplateSpecialization: EmitGlobal(cast<VarDecl>(D)); if (auto *DD = dyn_cast<DecompositionDecl>(D)) diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index 9ab2e176845c..ad2b4ada9a83 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -48,13 +48,14 @@ enum CoverageFeature { CoverageBB = 1 << 1, CoverageEdge = 1 << 2, CoverageIndirCall = 1 << 3, - CoverageTraceBB = 1 << 4, + CoverageTraceBB = 1 << 4, // Deprecated. CoverageTraceCmp = 1 << 5, CoverageTraceDiv = 1 << 6, CoverageTraceGep = 1 << 7, - Coverage8bitCounters = 1 << 8, + Coverage8bitCounters = 1 << 8, // Deprecated. CoverageTracePC = 1 << 9, CoverageTracePCGuard = 1 << 10, + CoverageInline8bitCounters = 1 << 12, CoverageNoPrune = 1 << 11, }; @@ -530,7 +531,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, } // trace-pc w/o func/bb/edge implies edge. - if ((CoverageFeatures & (CoverageTracePC | CoverageTracePCGuard)) && + if ((CoverageFeatures & + (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters)) && !(CoverageFeatures & InsertionPointTypes)) CoverageFeatures |= CoverageEdge; @@ -637,6 +639,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"), std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"), std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard"), + std::make_pair(CoverageInline8bitCounters, "-fsanitize-coverage-inline-8bit-counters"), std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune")}; for (auto F : CoverageFlags) { if (CoverageFeatures & F.first) @@ -798,6 +801,7 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) { .Case("trace-pc", CoverageTracePC) .Case("trace-pc-guard", CoverageTracePCGuard) .Case("no-prune", CoverageNoPrune) + .Case("inline-8bit-counters", CoverageInline8bitCounters) .Default(0); if (F == 0) D.Diag(clang::diag::err_drv_unsupported_option_argument) diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp index 2148316532de..dc501b564eea 100644 --- a/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -798,24 +798,28 @@ static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, case NSAPI::NSNumberWithUnsignedInt: case NSAPI::NSNumberWithUnsignedInteger: CallIsUnsigned = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithInt: case NSAPI::NSNumberWithInteger: break; case NSAPI::NSNumberWithUnsignedLong: CallIsUnsigned = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithLong: CallIsLong = true; break; case NSAPI::NSNumberWithUnsignedLongLong: CallIsUnsigned = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithLongLong: CallIsLongLong = true; break; case NSAPI::NSNumberWithDouble: CallIsDouble = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithFloat: CallIsFloating = true; break; diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index a7b5fa7dfd29..e92672a785da 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -1727,6 +1727,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, diag::warn_module_config_mismatch) << ModuleFileName; // Fall through to error out. + LLVM_FALLTHROUGH; case ASTReader::VersionMismatch: case ASTReader::HadErrors: ModuleLoader::HadFatalFailure = true; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 47c763d29357..adb15f1730bf 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -768,6 +768,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeCoverageTracePCGuard = Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard); Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune); + Opts.SanitizeCoverageInline8bitCounters = + Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeMemoryUseAfterDtor = @@ -2700,6 +2702,13 @@ std::string CompilerInvocation::getModuleHash() const { code = ext->hashExtension(code); } + // Extend the signature with the enabled sanitizers, if at least one is + // enabled. Sanitizers which cannot affect AST generation aren't hashed. + SanitizerSet SanHash = LangOpts->Sanitize; + SanHash.clear(getPPTransparentSanitizers()); + if (!SanHash.empty()) + code = hash_combine(code, SanHash.Mask); + return llvm::APInt(64, code).toString(36, /*Signed=*/false); } diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index cd67e469ddad..e2fbe965349f 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -289,14 +289,28 @@ static void addHeaderInclude(StringRef HeaderName, /// /// \param Includes Will be augmented with the set of \#includes or \#imports /// needed to load all of the named headers. -static std::error_code -collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, - ModuleMap &ModMap, clang::Module *Module, - SmallVectorImpl<char> &Includes) { +static std::error_code collectModuleHeaderIncludes( + const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag, + ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl<char> &Includes) { // Don't collect any headers for unavailable modules. if (!Module->isAvailable()) return std::error_code(); + // Resolve all lazy header directives to header files. + ModMap.resolveHeaderDirectives(Module); + + // If any headers are missing, we can't build this module. In most cases, + // diagnostics for this should have already been produced; we only get here + // if explicit stat information was provided. + // FIXME: If the name resolves to a file with different stat information, + // produce a better diagnostic. + if (!Module->MissingHeaders.empty()) { + auto &MissingHeader = Module->MissingHeaders.front(); + Diag.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) + << MissingHeader.IsUmbrella << MissingHeader.FileName; + return std::error_code(); + } + // Add includes for each of these headers. for (auto HK : {Module::HK_Normal, Module::HK_Private}) { for (Module::Header &H : Module->Headers[HK]) { @@ -367,7 +381,7 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, SubEnd = Module->submodule_end(); Sub != SubEnd; ++Sub) if (std::error_code Err = collectModuleHeaderIncludes( - LangOpts, FileMgr, ModMap, *Sub, Includes)) + LangOpts, FileMgr, Diag, ModMap, *Sub, Includes)) return Err; return std::error_code(); @@ -494,7 +508,7 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) { addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents, CI.getLangOpts(), M->IsExternC); Err = collectModuleHeaderIncludes( - CI.getLangOpts(), FileMgr, + CI.getLangOpts(), FileMgr, CI.getDiagnostics(), CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M, HeaderContents); diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index baaf93b167bc..89ac385ca45d 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -546,8 +546,11 @@ void PrintPreprocessedAction::ExecuteAction() { // module itself before switching to the input buffer. auto &Input = getCurrentInput(); if (Input.getKind().getFormat() == InputKind::ModuleMap) { - if (Input.isFile()) - (*OS) << "# 1 \"" << Input.getFile() << "\"\n"; + if (Input.isFile()) { + (*OS) << "# 1 \""; + OS->write_escaped(Input.getFile()); + (*OS) << "\"\n"; + } // FIXME: Include additional information here so that we don't need the // original source files to exist on disk. getCurrentModule()->print(*OS); diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index d50fb6d788a4..1d7c8a0c871b 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -221,6 +221,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, case llvm::Triple::Win32: if (triple.getEnvironment() != llvm::Triple::Cygnus) break; + LLVM_FALLTHROUGH; default: // FIXME: temporary hack: hard-coded paths. AddPath("/usr/local/include", System, false); @@ -343,6 +344,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, AddPath(BaseSDKPath + "/target/include", System, false); if (triple.isPS4CPU()) AddPath(BaseSDKPath + "/target/include_common", System, false); + LLVM_FALLTHROUGH; } default: AddPath("/usr/include", ExternCSystem, false); diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp index 8c5eb161b5ab..b2dfd2941130 100644 --- a/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/lib/Frontend/Rewrite/FrontendActions.cpp @@ -200,8 +200,11 @@ void RewriteIncludesAction::ExecuteAction() { // module itself before switching to the input buffer. auto &Input = getCurrentInput(); if (Input.getKind().getFormat() == InputKind::ModuleMap) { - if (Input.isFile()) - (*OS) << "# 1 \"" << Input.getFile() << "\"\n"; + if (Input.isFile()) { + (*OS) << "# 1 \""; + OS->write_escaped(Input.getFile()); + (*OS) << "\"\n"; + } // FIXME: Include additional information here so that we don't need the // original source files to exist on disk. getCurrentModule()->print(*OS); diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp index d45cbc01df8c..3564cebba8a8 100644 --- a/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -177,7 +177,9 @@ void InclusionRewriter::FileSkipped(const FileEntry &/*SkippedFile*/, /// directives. It does not say whether the file has been included, but it /// provides more information about the directive (hash location instead /// of location inside the included file). It is assumed that the matching -/// FileChanged() or FileSkipped() is called after this. +/// FileChanged() or FileSkipped() is called after this (or neither is +/// called if this #include results in an error or does not textually include +/// anything). void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, const Token &/*IncludeTok*/, StringRef /*FileName*/, @@ -187,9 +189,6 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, StringRef /*SearchPath*/, StringRef /*RelativePath*/, const Module *Imported) { - assert(LastInclusionLocation.isInvalid() && - "Another inclusion directive was found before the previous one " - "was processed"); if (Imported) { auto P = ModuleIncludes.insert( std::make_pair(HashLoc.getRawEncoding(), Imported)); diff --git a/lib/Frontend/SerializedDiagnosticReader.cpp b/lib/Frontend/SerializedDiagnosticReader.cpp index c4461d452e7b..8a8161488f44 100644 --- a/lib/Frontend/SerializedDiagnosticReader.cpp +++ b/lib/Frontend/SerializedDiagnosticReader.cpp @@ -125,6 +125,7 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) { case Cursor::BlockBegin: if (Stream.SkipBlock()) return SDError::MalformedMetadataBlock; + LLVM_FALLTHROUGH; case Cursor::BlockEnd: if (!VersionChecked) return SDError::MissingVersion; diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 9084bc352f76..1ebcc0a1c657 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -1114,6 +1114,8 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, auto TryEnterImported = [&](void) -> bool { if (!ModulesEnabled) return false; + // Ensure FileInfo bits are up to date. + ModMap.resolveHeaderDirectives(File); // Modules with builtins are special; multiple modules use builtins as // modular headers, example: // diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index f5a35e97d6e1..447ff212f06e 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -2498,6 +2498,7 @@ void Lexer::ReadToEndOfLine(SmallVectorImpl<char> *Result) { break; } // FALL THROUGH. + LLVM_FALLTHROUGH; case '\r': case '\n': // Okay, we found the end of the line. First, back up past the \0, \r, \n. @@ -3247,6 +3248,7 @@ LexNextToken: return LexCharConstant(Result, ConsumeChar(CurPtr, SizeTmp, Result), tok::wide_char_constant); // FALL THROUGH, treating L like the start of an identifier. + LLVM_FALLTHROUGH; // C99 6.4.2: Identifiers. case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index 1e2cbde825f5..a598a467816a 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -456,10 +456,17 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, // Finally, we write the bytes into ResultBuf. ResultBuf += bytesToWrite; switch (bytesToWrite) { // note: everything falls through. - case 4: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 3: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 2: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 1: *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]); + case 4: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 3: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 2: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 1: + *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]); } // Update the buffer. ResultBuf += bytesToWrite; diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 8c57931e47b7..018d59e5e871 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -36,6 +36,37 @@ #endif using namespace clang; +Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { + switch ((int)Role) { + default: llvm_unreachable("unknown header role"); + case NormalHeader: + return Module::HK_Normal; + case PrivateHeader: + return Module::HK_Private; + case TextualHeader: + return Module::HK_Textual; + case PrivateHeader | TextualHeader: + return Module::HK_PrivateTextual; + } +} + +ModuleMap::ModuleHeaderRole +ModuleMap::headerKindToRole(Module::HeaderKind Kind) { + switch ((int)Kind) { + case Module::HK_Normal: + return NormalHeader; + case Module::HK_Private: + return PrivateHeader; + case Module::HK_Textual: + return TextualHeader; + case Module::HK_PrivateTextual: + return ModuleHeaderRole(PrivateHeader | TextualHeader); + case Module::HK_Excluded: + llvm_unreachable("unexpected header kind"); + } + llvm_unreachable("unknown header kind"); +} + Module::ExportDecl ModuleMap::resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, @@ -104,12 +135,22 @@ static void appendSubframeworkPaths(Module *Mod, } const FileEntry * -ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header, - SmallVectorImpl<char> &RelativePathName) { +ModuleMap::findHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header, + SmallVectorImpl<char> &RelativePathName) { + auto GetFile = [&](StringRef Filename) -> const FileEntry * { + auto *File = SourceMgr.getFileManager().getFile(Filename); + if (!File || + (Header.Size && File->getSize() != *Header.Size) || + (Header.ModTime && File->getModificationTime() != *Header.ModTime)) + return nullptr; + return File; + }; + if (llvm::sys::path::is_absolute(Header.FileName)) { RelativePathName.clear(); RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); - return SourceMgr.getFileManager().getFile(Header.FileName); + return GetFile(Header.FileName); } // Search for the header file within the module's home directory. @@ -124,7 +165,7 @@ ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header, // Check whether this file is in the public headers. llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - if (auto *File = SourceMgr.getFileManager().getFile(FullPathName)) + if (auto *File = GetFile(FullPathName)) return File; // Check whether this file is in the private headers. @@ -141,31 +182,74 @@ ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header, llvm::sys::path::append(RelativePathName, "PrivateHeaders", Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - return SourceMgr.getFileManager().getFile(FullPathName); + return GetFile(FullPathName); } // Lookup for normal headers. llvm::sys::path::append(RelativePathName, Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - return SourceMgr.getFileManager().getFile(FullPathName); + return GetFile(FullPathName); } -const FileEntry * -ModuleMap::resolveAsBuiltinHeader(Module *M, - Module::UnresolvedHeaderDirective Header, - SmallVectorImpl<char> &BuiltinPathName) { - if (llvm::sys::path::is_absolute(Header.FileName) || M->isPartOfFramework() || - !M->IsSystem || Header.IsUmbrella || !BuiltinIncludeDir || - BuiltinIncludeDir == M->Directory || !isBuiltinHeader(Header.FileName)) - return nullptr; +void ModuleMap::resolveHeader(Module *Mod, + const Module::UnresolvedHeaderDirective &Header) { + SmallString<128> RelativePathName; + if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) { + if (Header.IsUmbrella) { + const DirectoryEntry *UmbrellaDir = File->getDir(); + if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) + Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) + << UmbrellaMod->getFullModuleName(); + else + // Record this umbrella header. + setUmbrellaHeader(Mod, File, RelativePathName.str()); + } else { + Module::Header H = {RelativePathName.str(), File}; + if (Header.Kind == Module::HK_Excluded) + excludeHeader(Mod, H); + else + addHeader(Mod, H, headerKindToRole(Header.Kind)); + } + } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { + // There's a builtin header but no corresponding on-disk header. Assume + // this was supposed to modularize the builtin header alone. + } else if (Header.Kind == Module::HK_Excluded) { + // Ignore missing excluded header files. They're optional anyway. + } else { + // If we find a module that has a missing header, we mark this module as + // unavailable and store the header directive for displaying diagnostics. + Mod->MissingHeaders.push_back(Header); + // A missing header with stat information doesn't make the module + // unavailable; this keeps our behavior consistent as headers are lazily + // resolved. (Such a module still can't be built though, except from + // preprocessed source.) + if (!Header.Size && !Header.ModTime) + Mod->markUnavailable(); + } +} + +bool ModuleMap::resolveAsBuiltinHeader( + Module *Mod, const Module::UnresolvedHeaderDirective &Header) { + if (Header.Kind == Module::HK_Excluded || + llvm::sys::path::is_absolute(Header.FileName) || + Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || + !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || + !isBuiltinHeader(Header.FileName)) + return false; // This is a system module with a top-level header. This header // may have a counterpart (or replacement) in the set of headers // supplied by Clang. Find that builtin header. - llvm::sys::path::append(BuiltinPathName, BuiltinIncludeDir->getName(), - Header.FileName); - return SourceMgr.getFileManager().getFile( - StringRef(BuiltinPathName.data(), BuiltinPathName.size())); + SmallString<128> Path; + llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); + auto *File = SourceMgr.getFileManager().getFile(Path); + if (!File) + return false; + + auto Role = headerKindToRole(Header.Kind); + Module::Header H = {Path.str(), File}; + addHeader(Mod, H, Role); + return true; } ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, @@ -246,6 +330,7 @@ bool ModuleMap::isBuiltinHeader(StringRef FileName) { ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(const FileEntry *File) { + resolveHeaderDirectives(File); HeadersMap::iterator Known = Headers.find(File); if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && Known == Headers.end() && File->getDir() == BuiltinIncludeDir && @@ -328,8 +413,10 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) return; - if (RequestingModule) + if (RequestingModule) { resolveUses(RequestingModule, /*Complain=*/false); + resolveHeaderDirectives(RequestingModule); + } bool Excluded = false; Module *Private = nullptr; @@ -511,6 +598,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { ArrayRef<ModuleMap::KnownHeader> ModuleMap::findAllModulesForHeader(const FileEntry *File) const { + resolveHeaderDirectives(File); auto It = Headers.find(File); if (It == Headers.end()) return None; @@ -524,6 +612,7 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { bool ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, const Module *RequestingModule) const { + resolveHeaderDirectives(Header); HeadersMap::const_iterator Known = Headers.find(Header); if (Known != Headers.end()) { for (SmallVectorImpl<KnownHeader>::const_iterator @@ -896,20 +985,65 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, UmbrellaDirs[UmbrellaDir] = Mod; } -static Module::HeaderKind headerRoleToKind(ModuleMap::ModuleHeaderRole Role) { - switch ((int)Role) { - default: llvm_unreachable("unknown header role"); - case ModuleMap::NormalHeader: - return Module::HK_Normal; - case ModuleMap::PrivateHeader: - return Module::HK_Private; - case ModuleMap::TextualHeader: - return Module::HK_Textual; - case ModuleMap::PrivateHeader | ModuleMap::TextualHeader: - return Module::HK_PrivateTextual; +void ModuleMap::addUnresolvedHeader(Module *Mod, + Module::UnresolvedHeaderDirective Header) { + // If there is a builtin counterpart to this file, add it now so it can + // wrap the system header. + if (resolveAsBuiltinHeader(Mod, Header)) { + // If we have both a builtin and system version of the file, the + // builtin version may want to inject macros into the system header, so + // force the system header to be treated as a textual header in this + // case. + Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( + headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); + Header.HasBuiltinHeader = true; + } + + // If possible, don't stat the header until we need to. This requires the + // user to have provided us with some stat information about the file. + // FIXME: Add support for lazily stat'ing umbrella headers and excluded + // headers. + if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && + Header.Kind != Module::HK_Excluded) { + // We expect more variation in mtime than size, so if we're given both, + // use the mtime as the key. + if (Header.ModTime) + LazyHeadersByModTime[*Header.ModTime].push_back(Mod); + else + LazyHeadersBySize[*Header.Size].push_back(Mod); + Mod->UnresolvedHeaders.push_back(Header); + return; + } + + // We don't have stat information or can't defer looking this file up. + // Perform the lookup now. + resolveHeader(Mod, Header); +} + +void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { + auto BySize = LazyHeadersBySize.find(File->getSize()); + if (BySize != LazyHeadersBySize.end()) { + for (auto *M : BySize->second) + resolveHeaderDirectives(M); + LazyHeadersBySize.erase(BySize); + } + + auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); + if (ByModTime != LazyHeadersByModTime.end()) { + for (auto *M : ByModTime->second) + resolveHeaderDirectives(M); + LazyHeadersByModTime.erase(ByModTime); } } +void ModuleMap::resolveHeaderDirectives(Module *Mod) const { + for (auto &Header : Mod->UnresolvedHeaders) + // This operation is logically const; we're just changing how we represent + // the header information for this file. + const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header); + Mod->UnresolvedHeaders.clear(); +} + void ModuleMap::addHeader(Module *Mod, Module::Header Header, ModuleHeaderRole Role, bool Imported) { KnownHeader KH(Mod, Role); @@ -1063,6 +1197,7 @@ namespace clang { RequiresKeyword, Star, StringLiteral, + IntegerLiteral, TextualKeyword, LBrace, RBrace, @@ -1072,7 +1207,12 @@ namespace clang { unsigned Location; unsigned StringLength; - const char *StringData; + union { + // If Kind != IntegerLiteral. + const char *StringData; + // If Kind == IntegerLiteral. + uint64_t IntegerValue; + }; void clear() { Kind = EndOfFile; @@ -1086,9 +1226,14 @@ namespace clang { SourceLocation getLocation() const { return SourceLocation::getFromRawEncoding(Location); } + + uint64_t getInteger() const { + return Kind == IntegerLiteral ? IntegerValue : 0; + } StringRef getString() const { - return StringRef(StringData, StringLength); + return Kind == IntegerLiteral ? StringRef() + : StringRef(StringData, StringLength); } }; @@ -1278,6 +1423,25 @@ retry: Tok.StringLength = Length; break; } + + case tok::numeric_constant: { + // We don't support any suffixes or other complications. + SmallString<32> SpellingBuffer; + SpellingBuffer.resize(LToken.getLength() + 1); + const char *Start = SpellingBuffer.data(); + unsigned Length = + Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); + uint64_t Value; + if (StringRef(Start, Length).getAsInteger(0, Value)) { + Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); + HadError = true; + goto retry; + } + + Tok.Kind = MMToken::IntegerLiteral; + Tok.IntegerValue = Value; + break; + } case tok::comment: goto retry; @@ -1904,6 +2068,9 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, Header.FileName = Tok.getString(); Header.FileNameLoc = consumeToken(); Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; + Header.Kind = + (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded + : Map.headerRoleToKind(Role)); // Check whether we already have an umbrella. if (Header.IsUmbrella && ActiveModule->Umbrella) { @@ -1913,64 +2080,62 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, return; } - // Look for this file by name if we don't have any stat information. - SmallString<128> RelativePathName, BuiltinPathName; - const FileEntry *File = - Map.resolveHeader(ActiveModule, Header, RelativePathName); - const FileEntry *BuiltinFile = - Map.resolveAsBuiltinHeader(ActiveModule, Header, BuiltinPathName); + // If we were given stat information, parse it so we can skip looking for + // the file. + if (Tok.is(MMToken::LBrace)) { + SourceLocation LBraceLoc = consumeToken(); + + while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { + enum Attribute { Size, ModTime, Unknown }; + StringRef Str = Tok.getString(); + SourceLocation Loc = consumeToken(); + switch (llvm::StringSwitch<Attribute>(Str) + .Case("size", Size) + .Case("mtime", ModTime) + .Default(Unknown)) { + case Size: + if (Header.Size) + Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; + if (!Tok.is(MMToken::IntegerLiteral)) { + Diags.Report(Tok.getLocation(), + diag::err_mmap_invalid_header_attribute_value) << Str; + skipUntil(MMToken::RBrace); + break; + } + Header.Size = Tok.getInteger(); + consumeToken(); + break; - // If Clang supplies this header but the underlying system does not, - // just silently swap in our builtin version. Otherwise, we'll end - // up adding both (later). - if (BuiltinFile && !File) { - RelativePathName = BuiltinPathName; - File = BuiltinFile; - BuiltinFile = nullptr; - } + case ModTime: + if (Header.ModTime) + Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; + if (!Tok.is(MMToken::IntegerLiteral)) { + Diags.Report(Tok.getLocation(), + diag::err_mmap_invalid_header_attribute_value) << Str; + skipUntil(MMToken::RBrace); + break; + } + Header.ModTime = Tok.getInteger(); + consumeToken(); + break; - // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. - // Come up with a lazy way to do this. - if (File) { - if (Header.IsUmbrella) { - const DirectoryEntry *UmbrellaDir = File->getDir(); - if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) { - Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash) - << UmbrellaModule->getFullModuleName(); - HadError = true; - } else { - // Record this umbrella header. - Map.setUmbrellaHeader(ActiveModule, File, RelativePathName.str()); - } - } else if (LeadingToken == MMToken::ExcludeKeyword) { - Module::Header H = {RelativePathName.str(), File}; - Map.excludeHeader(ActiveModule, H); - } else { - // If there is a builtin counterpart to this file, add it now so it can - // wrap the system header. - if (BuiltinFile) { - Module::Header H = { BuiltinPathName.str(), BuiltinFile }; - Map.addHeader(ActiveModule, H, Role); - - // If we have both a builtin and system version of the file, the - // builtin version may want to inject macros into the system header, so - // force the system header to be treated as a textual header in this - // case. - Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); + case Unknown: + Diags.Report(Loc, diag::err_mmap_expected_header_attribute); + skipUntil(MMToken::RBrace); + break; } - - // Record this header. - Module::Header H = { RelativePathName.str(), File }; - Map.addHeader(ActiveModule, H, Role); } - } else if (LeadingToken != MMToken::ExcludeKeyword) { - // Ignore excluded header files. They're optional anyway. - // If we find a module that has a missing header, we mark this module as - // unavailable and store the header directive for displaying diagnostics. - ActiveModule->markUnavailable(); - ActiveModule->MissingHeaders.push_back(Header); + if (Tok.is(MMToken::RBrace)) + consumeToken(); + else { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); + Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); + HadError = true; + } } + + Map.addUnresolvedHeader(ActiveModule, std::move(Header)); } static int compareModuleHeaders(const Module::Header *A, @@ -2521,6 +2686,7 @@ bool ModuleMapParser::parseModuleMapFile() { case MMToken::RequiresKeyword: case MMToken::Star: case MMToken::StringLiteral: + case MMToken::IntegerLiteral: case MMToken::TextualKeyword: case MMToken::UmbrellaKeyword: case MMToken::UseKeyword: diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 8b5877934f61..2d3ad690987e 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -689,6 +689,8 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, while (!Loc.isInvalid() && !SM.isInMainFile(Loc)) { auto ID = SM.getFileID(SM.getExpansionLoc(Loc)); auto *FE = SM.getFileEntryForID(ID); + if (!FE) + break; bool InTextualHeader = false; for (auto Header : HeaderInfo.getModuleMap().findAllModulesForHeader(FE)) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index b785f5f7d2e6..22696a957a10 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2552,6 +2552,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, } } // Fall through. + LLVM_FALLTHROUGH; } case tok::comma: case tok::equal: @@ -3678,6 +3679,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = true; break; }; + LLVM_FALLTHROUGH; case tok::kw___private: case tok::kw___global: case tok::kw___local: @@ -5045,6 +5047,7 @@ void Parser::ParseTypeQualifierListOpt( if (TryKeywordIdentFallback(false)) continue; } + LLVM_FALLTHROUGH; case tok::kw___sptr: case tok::kw___w64: case tok::kw___ptr64: @@ -5094,6 +5097,7 @@ void Parser::ParseTypeQualifierListOpt( continue; // do *not* consume the next token! } // otherwise, FALL THROUGH! + LLVM_FALLTHROUGH; default: DoneWithTypeQuals: // If this is not a type-qualifier token, we're done reading type diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 527d45b1e203..4c117f531ef1 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -4215,6 +4215,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. + LLVM_FALLTHROUGH; case IEB_Skip: Braces.skipToEnd(); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index c739a50f0b38..aacb00e8be64 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1314,6 +1314,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } // Fall through to treat the template-id as an id-expression. + LLVM_FALLTHROUGH; } case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id @@ -1484,9 +1485,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { nullptr, LHS.get()); break; } - // Fall through; this isn't a message send. - + LLVM_FALLTHROUGH; + default: // Not a postfix-expression suffix. return LHS; case tok::l_square: { // postfix-expression: p-e '[' expression ']' diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index f48d01e0f630..90f3561cb963 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -501,7 +501,8 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. - + LLVM_FALLTHROUGH; + case IEB_Skip: Braces.skipToEnd(); return false; diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index b925dd7053dc..2e5e36242ed5 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -192,6 +192,7 @@ static DeclarationName parseOpenMPReductionId(Parser &P) { case tok::identifier: // identifier if (!WithOperator) break; + LLVM_FALLTHROUGH; default: P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, @@ -869,6 +870,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( // pseudo-clause OMPFlushClause. PP.EnterToken(Tok); } + LLVM_FALLTHROUGH; case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -883,6 +885,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( } HasAssociatedStatement = false; // Fall through for further analysis. + LLVM_FALLTHROUGH; case OMPD_parallel: case OMPD_simd: case OMPD_for: @@ -1184,6 +1187,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } + LLVM_FALLTHROUGH; case OMPC_if: Clause = ParseOpenMPSingleExprWithArgClause(CKind); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index d147ab0a5674..b1fbb20c721b 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -203,6 +203,7 @@ Retry: } // Fall through + LLVM_FALLTHROUGH; } default: { diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 0d783131dd6e..d6684c39aa73 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -1450,6 +1450,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::False; } // If that succeeded, fallthrough into the generic simple-type-id case. + LLVM_FALLTHROUGH; // The ambiguity resides in a simple-type-specifier/typename-specifier // followed by a '('. The '(' could either be the start of: @@ -1492,6 +1493,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::True; } + LLVM_FALLTHROUGH; case tok::kw_char: case tok::kw_wchar_t: diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 4fe038d271ad..af29b5e9c673 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -763,6 +763,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, } // This must be 'export template'. Parse it so we can diagnose our lack // of support. + LLVM_FALLTHROUGH; case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: @@ -1875,6 +1876,7 @@ bool Parser::isTokenEqualOrEqualTypo() { Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal) << Kind << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); + LLVM_FALLTHROUGH; case tok::equal: return true; } diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp index 27bb976a6e1a..9e307f31be11 100644 --- a/lib/Rewrite/HTMLRewrite.cpp +++ b/lib/Rewrite/HTMLRewrite.cpp @@ -409,6 +409,7 @@ void html::SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP) { ++TokOffs; --TokLen; // FALL THROUGH to chop the 8 + LLVM_FALLTHROUGH; case tok::wide_string_literal: case tok::utf16_string_literal: case tok::utf32_string_literal: diff --git a/lib/Sema/CoroutineStmtBuilder.h b/lib/Sema/CoroutineStmtBuilder.h index 954a0f100ebb..33a368d92ff4 100644 --- a/lib/Sema/CoroutineStmtBuilder.h +++ b/lib/Sema/CoroutineStmtBuilder.h @@ -51,6 +51,9 @@ public: /// name lookup. bool buildDependentStatements(); + /// \brief Build just parameter moves. To use for rebuilding in TreeTransform. + bool buildParameterMoves(); + bool isInvalid() const { return !this->IsValid; } private: diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 8fb2f4139236..224d9e9a0ee2 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1866,6 +1866,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, case Sema::PCC_Condition: AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); // Fall through: conditions and statements can have expressions. + LLVM_FALLTHROUGH; case Sema::PCC_ParenthesizedExpression: if (SemaRef.getLangOpts().ObjCAutoRefCount && @@ -1895,6 +1896,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result(Builder.TakeString())); } // Fall through + LLVM_FALLTHROUGH; case Sema::PCC_Expression: { if (SemaRef.getLangOpts().CPlusPlus) { diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index 8a548c0ab861..06ae66076e8a 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -832,6 +832,12 @@ bool CoroutineStmtBuilder::buildDependentStatements() { return this->IsValid; } +bool CoroutineStmtBuilder::buildParameterMoves() { + assert(this->IsValid && "coroutine already invalid"); + assert(this->ParamMoves.empty() && "param moves already built"); + return this->IsValid = makeParamMoves(); +} + bool CoroutineStmtBuilder::makePromiseStmt() { // Form a declaration statement for the promise declaration, so that AST // visitors can more easily find it. @@ -1244,14 +1250,13 @@ static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) { .get(); } + /// \brief Build a variable declaration for move parameter. static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, - StringRef Name) { - DeclContext *DC = S.CurContext; - IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name); + IdentifierInfo *II) { TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc); VarDecl *Decl = - VarDecl::Create(S.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); + VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type, TInfo, SC_None); Decl->setImplicit(); return Decl; } @@ -1264,9 +1269,6 @@ bool CoroutineStmtBuilder::makeParamMoves() { // No need to copy scalars, llvm will take care of them. if (Ty->getAsCXXRecordDecl()) { - if (!paramDecl->getIdentifier()) - continue; - ExprResult ParamRef = S.BuildDeclRefExpr(paramDecl, paramDecl->getType(), ExprValueKind::VK_LValue, Loc); // FIXME: scope? @@ -1275,8 +1277,7 @@ bool CoroutineStmtBuilder::makeParamMoves() { Expr *RCast = castForMoving(S, ParamRef.get()); - auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()->getName()); - + auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()); S.AddInitializerToDecl(D, RCast, /*DirectInit=*/true); // Convert decl to a statement. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ea1f7526a832..ef6dfaa2f28c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -404,6 +404,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, } } // If typo correction failed or was not performed, fall through + LLVM_FALLTHROUGH; case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: Result.suppressDiagnostics(); @@ -6160,7 +6161,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( QualType NR = R; while (NR->isPointerType()) { if (NR->isFunctionPointerType()) { - Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer_variable); + Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer); D.setInvalidType(); break; } @@ -12309,7 +12310,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, TypeSourceInfo *TI = FD->getTypeSourceInfo(); TypeLoc TL = TI->getTypeLoc(); FunctionTypeLoc FTL = TL.getAsAdjusted<FunctionTypeLoc>(); - Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1; + Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 2; } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index d9528be2d383..acacdc263c08 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -14639,6 +14639,7 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { case EST_ComputedNoexcept: if (!Finder.TraverseStmt(Proto->getNoexceptExpr())) return true; + LLVM_FALLTHROUGH; case EST_Dynamic: for (const auto &E : Proto->exceptions()) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index b1a07ffb7206..4e7fb19b282b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -11462,6 +11462,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, break; case BO_And: checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc); + LLVM_FALLTHROUGH; case BO_Xor: case BO_Or: ResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc); @@ -11504,6 +11505,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, case BO_AndAssign: case BO_OrAssign: // fallthrough DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc); + LLVM_FALLTHROUGH; case BO_XorAssign: CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc); CompLHSTy = CompResultTy; diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 4b1d7fd3cf23..a6239283b47b 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -337,6 +337,7 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC, return nullptr; } // Fall through to get the current context. + LLVM_FALLTHROUGH; case DataMember: // -- the in-class initializers of class members diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index c97da740e4d2..1d32e5796812 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2594,6 +2594,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { for (const auto &Arg : Proto->param_types()) Queue.push_back(Arg.getTypePtr()); // fallthrough + LLVM_FALLTHROUGH; } case Type::FunctionNoProto: { const FunctionType *FnType = cast<FunctionType>(T); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 33a8f9c4afa3..dcb2c11c73c7 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1288,17 +1288,22 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, } namespace { + // Use SetVector since the diagnostic cares about the ordering of the Decl's. + using DeclSetVector = + llvm::SetVector<VarDecl *, llvm::SmallVector<VarDecl *, 8>, + llvm::SmallPtrSet<VarDecl *, 8>>; + // This visitor will traverse a conditional statement and store all // the evaluated decls into a vector. Simple is set to true if none // of the excluded constructs are used. class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> { - llvm::SmallPtrSetImpl<VarDecl*> &Decls; + DeclSetVector &Decls; SmallVectorImpl<SourceRange> &Ranges; bool Simple; public: typedef EvaluatedExprVisitor<DeclExtractor> Inherited; - DeclExtractor(Sema &S, llvm::SmallPtrSetImpl<VarDecl*> &Decls, + DeclExtractor(Sema &S, DeclSetVector &Decls, SmallVectorImpl<SourceRange> &Ranges) : Inherited(S.Context), Decls(Decls), @@ -1370,14 +1375,13 @@ namespace { // DeclMatcher checks to see if the decls are used in a non-evaluated // context. class DeclMatcher : public EvaluatedExprVisitor<DeclMatcher> { - llvm::SmallPtrSetImpl<VarDecl*> &Decls; + DeclSetVector &Decls; bool FoundDecl; public: typedef EvaluatedExprVisitor<DeclMatcher> Inherited; - DeclMatcher(Sema &S, llvm::SmallPtrSetImpl<VarDecl*> &Decls, - Stmt *Statement) : + DeclMatcher(Sema &S, DeclSetVector &Decls, Stmt *Statement) : Inherited(S.Context), Decls(Decls), FoundDecl(false) { if (!Statement) return; @@ -1459,7 +1463,7 @@ namespace { return; PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body); - llvm::SmallPtrSet<VarDecl*, 8> Decls; + DeclSetVector Decls; SmallVector<SourceRange, 10> Ranges; DeclExtractor DE(S, Decls, Ranges); DE.Visit(Second); @@ -1471,11 +1475,9 @@ namespace { if (Decls.size() == 0) return; // Don't warn on volatile, static, or global variables. - for (llvm::SmallPtrSetImpl<VarDecl*>::iterator I = Decls.begin(), - E = Decls.end(); - I != E; ++I) - if ((*I)->getType().isVolatileQualified() || - (*I)->hasGlobalStorage()) return; + for (auto *VD : Decls) + if (VD->getType().isVolatileQualified() || VD->hasGlobalStorage()) + return; if (DeclMatcher(S, Decls, Second).FoundDeclInUse() || DeclMatcher(S, Decls, Third).FoundDeclInUse() || @@ -1483,25 +1485,16 @@ namespace { return; // Load decl names into diagnostic. - if (Decls.size() > 4) + if (Decls.size() > 4) { PDiag << 0; - else { - PDiag << Decls.size(); - for (llvm::SmallPtrSetImpl<VarDecl*>::iterator I = Decls.begin(), - E = Decls.end(); - I != E; ++I) - PDiag << (*I)->getDeclName(); - } - - // Load SourceRanges into diagnostic if there is room. - // Otherwise, load the SourceRange of the conditional expression. - if (Ranges.size() <= PartialDiagnostic::MaxArguments) - for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), - E = Ranges.end(); - I != E; ++I) - PDiag << *I; - else - PDiag << Second->getSourceRange(); + } else { + PDiag << (unsigned)Decls.size(); + for (auto *VD : Decls) + PDiag << VD->getDeclName(); + } + + for (auto Range : Ranges) + PDiag << Range; S.Diag(Ranges.begin()->getBegin(), PDiag); } diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 5f91cac14a38..c182b35bfad4 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -277,6 +277,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); + LLVM_FALLTHROUGH; default: return StmtError(Diag(OutputExpr->getLocStart(), diag::err_asm_invalid_lvalue_in_output) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index ebdf6dd57fc5..75b69ae04f56 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2383,7 +2383,8 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( bool HasDefaultArg = false; TemplateDecl *TD = dyn_cast<TemplateDecl>(Template); if (!TD) { - assert(isa<ClassTemplatePartialSpecializationDecl>(Template)); + assert(isa<ClassTemplatePartialSpecializationDecl>(Template) || + isa<VarTemplatePartialSpecializationDecl>(Template)); return Sema::TDK_Incomplete; } @@ -5093,6 +5094,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, cast<DependentSizedArrayType>(T)->getSizeExpr(), OnlyDeduced, Depth, Used); // Fall through to check the element type + LLVM_FALLTHROUGH; case Type::ConstantArray: case Type::IncompleteArray: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index e7315934b515..c189112e3455 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -643,6 +643,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; // fallthrough + LLVM_FALLTHROUGH; FUNCTION_TYPE_ATTRS_CASELIST: distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType); @@ -1881,6 +1882,11 @@ QualType Sema::BuildPointerType(QualType T, return QualType(); } + if (T->isFunctionType() && getLangOpts().OpenCL) { + Diag(Loc, diag::err_opencl_function_pointer); + return QualType(); + } + if (checkQualifiedFunction(*this, T, Loc, QFK_Pointer)) return QualType(); @@ -4347,19 +4353,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (FTI.isAmbiguous) warnAboutAmbiguousFunction(S, D, DeclType, T); - // GNU warning -Wstrict-prototypes - // Warn if a function declaration is without a prototype. - // This warning is issued for all kinds of unprototyped function - // declarations (i.e. function type typedef, function pointer etc.) - // C99 6.7.5.3p14: - // The empty list in a function declarator that is not part of a - // definition of that function specifies that no information - // about the number or types of the parameters is supplied. - if (D.getFunctionDefinitionKind() == FDK_Declaration && - FTI.NumParams == 0 && !LangOpts.CPlusPlus) - S.Diag(DeclType.Loc, diag::warn_strict_prototypes) - << 0 << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void"); - FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex)); if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) { @@ -4602,6 +4595,36 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, const_cast<AttributeList *>(DeclType.getAttrs())); } + // GNU warning -Wstrict-prototypes + // Warn if a function declaration is without a prototype. + // This warning is issued for all kinds of unprototyped function + // declarations (i.e. function type typedef, function pointer etc.) + // C99 6.7.5.3p14: + // The empty list in a function declarator that is not part of a definition + // of that function specifies that no information about the number or types + // of the parameters is supplied. + if (!LangOpts.CPlusPlus && D.getFunctionDefinitionKind() == FDK_Declaration) { + bool IsBlock = false; + for (const DeclaratorChunk &DeclType : D.type_objects()) { + switch (DeclType.Kind) { + case DeclaratorChunk::BlockPointer: + IsBlock = true; + break; + case DeclaratorChunk::Function: { + const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + if (FTI.NumParams == 0) + S.Diag(DeclType.Loc, diag::warn_strict_prototypes) + << IsBlock + << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void"); + IsBlock = false; + break; + } + default: + break; + } + } + } + assert(!T.isNull() && "T must not be null after this point"); if (LangOpts.CPlusPlus && T->isFunctionType()) { @@ -6925,6 +6948,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; // fallthrough into the function attrs + LLVM_FALLTHROUGH; FUNCTION_TYPE_ATTRS_CASELIST: attr.setUsedAsTypeAttr(); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index a65584e3c912..7aa8f64d5081 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -6959,6 +6959,8 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) { Builder.ReturnStmt = Res.get(); } } + if (!Builder.buildParameterMoves()) + return StmtError(); return getDerived().RebuildCoroutineBodyStmt(Builder); } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index b7bbb9dc7be1..e16a9b3ee3b5 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -292,6 +292,33 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, return true; } + // Sanitizer feature mismatches are treated as compatible differences. If + // compatible differences aren't allowed, we still only want to check for + // mismatches of non-modular sanitizers (the only ones which can affect AST + // generation). + if (!AllowCompatibleDifferences) { + SanitizerMask ModularSanitizers = getPPTransparentSanitizers(); + SanitizerSet ExistingSanitizers = ExistingLangOpts.Sanitize; + SanitizerSet ImportedSanitizers = LangOpts.Sanitize; + ExistingSanitizers.clear(ModularSanitizers); + ImportedSanitizers.clear(ModularSanitizers); + if (ExistingSanitizers.Mask != ImportedSanitizers.Mask) { + const std::string Flag = "-fsanitize="; + if (Diags) { +#define SANITIZER(NAME, ID) \ + { \ + bool InExistingModule = ExistingSanitizers.has(SanitizerKind::ID); \ + bool InImportedModule = ImportedSanitizers.has(SanitizerKind::ID); \ + if (InExistingModule != InImportedModule) \ + Diags->Report(diag::err_pch_targetopt_feature_mismatch) \ + << InExistingModule << (Flag + NAME); \ + } +#include "clang/Basic/Sanitizers.def" + } + return true; + } + } + return false; } @@ -3670,6 +3697,8 @@ static void updateModuleTimestamp(ModuleFile &MF) { if (EC) return; OS << "Timestamp file\n"; + OS.close(); + OS.clear_error(); // Avoid triggering a fatal error. } /// \brief Given a cursor at the start of an AST file, scan ahead and drop the diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 95cb54f944e4..044a26433a93 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1856,24 +1856,31 @@ namespace { // Trait used for the on-disk hash table of header search information. class HeaderFileInfoTrait { ASTWriter &Writer; - const HeaderSearch &HS; // Keep track of the framework names we've used during serialization. SmallVector<char, 128> FrameworkStringData; llvm::StringMap<unsigned> FrameworkNameOffset; public: - HeaderFileInfoTrait(ASTWriter &Writer, const HeaderSearch &HS) - : Writer(Writer), HS(HS) { } - + HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {} + struct key_type { - const FileEntry *FE; StringRef Filename; + off_t Size; + time_t ModTime; }; typedef const key_type &key_type_ref; + + using UnresolvedModule = + llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>; - typedef HeaderFileInfo data_type; + struct data_type { + const HeaderFileInfo &HFI; + ArrayRef<ModuleMap::KnownHeader> KnownHeaders; + UnresolvedModule Unresolved; + }; typedef const data_type &data_type_ref; + typedef unsigned hash_value_type; typedef unsigned offset_type; @@ -1881,8 +1888,7 @@ namespace { // The hash is based only on size/time of the file, so that the reader can // match even when symlinking or excess path elements ("foo/../", "../") // change the form of the name. However, complete path is still the key. - return llvm::hash_combine(key.FE->getSize(), - Writer.getTimestampForOutput(key.FE)); + return llvm::hash_combine(key.Size, key.ModTime); } std::pair<unsigned,unsigned> @@ -1892,68 +1898,74 @@ namespace { unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write<uint16_t>(KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; - for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) + for (auto ModInfo : Data.KnownHeaders) if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) DataLen += 4; + if (Data.Unresolved.getPointer()) + DataLen += 4; LE.write<uint8_t>(DataLen); return std::make_pair(KeyLen, DataLen); } - + void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) { using namespace llvm::support; endian::Writer<little> LE(Out); - LE.write<uint64_t>(key.FE->getSize()); + LE.write<uint64_t>(key.Size); KeyLen -= 8; - LE.write<uint64_t>(Writer.getTimestampForOutput(key.FE)); + LE.write<uint64_t>(key.ModTime); KeyLen -= 8; Out.write(key.Filename.data(), KeyLen); } - + void EmitData(raw_ostream &Out, key_type_ref key, data_type_ref Data, unsigned DataLen) { using namespace llvm::support; endian::Writer<little> LE(Out); uint64_t Start = Out.tell(); (void)Start; - unsigned char Flags = (Data.isImport << 4) - | (Data.isPragmaOnce << 3) - | (Data.DirInfo << 1) - | Data.IndexHeaderMapHeader; + unsigned char Flags = (Data.HFI.isImport << 4) + | (Data.HFI.isPragmaOnce << 3) + | (Data.HFI.DirInfo << 1) + | Data.HFI.IndexHeaderMapHeader; LE.write<uint8_t>(Flags); - LE.write<uint16_t>(Data.NumIncludes); + LE.write<uint16_t>(Data.HFI.NumIncludes); - if (!Data.ControllingMacro) - LE.write<uint32_t>(Data.ControllingMacroID); + if (!Data.HFI.ControllingMacro) + LE.write<uint32_t>(Data.HFI.ControllingMacroID); else - LE.write<uint32_t>(Writer.getIdentifierRef(Data.ControllingMacro)); - + LE.write<uint32_t>(Writer.getIdentifierRef(Data.HFI.ControllingMacro)); + unsigned Offset = 0; - if (!Data.Framework.empty()) { + if (!Data.HFI.Framework.empty()) { // If this header refers into a framework, save the framework name. llvm::StringMap<unsigned>::iterator Pos - = FrameworkNameOffset.find(Data.Framework); + = FrameworkNameOffset.find(Data.HFI.Framework); if (Pos == FrameworkNameOffset.end()) { Offset = FrameworkStringData.size() + 1; - FrameworkStringData.append(Data.Framework.begin(), - Data.Framework.end()); + FrameworkStringData.append(Data.HFI.Framework.begin(), + Data.HFI.Framework.end()); FrameworkStringData.push_back(0); - FrameworkNameOffset[Data.Framework] = Offset; + FrameworkNameOffset[Data.HFI.Framework] = Offset; } else Offset = Pos->second; } LE.write<uint32_t>(Offset); - // FIXME: If the header is excluded, we should write out some - // record of that fact. - for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) { - if (uint32_t ModID = - Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) { - uint32_t Value = (ModID << 2) | (unsigned)ModInfo.getRole(); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { + if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { + uint32_t Value = (ModID << 2) | (unsigned)Role; assert((Value >> 2) == ModID && "overflow in header module info"); LE.write<uint32_t>(Value); } - } + }; + + // FIXME: If the header is excluded, we should write out some + // record of that fact. + for (auto ModInfo : Data.KnownHeaders) + EmitModule(ModInfo.getModule(), ModInfo.getRole()); + if (Data.Unresolved.getPointer()) + EmitModule(Data.Unresolved.getPointer(), Data.Unresolved.getInt()); assert(Out.tell() - Start == DataLen && "Wrong data length"); } @@ -1968,16 +1980,72 @@ namespace { /// /// \param HS The header search structure to save. void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { + HeaderFileInfoTrait GeneratorTrait(*this); + llvm::OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator; + SmallVector<const char *, 4> SavedStrings; + unsigned NumHeaderSearchEntries = 0; + + // Find all unresolved headers for the current module. We generally will + // have resolved them before we get here, but not necessarily: we might be + // compiling a preprocessed module, where there is no requirement for the + // original files to exist any more. + const HeaderFileInfo Empty; // So we can take a reference. + if (WritingModule) { + llvm::SmallVector<Module *, 16> Worklist(1, WritingModule); + while (!Worklist.empty()) { + Module *M = Worklist.pop_back_val(); + if (!M->isAvailable()) + continue; + + // Map to disk files where possible, to pick up any missing stat + // information. This also means we don't need to check the unresolved + // headers list when emitting resolved headers in the first loop below. + // FIXME: It'd be preferable to avoid doing this if we were given + // sufficient stat information in the module map. + HS.getModuleMap().resolveHeaderDirectives(M); + + // If the file didn't exist, we can still create a module if we were given + // enough information in the module map. + for (auto U : M->MissingHeaders) { + // Check that we were given enough information to build a module + // without this file existing on disk. + if (!U.Size || (!U.ModTime && IncludeTimestamps)) { + PP->Diag(U.FileNameLoc, diag::err_module_no_size_mtime_for_header) + << WritingModule->getFullModuleName() << U.Size.hasValue() + << U.FileName; + continue; + } + + // Form the effective relative pathname for the file. + SmallString<128> Filename(M->Directory->getName()); + llvm::sys::path::append(Filename, U.FileName); + PreparePathForOutput(Filename); + + StringRef FilenameDup = strdup(Filename.c_str()); + SavedStrings.push_back(FilenameDup.data()); + + HeaderFileInfoTrait::key_type Key = { + FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0 + }; + HeaderFileInfoTrait::data_type Data = { + Empty, {}, {M, ModuleMap::headerKindToRole(U.Kind)} + }; + // FIXME: Deal with cases where there are multiple unresolved header + // directives in different submodules for the same header. + Generator.insert(Key, Data, GeneratorTrait); + ++NumHeaderSearchEntries; + } + + Worklist.append(M->submodule_begin(), M->submodule_end()); + } + } + SmallVector<const FileEntry *, 16> FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); if (FilesByUID.size() > HS.header_file_size()) FilesByUID.resize(HS.header_file_size()); - - HeaderFileInfoTrait GeneratorTrait(*this, HS); - llvm::OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator; - SmallVector<const char *, 4> SavedStrings; - unsigned NumHeaderSearchEntries = 0; + for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { const FileEntry *File = FilesByUID[UID]; if (!File) @@ -2004,11 +2072,16 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { SavedStrings.push_back(Filename.data()); } - HeaderFileInfoTrait::key_type key = { File, Filename }; - Generator.insert(key, *HFI, GeneratorTrait); + HeaderFileInfoTrait::key_type Key = { + Filename, File->getSize(), getTimestampForOutput(File) + }; + HeaderFileInfoTrait::data_type Data = { + *HFI, HS.getModuleMap().findAllModulesForHeader(File), {} + }; + Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; } - + // Create the on-disk hash table in a buffer. SmallString<4096> TableData; uint32_t BucketOffset; diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index 8ca2a24cffe7..f7b5f61cfb8a 100644 --- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -189,6 +189,7 @@ public: case DeadIncrement: BugType = "Dead increment"; + LLVM_FALLTHROUGH; case Standard: if (!BugType) BugType = "Dead assignment"; os << "Value stored to '" << *V << "' is never read"; diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 8ee34190891a..f84c0ee800a3 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1176,6 +1176,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, } } // FALLTHROUGH + LLVM_FALLTHROUGH; } case Stmt::CallExprClass: case Stmt::CXXMemberCallExprClass: diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index ffaa0eda918a..04452e3e7cc2 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -325,6 +325,7 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) { } } // FALLTHROUGH + LLVM_FALLTHROUGH; } // If we don't have a special case, fall back to the AST's constant evaluator. diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 82ce8b45fe78..9c28457b2139 100644 --- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -163,6 +163,7 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) { return nonloc::SymbolVal(SymR->getSymbol()); // FALL-THROUGH + LLVM_FALLTHROUGH; } case loc::GotoLabelKind: |