Start implementing semantic analysis for C initializers.
Step 1: Start instantiating InitListExpr's. Step 2: Call newly added function Sema::CheckInitializer() from Sema::ParseDeclarator(). Step 3: Give InitListExpr's a preliminary type. Step 4: Start emitting diagnostics for simple assignments. Note: As a result of step 1, the CodeGen/mandel.c test asserts "Unimplemented agg expr!", which is expected. As a result of step 4, the test below now fails. This isn't expected and needs to be investigated (it appears type checking for C++ references is flawed in some way). ******************** TEST 'Sema/cxx-references.cpp' FAILED! ******************** Command: clang -fsyntax-only Sema/cxx-references.cpp Output: Sema/cxx-references.cpp:8:12: warning: incompatible pointer types assigning 'int &*' to 'int *' int *p = &r; ^~ Sema/cxx-references.cpp:10:20: error: incompatible types assigning 'int (int)' to 'int (&)(int)' int (&rg)(int) = g; ^ Sema/cxx-references.cpp:13:18: error: incompatible types assigning 'int [3]' to 'int (&)[3]' int (&ra)[3] = a; ^ Sema/cxx-references.cpp:16:14: error: incompatible types assigning 'int *' to 'int *&' int *& P = Q; ^ 4 diagnostics generated. ******************** TEST 'Sema/cxx-references.cpp' FAILED! ******************** llvm-svn: 41671
This commit is contained in:
parent
42a350a18a
commit
2fea13926f
|
@ -440,6 +440,10 @@ private:
|
|||
QualType CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc,
|
||||
IdentifierInfo &Comp, SourceLocation CmpLoc);
|
||||
|
||||
/// type checking declaration initializers (C99 6.7.8)
|
||||
QualType CheckInitializer(Expr *simpleInit_or_initList, QualType declType);
|
||||
bool CheckSingleInitializer(Expr *simpleInit, QualType declType);
|
||||
|
||||
/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
|
||||
/// the specified width and sign. If an overflow occurs, detect it and emit
|
||||
/// the specified diagnostic.
|
||||
|
|
|
@ -239,6 +239,63 @@ Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool Sema::CheckSingleInitializer(Expr *Init, QualType DeclType) {
|
||||
AssignmentCheckResult result;
|
||||
SourceLocation loc = Init->getLocStart();
|
||||
// Get the type before calling CheckSingleAssignmentConstraints(), since
|
||||
// it can promote the expression.
|
||||
QualType rhsType = Init->getType();
|
||||
|
||||
result = CheckSingleAssignmentConstraints(DeclType, Init);
|
||||
|
||||
// decode the result (notice that extensions still return a type).
|
||||
switch (result) {
|
||||
case Compatible:
|
||||
break;
|
||||
case Incompatible:
|
||||
Diag(loc, diag::err_typecheck_assign_incompatible,
|
||||
DeclType.getAsString(), rhsType.getAsString(),
|
||||
Init->getSourceRange());
|
||||
return true;
|
||||
case PointerFromInt:
|
||||
// check for null pointer constant (C99 6.3.2.3p3)
|
||||
if (!Init->isNullPointerConstant(Context)) {
|
||||
Diag(loc, diag::ext_typecheck_assign_pointer_int,
|
||||
DeclType.getAsString(), rhsType.getAsString(),
|
||||
Init->getSourceRange());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case IntFromPointer:
|
||||
Diag(loc, diag::ext_typecheck_assign_pointer_int,
|
||||
DeclType.getAsString(), rhsType.getAsString(),
|
||||
Init->getSourceRange());
|
||||
break;
|
||||
case IncompatiblePointer:
|
||||
Diag(loc, diag::ext_typecheck_assign_incompatible_pointer,
|
||||
DeclType.getAsString(), rhsType.getAsString(),
|
||||
Init->getSourceRange());
|
||||
break;
|
||||
case CompatiblePointerDiscardsQualifiers:
|
||||
Diag(loc, diag::ext_typecheck_assign_discards_qualifiers,
|
||||
DeclType.getAsString(), rhsType.getAsString(),
|
||||
Init->getSourceRange());
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QualType Sema::CheckInitializer(Expr *Init, QualType DeclType) {
|
||||
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
|
||||
if (!InitList) {
|
||||
return CheckSingleInitializer(Init, DeclType) ? QualType() : DeclType;
|
||||
}
|
||||
// We have an InitListExpr, make sure we set the type.
|
||||
Init->setType(DeclType);
|
||||
// FIXME: Lot of checking still to do...
|
||||
return DeclType;
|
||||
}
|
||||
|
||||
Sema::DeclTy *
|
||||
Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
|
||||
DeclTy *lastDeclarator) {
|
||||
|
@ -376,6 +433,9 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
|
|||
}
|
||||
NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
|
||||
} else {
|
||||
if (Init) {
|
||||
CheckInitializer(Init, R);
|
||||
}
|
||||
// Block scope. C99 6.7p7: If an identifier for an object is declared with
|
||||
// no linkage (C99 6.2.2p6), the type for the object shall be complete...
|
||||
if (SC != VarDecl::Extern) {
|
||||
|
@ -410,10 +470,7 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
|
|||
NewVD = MergeVarDecl(NewVD, PrevDecl);
|
||||
if (NewVD == 0) return 0;
|
||||
}
|
||||
if (Init) {
|
||||
AssignmentCheckResult result;
|
||||
result = CheckSingleAssignmentConstraints(R, Init);
|
||||
// FIXME: emit errors if appropriate.
|
||||
if (Init) { // FIXME: This will likely move up above...for now, it stays.
|
||||
NewVD->setInit(Init);
|
||||
}
|
||||
New = NewVD;
|
||||
|
|
|
@ -642,15 +642,14 @@ ParseCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
|
|||
Action::ExprResult Sema::
|
||||
ParseInitList(SourceLocation LBraceLoc, ExprTy **initlist, unsigned NumInit,
|
||||
SourceLocation RBraceLoc) {
|
||||
// Expr **InitList = reinterpret_cast<Expr**>(initlist);
|
||||
Expr **InitList = reinterpret_cast<Expr**>(initlist);
|
||||
|
||||
// FIXME: add semantic analysis (C99 6.7.8). This involves
|
||||
// knowledge of the object being intialized. As a result, the code for
|
||||
// doing the semantic analysis will likely be located elsewhere (i.e. in
|
||||
// consumers of InitListExpr (e.g. ParseDeclarator, ParseCompoundLiteral).
|
||||
|
||||
//return new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc);
|
||||
return false; // FIXME instantiate an InitListExpr.
|
||||
return new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc);
|
||||
}
|
||||
|
||||
Action::ExprResult Sema::
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// RUN: clang -parse-ast-check -pedantic %s
|
||||
|
||||
void func() {
|
||||
int x = 1;
|
||||
|
||||
//int x2[] = { 1, 3, 5 };
|
||||
|
||||
int x3[x] = { 1, 2 }; // gcc-error {{variable-sized object may not be initialized}}
|
||||
|
||||
int x4 = { 1, 2 }; // gcc-warning {{excess elements in array initializer}}
|
||||
|
||||
int y[4][3] = {
|
||||
{ 1, 3, 5 },
|
||||
{ 2, 4, 6 },
|
||||
{ 3, 5, 7 },
|
||||
};
|
||||
|
||||
int y2[4][3] = {
|
||||
1, 3, 5, 2, 4, 6, 3, 5, 7
|
||||
};
|
||||
|
||||
struct threeElements {
|
||||
int a,b,c;
|
||||
} z = { 1 };
|
||||
|
||||
struct threeElements *p = 7; // expected-warning{{incompatible types assigning 'int' to 'struct threeElements *'}}
|
||||
}
|
Loading…
Reference in New Issue