From 49e6bc024d0269f580e8601aecf17eaf5537df50 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sun, 4 Jan 2015 20:32:12 +0000 Subject: [PATCH] Remove an assert that's not true on invalid code. r185773 added an assert that checked that a CXXUnresolvedConstructExpr either has a valid rparen, or exactly one argument. This doesn't have to be true for invalid inputs. Convert the assert to an if, and add a test for this case. Found by SLi's afl bot. llvm-svn: 225140 --- clang/include/clang/AST/ExprCXX.h | 5 +++-- clang/test/Misc/ast-dump-invalid.cpp | 20 ++++++++++++++++++++ clang/test/SemaCXX/return.cpp | 8 ++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 clang/test/Misc/ast-dump-invalid.cpp diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 040fbe7..aa33b61 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -2915,8 +2915,9 @@ public: SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY { - assert(RParenLoc.isValid() || NumArgs == 1); - return RParenLoc.isValid() ? RParenLoc : getArg(0)->getLocEnd(); + if (!RParenLoc.isValid() && NumArgs > 0) + return getArg(NumArgs - 1)->getLocEnd(); + return RParenLoc; } static bool classof(const Stmt *T) { diff --git a/clang/test/Misc/ast-dump-invalid.cpp b/clang/test/Misc/ast-dump-invalid.cpp new file mode 100644 index 0000000..3b97cc6 --- /dev/null +++ b/clang/test/Misc/ast-dump-invalid.cpp @@ -0,0 +1,20 @@ +// RUN: not %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s + +namespace TestInvalidRParenOnCXXUnresolvedConstructExpr { +template +void f(T i, T j) { + return T (i, j; +} +} + +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidRParenOnCXXUnresolvedConstructExpr +// CHECK-NEXT: `-FunctionTemplateDecl +// CHECK-NEXT: |-TemplateTypeParmDecl +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-ReturnStmt +// CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'T' +// CHECK-NEXT: |-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'i' 'T' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'j' 'T' diff --git a/clang/test/SemaCXX/return.cpp b/clang/test/SemaCXX/return.cpp index 98dbd51..8c16645 100644 --- a/clang/test/SemaCXX/return.cpp +++ b/clang/test/SemaCXX/return.cpp @@ -112,3 +112,11 @@ namespace ctor_returns_void { ~S() { return f(); } // expected-error {{destructor '~S' must not return void expression}} }; } + +void cxx_unresolved_expr() { + // The use of an undeclared variable tricks clang into building a + // CXXUnresolvedConstructExpr, and the missing ')' gives it an invalid source + // location for its rparen. Check that emitting a diag on the range of the + // expr doesn't assert. + return int(undeclared, 4; // expected-error {{expected ')'}} expected-note{{to match this '('}} expected-error {{void function 'cxx_unresolved_expr' should not return a value}} expected-error {{use of undeclared identifier 'undeclared'}} +} -- 2.7.4