aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/DeclSpec.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-08-03 20:12:06 +0000
committerJohn McCall <rjmccall@apple.com>2009-08-03 20:12:06 +0000
commitfec54013fcd0eb72642741584ca04c1bc292bef8 (patch)
tree296d1773fbdb933456493aefe724350b35eb2227 /lib/Parse/DeclSpec.cpp
parentd1e1ef3b0a54d7e1e9247326a4dab3ec0d4b8ce8 (diff)
Refactor methods on DeclSpec to take a diagnostic& parameter, and reflect this
elsewhere. Very slightly decouples DeclSpec users from knowing the exact diagnostics to report, and makes it easier to provide different diagnostics in some places. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77990 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/DeclSpec.cpp')
-rw-r--r--lib/Parse/DeclSpec.cpp61
1 files changed, 40 insertions, 21 deletions
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 216847a7e1..80078660b6 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -105,8 +105,12 @@ unsigned DeclSpec::getParsedSpecifiers() const {
return Res;
}
-template <class T> static bool BadSpecifier(T TPrev, const char *&PrevSpec) {
+template <class T> static bool BadSpecifier(T TNew, T TPrev,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
PrevSpec = DeclSpec::getSpecifierName(TPrev);
+ DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec
+ : diag::err_invalid_decl_spec_combination);
return true;
}
@@ -193,9 +197,10 @@ const char *DeclSpec::getSpecifierName(TQ T) {
}
bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
- const char *&PrevSpec) {
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (StorageClassSpec != SCS_unspecified)
- return BadSpecifier((SCS)StorageClassSpec, PrevSpec);
+ return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
StorageClassSpec = S;
StorageClassSpecLoc = Loc;
assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield");
@@ -203,9 +208,11 @@ bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
}
bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
- const char *&PrevSpec) {
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (SCS_thread_specified) {
PrevSpec = "__thread";
+ DiagID = diag::ext_duplicate_declspec;
return true;
}
SCS_thread_specified = true;
@@ -218,39 +225,46 @@ bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
/// and ignore the request if invalid (e.g. "extern" then "auto" is
/// specified).
bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
- const char *&PrevSpec) {
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (TypeSpecWidth != TSW_unspecified &&
// Allow turning long -> long long.
(W != TSW_longlong || TypeSpecWidth != TSW_long))
- return BadSpecifier((TSW)TypeSpecWidth, PrevSpec);
+ return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
TypeSpecWidth = W;
TSWLoc = Loc;
return false;
}
bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc,
- const char *&PrevSpec) {
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (TypeSpecComplex != TSC_unspecified)
- return BadSpecifier((TSC)TypeSpecComplex, PrevSpec);
+ return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID);
TypeSpecComplex = C;
TSCLoc = Loc;
return false;
}
bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
- const char *&PrevSpec) {
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (TypeSpecSign != TSS_unspecified)
- return BadSpecifier((TSS)TypeSpecSign, PrevSpec);
+ return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID);
TypeSpecSign = S;
TSSLoc = Loc;
return false;
}
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
- const char *&PrevSpec, void *Rep,
- bool Owned) {
- if (TypeSpecType != TST_unspecified)
- return BadSpecifier((TST)TypeSpecType, PrevSpec);
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ void *Rep, bool Owned) {
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
TypeSpecType = T;
TypeRep = Rep;
TSTLoc = Loc;
@@ -266,10 +280,10 @@ bool DeclSpec::SetTypeSpecError() {
}
bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
- const LangOptions &Lang) {
+ unsigned &DiagID, const LangOptions &Lang) {
// Duplicates turn into warnings pre-C99.
if ((TypeQualifiers & T) && !Lang.C99)
- return BadSpecifier(T, PrevSpec);
+ return BadSpecifier(T, T, PrevSpec, DiagID);
TypeQualifiers |= T;
switch (T) {
@@ -281,33 +295,38 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
return false;
}
-bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec){
+bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
// 'inline inline' is ok.
FS_inline_specified = true;
FS_inlineLoc = Loc;
return false;
}
-bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec){
+bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
// 'virtual virtual' is ok.
FS_virtual_specified = true;
FS_virtualLoc = Loc;
return false;
}
-bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec){
+bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
// 'explicit explicit' is ok.
FS_explicit_specified = true;
FS_explicitLoc = Loc;
return false;
}
-bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec) {
+bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
if (Friend_specified) {
PrevSpec = "friend";
+ DiagID = diag::ext_duplicate_declspec;
return true;
}
-
+
Friend_specified = true;
FriendLoc = Loc;
return false;