diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp index 77410db..e935fc7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp @@ -263,9 +263,6 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, Context->setAlignment(AlignmentVal); } break; - - default: - llvm_unreachable("Invalid #pragma pack kind."); } } @@ -348,9 +345,9 @@ static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) { Stack->push_back(std::make_pair(type, loc)); } -void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, +void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, SourceLocation PragmaLoc) { - if (IsPush) { + if (VisType) { // Compute visibility to use. VisibilityAttr::VisibilityType type; if (VisType->isStr("default")) @@ -368,7 +365,7 @@ void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, } PushPragmaVisibility(*this, type, PragmaLoc); } else { - PopPragmaVisibility(); + PopPragmaVisibility(false, PragmaLoc); } } @@ -381,28 +378,49 @@ void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) { FPFeatures.fp_contract = 0; break; case tok::OOS_DEFAULT: - FPFeatures.fp_contract = getLangOptions().DefaultFPContract; + FPFeatures.fp_contract = getLangOpts().DefaultFPContract; break; } } -void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr) { +void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, + SourceLocation Loc) { // Visibility calculations will consider the namespace's visibility. // Here we just want to note that we're in a visibility context // which overrides any enclosing #pragma context, but doesn't itself // contribute visibility. - PushPragmaVisibility(*this, NoVisibility, SourceLocation()); + PushPragmaVisibility(*this, NoVisibility, Loc); } -void Sema::PopPragmaVisibility() { - // Pop visibility from stack, if there is one on the stack. - if (VisContext) { - VisStack *Stack = static_cast<VisStack*>(VisContext); +void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) { + if (!VisContext) { + Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); + return; + } + + // Pop visibility from stack + VisStack *Stack = static_cast<VisStack*>(VisContext); - Stack->pop_back(); - // To simplify the implementation, never keep around an empty stack. - if (Stack->empty()) - FreeVisContext(); + const std::pair<unsigned, SourceLocation> *Back = &Stack->back(); + bool StartsWithPragma = Back->first != NoVisibility; + if (StartsWithPragma && IsNamespaceEnd) { + Diag(Back->second, diag::err_pragma_push_visibility_mismatch); + Diag(EndLoc, diag::note_surrounding_namespace_ends_here); + + // For better error recovery, eat all pushes inside the namespace. + do { + Stack->pop_back(); + Back = &Stack->back(); + StartsWithPragma = Back->first != NoVisibility; + } while (StartsWithPragma); + } else if (!StartsWithPragma && !IsNamespaceEnd) { + Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); + Diag(Back->second, diag::note_surrounding_namespace_starts_here); + return; } - // FIXME: Add diag for pop without push. + + Stack->pop_back(); + // To simplify the implementation, never keep around an empty stack. + if (Stack->empty()) + FreeVisContext(); } |