0

In the short snippet of C code below:

#include <stdio.h>

int main() {
    int i1, i2;
    float f1, f2;
    scanf("%d %d\n%f %f[^\n]%*c", &i1, &i2, &f1, &f2);
    printf("%d %d\n", i1, i2);
    printf("%f %f\n", f1, f2);
    return 0;
}

How does one disable this cert-err34-c warning:

Clang-Tidy: 'scanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead

I tried to look at this one: Concise way to disable specific warning instances in Clang

Then did something like that:

#include <stdio.h>

int main() {
    int i1, i2;
    float f1, f2;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "cert-err34-c"
    scanf("%d %d\n%f %f[^\n]%*c", &i1, &i2, &f1, &f2);
#pragma clang diagnostic pop
    printf("%d %d\n", i1, i2);
    printf("%f %f\n", f1, f2);
    return 0;
}

But now I'm getting:

Pragma diagnostic expected option name (e.g. "-Wundef")

I can't find where is the related -Wxxxx flag, any idea?


Also already answered there: Inline way to disable clang-tidy checks

Natalie Perret
  • 8,013
  • 12
  • 66
  • 129
  • 1
    Unrelated to your problem, but `[^\n]` in the format will be taken literally. – Some programmer dude Sep 26 '20 at 14:11
  • Hmm weird, it doesn't behave like such – Natalie Perret Sep 26 '20 at 14:13
  • Correction: `[^` and `]` will be taken literally. The newline will cause `scanf` to swallow (read and discard) all consecutive white-space. – Some programmer dude Sep 26 '20 at 14:15
  • Yes and this is what I want afaik, just trying to sanitize a bit my input. Or did I get something wrong? – Natalie Perret Sep 26 '20 at 14:19
  • It's just that `%[^\n]` is a valid format specifier, it looks so close to your `[^\n]`. – Some programmer dude Sep 26 '20 at 14:41
  • @KerryPerret yes, you did it wrong, it will have a match failure because your input did not have a `[` character and stop there then. And the fact that you use *both* ` ` and `\n` in `scanf`, even though their behaviour is identical might suggest that you also might not have internalized what the warning means and how seriously defective `scanf` is, i.e. if you *care* about what clang-tidy says at all, perhaps you should take it seriously in this instance too – Antti Haapala -- Слава Україні Sep 26 '20 at 15:03
  • You should post the input you use with this and the reasoning that led you to use this code, I'm almost certain that there is a better way to parse your input, that is if you want or are allowed to change it. Also, a basic way to verify scanf parsing is to check its return. – anastaciu Sep 26 '20 at 15:07
  • 1
    I think this is a duplicate of https://stackoverflow.com/questions/37950439/inline-way-to-disable-clang-tidy-checks. But I am not sure how duplicates work in SO. But @KerryPerret could surely refer to this question – pratikpc Sep 26 '20 at 16:32
  • @AnttiHaapala thanks! Makes more sense! – Natalie Perret Sep 26 '20 at 17:56
  • 1
    @pratikpc oopsie, didn't see that one, thanks! Will add a reference to this post! – Natalie Perret Sep 26 '20 at 17:57

2 Answers2

3

Instead of trying to disable these warnings, why not try to write better code? the scanf() format seems broken anyway.

You just want to read 2 lines an parse them with strtol() and strtod():

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    char buf[128];
    char *p1, *p2;
    long i1, i2;
    double f1, f2;

    if (!fgets(buf, sizeof buf, stdin)) {
        printf("no input\n");
        return 1;
    }
    errno = 0;
    i1 = strtol(buf, &p1, 10);
    i2 = strtol(p1, &p2, 10);
    if (p1 == buf || p2 == p1) {
        printf("input error\n");
        return 1;
    }
    if (errno != 0) {
        perror("conversion error");
        return 1;
    }
    if (!fgets(buf, sizeof buf, stdin)) {
        printf("missing input\n");
        return 1;
    }
    errno = 0;
    f1 = strtod(buf, &p1);
    f2 = strtod(p1, &p2);
    if (p1 == buf || p2 == p1) {
        printf("input error\n");
        return 1;
    }
    if (errno != 0) {
        perror("conversion error");
        return 1;
    }
    printf("%ld %ld\n", i1, i2);
    printf("%f %f\n", f1, f2);
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 1
    I like your solution (hence my upvote), even tho it doesn't address directly the issue. I like `scanf` cause you can put the expected pattern right from the get-go, I found that `fgets` takes a lot more ceremony to get things right. – Natalie Perret Sep 26 '20 at 17:52
1

What you did, did not disable Clang Tidy warnings
Clang Tidy works a little differently

https://stackoverflow.com/a/40325333/1691072

You need to use something like

badcode;  // NOLINT

// NOLINTNEXTLINE
badcode;

badcode; // NOLINT (cert-err-34-c)

to disable Clang-Tidy Warnings

Edit:- What you did actually disables warnings for Clang the compiler, not Clang-Tidy the Linter

Edit2:- Add Space after NOLINT parameters for it to work

alfC
  • 14,261
  • 4
  • 67
  • 118
pratikpc
  • 432
  • 4
  • 12
  • 1
    Thanks, // NOLINT(cert-err-34-c) didn't work, you actually need a space before the left parenthesis => // NOLINT (cert-err-34-c) – Natalie Perret Sep 27 '20 at 14:23