Skip to content

Add checking of redeclarations of variables with bounds. #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -1713,6 +1713,7 @@ class Type : public ExtQualsTypeCommonBase {
bool isDependentSizedArrayType() const;
/// \brief whether this is a Checked C checked array type.
bool isCheckedArrayType() const;
bool isUncheckedArrayType() const;
bool isRecordType() const;
bool isClassType() const;
bool isStructureType() const;
Expand Down Expand Up @@ -5670,6 +5671,12 @@ inline bool Type::isCheckedArrayType() const {
else
return false;
}
inline bool Type::isUncheckedArrayType() const {
if (const ArrayType *T = dyn_cast<ArrayType>(CanonicalType))
return !T->isChecked();
else
return false;
}
inline bool Type::isBuiltinType() const {
return isa<BuiltinType>(CanonicalType);
}
Expand Down
30 changes: 13 additions & 17 deletions include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -8843,23 +8843,19 @@ def err_bounds_type_annotation_lost_checking : Error<

def note_previous_bounds_decl : Note<"previous bounds declaration is here">;

def err_conflicting_parameter_bounds : Error<
"function redeclaration has conflicting parameter bounds">;

def err_conflicting_return_bounds : Error<
"function redeclaration has conflicting return bounds">;

def err_added_bounds_for_return : Error<
"function redeclaration added return bounds">;

def err_missing_bounds_for_return : Error <
"function redeclaration dropped return bounds">;

def err_added_bounds_for_parameter : Error<
"function redeclaration added bounds for parameter">;

def err_missing_bounds_for_parameter : Error<
"function redeclaration dropped bounds for parameter">;
def err_decl_conflicting_bounds : Error<
"%select{function redeclaration has conflicting parameter bounds|function "
"redeclaration has conflicting return bounds|variable redeclaration has "
"conflicting bounds}0">;

def err_decl_added_bounds : Error<
"%select{function redeclaration added bounds for parameter|function "
"redeclaration added return bounds|variable redeclaration added bounds}0">;

def err_decl_dropped_bounds : Error<
"%select{function redeclaration dropped bounds for parameter|function "
"redeclaration dropped return bounds|variable redeclaration dropped "
"bounds}0">;

def err_conflicting_bounds : Error<"conflicting bounds for %0">;

Expand Down
8 changes: 8 additions & 0 deletions include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -2267,6 +2267,14 @@ class Sema {
CCT_Union
};

// used for %select in diagnostics for errors involving redeclarations
// with bounds
enum class CheckedCBoundsError {
CCBE_Parameter,
CCBE_Return,
CCBE_Variable
};

CheckedTypeClassification classifyForCheckedTypeDiagnostic(QualType qt);

// AssignmentAction - This is used by all the assignment diagnostic functions
Expand Down
32 changes: 17 additions & 15 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2086,22 +2086,24 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(

bool TypeContainsAuto = D.getDeclSpec().containsPlaceholderType();

// Parse the optional Checked C bounds expression or interop type
// annotation.
if (getLangOpts().CheckedC && Tok.is(tok::colon)) {
ConsumeToken();
ExprResult Bounds = ParseBoundsExpressionOrInteropType(D);
if (Bounds.isInvalid())
SkipUntil(tok::comma, tok::equal, StopAtSemi | StopBeforeMatch);

// If this is a variable declarator in Checked C, parse the bounds expression
// (if any) and set the bounds expression. Function declarators are ignored
// here because return bounds expressions are parsed as part of function
// declarators already.
if (getLangOpts().CheckedC && isa<VarDecl>(ThisDecl)) {
VarDecl *ThisVarDecl = dyn_cast<VarDecl>(ThisDecl);
if (ThisVarDecl) {
if (Bounds.isInvalid())
Actions.ActOnInvalidBoundsDecl(ThisVarDecl);
else
Actions.ActOnBoundsDecl(ThisVarDecl, cast<BoundsExpr>(Bounds.get()));
} else
llvm_unreachable("Unexpected decl type");
BoundsExpr *Bounds = nullptr;
// The optional Checked C bounds expression or interop type annotation.
if (Tok.is(tok::colon)) {
ConsumeToken();
ExprResult ParsedBounds = ParseBoundsExpressionOrInteropType(D);
if (ParsedBounds.isInvalid()) {
SkipUntil(tok::comma, tok::equal, StopAtSemi | StopBeforeMatch);
Bounds = Actions.CreateInvalidBoundsExpr();
} else
Bounds = cast<BoundsExpr>(ParsedBounds.get());
}
Actions.ActOnBoundsDecl(ThisVarDecl, Bounds);
}

// Parse declarator '=' initializer.
Expand Down
Loading