[clang][Sema] Emit warnings about incorrect AVR interrupt/signal handlers (#125997)

1. interrupt/signal handlers can not have parameters
2. interrupt/signal handlers must be 'void' type
This commit is contained in:
Ben Shi 2025-02-11 14:04:28 +08:00 committed by GitHub
parent 27c034a9c6
commit 170b9caf33
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 63 additions and 32 deletions

View File

@ -350,10 +350,11 @@ def warn_arm_interrupt_vfp_clobber : Warning<
InGroup<DiagGroup<"arm-interrupt-vfp-clobber">>;
def err_arm_interrupt_called : Error<
"interrupt service routine cannot be called directly">;
def warn_interrupt_attribute_invalid : Warning<
"%select{MIPS|MSP430|RISC-V}0 'interrupt' attribute only applies to "
"functions that have %select{no parameters|a 'void' return type}1">,
InGroup<IgnoredAttributes>;
def warn_interrupt_signal_attribute_invalid : Warning<
"%select{MIPS|MSP430|RISC-V|AVR}0 '%select{interrupt|signal}1' "
"attribute only applies to functions that have "
"%select{no parameters|a 'void' return type}2">,
InGroup<IgnoredAttributes>;
def warn_riscv_repeated_interrupt_attribute : Warning<
"repeated RISC-V 'interrupt' attribute">, InGroup<IgnoredAttributes>;
def note_riscv_repeated_interrupt_attribute : Note<

View File

@ -30,6 +30,18 @@ void SemaAVR::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
if (!AL.checkExactlyNumArgs(SemaRef, 0))
return;
// AVR interrupt handlers must have no parameter and be void type.
if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*AVR*/ 3 << /*interrupt*/ 0 << 0;
return;
}
if (!getFunctionOrMethodResultType(D)->isVoidType()) {
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*AVR*/ 3 << /*interrupt*/ 0 << 1;
return;
}
handleSimpleAttribute<AVRInterruptAttr>(*this, D, AL);
}
@ -43,6 +55,18 @@ void SemaAVR::handleSignalAttr(Decl *D, const ParsedAttr &AL) {
if (!AL.checkExactlyNumArgs(SemaRef, 0))
return;
// AVR signal handlers must have no parameter and be void type.
if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*AVR*/ 3 << /*signal*/ 1 << 0;
return;
}
if (!getFunctionOrMethodResultType(D)->isVoidType()) {
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*AVR*/ 3 << /*signal*/ 1 << 1;
return;
}
handleSimpleAttribute<AVRSignalAttr>(*this, D, AL);
}

View File

@ -271,14 +271,14 @@ void SemaMIPS::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
}
if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
<< /*MIPS*/ 0 << 0;
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*MIPS*/ 0 << /*interrupt*/ 0 << 0;
return;
}
if (!getFunctionOrMethodResultType(D)->isVoidType()) {
Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
<< /*MIPS*/ 0 << 1;
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*MIPS*/ 0 << /*interrupt*/ 0 << 1;
return;
}

View File

@ -32,14 +32,14 @@ void SemaMSP430::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
}
if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
<< /*MSP430*/ 1 << 0;
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*MSP430*/ 1 << /*interrupt*/ 0 << 0;
return;
}
if (!getFunctionOrMethodResultType(D)->isVoidType()) {
Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
<< /*MSP430*/ 1 << 1;
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*MSP430*/ 1 << /*interrupt*/ 0 << 1;
return;
}

View File

@ -1457,14 +1457,14 @@ void SemaRISCV::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
}
if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
<< /*RISC-V*/ 2 << 0;
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*RISC-V*/ 2 << /*interrupt*/ 0 << 0;
return;
}
if (!getFunctionOrMethodResultType(D)->isVoidType()) {
Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
<< /*RISC-V*/ 2 << 1;
Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)
<< /*RISC-V*/ 2 << /*interrupt*/ 0 << 1;
return;
}

View File

@ -0,0 +1,22 @@
// RUN: %clang_cc1 %s -triple avr-unknown-unknown -verify -fsyntax-only
struct a { int b; };
struct a test __attribute__((interrupt)); // expected-warning {{'interrupt' attribute only applies to functions}}
__attribute__((interrupt(12))) void foo(void) { } // expected-error {{'interrupt' attribute takes no arguments}}
__attribute__((interrupt)) int fooa(void) { return 0; } // expected-warning {{'interrupt' attribute only applies to functions that have a 'void' return type}}
__attribute__((interrupt)) void foob(int a) {} // expected-warning {{'interrupt' attribute only applies to functions that have no parameters}}
__attribute__((signal)) int fooc(void) { return 0; } // expected-warning {{'signal' attribute only applies to functions that have a 'void' return type}}
__attribute__((signal)) void food(int a) {} // expected-warning {{'signal' attribute only applies to functions that have no parameters}}
__attribute__((interrupt)) void fooe(void) {}
__attribute__((interrupt)) void foof() {}
__attribute__((signal)) void foog(void) {}
__attribute__((signal)) void fooh() {}

View File

@ -1,8 +0,0 @@
// RUN: %clang_cc1 %s -triple avr-unknown-unknown -verify -fsyntax-only
struct a { int b; };
struct a test __attribute__((interrupt)); // expected-warning {{'interrupt' attribute only applies to functions}}
__attribute__((interrupt(12))) void foo(void) { } // expected-error {{'interrupt' attribute takes no arguments}}
__attribute__((interrupt)) void food(void) {}

View File

@ -1,8 +0,0 @@
// RUN: %clang_cc1 %s -triple avr-unknown-unknown -verify -fsyntax-only
struct a { int b; };
struct a test __attribute__((signal)); // expected-warning {{'signal' attribute only applies to functions}}
__attribute__((signal(12))) void foo(void) { } // expected-error {{'signal' attribute takes no arguments}}
__attribute__((signal)) void food(void) {}