[cfe-commits] r38807 - in /cfe/cfe/trunk: Parse/DeclSpec.cpp Parse/ParseDecl.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Parse/DeclSpec.h include/clang/Parse/Parser.h
sabre at cs.uiuc.edu
sabre at cs.uiuc.edu
Wed Jul 11 09:24:49 PDT 2007
Author: sabre
Date: Wed Jul 11 11:24:48 2007
New Revision: 38807
URL: http://llvm.org/viewvc/llvm-project?rev=38807&view=rev
Log:
Parse and validate cvr type-qualifiers
Modified:
cfe/cfe/trunk/Parse/DeclSpec.cpp
cfe/cfe/trunk/Parse/ParseDecl.cpp
cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/cfe/trunk/include/clang/Parse/DeclSpec.h
cfe/cfe/trunk/include/clang/Parse/Parser.h
Modified: cfe/cfe/trunk/Parse/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/DeclSpec.cpp?rev=38807&r1=38806&r2=38807&view=diff
==============================================================================
--- cfe/cfe/trunk/Parse/DeclSpec.cpp (original)
+++ cfe/cfe/trunk/Parse/DeclSpec.cpp Wed Jul 11 11:24:48 2007
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Declarations.h"
+#include "clang/Basic/LangOptions.h"
using namespace llvm;
using namespace clang;
@@ -82,6 +83,15 @@
return true;
}
+static bool BadSpecifier(DeclSpec::TQ T, const char *&PrevSpec) {
+ switch (T) {
+ case DeclSpec::TQ_unspecified: PrevSpec = "unspecified"; break;
+ case DeclSpec::TQ_const: PrevSpec = "const"; break;
+ case DeclSpec::TQ_restrict: PrevSpec = "restrict"; break;
+ case DeclSpec::TQ_volatile: PrevSpec = "volatile"; break;
+ }
+ return true;
+}
/// These methods set the specified attribute of the DeclSpec, but return true
/// and ignore the request if invalid (e.g. "extern" then "auto" is
@@ -112,6 +122,14 @@
return false;
}
+bool DeclSpec::SetTypeQual(TQ T, const char *&PrevSpec,
+ const LangOptions &Lang) {
+ // Duplicates turn into warnings pre-C99.
+ if ((TypeQualifiers & T) && !Lang.C99)
+ return BadSpecifier(T, PrevSpec);
+ TypeQualifiers |= T;
+ return false;
+}
bool DeclSpec::SetFuncSpec(FS F, const char *&PrevSpec) {
// 'inline inline' is ok.
@@ -123,7 +141,7 @@
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
-diag::kind DeclSpec::Finish() {
+diag::kind DeclSpec::Finish(const LangOptions &Lang) {
// FIXME: implement this.
return diag::NUM_DIAGNOSTICS;
Modified: cfe/cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseDecl.cpp?rev=38807&r1=38806&r2=38807&view=diff
==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:24:48 2007
@@ -22,12 +22,19 @@
/// ParseDeclarationSpecifiers
/// declaration-specifiers: [C99 6.7]
-/// storage-class-specifier declaration-specifiers [opt] [TODO]
-/// //__thread
+/// storage-class-specifier declaration-specifiers [opt]
/// type-specifier declaration-specifiers [opt]
-/// type-qualifier declaration-specifiers [opt] [TODO]
-/// [C99] function-specifier declaration-specifiers [opt] [TODO]
-///
+/// type-qualifier declaration-specifiers [opt]
+/// [C99] function-specifier declaration-specifiers [opt]
+/// [GNU] attributes declaration-specifiers [opt] [TODO]
+///
+/// storage-class-specifier: [C99 6.7.1]
+/// 'typedef'
+/// 'extern'
+/// 'static'
+/// 'auto'
+/// 'register'
+/// [GNU] '__thread'
/// type-specifier: [C99 6.7.2]
/// 'void'
/// 'char'
@@ -40,23 +47,33 @@
/// 'unsigned'
/// [C99] '_Bool'
/// [C99] '_Complex'
-/// [C99] '_Imaginary'
-/// struct-or-union-specifier [TODO]
-/// enum-specifier [TODO]
-/// typedef-name [TODO]
+/// [C99] '_Imaginary' // Removed in TC2?
+/// [GNU] '_Decimal32'
+/// [GNU] '_Decimal64'
+/// [GNU] '_Decimal128'
+/// [OBJC] class-name objc-protocol-refs [opt] [TODO]
+/// [OBJC] typedef-name objc-protocol-refs [TODO]
+/// [OBJC] objc-protocol-refs [TODO]
+/// struct-or-union-specifier [TODO]
+/// enum-specifier [TODO]
+/// typedef-name [TODO]
+/// type-qualifier:
+/// const
+/// volatile
+/// [C99] restrict
/// function-specifier: [C99 6.7.4]
/// [C99] inline
///
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
SourceLocation StartLoc = Tok.getLocation();
while (1) {
- bool isInvalid = false;
+ int isInvalid = false;
const char *PrevSpec = 0;
switch (Tok.getKind()) {
default:
// If this is not a declaration specifier token, we're done reading decl
// specifiers. First verify that DeclSpec's are consistent.
- diag::kind Res = DS.Finish();
+ diag::kind Res = DS.Finish(getLang());
if (Res != diag::NUM_DIAGNOSTICS)
Diag(StartLoc, Res);
return;
@@ -115,6 +132,17 @@
//case tok::kw_struct:
//case tok::kw_union:
//case tok::kw_enum:
+
+ // type-qualifier
+ case tok::kw_const:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
+ break;
+ case tok::kw_volatile:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
+ break;
+ case tok::kw_restrict:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
+ break;
// function-specifier
case tok::kw_inline:
@@ -124,7 +152,10 @@
// If the specifier combination wasn't legal, issue a diagnostic.
if (isInvalid) {
assert(PrevSpec && "Method did not return previous specifier!");
- Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
+ if (isInvalid == 1) // Error.
+ Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
+ else // extwarn.
+ Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
}
ConsumeToken();
}
Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=38807&r1=38806&r2=38807&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:24:48 2007
@@ -238,7 +238,8 @@
"ISO C forbids an empty source file")
DIAG(ext_top_level_semi, EXTENSION,
"ISO C does not allow extra ';' outside of a function")
-
+DIAG(ext_duplicate_declspec, EXTENSION,
+ "duplicate '%s' declaration specifier")
DIAG(err_invalid_decl_spec_combination, ERROR,
"cannot combine declaration specifier with previous '%s' specifier")
Modified: cfe/cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=38807&r1=38806&r2=38807&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/DeclSpec.h Wed Jul 11 11:24:48 2007
@@ -18,6 +18,7 @@
namespace llvm {
namespace clang {
+ class LangOptions;
/// DeclSpec - This class captures information about "declaration specifiers",
/// which encompases storage-class-specifiers, type-specifiers, type-qualifiers,
@@ -118,11 +119,13 @@
bool SetTypeSpecType(TST T, const char *&PrevSpec);
bool SetFuncSpec(FS F, const char *&PrevSpec);
+ bool SetTypeQual(TQ T, const char *&PrevSpec, const LangOptions &Lang);
+
/// Finish - This does final analysis of the declspec, rejecting things like
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
- diag::kind Finish();
+ diag::kind Finish(const LangOptions &Lang);
};
} // end namespace clang
Modified: cfe/cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Parse/Parser.h?rev=38807&r1=38806&r2=38807&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Parser.h Wed Jul 11 11:24:48 2007
@@ -38,6 +38,8 @@
public:
Parser(Preprocessor &PP, ParserActions &Actions);
+ const LangOptions &getLang() const { return PP.getLangOptions(); }
+
// Type forwarding. All of these are statically 'void*', but they may all be
// different actual classes based on the actions in place.
typedef ParserActions::ExprTy ExprTy;
More information about the cfe-commits
mailing list