aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp37
-rw-r--r--clang/lib/Sema/SemaDecl.cpp58
2 files changed, 65 insertions, 30 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 277a67f..c3c56dd 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2192,7 +2192,22 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
}
};
- // Inform the current actions module that we just parsed this declarator.
+ enum class InitKind { Uninitialized, Equal, CXXDirect, CXXBraced };
+ InitKind TheInitKind;
+ // If a '==' or '+=' is found, suggest a fixit to '='.
+ if (isTokenEqualOrEqualTypo())
+ TheInitKind = InitKind::Equal;
+ else if (Tok.is(tok::l_paren))
+ TheInitKind = InitKind::CXXDirect;
+ else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) &&
+ (!CurParsedObjCImpl || !D.isFunctionDeclarator()))
+ TheInitKind = InitKind::CXXBraced;
+ else
+ TheInitKind = InitKind::Uninitialized;
+ if (TheInitKind != InitKind::Uninitialized)
+ D.setHasInitializer();
+
+ // Inform Sema that we just parsed this declarator.
Decl *ThisDecl = nullptr;
Decl *OuterDecl = nullptr;
switch (TemplateInfo.Kind) {
@@ -2254,9 +2269,9 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
}
}
+ switch (TheInitKind) {
// Parse declarator '=' initializer.
- // If a '==' or '+=' is found, suggest a fixit to '='.
- if (isTokenEqualOrEqualTypo()) {
+ case InitKind::Equal: {
SourceLocation EqualLoc = ConsumeToken();
if (Tok.is(tok::kw_delete)) {
@@ -2311,7 +2326,9 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Actions.AddInitializerToDecl(ThisDecl, Init.get(),
/*DirectInit=*/false);
}
- } else if (Tok.is(tok::l_paren)) {
+ break;
+ }
+ case InitKind::CXXDirect: {
// Parse C++ direct initializer: '(' expression-list ')'
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
@@ -2365,8 +2382,9 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Actions.AddInitializerToDecl(ThisDecl, Initializer.get(),
/*DirectInit=*/true);
}
- } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) &&
- (!CurParsedObjCImpl || !D.isFunctionDeclarator())) {
+ break;
+ }
+ case InitKind::CXXBraced: {
// Parse C++0x braced-init-list.
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
@@ -2381,9 +2399,12 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Actions.ActOnInitializerError(ThisDecl);
} else
Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/true);
-
- } else {
+ break;
+ }
+ case InitKind::Uninitialized: {
Actions.ActOnUninitializedDecl(ThisDecl);
+ break;
+ }
}
Actions.FinalizeDeclaration(ThisDecl);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6da530c..dc11dac 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6023,6 +6023,31 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
return FixedTInfo;
}
+/// Attempt to fold a variable-sized type to a constant-sized type, returning
+/// true if we were successful.
+static bool tryToFixVariablyModifiedVarType(Sema &S, TypeSourceInfo *&TInfo,
+ QualType &T, SourceLocation Loc,
+ unsigned FailedFoldDiagID) {
+ bool SizeIsNegative;
+ llvm::APSInt Oversized;
+ TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo(
+ TInfo, S.Context, SizeIsNegative, Oversized);
+ if (FixedTInfo) {
+ S.Diag(Loc, diag::ext_vla_folded_to_constant);
+ TInfo = FixedTInfo;
+ T = FixedTInfo->getType();
+ return true;
+ }
+
+ if (SizeIsNegative)
+ S.Diag(Loc, diag::err_typecheck_negative_array_size);
+ else if (Oversized.getBoolValue())
+ S.Diag(Loc, diag::err_array_too_large) << Oversized.toString(10);
+ else if (FailedFoldDiagID)
+ S.Diag(Loc, FailedFoldDiagID);
+ return false;
+}
+
/// Register the given locally-scoped extern "C" declaration so
/// that it can be found later for redeclarations. We include any extern "C"
/// declaration that is not visible in the translation unit here, not just
@@ -6861,6 +6886,12 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
+ // If this variable has a variable-modified type and an initializer, try to
+ // fold to a constant-sized type. This is otherwise invalid.
+ if (D.hasInitializer() && R->isVariablyModifiedType())
+ tryToFixVariablyModifiedVarType(*this, TInfo, R, D.getIdentifierLoc(),
+ /*DiagID=*/0);
+
bool IsMemberSpecialization = false;
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;
@@ -16658,27 +16689,9 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
- bool SizeIsNegative;
- llvm::APSInt Oversized;
-
- TypeSourceInfo *FixedTInfo =
- TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
- SizeIsNegative,
- Oversized);
- if (FixedTInfo) {
- Diag(Loc, diag::ext_vla_folded_to_constant);
- TInfo = FixedTInfo;
- T = FixedTInfo->getType();
- } else {
- if (SizeIsNegative)
- Diag(Loc, diag::err_typecheck_negative_array_size);
- else if (Oversized.getBoolValue())
- Diag(Loc, diag::err_array_too_large)
- << Oversized.toString(10);
- else
- Diag(Loc, diag::err_typecheck_field_variable_size);
+ if (!tryToFixVariablyModifiedVarType(
+ *this, TInfo, T, Loc, diag::err_typecheck_field_variable_size))
InvalidDecl = true;
- }
}
// Fields can not have abstract class types
@@ -16904,8 +16917,9 @@ Decl *Sema::ActOnIvar(Scope *S,
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
else if (T->isVariablyModifiedType()) {
- Diag(Loc, diag::err_typecheck_ivar_variable_size);
- D.setInvalidType();
+ if (!tryToFixVariablyModifiedVarType(
+ *this, TInfo, T, Loc, diag::err_typecheck_ivar_variable_size))
+ D.setInvalidType();
}
// Get the visibility (access control) for this ivar.