diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/AttributeList.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/JumpDiagnostics.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 67 | ||||
-rw-r--r-- | lib/Sema/SemaAttr.cpp | 213 | ||||
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaCoroutine.cpp | 85 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 28 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaOpenMP.cpp | 88 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 7 |
16 files changed, 488 insertions, 84 deletions
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp index 55e9601bf5e5..724db456785f 100644 --- a/lib/Sema/AttributeList.cpp +++ b/lib/Sema/AttributeList.cpp @@ -16,6 +16,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaInternal.h" @@ -160,12 +161,16 @@ struct ParsedAttrInfo { unsigned IsType : 1; unsigned IsStmt : 1; unsigned IsKnownToGCC : 1; + unsigned IsSupportedByPragmaAttribute : 1; bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, const Decl *); bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); bool (*ExistsInTarget)(const TargetInfo &Target); unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr); + void (*GetPragmaAttributeMatchRules)( + llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules, + const LangOptions &LangOpts); }; namespace { @@ -192,6 +197,18 @@ bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const { return getInfo(*this).DiagAppertainsToDecl(S, *this, D); } +bool AttributeList::appliesToDecl(const Decl *D, + attr::SubjectMatchRule MatchRule) const { + return checkAttributeMatchRuleAppliesTo(D, MatchRule); +} + +void AttributeList::getMatchRules( + const LangOptions &LangOpts, + SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules) + const { + return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts); +} + bool AttributeList::diagnoseLangOpts(Sema &S) const { return getInfo(*this).DiagLangOpts(S, *this); } @@ -216,6 +233,10 @@ bool AttributeList::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; } +bool AttributeList::isSupportedByPragmaAttribute() const { + return getInfo(*this).IsSupportedByPragmaAttribute; +} + unsigned AttributeList::getSemanticSpelling() const { return getInfo(*this).SpellingIndexToSemanticSpelling(*this); } diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index 899d3fa83cc3..865aea9e2284 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -287,6 +287,15 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel()); break; + case Stmt::ObjCForCollectionStmtClass: { + auto *CS = cast<ObjCForCollectionStmt>(S); + unsigned Diag = diag::note_protected_by_objc_fast_enumeration; + unsigned NewParentScope = Scopes.size(); + Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getLocStart())); + BuildScopeInformation(CS->getBody(), NewParentScope); + return; + } + case Stmt::IndirectGotoStmtClass: // "goto *&&lbl;" is a special case which we treat as equivalent // to a normal goto. In addition, we don't calculate scope in the diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 294b56059b33..950f04088822 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -71,42 +71,35 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { } Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, - TranslationUnitKind TUKind, - CodeCompleteConsumer *CodeCompleter) - : ExternalSource(nullptr), - isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()), - LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), - Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), - CollectStats(false), CodeCompleter(CodeCompleter), - CurContext(nullptr), OriginalLexicalContext(nullptr), - MSStructPragmaOn(false), - MSPointerToMemberRepresentationMethod( - LangOpts.getMSPointerToMemberRepresentationMethod()), - VtorDispStack(MSVtorDispAttr::Mode(LangOpts.VtorDispMode)), - PackStack(0), DataSegStack(nullptr), BSSSegStack(nullptr), - ConstSegStack(nullptr), CodeSegStack(nullptr), CurInitSeg(nullptr), - VisContext(nullptr), - IsBuildingRecoveryCallExpr(false), - Cleanup{}, LateTemplateParser(nullptr), - LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), - StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), - CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), - NSNumberDecl(nullptr), NSValueDecl(nullptr), - NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), - ValueWithBytesObjCTypeMethod(nullptr), - NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr), - NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr), - GlobalNewDeleteDeclared(false), - TUKind(TUKind), - NumSFINAEErrors(0), - CachedFakeTopLevelModule(nullptr), - AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), - NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), - CurrentInstantiationScope(nullptr), DisableTypoCorrection(false), - TyposCorrected(0), AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr), - VarDataSharingAttributesStack(nullptr), CurScope(nullptr), - Ident_super(nullptr), Ident___float128(nullptr) -{ + TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter) + : ExternalSource(nullptr), isMultiplexExternalSource(false), + FPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp), + Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), + SourceMgr(PP.getSourceManager()), CollectStats(false), + CodeCompleter(CodeCompleter), CurContext(nullptr), + OriginalLexicalContext(nullptr), MSStructPragmaOn(false), + MSPointerToMemberRepresentationMethod( + LangOpts.getMSPointerToMemberRepresentationMethod()), + VtorDispStack(MSVtorDispAttr::Mode(LangOpts.VtorDispMode)), PackStack(0), + DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr), + CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr), + PragmaAttributeCurrentTargetDecl(nullptr), + IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr), + LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), + StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), + CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), + NSValueDecl(nullptr), NSStringDecl(nullptr), + StringWithUTF8StringMethod(nullptr), + ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), + ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), + DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false), + TUKind(TUKind), NumSFINAEErrors(0), CachedFakeTopLevelModule(nullptr), + AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), + NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), + CurrentInstantiationScope(nullptr), DisableTypoCorrection(false), + TyposCorrected(0), AnalysisWarnings(*this), + ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr), + CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) { TUScope = nullptr; LoadedExternalKnownNamespaces = false; @@ -731,6 +724,8 @@ void Sema::ActOnEndOfTranslationUnit() { CheckDelayedMemberExceptionSpecs(); } + DiagnoseUnterminatedPragmaAttribute(); + // All delayed member exception specs should be checked or we end up accepting // incompatible declarations. // FIXME: This is wrong for TUKind == TU_Prefix. In that case, we need to diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index c6e3cc886316..76ca65373dda 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -368,6 +368,219 @@ void Sema::AddCFAuditedAttribute(Decl *D) { D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc)); } +namespace { + +Optional<attr::SubjectMatchRule> +getParentAttrMatcherRule(attr::SubjectMatchRule Rule) { + using namespace attr; + switch (Rule) { + default: + return None; +#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) +#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ + case Value: \ + return Parent; +#include "clang/Basic/AttrSubMatchRulesList.inc" + } +} + +bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) { + using namespace attr; + switch (Rule) { + default: + return false; +#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) +#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ + case Value: \ + return IsNegated; +#include "clang/Basic/AttrSubMatchRulesList.inc" + } +} + +CharSourceRange replacementRangeForListElement(const Sema &S, + SourceRange Range) { + // Make sure that the ',' is removed as well. + SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken( + Range.getEnd(), tok::comma, S.getSourceManager(), S.getLangOpts(), + /*SkipTrailingWhitespaceAndNewLine=*/false); + if (AfterCommaLoc.isValid()) + return CharSourceRange::getCharRange(Range.getBegin(), AfterCommaLoc); + else + return CharSourceRange::getTokenRange(Range); +} + +std::string +attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) { + std::string Result; + llvm::raw_string_ostream OS(Result); + for (const auto &I : llvm::enumerate(Rules)) { + if (I.index()) + OS << (I.index() == Rules.size() - 1 ? ", and " : ", "); + OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'"; + } + return OS.str(); +} + +} // end anonymous namespace + +void Sema::ActOnPragmaAttributePush(AttributeList &Attribute, + SourceLocation PragmaLoc, + attr::ParsedSubjectMatchRuleSet Rules) { + SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules; + // Gather the subject match rules that are supported by the attribute. + SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> + StrictSubjectMatchRuleSet; + Attribute.getMatchRules(LangOpts, StrictSubjectMatchRuleSet); + + // Figure out which subject matching rules are valid. + if (StrictSubjectMatchRuleSet.empty()) { + // Check for contradicting match rules. Contradicting match rules are + // either: + // - a top-level rule and one of its sub-rules. E.g. variable and + // variable(is_parameter). + // - a sub-rule and a sibling that's negated. E.g. + // variable(is_thread_local) and variable(unless(is_parameter)) + llvm::SmallDenseMap<int, std::pair<int, SourceRange>, 2> + RulesToFirstSpecifiedNegatedSubRule; + for (const auto &Rule : Rules) { + attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); + Optional<attr::SubjectMatchRule> ParentRule = + getParentAttrMatcherRule(MatchRule); + if (!ParentRule) + continue; + auto It = Rules.find(*ParentRule); + if (It != Rules.end()) { + // A sub-rule contradicts a parent rule. + Diag(Rule.second.getBegin(), + diag::err_pragma_attribute_matcher_subrule_contradicts_rule) + << attr::getSubjectMatchRuleSpelling(MatchRule) + << attr::getSubjectMatchRuleSpelling(*ParentRule) << It->second + << FixItHint::CreateRemoval( + replacementRangeForListElement(*this, Rule.second)); + // Keep going without removing this rule as it won't change the set of + // declarations that receive the attribute. + continue; + } + if (isNegatedAttrMatcherSubRule(MatchRule)) + RulesToFirstSpecifiedNegatedSubRule.insert( + std::make_pair(*ParentRule, Rule)); + } + bool IgnoreNegatedSubRules = false; + for (const auto &Rule : Rules) { + attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); + Optional<attr::SubjectMatchRule> ParentRule = + getParentAttrMatcherRule(MatchRule); + if (!ParentRule) + continue; + auto It = RulesToFirstSpecifiedNegatedSubRule.find(*ParentRule); + if (It != RulesToFirstSpecifiedNegatedSubRule.end() && + It->second != Rule) { + // Negated sub-rule contradicts another sub-rule. + Diag( + It->second.second.getBegin(), + diag:: + err_pragma_attribute_matcher_negated_subrule_contradicts_subrule) + << attr::getSubjectMatchRuleSpelling( + attr::SubjectMatchRule(It->second.first)) + << attr::getSubjectMatchRuleSpelling(MatchRule) << Rule.second + << FixItHint::CreateRemoval( + replacementRangeForListElement(*this, It->second.second)); + // Keep going but ignore all of the negated sub-rules. + IgnoreNegatedSubRules = true; + RulesToFirstSpecifiedNegatedSubRule.erase(It); + } + } + + if (!IgnoreNegatedSubRules) { + for (const auto &Rule : Rules) + SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first)); + } else { + for (const auto &Rule : Rules) { + if (!isNegatedAttrMatcherSubRule(attr::SubjectMatchRule(Rule.first))) + SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first)); + } + } + Rules.clear(); + } else { + for (const auto &Rule : StrictSubjectMatchRuleSet) { + if (Rules.erase(Rule.first)) { + // Add the rule to the set of attribute receivers only if it's supported + // in the current language mode. + if (Rule.second) + SubjectMatchRules.push_back(Rule.first); + } + } + } + + if (!Rules.empty()) { + auto Diagnostic = + Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers) + << Attribute.getName(); + SmallVector<attr::SubjectMatchRule, 2> ExtraRules; + for (const auto &Rule : Rules) { + ExtraRules.push_back(attr::SubjectMatchRule(Rule.first)); + Diagnostic << FixItHint::CreateRemoval( + replacementRangeForListElement(*this, Rule.second)); + } + Diagnostic << attrMatcherRuleListToString(ExtraRules); + } + + PragmaAttributeStack.push_back( + {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false}); +} + +void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc) { + if (PragmaAttributeStack.empty()) { + Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch); + return; + } + const PragmaAttributeEntry &Entry = PragmaAttributeStack.back(); + if (!Entry.IsUsed) { + assert(Entry.Attribute && "Expected an attribute"); + Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused) + << Entry.Attribute->getName(); + Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here); + } + PragmaAttributeStack.pop_back(); +} + +void Sema::AddPragmaAttributes(Scope *S, Decl *D) { + if (PragmaAttributeStack.empty()) + return; + for (auto &Entry : PragmaAttributeStack) { + const AttributeList *Attribute = Entry.Attribute; + assert(Attribute && "Expected an attribute"); + + // Ensure that the attribute can be applied to the given declaration. + bool Applies = false; + for (const auto &Rule : Entry.MatchRules) { + if (Attribute->appliesToDecl(D, Rule)) { + Applies = true; + break; + } + } + if (!Applies) + continue; + Entry.IsUsed = true; + assert(!Attribute->getNext() && "Expected just one attribute"); + PragmaAttributeCurrentTargetDecl = D; + ProcessDeclAttributeList(S, D, Attribute); + PragmaAttributeCurrentTargetDecl = nullptr; + } +} + +void Sema::PrintPragmaAttributeInstantiationPoint() { + assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration"); + Diags.Report(PragmaAttributeCurrentTargetDecl->getLocStart(), + diag::note_pragma_attribute_applied_decl_here); +} + +void Sema::DiagnoseUnterminatedPragmaAttribute() { + if (PragmaAttributeStack.empty()) + return; + Diag(PragmaAttributeStack.back().Loc, diag::err_pragma_attribute_no_pop_eof); +} + void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) { if(On) OptimizeOffPragmaLocation = SourceLocation(); diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 57471de78d3e..6da4d2a26191 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -480,6 +480,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool ErrorRecoveryLookup, bool *IsCorrectedToColon, bool OnlyNamespace) { + if (IdInfo.Identifier->isEditorPlaceholder()) + return true; LookupResult Found(*this, IdInfo.Identifier, IdInfo.IdentifierLoc, OnlyNamespace ? LookupNamespaceName : LookupNestedNameSpecifierName); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 81db0d3d00a7..45523b30ef22 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1391,8 +1391,6 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, } bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { - llvm::APSInt Result; - if (BuiltinID == ARM::BI__builtin_arm_ldrex || BuiltinID == ARM::BI__builtin_arm_ldaex || BuiltinID == ARM::BI__builtin_arm_strex || @@ -1439,8 +1437,6 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { - llvm::APSInt Result; - if (BuiltinID == AArch64::BI__builtin_arm_ldrex || BuiltinID == AArch64::BI__builtin_arm_ldaex || BuiltinID == AArch64::BI__builtin_arm_strex || diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index 4a55e51495a8..c709a1a723d0 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -454,7 +454,7 @@ static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc, /*IsImplicit*/ true); Suspend = S.ActOnFinishFullExpr(Suspend.get()); if (Suspend.isInvalid()) { - S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required) + S.Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) << ((Name == "initial_suspend") ? 0 : 1); S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword; return StmtError(); @@ -660,6 +660,39 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E, return Res; } +/// Look up the std::nothrow object. +static Expr *buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc) { + NamespaceDecl *Std = S.getStdNamespace(); + assert(Std && "Should already be diagnosed"); + + LookupResult Result(S, &S.PP.getIdentifierTable().get("nothrow"), Loc, + Sema::LookupOrdinaryName); + if (!S.LookupQualifiedName(Result, Std)) { + // FIXME: <experimental/coroutine> should have been included already. + // If we require it to include <new> then this diagnostic is no longer + // needed. + S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found); + return nullptr; + } + + // FIXME: Mark the variable as ODR used. This currently does not work + // likely due to the scope at in which this function is called. + auto *VD = Result.getAsSingle<VarDecl>(); + if (!VD) { + Result.suppressDiagnostics(); + // We found something weird. Complain about the first thing we found. + NamedDecl *Found = *Result.begin(); + S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow); + return nullptr; + } + + ExprResult DR = S.BuildDeclRefExpr(VD, VD->getType(), VK_LValue, Loc); + if (DR.isInvalid()) + return nullptr; + + return DR.get(); +} + // Find an appropriate delete for the promise. static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType) { @@ -847,23 +880,53 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type)) return false; - // FIXME: Add nothrow_t placement arg for global alloc - // if ReturnStmtOnAllocFailure != nullptr. + const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr; + // FIXME: Add support for stateful allocators. FunctionDecl *OperatorNew = nullptr; FunctionDecl *OperatorDelete = nullptr; FunctionDecl *UnusedResult = nullptr; bool PassAlignment = false; + SmallVector<Expr *, 1> PlacementArgs; S.FindAllocationFunctions(Loc, SourceRange(), /*UseGlobal*/ false, PromiseType, - /*isArray*/ false, PassAlignment, - /*PlacementArgs*/ None, OperatorNew, UnusedResult); + /*isArray*/ false, PassAlignment, PlacementArgs, + OperatorNew, UnusedResult); + + bool IsGlobalOverload = + OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext()); + // If we didn't find a class-local new declaration and non-throwing new + // was is required then we need to lookup the non-throwing global operator + // instead. + if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) { + auto *StdNoThrow = buildStdNoThrowDeclRef(S, Loc); + if (!StdNoThrow) + return false; + PlacementArgs = {StdNoThrow}; + OperatorNew = nullptr; + S.FindAllocationFunctions(Loc, SourceRange(), + /*UseGlobal*/ true, PromiseType, + /*isArray*/ false, PassAlignment, PlacementArgs, + OperatorNew, UnusedResult); + } - OperatorDelete = findDeleteForPromise(S, Loc, PromiseType); + assert(OperatorNew && "expected definition of operator new to be found"); - if (!OperatorDelete || !OperatorNew) + if (RequiresNoThrowAlloc) { + const auto *FT = OperatorNew->getType()->getAs<FunctionProtoType>(); + if (!FT->isNothrow(S.Context, /*ResultIfDependent*/ false)) { + S.Diag(OperatorNew->getLocation(), + diag::err_coroutine_promise_new_requires_nothrow) + << OperatorNew; + S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required) + << OperatorNew; + return false; + } + } + + if ((OperatorDelete = findDeleteForPromise(S, Loc, PromiseType)) == nullptr) return false; Expr *FramePtr = @@ -879,8 +942,13 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { if (NewRef.isInvalid()) return false; + SmallVector<Expr *, 2> NewArgs(1, FrameSize); + for (auto Arg : PlacementArgs) + NewArgs.push_back(Arg); + ExprResult NewExpr = - S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, FrameSize, Loc); + S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc); + NewExpr = S.ActOnFinishFullExpr(NewExpr.get()); if (NewExpr.isInvalid()) return false; @@ -906,6 +974,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { ExprResult DeleteExpr = S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc); + DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get()); if (DeleteExpr.isInvalid()) return false; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c6a0b0101d37..f3ffcf5d696c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -628,6 +628,9 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, CXXScopeSpec *SS, ParsedType &SuggestedType, bool AllowClassTemplates) { + // Don't report typename errors for editor placeholders. + if (II->isEditorPlaceholder()) + return; // We don't have anything to suggest (yet). SuggestedType = nullptr; @@ -13674,6 +13677,7 @@ CreateNewDecl: if (Attr) ProcessDeclAttributeList(S, New, Attr); + AddPragmaAttributes(S, New); // If this has an identifier, add it to the scope stack. if (TUK == TUK_Friend) { @@ -15185,6 +15189,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, // Process attributes. if (Attr) ProcessDeclAttributeList(S, New, Attr); + AddPragmaAttributes(S, New); // Register this decl in the current scope stack. New->setAccess(TheEnumDecl->getAccess()); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index a1ba9de368db..027b3fe0e782 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2398,10 +2398,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, << Platform->Ident; NamedDecl *ND = dyn_cast<NamedDecl>(D); - if (!ND) { - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + if (!ND) // We warned about this already, so just return. return; - } AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); @@ -2511,12 +2509,6 @@ static void handleExternalSourceSymbolAttr(Sema &S, Decl *D, assert(checkAttributeAtMostNumArgs(S, Attr, 3) && "Invalid number of arguments in an external_source_symbol attribute"); - if (!isa<NamedDecl>(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedNamedDecl; - return; - } - StringRef Language; if (const auto *SE = dyn_cast_or_null<StringLiteral>(Attr.getArgAsExpr(0))) Language = SE->getString(); @@ -5765,18 +5757,21 @@ static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const AttributeList &Attr) { static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr) { // Several attributes carry different semantics than the parsing requires, so - // those are opted out of the common handling. + // those are opted out of the common argument checks. // // We also bail on unknown and ignored attributes because those are handled // as part of the target-specific handling logic. - if (Attr.hasCustomParsing() || - Attr.getKind() == AttributeList::UnknownAttribute) + if (Attr.getKind() == AttributeList::UnknownAttribute) return false; - // Check whether the attribute requires specific language extensions to be // enabled. if (!Attr.diagnoseLangOpts(S)) return true; + // Check whether the attribute appertains to the given subject. + if (!Attr.diagnoseAppertainsTo(S, D)) + return true; + if (Attr.hasCustomParsing()) + return false; if (Attr.getMinArgs() == Attr.getMaxArgs()) { // If there are no optional arguments, then checking for the argument count @@ -5793,10 +5788,6 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, return true; } - // Check whether the attribute appertains to the given subject. - if (!Attr.diagnoseAppertainsTo(S, D)) - return true; - return false; } @@ -6676,6 +6667,9 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { // Finally, apply any attributes on the decl itself. if (const AttributeList *Attrs = PD.getAttributes()) ProcessDeclAttributeList(S, D, Attrs); + + // Apply additional attributes specified by '#pragma clang attribute'. + AddPragmaAttributes(S, D); } /// Is the given declaration allowed to use a forbidden type? diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index fd3f266c9a08..b543a731641f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -8445,6 +8445,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, Namespc->setInvalidDecl(); ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); + AddPragmaAttributes(DeclRegionScope, Namespc); // FIXME: Should we be merging attributes? if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) @@ -9931,6 +9932,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, NewTD->setInvalidDecl(); ProcessDeclAttributeList(S, NewTD, AttrList); + AddPragmaAttributes(S, NewTD); CheckTypedefForVariablyModifiedType(S, NewTD); Invalid |= NewTD->isInvalidDecl(); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index e50f8b206779..4f51cd399c0c 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -993,6 +993,7 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, if (AttrList) ProcessDeclAttributeList(TUScope, IDecl, AttrList); + AddPragmaAttributes(TUScope, IDecl); PushOnScopeChains(IDecl, TUScope); // Start the definition of this class. If we're in a redefinition case, there @@ -1176,7 +1177,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, if (AttrList) ProcessDeclAttributeList(TUScope, PDecl, AttrList); - + AddPragmaAttributes(TUScope, PDecl); + // Merge attributes from previous declarations. if (PrevDecl) mergeDeclAttributes(PDecl, PrevDecl); @@ -1706,7 +1708,8 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, if (attrList) ProcessDeclAttributeList(TUScope, PDecl, attrList); - + AddPragmaAttributes(TUScope, PDecl); + if (PrevDecl) mergeDeclAttributes(PDecl, PrevDecl); @@ -1805,6 +1808,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, if (AttrList) ProcessDeclAttributeList(TUScope, CDecl, AttrList); + AddPragmaAttributes(TUScope, CDecl); CheckObjCDeclScope(CDecl); return ActOnObjCContainerStartDefinition(CDecl); @@ -1954,6 +1958,7 @@ Decl *Sema::ActOnStartClassImplementation( ClassName, /*typeParamList=*/nullptr, /*PrevDecl=*/nullptr, ClassLoc, true); + AddPragmaAttributes(TUScope, IDecl); IDecl->startDefinition(); if (SDecl) { IDecl->setSuperClass(Context.getTrivialTypeSourceInfo( @@ -3043,7 +3048,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, ClassName, TypeParams, PrevIDecl, IdentLocs[i]); IDecl->setAtEndRange(IdentLocs[i]); - + PushOnScopeChains(IDecl, TUScope); CheckObjCDeclScope(IDecl); DeclsInGroup.push_back(IDecl); @@ -4399,6 +4404,7 @@ Decl *Sema::ActOnMethodDeclaration( // Apply the attributes to the parameter. ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); + AddPragmaAttributes(TUScope, Param); if (Param->hasAttr<BlocksAttr>()) { Diag(Param->getLocation(), diag::err_block_on_nonlocal); @@ -4429,6 +4435,7 @@ Decl *Sema::ActOnMethodDeclaration( if (AttrList) ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); + AddPragmaAttributes(TUScope, ObjCMethod); // Add the method now. const ObjCMethodDecl *PrevMethod = nullptr; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bb174521c72c..5a56f7093777 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2129,6 +2129,12 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, IdentifierInfo *II = Name.getAsIdentifierInfo(); SourceLocation NameLoc = NameInfo.getLoc(); + if (II && II->isEditorPlaceholder()) { + // FIXME: When typed placeholders are supported we can create a typed + // placeholder expression node. + return ExprError(); + } + // C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: // -- an identifier that was declared with a dependent type, diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 616ab05eaec8..d7a6d2e5885e 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -4068,7 +4068,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin(); // Build variables passed into runtime, necessary for worksharing directives. - ExprResult LB, UB, IL, ST, EUB, PrevLB, PrevUB; + ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB; if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)) { // Lower bound variable, initialized with zero. @@ -4116,8 +4116,32 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // enclosing region. E.g. in 'distribute parallel for' the bounds obtained // by scheduling 'distribute' have to be passed to the schedule of 'for'. if (isOpenMPLoopBoundSharingDirective(DKind)) { - auto *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl(); + // Lower bound variable, initialized with zero. + VarDecl *CombLBDecl = + buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb"); + CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc); + SemaRef.AddInitializerToDecl( + CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), + /*DirectInit*/ false); + + // Upper bound variable, initialized with last iteration number. + VarDecl *CombUBDecl = + buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub"); + CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc); + SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(), + /*DirectInit*/ false); + + ExprResult CombIsUBGreater = SemaRef.BuildBinOp( + CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get()); + ExprResult CombCondOp = + SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(), + LastIteration.get(), CombUB.get()); + CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), + CombCondOp.get()); + CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get()); + + auto *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl(); // We expect to have at least 2 more parameters than the 'parallel' // directive does - the lower and upper bounds of the previous schedule. assert(CD->getNumParams() >= 4 && @@ -4139,7 +4163,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Build the iteration variable and its initialization before loop. ExprResult IV; - ExprResult Init; + ExprResult Init, CombInit; { VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv"); IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc); @@ -4150,6 +4174,18 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); Init = SemaRef.ActOnFinishFullExpr(Init.get()); + + if (isOpenMPLoopBoundSharingDirective(DKind)) { + Expr *CombRHS = + (isOpenMPWorksharingDirective(DKind) || + isOpenMPTaskLoopDirective(DKind) || + isOpenMPDistributeDirective(DKind)) + ? CombLB.get() + : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); + CombInit = + SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); + CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get()); + } } // Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops. @@ -4160,7 +4196,11 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, ? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get()) : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), NumIterations.get()); - + ExprResult CombCond; + if (isOpenMPLoopBoundSharingDirective(DKind)) { + CombCond = + SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), CombUB.get()); + } // Loop increment (IV = IV + 1) SourceLocation IncLoc; ExprResult Inc = @@ -4175,7 +4215,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Increments for worksharing loops (LB = LB + ST; UB = UB + ST). // Used for directives with static scheduling. - ExprResult NextLB, NextUB; + // In combined construct, add combined version that use CombLB and CombUB + // base variables for the update + ExprResult NextLB, NextUB, CombNextLB, CombNextUB; if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)) { // LB + ST @@ -4198,9 +4240,32 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get()); if (!NextUB.isUsable()) return 0; - } - - // Create: increment expression for distribute loop when combined in a same + if (isOpenMPLoopBoundSharingDirective(DKind)) { + CombNextLB = + SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get()); + if (!NextLB.isUsable()) + return 0; + // LB = LB + ST + CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), + CombNextLB.get()); + CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get()); + if (!CombNextLB.isUsable()) + return 0; + // UB + ST + CombNextUB = + SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get()); + if (!CombNextUB.isUsable()) + return 0; + // UB = UB + ST + CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), + CombNextUB.get()); + CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get()); + if (!CombNextUB.isUsable()) + return 0; + } + } + + // Create increment expression for distribute loop when combined in a same // directive with for as IV = IV + ST; ensure upper bound expression based // on PrevUB instead of NumIterations - used to implement 'for' when found // in combination with 'distribute', like in 'distribute parallel for' @@ -4346,6 +4411,13 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.PrevUB = PrevUB.get(); Built.DistInc = DistInc.get(); Built.PrevEUB = PrevEUB.get(); + Built.DistCombinedFields.LB = CombLB.get(); + Built.DistCombinedFields.UB = CombUB.get(); + Built.DistCombinedFields.EUB = CombEUB.get(); + Built.DistCombinedFields.Init = CombInit.get(); + Built.DistCombinedFields.Cond = CombCond.get(); + Built.DistCombinedFields.NLB = CombNextLB.get(); + Built.DistCombinedFields.NUB = CombNextUB.get(); Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get(); // Fill data for doacross depend clauses. diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 9be1c56f0622..9ffc23b5adba 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1783,6 +1783,7 @@ StmtResult Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, Stmt *First, Expr *collection, SourceLocation RParenLoc) { + getCurFunction()->setHasBranchProtectedScope(); ExprResult CollectionExprResult = CheckObjCForCollectionOperand(ForLoc, collection); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f522e76b0673..61b4df40964c 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1636,11 +1636,22 @@ private: transformFunctionTypeParam(ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args) { TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo(); - TypeSourceInfo *NewDI = - Args.getNumLevels() - ? SemaRef.SubstType(OldDI, Args, OldParam->getLocation(), - OldParam->getDeclName()) - : OldDI; + TypeSourceInfo *NewDI; + if (!Args.getNumLevels()) + NewDI = OldDI; + else if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) { + // Expand out the one and only element in each inner pack. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, 0); + NewDI = + SemaRef.SubstType(PackTL.getPatternLoc(), Args, + OldParam->getLocation(), OldParam->getDeclName()); + if (!NewDI) return nullptr; + NewDI = + SemaRef.CheckPackExpansion(NewDI, PackTL.getEllipsisLoc(), + PackTL.getTypePtr()->getNumExpansions()); + } else + NewDI = SemaRef.SubstType(OldDI, Args, OldParam->getLocation(), + OldParam->getDeclName()); if (!NewDI) return nullptr; diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index edd6edfce9dc..2d44489023ef 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2605,10 +2605,11 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, == TSK_ExplicitSpecialization) continue; - if (Context.getTargetInfo().getCXXABI().isMicrosoft() && + if ((Context.getTargetInfo().getCXXABI().isMicrosoft() || + Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && TSK == TSK_ExplicitInstantiationDeclaration) { - // In MSVC mode, explicit instantiation decl of the outer class doesn't - // affect the inner class. + // In MSVC and Windows Itanium mode, explicit instantiation decl of the + // outer class doesn't affect the inner class. continue; } |