C++: Transfer noexcept specifier for refactoring actions

This applies for e.g.

* "Add Definition..." (on function decl)
* "Move Definition..." (on function decl)
* "Insert Virtual Functions of Base Class" (on class specifier)

Fixes: QTCREATORBUG-11849
Fixes: QTCREATORBUG-19699
Change-Id: I0d259bc1782470f3b3f19617230005a5594a5cca
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Nikolai Kosjar
2019-10-07 14:31:32 +02:00
parent c2aaa93408
commit 54fefd89b8
8 changed files with 49 additions and 2 deletions

View File

@@ -1232,7 +1232,7 @@ FullySpecifiedType Bind::trailingReturnType(TrailingReturnTypeAST *ast, const Fu
return type;
}
const StringLiteral *Bind::asStringLiteral(const ExpressionAST *ast)
const StringLiteral *Bind::asStringLiteral(const AST *ast)
{
CPP_ASSERT(ast, return nullptr);
const int firstToken = ast->firstToken();
@@ -3265,7 +3265,11 @@ bool Bind::visit(FunctionDeclaratorAST *ast)
Function::RvalueRefQualifier);
}
// propagate exception spec
this->exceptionSpecification(ast->exception_specification, type);
if (ExceptionSpecificationAST *spec = ast->exception_specification)
fun->setExceptionSpecification(asStringLiteral(spec));
if (ast->as_cpp_initializer != nullptr) {
fun->setAmbiguous(true);
/*ExpressionTy as_cpp_initializer =*/ this->expression(ast->as_cpp_initializer);

View File

@@ -104,7 +104,7 @@ protected:
void capture(CaptureAST *ast);
Function *lambdaDeclarator(LambdaDeclaratorAST *ast);
FullySpecifiedType trailingReturnType(TrailingReturnTypeAST *ast, const FullySpecifiedType &init);
const StringLiteral *asStringLiteral(const ExpressionAST *ast);
const StringLiteral *asStringLiteral(const AST *ast);
virtual bool preVisit(AST *);
virtual void postVisit(AST *);

View File

@@ -303,6 +303,7 @@ Function::Function(TranslationUnit *translationUnit, int sourceLocation, const N
Function::Function(Clone *clone, Subst *subst, Function *original)
: Scope(clone, subst, original)
, _returnType(clone->type(original->_returnType, subst))
, _exceptionSpecification(original->_exceptionSpecification)
, _flags(original->_flags)
{ }
@@ -534,6 +535,11 @@ bool Function::maybeValidPrototype(int actualArgumentCount) const
return true;
}
const StringLiteral *Function::exceptionSpecification()
{ return _exceptionSpecification; }
void Function::setExceptionSpecification(const StringLiteral *spec)
{ _exceptionSpecification = spec; }
Block::Block(TranslationUnit *translationUnit, int sourceLocation)
: Scope(translationUnit, sourceLocation, /*name = */ nullptr)

View File

@@ -29,6 +29,8 @@
namespace CPlusPlus {
class StringLiteral;
class CPLUSPLUS_EXPORT UsingNamespaceDirective: public Symbol
{
public:
@@ -363,6 +365,9 @@ public:
bool maybeValidPrototype(int actualArgumentCount) const;
const StringLiteral *exceptionSpecification();
void setExceptionSpecification(const StringLiteral *spec);
// Symbol's interface
virtual FullySpecifiedType type() const;
@@ -386,6 +391,7 @@ protected:
private:
FullySpecifiedType _returnType;
const StringLiteral *_exceptionSpecification = nullptr;
struct Flags {
unsigned _isVirtual: 1;
unsigned _isOverride: 1;

View File

@@ -136,6 +136,7 @@ public:
funTy->setConst(type->isConst());
funTy->setVolatile(type->isVolatile());
funTy->setRefQualifier(type->refQualifier());
funTy->setExceptionSpecification(type->exceptionSpecification());
funTy->setName(rewrite->rewriteName(type->name()));

View File

@@ -487,6 +487,12 @@ void TypePrettyPrinter::visit(Function *type)
? QLatin1String("&")
: QLatin1String("&&");
}
// add exception specifier
if (const StringLiteral *spec = type->exceptionSpecification()) {
appendSpace();
_text += QLatin1String(spec->chars());
}
}
}

View File

@@ -126,6 +126,7 @@ private slots:
void test_quickfix_InsertDefFromDecl_ignoreSurroundingGeneratedDeclarations();
void test_quickfix_InsertDefFromDecl_respectWsInOperatorNames1();
void test_quickfix_InsertDefFromDecl_respectWsInOperatorNames2();
void test_quickfix_InsertDefFromDecl_noexcept_specifier();
void test_quickfix_InsertDefFromDecl_macroUsesAtEndOfFile1();
void test_quickfix_InsertDefFromDecl_macroUsesAtEndOfFile2();
void test_quickfix_InsertDefFromDecl_erroneousStatementAtEndOfFile();

View File

@@ -2502,6 +2502,29 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_respectWsInOperatorNames2(
QuickFixOperationTest(singleDocument(original, expected), &factory);
}
/// Check that the noexcept exception specifier is transferred
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_noexcept_specifier()
{
QByteArray original =
"class Foo\n"
"{\n"
" void @foo() noexcept(false);\n"
"};\n";
QByteArray expected =
"class Foo\n"
"{\n"
" void foo() noexcept(false);\n"
"};\n"
"\n"
"void Foo::foo() noexcept(false)\n"
"{\n"
"\n"
"}\n";
InsertDefFromDecl factory;
QuickFixOperationTest(singleDocument(original, expected), &factory);
}
/// Check if a function like macro use is not separated by the function to insert
/// Case: Macro preceded by preproceesor directives and declaration.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_macroUsesAtEndOfFile1()