summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/Sema.cpp54
-rw-r--r--clang/lib/Sema/SemaAttr.cpp37
2 files changed, 90 insertions, 1 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 6f0db6ce1c6..40ffa09de1a 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -70,6 +70,49 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
PushDeclContext(S, Context.getTranslationUnitDecl());
}
+namespace clang {
+namespace sema {
+
+class SemaPPCallbacks : public PPCallbacks {
+ Sema *S = nullptr;
+ llvm::SmallVector<SourceLocation, 8> IncludeStack;
+
+public:
+ void set(Sema &S) { this->S = &S; }
+
+ void reset() { S = nullptr; }
+
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override {
+ if (!S)
+ return;
+ switch (Reason) {
+ case EnterFile: {
+ SourceManager &SM = S->getSourceManager();
+ SourceLocation IncludeLoc = SM.getIncludeLoc(SM.getFileID(Loc));
+ if (IncludeLoc.isValid()) {
+ IncludeStack.push_back(IncludeLoc);
+ S->DiagnoseNonDefaultPragmaPack(
+ Sema::PragmaPackDiagnoseKind::NonDefaultStateAtInclude, IncludeLoc);
+ }
+ break;
+ }
+ case ExitFile:
+ if (!IncludeStack.empty())
+ S->DiagnoseNonDefaultPragmaPack(
+ Sema::PragmaPackDiagnoseKind::ChangedStateAtExit,
+ IncludeStack.pop_back_val());
+ break;
+ default:
+ break;
+ }
+ }
+};
+
+} // end namespace sema
+} // end namespace clang
+
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter)
: ExternalSource(nullptr), isMultiplexExternalSource(false),
@@ -122,6 +165,12 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
// Initilization of data sharing attributes stack for OpenMP
InitDataSharingAttributesStack();
+
+ std::unique_ptr<sema::SemaPPCallbacks> Callbacks =
+ llvm::make_unique<sema::SemaPPCallbacks>();
+ SemaPPCallbackHandler = Callbacks.get();
+ PP.addPPCallbacks(std::move(Callbacks));
+ SemaPPCallbackHandler->set(*this);
}
void Sema::addImplicitTypedef(StringRef Name, QualType T) {
@@ -306,6 +355,10 @@ Sema::~Sema() {
// Destroys data sharing attributes stack for OpenMP
DestroyDataSharingAttributesStack();
+ // Detach from the PP callback handler which outlives Sema since it's owned
+ // by the preprocessor.
+ SemaPPCallbackHandler->reset();
+
assert(DelayedTypos.empty() && "Uncorrected typos!");
}
@@ -766,6 +819,7 @@ void Sema::ActOnEndOfTranslationUnit() {
CheckDelayedMemberExceptionSpecs();
}
+ DiagnoseUnterminatedPragmaPack();
DiagnoseUnterminatedPragmaAttribute();
// All delayed member exception specs should be checked or we end up accepting
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 8c13ead6445..7193450220a 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -202,6 +202,40 @@ void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal);
}
+void Sema::DiagnoseNonDefaultPragmaPack(PragmaPackDiagnoseKind Kind,
+ SourceLocation IncludeLoc) {
+ if (Kind == PragmaPackDiagnoseKind::NonDefaultStateAtInclude) {
+ SourceLocation PrevLocation = PackStack.CurrentPragmaLocation;
+ // Warn about non-default alignment at #includes (without redundant
+ // warnings for the same directive in nested includes).
+ if (PackStack.hasValue() &&
+ (PackIncludeStack.empty() ||
+ PackIncludeStack.back().second != PrevLocation)) {
+ Diag(IncludeLoc, diag::warn_pragma_pack_non_default_at_include);
+ Diag(PrevLocation, diag::note_pragma_pack_here);
+ }
+ PackIncludeStack.push_back(
+ {PackStack.CurrentValue,
+ PackStack.hasValue() ? PrevLocation : SourceLocation()});
+ return;
+ }
+
+ assert(Kind == PragmaPackDiagnoseKind::ChangedStateAtExit && "invalid kind");
+ unsigned PreviousValue = PackIncludeStack.pop_back_val().first;
+ // Warn about modified alignment after #includes.
+ if (PreviousValue != PackStack.CurrentValue) {
+ Diag(IncludeLoc, diag::warn_pragma_pack_modified_after_include);
+ Diag(PackStack.CurrentPragmaLocation, diag::note_pragma_pack_here);
+ }
+}
+
+void Sema::DiagnoseUnterminatedPragmaPack() {
+ if (PackStack.Stack.empty())
+ return;
+ for (const auto &StackSlot : llvm::reverse(PackStack.Stack))
+ Diag(StackSlot.PragmaPushLocation, diag::warn_pragma_pack_no_pop_eof);
+}
+
void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
MSStructPragmaOn = (Kind == PMSST_ON);
}
@@ -249,7 +283,8 @@ void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
return;
}
if (Action & PSK_Push)
- Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation));
+ Stack.emplace_back(StackSlotLabel, CurrentValue, CurrentPragmaLocation,
+ PragmaLocation);
else if (Action & PSK_Pop) {
if (!StackSlotLabel.empty()) {
// If we've got a label, try to find it and jump there.
OpenPOWER on IntegriCloud