summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaAttr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaAttr.cpp')
-rw-r--r--lib/Sema/SemaAttr.cpp54
1 files changed, 36 insertions, 18 deletions
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 77410db..e935fc7 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/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();
}
OpenPOWER on IntegriCloud